update
1.替换修改救助人员接口 2.用户管理添加专业人员和操作人员模块
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
import { Ref, ref } from 'vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
export function showFormTip(domId: string) {
|
||||
const dom: HTMLElement | null = document.getElementById(domId);
|
||||
|
||||
function showDom() {
|
||||
if (dom) {
|
||||
dom.style.display = 'block';
|
||||
dom.scrollIntoView();
|
||||
}
|
||||
}
|
||||
|
||||
function hiddenDom() {
|
||||
if (dom) {
|
||||
dom.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
showDom,
|
||||
hiddenDom,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户其他信息
|
||||
*/
|
||||
export function useUserOtherInfo() {
|
||||
//就诊人信息
|
||||
const userOtherInfo = ref({
|
||||
sex_dictText: '',
|
||||
age: '',
|
||||
idCard: '',
|
||||
phone: '',
|
||||
departName: '',
|
||||
userDepartName: '',
|
||||
workNo: '',
|
||||
});
|
||||
function setUserOtherInfo(values) {
|
||||
for (const key in userOtherInfo.value) {
|
||||
userOtherInfo.value[key] = values[key] || '';
|
||||
}
|
||||
userOtherInfo.value['departName'] = values?.userOrgName || values?.secondDepart?.departName || '';
|
||||
userOtherInfo.value['userDepartName'] = values?.userDepartName || values?.threeDepart?.departName || '';
|
||||
}
|
||||
return {
|
||||
userOtherInfo,
|
||||
setUserOtherInfo,
|
||||
};
|
||||
}
|
||||
function setInfo(record, list, callback?: Function) {
|
||||
if (callback) {
|
||||
callback(list);
|
||||
return;
|
||||
}
|
||||
list.forEach((item) => {
|
||||
const { field } = item;
|
||||
const isEmpty = (obj, field) => {
|
||||
if (!obj) return true;
|
||||
return obj[field] === undefined || obj[field] === null || obj[field] === '';
|
||||
};
|
||||
if (!isEmpty(record, field)) {
|
||||
if (Object.hasOwn(item, 'customRender')) {
|
||||
// @ts-ignore
|
||||
item.value = item.customRender(record);
|
||||
} else if (Object.hasOwn(item, 'slot')) {
|
||||
item.value = { ...record, dataIndex: field };
|
||||
} else {
|
||||
item.value = record[field] || '';
|
||||
}
|
||||
} else {
|
||||
item.value = '';
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
interface IUseTreatmentInfo {
|
||||
label?: string;
|
||||
value: string;
|
||||
component: string;
|
||||
field: string;
|
||||
slot?: string;
|
||||
}
|
||||
/**
|
||||
* 就诊详情
|
||||
*/
|
||||
export function useTreatmentInfo() {
|
||||
const basicInfo: Ref<IUseTreatmentInfo[]> = ref([
|
||||
{
|
||||
label: '就诊人',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'userName',
|
||||
slot: 'userName',
|
||||
},
|
||||
{
|
||||
label: '工号',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'workNo',
|
||||
},
|
||||
{
|
||||
label: '联系电话',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'phone',
|
||||
},
|
||||
{
|
||||
label: '身份证号',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'idCard',
|
||||
},
|
||||
{
|
||||
label: '所属单位',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'userOrgName',
|
||||
},
|
||||
{
|
||||
label: '所属部门',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'userDepartName',
|
||||
},
|
||||
{
|
||||
label: '员工档案',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'createTime',
|
||||
slot: 'employeeFile',
|
||||
},
|
||||
]);
|
||||
const medicalInformation: Ref<IUseTreatmentInfo[]> = ref([
|
||||
{
|
||||
label: '就诊医生',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'doctorName',
|
||||
},
|
||||
{
|
||||
label: '就诊时间',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'diagnosisDate',
|
||||
},
|
||||
{
|
||||
label: '诊断',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'diagnosisDisease',
|
||||
},
|
||||
{
|
||||
label: '主诉',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'mainDemands',
|
||||
},
|
||||
{
|
||||
label: '查体',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'inspectionTool',
|
||||
},
|
||||
{
|
||||
label: '现病史',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'historyPresentIllness',
|
||||
},
|
||||
{
|
||||
label: '既往史',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'pastHistory',
|
||||
},
|
||||
{
|
||||
label: '过敏史',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'allergicHistory',
|
||||
},
|
||||
]);
|
||||
const medicineList: Ref<IUseTreatmentInfo[]> = ref([
|
||||
{
|
||||
label: '药品名称',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'medicineName',
|
||||
},
|
||||
{
|
||||
label: '规格',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'medicineSpecification',
|
||||
},
|
||||
{
|
||||
label: '价格',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'sellingPrice',
|
||||
},
|
||||
{
|
||||
label: '数量',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'drugsNum',
|
||||
},
|
||||
{
|
||||
label: '用法用量',
|
||||
value: '',
|
||||
component: 'Input',
|
||||
field: 'dosage',
|
||||
},
|
||||
]);
|
||||
const lifeAdvice: Ref<IUseTreatmentInfo[]> = ref([
|
||||
{
|
||||
label: '医嘱',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'doctorAdvice',
|
||||
},
|
||||
{
|
||||
label: '运动处方',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'exerciseFormula',
|
||||
},
|
||||
{
|
||||
label: '膳食处方',
|
||||
value: '',
|
||||
component: 'Textarea',
|
||||
field: 'foodFormula',
|
||||
},
|
||||
]);
|
||||
|
||||
function setFormValues(values = {}) {
|
||||
basicInfo.value = setInfo(values, basicInfo.value);
|
||||
medicalInformation.value = setInfo(values, medicalInformation.value);
|
||||
lifeAdvice.value = setInfo(values, lifeAdvice.value);
|
||||
}
|
||||
function getMedicineList(values = []) {
|
||||
return setInfo(values, medicineList.value);
|
||||
}
|
||||
|
||||
function getMedicineDetail(values = []) {
|
||||
let res = setInfo(values, medicineList.value);
|
||||
return cloneDeep(res);
|
||||
}
|
||||
return {
|
||||
basicInfo,
|
||||
medicalInformation,
|
||||
lifeAdvice,
|
||||
setFormValues,
|
||||
getMedicineList,
|
||||
getMedicineDetail,
|
||||
};
|
||||
}
|
||||
|
||||
//val是正常值则返回正常,否则返回--
|
||||
export function useShowValue(val: string | boolean | number) {
|
||||
if (typeof val == undefined || val == null || val == '') {
|
||||
return '--';
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="medical-card">
|
||||
<div v-if="$slots.title"><slot name="title"></slot></div>
|
||||
<div v-if="!$slots.title && title" class="title">{{ title }}</div>
|
||||
<div v-for="(item, index) in cardList" :key="index">
|
||||
<template v-if="item.hasOwnProperty('slot')">
|
||||
<slot :name="item.slot" v-bind="item.value"></slot>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div v-if="item.component == 'Input'" class="input-box">
|
||||
<div class="input-label">{{ item.label }}:</div>
|
||||
<div class="input-value">{{ useShowValue(item.value) }}</div>
|
||||
</div>
|
||||
<div v-if="item.component == 'Textarea' || item.component == 'InputTextArea'" class="textarea-box">
|
||||
<div class="textarea-label">{{ item.label }}:</div>
|
||||
<div class="textarea-value">{{ useShowValue(item.value) }}</div>
|
||||
</div>
|
||||
<div v-if="item.component == 'Image'" class="input-box">
|
||||
<div class="input-label">{{ item.label }}:</div>
|
||||
<div>
|
||||
<Image
|
||||
:width="100"
|
||||
:height="100"
|
||||
style="margin: 0"
|
||||
:src="getFileAccessHttpUrl(item.value)"
|
||||
:fallback="getFamaleDefaultImage()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { Image } from 'ant-design-vue';
|
||||
import { useShowValue } from '/@/views/emergency/personnelManagement/components/hooks';
|
||||
import { getFamaleDefaultImage, getFileAccessHttpUrl } from '/@/utils/common/compUtils';
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return '';
|
||||
},
|
||||
},
|
||||
});
|
||||
const cardList = computed(() => props.list);
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.medical-card {
|
||||
border: 1px solid #f0f0f0;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
position: relative;
|
||||
.title {
|
||||
font-weight: bold;
|
||||
line-height: 30px;
|
||||
}
|
||||
.input-box {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.input-label {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
.input-value {
|
||||
width: calc(100% - 100px);
|
||||
}
|
||||
}
|
||||
.textarea-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
overflow: hidden;
|
||||
flex-wrap: wrap;
|
||||
.textarea-label {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
.textarea-value {
|
||||
width: calc(100% - 100px);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<BasicDrawer
|
||||
v-bind="$attrs"
|
||||
@register="registerDrawer"
|
||||
destroyOnClose
|
||||
:title="title"
|
||||
:width="600"
|
||||
@ok="handleSubmit"
|
||||
:showFooter="showFooter"
|
||||
:maskClosable="false"
|
||||
>
|
||||
<div class="form-container" v-show="title != '详情'">
|
||||
<BasicForm @register="registerForm" />
|
||||
</div>
|
||||
<div class="form-container" v-show="title == '详情'">
|
||||
<MedicalCard :list="getDetailSchema()" title="" />
|
||||
</div>
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref } from 'vue';
|
||||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { saveOrUpdate } from '../personnelManagement.api';
|
||||
import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth';
|
||||
import { dealPassword } from '/@/views/system/user/user.data';
|
||||
import { formSchema, getPersonType, useDetailForm } from '/@/views/emergency/personnelManagement/personnelManagement.data';
|
||||
import MedicalCard from '/@/views/emergency/personnelManagement/components/medicalCard.vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const { adaptiveWidth } = useDrawerAdaptiveWidth();
|
||||
// Emits声明
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const isUpdate = ref(true);
|
||||
const showFooter = ref(true);
|
||||
//设置标题
|
||||
const title = ref('');
|
||||
const route = useRoute();
|
||||
/**
|
||||
* 5 操作人员
|
||||
* 6 专业人员
|
||||
*/
|
||||
const type = getPersonType(route.path.split('/').pop() as string);
|
||||
const { setDetailFormData, getDetailSchema } = useDetailForm(type == 6);
|
||||
//表单配置
|
||||
const [registerForm, { setProps, resetFields, setFieldsValue, validate, clearValidate, updateSchema }] = useForm({
|
||||
labelWidth: 120,
|
||||
schemas: formSchema(type == 6),
|
||||
showActionButtonGroup: false,
|
||||
baseColProps: { span: 24 },
|
||||
});
|
||||
|
||||
//表单赋值
|
||||
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
|
||||
//重置表单
|
||||
await resetFields();
|
||||
setDrawerProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
title.value = data.type;
|
||||
if (unref(isUpdate)) {
|
||||
//表单赋值
|
||||
await setFieldsValue({
|
||||
...data.record,
|
||||
});
|
||||
setDetailFormData(data.record);
|
||||
}
|
||||
await clearValidate();
|
||||
// 隐藏底部时禁用整个表单
|
||||
await setProps({ disabled: !data?.showFooter });
|
||||
});
|
||||
//表单提交事件
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
let data = await validate();
|
||||
if (!isUpdate.value) {
|
||||
data = {
|
||||
...data,
|
||||
password: dealPassword(data?.password),
|
||||
};
|
||||
}
|
||||
|
||||
setDrawerProps({ confirmLoading: true });
|
||||
//提交表单
|
||||
await saveOrUpdate({ ...data, type }, isUpdate.value);
|
||||
//关闭弹窗
|
||||
closeDrawer();
|
||||
//刷新列表
|
||||
emit('success');
|
||||
} finally {
|
||||
setDrawerProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form-container {
|
||||
overflow: auto;
|
||||
}
|
||||
.title {
|
||||
box-sizing: border-box;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-calendar-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,61 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const { createConfirm } = useMessage();
|
||||
export enum Api {
|
||||
list = '/health-emergency/emergency/profession/user/list',
|
||||
save = '/health-emergency/emergency/profession/user/add',
|
||||
edit = '/health-emergency/emergency/profession/user/edit',
|
||||
deleteOne = '/health-emergency/emergency/profession/user/deleteBatch',
|
||||
deleteBatch = '/health-emergency/emergency/profession/user/deleteBatch',
|
||||
}
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const list = (params: any) => defHttp.get({ url: Api.list, params });
|
||||
/**
|
||||
* 删除单个
|
||||
*/
|
||||
export const deleteOne = (params: any, handleSuccess: Function) => {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认删除',
|
||||
content: '是否删除选中数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp.post({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 批量删除
|
||||
* @param params
|
||||
* @param handleSuccess
|
||||
*/
|
||||
export const batchDelete = (params: any, handleSuccess: Function) => {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认删除',
|
||||
content: '是否删除选中数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp.post({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 保存或者更新
|
||||
* @param params
|
||||
* @param isUpdate
|
||||
*/
|
||||
export const saveOrUpdate = (params: any, isUpdate: Boolean) => {
|
||||
const url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params });
|
||||
};
|
||||
@@ -0,0 +1,397 @@
|
||||
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
import { h, ref } from 'vue';
|
||||
import { checkPassword } from '/@/hooks/checkPassword/checkPassword';
|
||||
import { getEmergencyList } from '/@/views/consult/agentManagement/agentManagement.api';
|
||||
import { allCenterApi } from '/@/views/emergency/scheduling/scheduling.api';
|
||||
import { rules } from '/@/utils/helper/validator';
|
||||
import { Image } from 'ant-design-vue';
|
||||
import { getFamaleDefaultImage, getFileAccessHttpUrl } from '/@/utils/common/compUtils';
|
||||
import { EyeOutlined } from '@ant-design/icons-vue';
|
||||
import { ComponentType } from '/@/components/Form/src/types';
|
||||
|
||||
//列表数据
|
||||
export const columns = function (showGoodAt: boolean): BasicColumn[] {
|
||||
return [
|
||||
{
|
||||
title: '用户账号',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'left',
|
||||
dataIndex: 'username',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
dataIndex: 'realname',
|
||||
},
|
||||
{
|
||||
title: '头像',
|
||||
align: 'center',
|
||||
dataIndex: 'avatar',
|
||||
width: 100,
|
||||
customRender: ({ text }) => {
|
||||
const t = text ? text.replace(',', '') : null;
|
||||
return h(Image, {
|
||||
placeholder: true,
|
||||
src: getFileAccessHttpUrl(t),
|
||||
height: 50,
|
||||
width: 50,
|
||||
fallback: getFamaleDefaultImage(''),
|
||||
previewMask: () => {
|
||||
return h(EyeOutlined, {
|
||||
style: {
|
||||
color: 'white',
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '所属应急中心',
|
||||
align: 'center',
|
||||
dataIndex: 'centerName',
|
||||
},
|
||||
{
|
||||
title: '职称',
|
||||
align: 'center',
|
||||
width: 90,
|
||||
dataIndex: 'post_dictText',
|
||||
},
|
||||
{
|
||||
title: '毕业院校',
|
||||
align: 'center',
|
||||
dataIndex: 'school',
|
||||
},
|
||||
{
|
||||
title: '学历',
|
||||
align: 'center',
|
||||
dataIndex: 'edu_dictText',
|
||||
},
|
||||
{
|
||||
title: '擅长症状',
|
||||
align: 'center',
|
||||
dataIndex: 'goodAt',
|
||||
ifShow: showGoodAt,
|
||||
},
|
||||
];
|
||||
};
|
||||
//查询数据
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
label: '姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '所属应急中心',
|
||||
field: 'centerId',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
//@ts-ignore
|
||||
api: allCenterApi,
|
||||
labelField: 'centerName',
|
||||
valueField: 'id',
|
||||
immediate: true,
|
||||
resultField: 'records',
|
||||
showSearch: true,
|
||||
filterOption: (input: string, option: any): boolean => {
|
||||
const str: string = input?.trim()?.toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
},
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
//表单数据
|
||||
// @ts-ignore
|
||||
export const formSchema = function (showGoodAt: boolean): FormSchema[] {
|
||||
return [
|
||||
// 主键Id
|
||||
{
|
||||
label: '',
|
||||
field: 'userId',
|
||||
show: false,
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '用户账号',
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
componentProps: ({ formModel }) => {
|
||||
return {
|
||||
autocomplete: 'off',
|
||||
onInput: (event: Event) => {
|
||||
const target = event.target;
|
||||
formModel.username = target?.value?.replace(/[^\w]/g, '');
|
||||
},
|
||||
};
|
||||
},
|
||||
rules: [{ required: true, message: '请输入用户账号' }],
|
||||
dynamicDisabled: ({ values }) => {
|
||||
return !!values.userId;
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '头像',
|
||||
field: 'avatar',
|
||||
component: 'JImageUpload',
|
||||
required: true,
|
||||
componentProps: () => ({
|
||||
maxCount: 1,
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '密码',
|
||||
field: 'password',
|
||||
component: 'StrengthMeter',
|
||||
componentProps: {
|
||||
//@ts-ignore
|
||||
autocomplete: 'new-password',
|
||||
readOnly: true,
|
||||
onfocus: (field) => {
|
||||
field.target.readOnly = false;
|
||||
},
|
||||
},
|
||||
dynamicRules: () => {
|
||||
return [
|
||||
{
|
||||
required: true,
|
||||
validator: (_, value) => {
|
||||
const { message } = checkPassword(value);
|
||||
if (message === 'ok') {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject(message);
|
||||
}
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
];
|
||||
},
|
||||
ifShow: ({ values }) => {
|
||||
return !values.userId;
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '确认密码',
|
||||
field: 'confirmPassword',
|
||||
component: 'InputPassword',
|
||||
dynamicRules: ({ values }) => rules.confirmPassword(values, true),
|
||||
ifShow: ({ values }) => {
|
||||
return !values.userId;
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '姓名',
|
||||
field: 'realname',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: '所属应急中心',
|
||||
field: 'centerId',
|
||||
component: 'ApiSelect',
|
||||
required: true,
|
||||
componentProps: {
|
||||
//@ts-ignore
|
||||
api: getEmergencyList,
|
||||
params: {
|
||||
pageNo: 1,
|
||||
pageSize: 200,
|
||||
},
|
||||
labelField: 'centerName',
|
||||
valueField: 'id',
|
||||
immediate: true,
|
||||
resultField: 'records',
|
||||
showSearch: true,
|
||||
filterOption: (input: string, option: any): boolean => {
|
||||
const str: string = input?.trim()?.toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
},
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '擅长症状',
|
||||
field: 'goodAt',
|
||||
component: 'InputTextArea',
|
||||
required: true,
|
||||
ifShow: showGoodAt,
|
||||
},
|
||||
{
|
||||
label: '职称',
|
||||
field: 'post',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: () => ({
|
||||
dictCode: 'z_doct_lev',
|
||||
getPopupContainer: () => document.body,
|
||||
}),
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: '毕业院校',
|
||||
field: 'school',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '学历',
|
||||
field: 'edu',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
//@ts-ignore
|
||||
dictCode: 'education',
|
||||
showSearch: true,
|
||||
filterOption: (input: string, option: any): boolean => {
|
||||
const str: string = input.trim().toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
},
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '人员类型',
|
||||
field: 'type',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
interface DetailForm extends FormSchema {
|
||||
value: string;
|
||||
customRender?: Function;
|
||||
component: ComponentType | 'Image';
|
||||
}
|
||||
|
||||
export function useDetailForm(showGoodAt: boolean) {
|
||||
const detailFormSchema = ref<DetailForm[]>([
|
||||
{
|
||||
label: '用户账号',
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
value: '',
|
||||
},
|
||||
|
||||
{
|
||||
label: '姓名',
|
||||
field: 'realname',
|
||||
component: 'Input',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: '头像',
|
||||
field: 'avatar',
|
||||
component: 'Image',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: '所属应急中心',
|
||||
field: 'centerName',
|
||||
component: 'Input',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: '职称',
|
||||
field: 'post_dictText',
|
||||
component: 'Input',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: '毕业院校',
|
||||
field: 'school',
|
||||
component: 'Input',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: '学历',
|
||||
field: 'edu_dictText',
|
||||
component: 'Input',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: '擅长症状',
|
||||
field: 'goodAt',
|
||||
component: 'InputTextArea',
|
||||
value: '',
|
||||
ifShow: showGoodAt,
|
||||
},
|
||||
]);
|
||||
function setData(record: Recordable, list: DetailForm[], callback?: Function) {
|
||||
if (callback) {
|
||||
callback(list);
|
||||
return;
|
||||
}
|
||||
list = list.filter((item) => {
|
||||
return item.ifShow === undefined || item.ifShow;
|
||||
});
|
||||
list.forEach((item) => {
|
||||
const { field } = item;
|
||||
const isEmpty = (obj, field) => {
|
||||
if (!obj) return true;
|
||||
return obj[field] === undefined || obj[field] === null || obj[field] === '';
|
||||
};
|
||||
if (!isEmpty(record, field)) {
|
||||
if (Object.hasOwn(item, 'customRender')) {
|
||||
// @ts-ignore
|
||||
item.value = item.customRender(record);
|
||||
} else if (Object.hasOwn(item, 'slot')) {
|
||||
//@ts-ignore
|
||||
item.value = { ...record, dataIndex: field };
|
||||
} else {
|
||||
item.value = record[field] || '';
|
||||
}
|
||||
} else {
|
||||
item.value = '';
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
function getDetailSchema() {
|
||||
return detailFormSchema.value.filter((item) => {
|
||||
return item.ifShow === undefined || item.ifShow;
|
||||
});
|
||||
}
|
||||
function setDetailFormData(record: Recordable) {
|
||||
//@ts-ignore
|
||||
setData(record, getDetailSchema());
|
||||
}
|
||||
return {
|
||||
detailFormSchema,
|
||||
getDetailSchema,
|
||||
setDetailFormData,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 流程表单调用这个方法获取formSchema
|
||||
*/
|
||||
export function getBpmFormSchema(): FormSchema[] {
|
||||
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
|
||||
return formSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 人员类型
|
||||
*/
|
||||
export function getPersonType(t: string) {
|
||||
enum PersonType {
|
||||
'professional' = '6', //专业人员
|
||||
'operation' = '5', //操作人员
|
||||
}
|
||||
return PersonType[t];
|
||||
}
|
||||
export const week_text = (key) => {
|
||||
const type = {
|
||||
1: '星期一',
|
||||
2: '星期二',
|
||||
3: '星期三',
|
||||
4: '星期四',
|
||||
5: '星期五',
|
||||
6: '星期六',
|
||||
7: '星期日',
|
||||
};
|
||||
return type[key];
|
||||
};
|
||||
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--引用表格-->
|
||||
<BasicTable :rowSelection="rowSelection" @register="registerTable">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button v-auth="'profession:person_add'" preIcon="ant-design:plus-outlined" type="primary" @click="handleAdd"> 新增 </a-button>
|
||||
<a-button v-auth="'profession:person_delete'" @click="batchHandleDelete" type="primary" preIcon="ant-design:delete-outlined"
|
||||
>批量删除
|
||||
</a-button>
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 表单区域 -->
|
||||
<PersonnelModal @register="registerDrawer" @success="handleSuccess" />
|
||||
<!--修改密码-->
|
||||
<RestPass @register="restPassModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import { columns, searchFormSchema } from './personnelManagement.data';
|
||||
import { batchDelete, deleteOne, list } from './personnelManagement.api';
|
||||
import RestPass from '/@/views/system/user/restPass/RestPass.vue';
|
||||
import PersonnelModal from './components/personnelModal.vue';
|
||||
|
||||
const [registerDrawer, { openDrawer: openFormDrawer }] = useDrawer();
|
||||
//注册model
|
||||
const [restPassModal, { openModal: restPaddModel }] = useModal();
|
||||
/**
|
||||
* 5 操作人员
|
||||
* 6 专业人员
|
||||
*/
|
||||
const props = defineProps({
|
||||
type: { type: String, default: () => '5' },
|
||||
});
|
||||
|
||||
console.log(props);
|
||||
|
||||
//注册table数据
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '应急分中心-操作人员/专业人员',
|
||||
api: list,
|
||||
columns: columns(props.type === '6'),
|
||||
canResize: false,
|
||||
showIndexColumn: true,
|
||||
rowKey: 'userId',
|
||||
formConfig: {
|
||||
labelWidth: 100,
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
showAdvancedButton: false,
|
||||
fieldMapToNumber: [],
|
||||
fieldMapToTime: [],
|
||||
},
|
||||
beforeFetch: (par) => {
|
||||
par['type'] = props.type;
|
||||
return par;
|
||||
},
|
||||
actionColumn: {
|
||||
width: 180,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
function handleAdd() {
|
||||
openFormDrawer(true, {
|
||||
isUpdate: false,
|
||||
showFooter: true,
|
||||
type: '新增',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
async function handleEdit(record: Recordable) {
|
||||
openFormDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: true,
|
||||
type: '编辑',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 详情事件
|
||||
*/
|
||||
async function handleDetail(record: Recordable) {
|
||||
openFormDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
type: '详情',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
function handleDelete(record: Recordable) {
|
||||
deleteOne({ ids: record.userId }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
function batchHandleDelete() {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
message.warning('未选中任何数据');
|
||||
return;
|
||||
}
|
||||
batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
reload();
|
||||
}
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record: Recordable) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: 'profession:person_update',
|
||||
},
|
||||
{
|
||||
label: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
// 重置密码
|
||||
function restPass(record: Recordable) {
|
||||
restPaddModel(true, {
|
||||
record: record.userId,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record: Recordable) {
|
||||
return [
|
||||
{
|
||||
label: '删除',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
auth: 'profession:person_delete',
|
||||
},
|
||||
{
|
||||
label: '重置密码',
|
||||
onClick: restPass.bind(null, record),
|
||||
auth: 'profession:person_reset_pass',
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-popover-buttons) {
|
||||
display: flex !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--引用表格-->
|
||||
<BasicTable :rowSelection="rowSelection" @register="registerTable">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button v-auth="'profession:person_add'" preIcon="ant-design:plus-outlined" type="primary" @click="handleAdd"> 新增 </a-button>
|
||||
<a-button v-auth="'profession:person_delete'" @click="batchHandleDelete" type="primary" preIcon="ant-design:delete-outlined"
|
||||
>批量删除
|
||||
</a-button>
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 表单区域 -->
|
||||
<PersonnelModal @register="registerDrawer" @success="handleSuccess" />
|
||||
<!--修改密码-->
|
||||
<RestPass @register="restPassModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import { columns, searchFormSchema } from './personnelManagement.data';
|
||||
import { batchDelete, deleteOne, list } from './personnelManagement.api';
|
||||
import RestPass from '/@/views/system/user/restPass/RestPass.vue';
|
||||
import PersonnelModal from './components/personnelModal.vue';
|
||||
|
||||
const [registerDrawer, { openDrawer: openFormDrawer }] = useDrawer();
|
||||
//注册model
|
||||
const [restPassModal, { openModal: restPaddModel }] = useModal();
|
||||
/**
|
||||
* 5 操作人员
|
||||
* 6 专业人员
|
||||
*/
|
||||
const props = defineProps({
|
||||
type: { type: String, default: () => '6' },
|
||||
});
|
||||
|
||||
console.log(props);
|
||||
|
||||
//注册table数据
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '应急分中心-操作人员/专业人员',
|
||||
api: list,
|
||||
columns: columns(props.type === '6'),
|
||||
canResize: false,
|
||||
showIndexColumn: true,
|
||||
rowKey: 'userId',
|
||||
formConfig: {
|
||||
labelWidth: 100,
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
showAdvancedButton: false,
|
||||
fieldMapToNumber: [],
|
||||
fieldMapToTime: [],
|
||||
},
|
||||
beforeFetch: (par) => {
|
||||
par['type'] = props.type;
|
||||
return par;
|
||||
},
|
||||
actionColumn: {
|
||||
width: 180,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
function handleAdd() {
|
||||
openFormDrawer(true, {
|
||||
isUpdate: false,
|
||||
showFooter: true,
|
||||
type: '新增',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
async function handleEdit(record: Recordable) {
|
||||
openFormDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: true,
|
||||
type: '编辑',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 详情事件
|
||||
*/
|
||||
async function handleDetail(record: Recordable) {
|
||||
openFormDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
type: '详情',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
function handleDelete(record: Recordable) {
|
||||
deleteOne({ ids: record.userId }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
function batchHandleDelete() {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
message.warning('未选中任何数据');
|
||||
return;
|
||||
}
|
||||
batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
reload();
|
||||
}
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record: Recordable) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: 'profession:person_update',
|
||||
},
|
||||
{
|
||||
label: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
// 重置密码
|
||||
function restPass(record: Recordable) {
|
||||
restPaddModel(true, {
|
||||
record: record.userId,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record: Recordable) {
|
||||
return [
|
||||
{
|
||||
label: '删除',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
auth: 'profession:person_delete',
|
||||
},
|
||||
{
|
||||
label: '重置密码',
|
||||
onClick: restPass.bind(null, record),
|
||||
auth: 'profession:person_reset_pass',
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-popover-buttons) {
|
||||
display: flex !important;
|
||||
}
|
||||
</style>
|
||||
@@ -6,6 +6,8 @@ import { Component, h } from 'vue';
|
||||
import HealthUserEmployeeEx from './HealthUserEmployeeEx/HealthUserEmployeeExList.vue';
|
||||
import healthExpert from '/@/views/consult/doctor/message/conDoctorList.vue';
|
||||
import healthHelper from '/@/views/consult/helper/conHelperList.vue';
|
||||
import personnelManagement1 from '/@/views/system/user/personnelManagement/personnelManagement1.vue';
|
||||
import personnelManagement2 from '/@/views/system/user/personnelManagement/personnelManagement2.vue';
|
||||
import { encipher } from '/@/utils/jsencrypt';
|
||||
import { checkPassword } from '/@/hooks/checkPassword/checkPassword';
|
||||
import { isShowIdCard } from '/@/utils/getEnv';
|
||||
@@ -649,6 +651,7 @@ export interface UserType {
|
||||
title: string;
|
||||
component: Component;
|
||||
auth?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export const typeList: UserType[] = [
|
||||
@@ -664,6 +667,20 @@ export const typeList: UserType[] = [
|
||||
component: healthExpert,
|
||||
auth: 'system:consultation:con_doctor:list',
|
||||
},
|
||||
{
|
||||
key: 4,
|
||||
title: '操作人员',
|
||||
component: personnelManagement1,
|
||||
auth: 'system:health_operator_ex:list',
|
||||
type: '5',
|
||||
},
|
||||
{
|
||||
key: 5,
|
||||
title: '专业人员',
|
||||
component: personnelManagement2,
|
||||
auth: 'system:health_user_operator_ex:list',
|
||||
type: '6',
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
title: '全科医生',
|
||||
|
||||
Reference in New Issue
Block a user