Commit f4cf2089 authored by 刘春's avatar 刘春

feat(doctor, report, sys): 新增医生、报表和系统管理功能

- 新增医生管理模块,包括医生列表、添加医生、编辑医生和删除医生功能
- 新增报表管理模块,包括报表列表、添加报表、编辑报表和删除报表功能
- 新增系统管理模块,包括系统列表、添加系统、编辑系统和删除系统功能
- 优化了页面布局和样式,增加了搜索功能和操作按钮
parent 53e9703e
import { request } from '@/utils/request';
import type { addUserDto, getUserListDto, resetPd } from '@/types/BiDoctor';
import { delMenuDto } from '@/types/BiMenu';
import type {
addUserDto,
getUserListDto,
resetPd,
DelUserDTO
} from '@/types/BiDoctor';
/**
* 新增用户
......@@ -14,10 +18,10 @@ const addUser = (data: addUserDto) => {
/**
* 删除用户
* @param delMenuDto
* @param DelUserDTO
* @returns
*/
const delUser = (data: delMenuDto) => {
const delUser = (data: DelUserDTO) => {
return request('/bi-manager/user/delUser', 'POST', data);
};
......@@ -36,7 +40,7 @@ const editUser = (data: addUserDto & { id: string }) => {
* @returns
*/
const getUserList = (data: getUserListDto) => {
return request('/bi-manager/user/getUserList', 'POST', data);
return request<any>('/bi-manager/user/getUserList', 'POST', data);
};
/**
......
import { request } from '@/utils/request';
import type { addSysDto, delSysDto, getSysListDto } from '@/types/BiSysTem';
/**
* @description 新增系统
* @param addSysDto
* @returns
*/
const addSys = (data: addSysDto) => {
return request<any>('/bi-manager/sysInfo/addSys', 'POST', data);
};
/**
* @description 删除系统
* @param addSysDto
* @returns
*/
const deleteSys = (data: delSysDto) => {
return request<any>('/bi-manager/sysInfo/deleteSys', 'POST', data);
};
/**
* @description 修改系统
* @param addSysDto
* @returns
*/
const editSys = (data: addSysDto) => {
return request<any>('/bi-manager/sysInfo/editSys', 'POST', data);
};
/**
* @description 查询系统
* @param getSysListDto
* @returns
*/
const getSysList = (data: getSysListDto) => {
return request<any>('/bi-manager/sysInfo/getSysList', 'POST', data);
};
export default { addSys, deleteSys, editSys, getSysList };
......@@ -14,11 +14,11 @@ export interface addUserDto {
/**
* 权限编码:0web,1移动(多个逗号隔开)
*/
jurisdictionCode?: string[];
jurisdictionCode?: string[] | string;
/**
* 角色ID集合
*/
roleIds?: number[];
roleIds?: number[] | number | string;
/**
* 0启用1关闭
*/
......
// 新增系统
export type addSysDto = {
/**
* 系统编码
*/
sysCode: string;
/**
* 系统ID
*/
sysId: string;
/**
* 系统名称
*/
sysName: string;
};
// 删除系统
export type delSysDto = {
/**
* 系统ID
*/
sysId: string;
};
/**
* 查询系统
*/
export interface getSysListDto {
/**
* 搜索名称
*/
name?: string;
/**
* 当前页
*/
pageNum?: number;
/**
* 每页条数
*/
pageSize?: number;
}
......@@ -9,6 +9,7 @@ declare global {
const EffectScope: typeof import('vue')['EffectScope']
const ElMessage: typeof import('element-plus/es')['ElMessage']
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const EleMessage: typeof import('ele-admin-plus/es')['EleMessage']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
......@@ -85,6 +86,7 @@ declare module 'vue' {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']>
readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']>
readonly EleMessage: UnwrapRef<typeof import('ele-admin-plus/es')['EleMessage']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
......
......@@ -7,8 +7,12 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
AddDoctor: typeof import('./../views/doctor/components/AddDoctor.vue')['default']
AddExpert: typeof import('./../components/TaskAllocation/AddExpert.vue')['default']
AddMenu: typeof import('./../views/web/components/AddMenu.vue')['default']
AddReport: typeof import('./../views/report/components/AddReport.vue')['default']
AddRole: typeof import('./../views/role/components/AddRole.vue')['default']
AddSys: typeof import('./../views/report/components/AddSys.vue')['default']
AddTheme: typeof import('./../views/theme/components/AddTheme.vue')['default']
AddUser: typeof import('./../views/role/components/AddUser.vue')['default']
AlipayFilled: typeof import('./../components/icons/AlipayFilled.vue')['default']
......
<template>
<ele-modal
v-model="modalVisible"
:title="modalTitle"
width="600px"
position="center"
>
<ele-loading :loading="pageLoading">
<ele-card>
<pro-form
ref="ProFormRef"
label-width="auto"
:model="form"
:items="items"
:footer="false"
:grid="{ span: 12 }"
@updateValue="setFieldValue"
/>
</ele-card>
</ele-loading>
<template #footer>
<el-button type="primary" plain @click="handleCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</template>
</ele-modal>
</template>
<script lang="ts" setup>
// tools
import { useFormData } from '@/utils/use-form-data';
import { tryit } from 'radash';
// types
import type { addUserDto } from '@/types/BiDoctor';
import type { ProFormItemProps } from '@/components/ProForm/types';
import type { FormInstance } from 'element-plus';
import { EleMessage } from 'ele-admin-plus';
// apis
import roleApi from '@/api/roleApi';
import doctorApi from '@/api/doctorApi';
const useType = ref<'add' | 'edit'>('add');
const modalVisible = ref(false);
const modalTitle = computed(() => {
return useType.value === 'add' ? '添加医生' : '编辑医生';
});
// 打开
const curInfo = ref<addUserDto>();
const open = (type: 'add' | 'edit' = 'add', info?: addUserDto) => {
useType.value = type;
modalVisible.value = true;
if (type === 'edit') {
curInfo.value = info;
Object.assign(form, info);
if ('jurisdictionCode' in info!) {
form.jurisdictionCode = (info.jurisdictionCode as string)!.split(',');
}
console.log(info, form, '表单数据');
}
};
defineExpose({
open: open as (type: 'add' | 'edit', info?: addUserDto) => void
});
/** 表单数据 */
const [form, resetFields, , setFieldValue] = useFormData<addUserDto>({
deptCode: '',
deptName: '',
jurisdictionCode: [],
roleIds: [],
status: 0,
userCode: '',
userName: '',
userPassword: '',
wxId: ''
});
// 获取医生列表
onMounted(() => {
fetchRoleList();
});
const roleList = ref([]);
const fetchRoleList = async () => {
pageLoading.value = true;
const [err, ret] = await tryit(roleApi.getRoleList)({});
if (err) {
console.error(err);
return;
}
if (ret.code === 200) {
roleList.value = ret.data.map((item) => {
return {
label: item.roleName,
value: item.roleId
};
});
}
pageLoading.value = false;
};
/** 表单项 */
const items = computed<Array<ProFormItemProps>>(() => [
{ label: '医生名称', prop: 'userName', type: 'input', required: true },
{
label: '医生编码',
prop: 'userCode',
type: 'input',
required: true
},
{ label: '科室名称', prop: 'deptName', type: 'input', required: true },
{ label: '科室编码', prop: 'deptCode', type: 'input', required: true },
{ label: '用户密码', prop: 'userPassword', type: 'input', required: true },
{ label: '微信id', prop: 'wxId', type: 'input', required: false },
{
label: '权限',
prop: 'jurisdictionCode',
type: 'multipleSelect',
options: [
{
value: '0',
label: 'web'
},
{
value: '1',
label: '移动'
}
],
required: true
},
{
label: '关联角色',
prop: 'roleIds',
type: 'multipleSelect',
options: roleList.value,
required: true
},
{
label: '状态',
prop: 'status',
type: 'radio',
options: [
{ label: '开启', value: 0 },
{ label: '关闭', value: 1 }
],
required: true
}
]);
/** 提交 */
const ProFormRef = ref<FormInstance>();
const pageLoading = ref(false);
const emits = defineEmits(['reload']);
const onSubmit = () => {
ProFormRef.value?.validate(async (valid) => {
if (!valid) {
EleMessage.warning('请填写必填项');
return;
}
ElMessageBox.confirm(
`确定要${useType.value === 'add' ? '保存' : '修改'}?`,
'提示',
{
type: 'warning'
}
).then(async () => {
pageLoading.value = true;
const apiObj = {
add: doctorApi.addUser,
edit: doctorApi.editUser
};
const [, ret] = await tryit(apiObj[useType.value!])(form);
if (ret?.code === 200) {
EleMessage.success(useType.value === 'add' ? '添加成功' : '修改成功');
emits('reload');
handleClose();
}
pageLoading.value = false;
});
});
};
// 关闭
const handleClose = () => {
modalVisible.value = false;
resetFields();
};
// 点击取消
const handleCancel = () => {
modalVisible.value = false;
};
</script>
......@@ -4,25 +4,58 @@
<vxe-grid ref="xGrid" v-bind="gridOptions">
<template #buttons_slot>
<div class="p-l-4px">
<FcCardTip title="提示" />
<FcCardTip title="医生管理" />
</div>
</template>
<template #toolbar_tools>
<div class="p-r-4px">
<el-button type="primary" size="small">添加用户</el-button>
<el-button
type="primary"
size="small"
@click="() => AddDoctorRef.open()"
>
添加医生
</el-button>
</div>
</template>
<template #option_slot>
<el-link type="primary">编辑</el-link>
<template #option_slot="{ row }">
<el-link type="primary" @click="AddDoctorRef.open('edit', row)">
编辑
</el-link>
<el-divider direction="vertical" />
<el-link type="danger">删除</el-link>
<el-link type="success" @click="handleResetPwd(row)">
重置密码
</el-link>
<el-divider direction="vertical" />
<el-link type="success">重置密码</el-link>
<el-link type="danger" @click="handleDelUser(row)">删除</el-link>
</template>
<!-- 权限列表 -->
<template #jurisdictionName_slot="{ row }">
<el-tag
style="margin: 0 3px"
type="primary"
v-for="item in row.jurisdictionName"
:key="item"
>{{ item }}</el-tag
>
</template>
<!-- 角色列表 -->
<template #roleNames_slot="{ row }">
<el-tag
style="margin: 0 3px"
type="primary"
v-for="item in row.roleNames"
:key="item"
>{{ item }}</el-tag
>
</template>
</vxe-grid>
</div>
<AddDoctor ref="AddDoctorRef" @reload="fetchDoctorList" />
</ele-loading>
</template>
......@@ -30,8 +63,85 @@
// tools
import { VxeGridProps } from 'vxe-table';
import { FcCardTip } from '@fancy-design/coms';
import { tryit } from 'radash';
// apis
import doctorApi from '@/api/doctorApi';
// coms
import AddDoctor from './components/AddDoctor.vue';
const AddDoctorRef = ref();
// 重置密码
const handleResetPwd = (row) => {
ElMessageBox.confirm('确定要重置密码吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
pageLoading.value = true;
const [err, res] = await tryit(doctorApi.resetPd)({ userId: row.userId });
if (err) {
console.error(err.message);
return;
}
if (res.code === 200) {
console.log(res);
ElMessage.success('重置成功');
fetchDoctorList();
}
pageLoading.value = false;
});
};
// 删除医生
const handleDelUser = async (row) => {
ElMessageBox.confirm('此操作将永久删除该医生, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
pageLoading.value = true;
const [err, res] = await tryit(doctorApi.delUser)({
userId: row.userId
});
if (err) {
console.error(err.message);
return;
}
if (res.code === 200) {
ElMessage({
type: 'success',
message: '删除成功'
});
fetchDoctorList();
}
pageLoading.value = false;
});
};
// 获取医生列表
const params = reactive({
pageNum: 1,
pageSize: 10,
total: 0
});
const pageLoading = ref(false);
const fetchDoctorList = async () => {
pageLoading.value = true;
const [error, ret] = await tryit(doctorApi.getUserList)(params);
if (error) {
console.error(error);
return;
}
if (ret.code === 200) {
gridOptions.data = ret.data!.data;
params.total = ret.data!.total;
}
pageLoading.value = false;
};
onMounted(() => {
fetchDoctorList();
});
const gridOptions = reactive<VxeGridProps>({
border: 'inner',
showHeaderOverflow: true,
......@@ -60,40 +170,35 @@
columns: [
{
field: 'menuName',
title: '序号'
},
{
field: 'url',
title: 'URL地址'
},
{
field: 'menuName',
title: '菜单名称'
field: 'userName',
title: '医生名称'
},
{
field: 'url',
title: 'URL地址'
field: 'userCode',
title: '医生编码'
},
{
field: 'menuName',
title: '菜单名称'
field: 'deptName',
title: '科室名称'
},
{
field: 'url',
title: 'URL地址'
field: 'deptCode',
title: '科室编码'
},
{
field: 'menuName',
title: '菜单名称'
field: 'jurisdictionName',
title: '权限',
slots: { default: 'jurisdictionName_slot' }
},
{
field: 'url',
title: 'URL地址'
field: 'roleNames',
title: '角色',
slots: { default: 'roleNames_slot' }
},
{
field: 'url',
title: 'URL地址'
field: 'wxId',
title: '微信号',
formatter: 'em'
},
{
field: '操作',
......@@ -108,6 +213,6 @@
pageSize: 10,
pageSizes: [5, 10, 15, 20, 50, 100, 200, 500, 1000]
},
data: [{ menuName: '首页', url: 'www.ce.com' }]
data: []
});
</script>
......@@ -61,7 +61,7 @@
</div>
<!-- 新增/编辑弹窗 -->
<addMenu ref="AddMenuRef" @reload="getMenuList"></addMenu>
<addMenu ref="AddMenuRef" @reload="getMenuList" />
</ele-loading>
</template>
......@@ -219,7 +219,7 @@
const handleDelete = async (row) => {
ElMessageBox.confirm(`确定要删除此菜单吗?`, '提示', {
type: 'warning'
}).then(async (res) => {
}).then(async () => {
let params = {
menuId: row.menuId,
menuType: 1,
......@@ -237,11 +237,12 @@
});
};
// 展开/收起
// 展开/收起
const toggleExpand = () => {
console.log('🚀 ~ handleUnfold ~ xGrid.value:', xGrid.value);
// xGrid.value.setRowExpand();
gridOptions.data?.forEach((item) => {
xGrid.value.toggleRowExpand(item);
});
};
</script>
......
<template>
<ele-modal
v-model="modalVisible"
:title="modalTitle"
width="600px"
position="center"
>
<ele-loading :loading="pageLoading">
<ele-card>
<pro-form
ref="ProFormRef"
label-width="auto"
:model="form"
:items="items"
:footer="false"
:grid="{ span: 24 }"
@updateValue="setFieldValue"
/>
</ele-card>
</ele-loading>
<template #footer>
<el-button type="primary" plain @click="handleCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</template>
</ele-modal>
</template>
<script lang="ts" setup>
// tools
import { useFormData } from '@/utils/use-form-data';
import { tryit } from 'radash';
// types
import type { addReportDto } from '@/types/BiReport';
import type { ProFormItemProps } from '@/components/ProForm/types';
import type { FormInstance } from 'element-plus';
import { EleMessage } from 'ele-admin-plus';
// apis
import reportApi from '@/api/reportApi';
const props = defineProps<{
curSelectSys: any;
}>();
const useType = ref<'add' | 'edit'>('add');
const modalVisible = ref(false);
const modalTitle = computed(() => {
return useType.value === 'add' ? '添加报表' : '编辑报表';
});
// 打开
const curInfo = ref<addReportDto>();
const open = (type: 'add' | 'edit' = 'add', info?: addReportDto) => {
useType.value = type;
modalVisible.value = true;
if (type === 'edit') {
curInfo.value = info;
Object.assign(form, info);
}
console.log(props.curSelectSys);
form.sysId = [props.curSelectSys.sysId];
};
defineExpose({
open: open as (type: 'add' | 'edit', info?: addReportDto) => void
});
/** 表单数据 */
const [form, resetFields, , setFieldValue] = useFormData<addReportDto>({
reportStyleUrl: '',
reportName: '',
reportCategory: [],
sysId: [],
reportType: 1
});
/** 表单项 */
const items = computed<Array<ProFormItemProps>>(() => [
{ label: '报表名称', prop: 'reportName', type: 'input', required: true },
{
label: '报表样式图片地址',
prop: 'reportStyleUrl',
type: 'input',
required: true
},
{
label: '报表类型',
prop: 'reportType',
type: 'select',
options: [
{
label: '帆软',
value: 1
},
{
label: '自建',
value: 2
}
],
required: true
},
{
label: '报表分类',
prop: ' reportCategory',
type: 'select',
multiple: true,
options: [],
required: false
}
]);
/** 提交 */
const ProFormRef = ref<FormInstance>();
const pageLoading = ref(false);
const emits = defineEmits(['reload']);
const onSubmit = () => {
ProFormRef.value?.validate(async (valid) => {
if (!valid) {
EleMessage.warning('请填写必填项');
return;
}
ElMessageBox.confirm(
`确定要${useType.value === 'add' ? '保存' : '修改'}?`,
'提示',
{
type: 'warning'
}
).then(async () => {
pageLoading.value = true;
const apiObj = {
add: reportApi.addReport,
edit: reportApi.editReport
};
const [, ret] = await tryit(apiObj[useType.value!])(form);
if (ret?.code === 200) {
EleMessage.success(useType.value === 'add' ? '添加成功' : '修改成功');
emits('reload');
handleClose();
}
pageLoading.value = false;
});
});
};
// 关闭
const handleClose = () => {
modalVisible.value = false;
resetFields();
};
// 点击取消
const handleCancel = () => {
modalVisible.value = false;
};
</script>
<template>
<ele-modal
v-model="modalVisible"
:title="modalTitle"
width="600px"
position="center"
>
<ele-loading :loading="pageLoading">
<ele-card>
<pro-form
ref="ProFormRef"
label-width="auto"
:model="form"
:items="items"
:footer="false"
:grid="{ span: 12 }"
@updateValue="setFieldValue"
/>
</ele-card>
</ele-loading>
<template #footer>
<el-button type="primary" plain @click="handleCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</template>
</ele-modal>
</template>
<script lang="ts" setup>
// tools
import { useFormData } from '@/utils/use-form-data';
import { tryit } from 'radash';
// types
import type { addSysDto } from '@/types/BiSysTem';
import type { ProFormItemProps } from '@/components/ProForm/types';
import type { FormInstance } from 'element-plus';
import { EleMessage } from 'ele-admin-plus';
// apis
import sysApi from '@/api/sysApi';
const useType = ref<'add' | 'edit'>('add');
const modalVisible = ref(false);
const modalTitle = computed(() => {
return useType.value === 'add' ? '添加系统' : '编辑系统';
});
// 打开
const curInfo = ref<addSysDto>();
const open = (type: 'add' | 'edit' = 'add', info?: addSysDto) => {
useType.value = type;
modalVisible.value = true;
if (type === 'edit') {
curInfo.value = info;
Object.assign(form, info);
}
};
defineExpose({
open: open as (type: 'add' | 'edit', info?: addSysDto) => void
});
/** 表单数据 */
const [form, resetFields, , setFieldValue] = useFormData<addSysDto>({
sysCode: '',
sysName: '',
sysId: ''
});
/** 表单项 */
const items = computed<Array<ProFormItemProps>>(() => [
{ label: '系统名称', prop: 'sysName', type: 'input', required: true },
{
label: '系统编码',
prop: 'sysCode',
type: 'input',
required: true
}
]);
/** 提交 */
const ProFormRef = ref<FormInstance>();
const pageLoading = ref(false);
const emits = defineEmits(['reload']);
const onSubmit = () => {
ProFormRef.value?.validate(async (valid) => {
if (!valid) {
EleMessage.warning('请填写必填项');
return;
}
ElMessageBox.confirm(
`确定要${useType.value === 'add' ? '保存' : '修改'}?`,
'提示',
{
type: 'warning'
}
).then(async () => {
pageLoading.value = true;
const apiObj = {
add: sysApi.addSys,
edit: sysApi.editSys
};
const [, ret] = await tryit(apiObj[useType.value!])(form);
if (ret?.code === 200) {
EleMessage.success(useType.value === 'add' ? '添加成功' : '修改成功');
emits('reload');
handleClose();
}
pageLoading.value = false;
});
});
};
// 关闭
const handleClose = () => {
modalVisible.value = false;
resetFields();
};
// 点击取消
const handleCancel = () => {
modalVisible.value = false;
};
</script>
......@@ -3,23 +3,54 @@
<div class="page-wrapper-left">
<div class="page-wrapper-left-item">
<div class="p-10px flex w-full overflow-hidden">
<FcCardTip title="搜索报表" />
<FcCardTip title="搜索系统" />
<div flex-1 class="p-l-4px p-r-4px">
<el-input placeholder="搜索报表名称" />
<el-input
v-model="params.name"
@change="fetchSysList"
placeholder="搜索系统名称"
/>
</div>
<el-button class="m-r-15px" type="primary">新增报表</el-button>
<el-button
class="m-r-15px"
type="primary"
@click="() => AddSysRef.open()"
>新增系统</el-button
>
</div>
<vxe-grid v-bind="leftTOptions" />
<vxe-grid v-bind="leftTOptions" @cell-click="handleCellClickTopGrid">
<template #option_slot="{ row }">
<el-link type="success" @click="AddSysRef.open('edit', row)">
编辑
</el-link>
<el-divider direction="vertical" />
<el-link type="danger" @click="handleDelSys(row)">删除</el-link>
</template>
</vxe-grid>
</div>
<div class="page-wrapper-left-item">
<div class="p-10px flex w-full overflow-hidden">
<FcCardTip title="搜索报表" />
<div flex-1 class="p-l-4px p-r-4px">
<el-input placeholder="搜索报表名称" />
<el-input
v-model="reportParams.name"
@change="fetchReportList"
placeholder="搜索报表名称"
/>
</div>
<el-button class="m-r-15px" type="primary">新增报表</el-button>
<el-button class="m-r-15px" type="primary" @click="handleAddReport"
>新增报表</el-button
>
</div>
<vxe-grid v-bind="leftBOptions" />
<vxe-grid v-bind="leftBOptions">
<template #option_slot="{ row }">
<el-link type="success" @click="AddReportRef.open('edit', row)">
编辑
</el-link>
<el-divider direction="vertical" />
<el-link type="danger" @click="handleDelReport(row)">删除</el-link>
</template>
</vxe-grid>
</div>
</div>
......@@ -39,33 +70,169 @@
</div>
<div class="page-wrapper-item"> 报表样式 </div>
<AddSys ref="AddSysRef" @reload="fetchSysList" />
<AddReport ref="AddReportRef" :curSelectSys @reload="fetchReportList" />
</div>
</template>
<script lang="ts" setup>
// tools
import { FcCardTip } from '@fancy-design/coms';
import { tryit } from 'radash';
// types
import { VxeGridProps } from 'vxe-table';
import { getReportListDto } from '@/types/BiReport';
import { getSysListDto } from '@/types/BiSysTem';
// coms
import AddSys from './components/AddSys.vue';
import AddReport from './components/AddReport.vue';
// apis
import reportApi from '@/api/reportApi';
import sysApi from '@/api/sysApi';
const AddSysRef = ref();
const AddReportRef = ref();
// 删除报表
const handleDelReport = ({ row }) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
leftBOptions.loading = true;
const [error, ret] = await tryit(reportApi.deleteReport)({
id: row.id
});
if (error) {
console.error(error);
return;
}
if (ret?.code === 200) {
ElMessage.success('删除成功');
fetchReportList();
}
});
};
// 删除系统
const handleDelSys = (row) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
leftTOptions.value.loading = true;
const [error, ret] = await tryit(sysApi.deleteSys)({
sysId: row.sysId
});
if (error) {
console.error(error);
return;
}
if (ret?.code === 200) {
ElMessage.success('删除成功');
fetchSysList();
}
leftTOptions.value.loading = false;
})
.catch(() => {
ElMessage.info('已取消删除');
});
};
// 点击新增报表
const handleAddReport = () => {
if (!curSelectSys.value) {
ElMessage.warning('请选择系统');
return;
}
AddReportRef.value.open();
};
// 点击上方报表表格
const curSelectSys = ref();
const handleCellClickTopGrid = ({ row }) => {
curSelectSys.value = row;
};
// 获取系统
const params = ref<getSysListDto>({
pageNum: 1,
pageSize: 100,
name: ''
});
// 获取报表
const reportParams = ref<getReportListDto>({
pageNum: 1,
pageSize: 100,
name: ''
});
const fetchReportList = async () => {
leftTOptions.value.loading = true;
const [err, ret] = await tryit(reportApi.getReportList)(reportParams.value);
if (err) {
console.error(err);
return;
}
if (ret.code === 200) {
leftTOptions.value.data = ret.data.list;
}
};
const leftTOptions: VxeGridProps = {
// 获取系统列表
const fetchSysList = async () => {
leftTOptions.value.loading = true;
const [error, ret] = await tryit(sysApi.getSysList)(params.value);
if (error) {
console.error(error);
return;
}
if (ret.code === 200) {
leftTOptions.value.data = ret.data.list;
}
leftTOptions.value.loading = false;
};
onMounted(() => {
fetchSysList();
fetchReportList();
});
const leftTOptions = ref<VxeGridProps<getSysListDto>>({
loading: false,
border: true,
showHeaderOverflow: true,
showOverflow: true,
height: '100%',
rowConfig: {
isCurrent: true,
isHover: true
},
columns: [
{
field: 'name',
title: 'Name',
width: 120,
field: 'sysName',
title: '系统名称',
align: 'center',
headerAlign: 'center'
},
{
field: 'sex'
field: 'sysCode',
title: '系统编码',
align: 'center',
headerAlign: 'center'
},
{
title: '操作',
slots: {
default: 'option_slot'
}
}
]
};
],
data: []
});
const leftBOptions: VxeGridProps = {
border: true,
showHeaderOverflow: true,
......@@ -73,8 +240,8 @@
height: '100%',
columns: [
{
field: 'name',
title: 'Name',
field: 'reportName',
title: '报表名称',
width: 120,
align: 'center',
headerAlign: 'center'
......@@ -106,7 +273,10 @@
headerAlign: 'center'
},
{
field: 'sex'
title: '操作',
slots: {
default: 'option_slot'
}
}
]
};
......
<template>
<ele-modal
v-model="modalVisible"
:title="modalTitle"
width="600px"
position="center"
>
<ele-loading :loading="pageLoading">
<ele-card>
<pro-form
ref="ProFormRef"
label-width="auto"
:model="form"
:items="items"
:footer="false"
:grid="{ span: 12 }"
@updateValue="setFieldValue"
/>
</ele-card>
</ele-loading>
<template #footer>
<el-button type="primary" plain @click="handleCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</template>
</ele-modal>
</template>
<script lang="ts" setup>
// tools
import { useFormData } from '@/utils/use-form-data';
import { tryit } from 'radash';
// types
import type { addUserDto } from '@/types/BiDoctor';
import type { ProFormItemProps } from '@/components/ProForm/types';
import type { FormInstance } from 'element-plus';
import { EleMessage } from 'ele-admin-plus';
// apis
import roleApi from '@/api/roleApi';
import doctorApi from '@/api/doctorApi';
const useType = ref<'add' | 'edit'>('add');
const modalVisible = ref(false);
const props = defineProps<{
curRole: any;
}>();
const modalTitle = computed(() => {
return useType.value === 'add' ? '添加用户' : '编辑用户';
});
// 打开
const curInfo = ref<addUserDto>();
const open = (type: 'add' | 'edit' = 'add', info?: addUserDto) => {
useType.value = type;
modalVisible.value = true;
if (type === 'edit') {
curInfo.value = info;
Object.assign(form, info);
if ('jurisdictionCode' in info!) {
form.jurisdictionCode = (info.jurisdictionCode as string)!.split(',');
}
console.log(info, form, '表单数据');
}
form.roleIds = [props.curRole.roleId];
};
defineExpose({
open: open as (type: 'add' | 'edit', info?: addUserDto) => void
});
/** 表单数据 */
const [form, resetFields, , setFieldValue] = useFormData<addUserDto>({
deptCode: '',
deptName: '',
jurisdictionCode: [],
roleIds: [],
status: 0,
userCode: '',
userName: '',
userPassword: '',
wxId: ''
});
// 获取用户列表
onMounted(() => {
fetchRoleList();
});
const roleList = ref([]);
const fetchRoleList = async () => {
pageLoading.value = true;
const [err, ret] = await tryit(roleApi.getRoleList)({});
if (err) {
console.error(err);
return;
}
if (ret.code === 200) {
roleList.value = ret.data.map((item) => {
return {
label: item.roleName,
value: item.roleId
};
});
}
pageLoading.value = false;
};
/** 表单项 */
const items = computed<Array<ProFormItemProps>>(() => [
{ label: '用户名称', prop: 'userName', type: 'input', required: true },
{
label: '用户编码',
prop: 'userCode',
type: 'input',
required: true
},
{ label: '科室名称', prop: 'deptName', type: 'input', required: true },
{ label: '科室编码', prop: 'deptCode', type: 'input', required: true },
{ label: '用户密码', prop: 'userPassword', type: 'input', required: true },
{ label: '微信id', prop: 'wxId', type: 'input', required: false },
{
label: '权限',
prop: 'jurisdictionCode',
type: 'multipleSelect',
options: [
{
value: '0',
label: 'web'
},
{
value: '1',
label: '移动'
}
],
required: true
},
{
label: '状态',
prop: 'status',
type: 'radio',
options: [
{ label: '开启', value: 0 },
{ label: '关闭', value: 1 }
],
required: true
}
]);
/** 提交 */
const ProFormRef = ref<FormInstance>();
const pageLoading = ref(false);
const emits = defineEmits(['reload']);
const onSubmit = () => {
ProFormRef.value?.validate(async (valid) => {
if (!valid) {
EleMessage.warning('请填写必填项');
return;
}
ElMessageBox.confirm(
`确定要${useType.value === 'add' ? '保存' : '修改'}?`,
'提示',
{
type: 'warning'
}
).then(async () => {
pageLoading.value = true;
const apiObj = {
add: doctorApi.addUser,
edit: doctorApi.editUser
};
const [, ret] = await tryit(apiObj[useType.value!])(form);
if (ret?.code === 200) {
EleMessage.success(useType.value === 'add' ? '添加成功' : '修改成功');
emits('reload');
handleClose();
}
pageLoading.value = false;
});
});
};
// 关闭
const handleClose = () => {
modalVisible.value = false;
resetFields();
};
// 点击取消
const handleCancel = () => {
modalVisible.value = false;
};
</script>
......@@ -44,11 +44,43 @@
</div>
</template>
<!-- 权限列表 -->
<template #jurisdictionName_slot="{ row }">
<el-tag
style="margin: 0 3px"
type="primary"
v-for="item in row.jurisdictionName"
:key="item"
>{{ item }}</el-tag
>
</template>
<!-- 角色列表 -->
<template #roleNames_slot="{ row }">
<el-tag
style="margin: 0 3px"
type="primary"
v-for="item in row.roleNames"
:key="item"
>{{ item }}</el-tag
>
</template>
<!-- 状态 -->
<template #status_slot="{ row }">
<el-switch
v-model="row.status"
:active-value="0"
:inactive-value="1"
@change="() => handleChangeStatus(row)"
/>
</template>
<!-- 操作 -->
<template #option_slot>
<el-link type="primary">编辑</el-link>
<el-divider direction="vertical" />
<el-link type="warning">页面预览</el-link>
<template #option_slot="{ row }">
<el-link type="primary" @click="AddUserRef?.open('edit', row)"
>编辑</el-link
>
<el-divider direction="vertical" />
<el-link type="danger">删除</el-link>
</template>
......@@ -63,12 +95,14 @@
</div>
</div>
<AddRole ref="AddRoleRef" @reload="fetchRoleList" />
<AddUser ref="AddUserRef" :curRole @reload="fetchRoleList" />"
</ele-loading>
</template>
<script lang="ts" setup>
// coms
import AddRole from './components/AddRole.vue';
import AddUser from './components/AddUser.vue';
// tools
import { FcCardTip } from '@fancy-design/coms';
import { CirclePlus } from '@element-plus/icons-vue';
......@@ -77,10 +111,13 @@
import { tryit } from 'radash';
// apis
import roleApi from '@/api/roleApi';
import doctorApi from '@/api/doctorApi';
// 添加用户
const AddUserRef = ref<InstanceType<typeof AddUser>>();
const handleAddUser = () => {
if (!curRole) return ElMessage.warning('请选择角色');
AddUserRef.value?.open('add');
};
// 获取角色列表
......@@ -101,6 +138,16 @@
handleClickFirst({ row: lgridOptions.data![0] });
};
// 切换状态
const handleChangeStatus = async (row) => {
pageLoading.value = true;
const [, ret] = await tryit(doctorApi.editUser)(row);
if (ret!.code === 200) {
ElMessage.success('操作成功');
}
pageLoading.value = false;
};
// 勾选默认操作
const curRole = ref();
const LGridRef = ref<VxeGridInstance>();
......@@ -189,7 +236,7 @@
const rgridOptions = reactive<VxeGridProps>({
round: true,
border: true,
border: 'inner',
showHeaderOverflow: true,
showOverflow: true,
height: 'auto',
......@@ -216,18 +263,47 @@
columns: [
{
field: 'menuName',
title: '菜单名称',
sortable: true
field: 'userName',
title: '用户名称'
},
{
field: 'userCode',
title: '用户编码'
},
{
field: 'deptName',
title: '科室名称'
},
{
field: 'deptCode',
title: '科室编码'
},
{
field: 'jurisdictionName',
title: '权限',
slots: { default: 'jurisdictionName_slot' }
},
{
field: 'roleNames',
title: '角色',
slots: { default: 'roleNames_slot' }
},
{
field: 'wxId',
title: '微信号',
formatter: 'em'
},
{
field: 'url',
title: 'URL地址'
field: 'status',
title: '状态',
formatter: 'em',
slots: { default: 'status_slot' }
},
{
field: '操作',
fixed: 'right',
title: '操作',
width: 200,
slots: { default: 'option_slot' }
}
],
......
......@@ -127,7 +127,7 @@
const [, ret] = await tryit(themeApi.getThemeList)();
if (ret?.code === 200) {
lgridOptions.data = ret.data || [];
if (lgridOptions.data.length) {
if (lgridOptions.data!.length) {
xGrid.value.setCurrentRow(ret.data[0]);
themeData.value = ret.data[0];
getMenuByMobile(); // 获取移动端菜单
......@@ -198,11 +198,13 @@
// 表格事件
const gridEvents: VxeGridListeners = {
cellClick({ rowIndex }) {
xGrid.value.setCurrentRow(lgridOptions.data[rowIndex]);
themeData.value = lgridOptions.data[rowIndex];
getMenuByMobile(); // 获取移动端菜单
getMenuByWeb(); // 获取web端菜单
async cellClick({ rowIndex }) {
pageLoading.value = true;
xGrid.value.setCurrentRow(lgridOptions.data![rowIndex]);
themeData.value = lgridOptions.data![rowIndex];
await getMenuByMobile(); // 获取移动端菜单
await getMenuByWeb(); // 获取web端菜单
pageLoading.value = false;
}
};
......
......@@ -61,7 +61,7 @@
</div>
<!-- 新增/编辑弹窗 -->
<addMenu ref="AddMenuRef" @reload="getMenuList"></addMenu>
<addMenu ref="AddMenuRef" @reload="getMenuList" />
</ele-loading>
</template>
......@@ -219,7 +219,7 @@
const handleDelete = async (row) => {
ElMessageBox.confirm(`确定要删除此菜单吗?`, '提示', {
type: 'warning'
}).then(async (res) => {
}).then(async () => {
let params = {
menuId: row.menuId,
menuType: 0,
......@@ -239,9 +239,9 @@
// 展开/收起
const toggleExpand = () => {
console.log('🚀 ~ handleUnfold ~ xGrid.value:', xGrid.value);
// xGrid.value.setRowExpand();
gridOptions.data.forEach((item) => {
xGrid.value.toggleRowExpand(item);
});
};
</script>
......
......@@ -159,7 +159,7 @@ export default defineConfig(({ command, mode }) => {
changeOrigin: true
},
'/bi-manager': {
target: 'http://10.1.0.153:4396',
target: 'http://10.1.0.98:4396',
changeOrigin: true
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment