From 15ef01aed98aa21ad423d6773df69f8f5ca51af8 Mon Sep 17 00:00:00 2001 From: sheng <15292050171@163.com> Date: Fri, 28 Jul 2023 14:37:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=20=E9=83=A8=E9=97=A8=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/dept/api.ts | 14 +- .../system/dept/components/DeptFormCom.vue | 25 +- .../system/dept/components/DeptUserCom/api.ts | 58 +++ .../dept/components/DeptUserCom/crud.tsx | 386 ++++++++++++++++++ .../dept/components/DeptUserCom/index.vue | 61 +++ .../views/system/dept/components/TreeCom.vue | 19 +- web/src/views/system/dept/crud.tsx | 251 ------------ web/src/views/system/dept/index.vue | 152 ++----- web/src/views/system/dept/types.ts | 6 + 9 files changed, 584 insertions(+), 388 deletions(-) create mode 100644 web/src/views/system/dept/components/DeptUserCom/api.ts create mode 100644 web/src/views/system/dept/components/DeptUserCom/crud.tsx create mode 100644 web/src/views/system/dept/components/DeptUserCom/index.vue delete mode 100644 web/src/views/system/dept/crud.tsx diff --git a/web/src/views/system/dept/api.ts b/web/src/views/system/dept/api.ts index 3ea5a6e..0779ffe 100644 --- a/web/src/views/system/dept/api.ts +++ b/web/src/views/system/dept/api.ts @@ -52,10 +52,20 @@ export function lazyLoadDept(query: UserPageQuery) { /** * 用户相关接口 */ -export function getUserDeptList(query: PageQuery) { +export function getDeptUserList(query: PageQuery) { return request({ - url: "/api/system/dept/dept_lazy_tree/", + url: "/api/system/user/", method: 'get', params: query, }); } + +/** + * 获取所有部门列表 + */ +export function getAllDeptList() { + return request({ + url: "/api/system/dept/all_dept/", + method: 'get', + }); +} diff --git a/web/src/views/system/dept/components/DeptFormCom.vue b/web/src/views/system/dept/components/DeptFormCom.vue index 2aff9a7..b19fb56 100644 --- a/web/src/views/system/dept/components/DeptFormCom.vue +++ b/web/src/views/system/dept/components/DeptFormCom.vue @@ -4,8 +4,10 @@ - - + + + + @@ -38,9 +40,9 @@ diff --git a/web/src/views/system/dept/components/DeptUserCom/api.ts b/web/src/views/system/dept/components/DeptUserCom/api.ts new file mode 100644 index 0000000..a18ba94 --- /dev/null +++ b/web/src/views/system/dept/components/DeptUserCom/api.ts @@ -0,0 +1,58 @@ +import { request, downloadFile } from '/@/utils/service'; +import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud'; + +export const apiPrefix = '/api/system/user/'; + +export function GetDept(query: PageQuery) { + return request({ + url: "/api/system/dept/dept_lazy_tree/", + method: 'get', + params: query, + }); +} + +export function GetList(query: PageQuery) { + return request({ + url: apiPrefix, + method: 'get', + params: query, + }); +} +export function GetObj(id: InfoReq) { + return request({ + url: apiPrefix + id, + method: 'get', + }); +} + +export function AddObj(obj: AddReq) { + return request({ + url: apiPrefix, + method: 'post', + data: obj, + }); +} + +export function UpdateObj(obj: EditReq) { + return request({ + url: apiPrefix + obj.id + '/', + method: 'put', + data: obj, + }); +} + +export function DelObj(id: DelReq) { + return request({ + url: apiPrefix + id + '/', + method: 'delete', + data: { id }, + }); +} + +export function exportData(params: any) { + return downloadFile({ + url: apiPrefix + 'export_data/', + params: params, + method: 'get' + }) +} diff --git a/web/src/views/system/dept/components/DeptUserCom/crud.tsx b/web/src/views/system/dept/components/DeptUserCom/crud.tsx new file mode 100644 index 0000000..9e2b383 --- /dev/null +++ b/web/src/views/system/dept/components/DeptUserCom/crud.tsx @@ -0,0 +1,386 @@ +import { inject } from 'vue'; +import { dict, UserPageQuery, AddReq, DelReq, EditReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'; +import { request } from '/@/utils/service'; +import * as api from './api'; +import { dictionary } from '/@/utils/dictionary'; +import { successMessage } from '/@/utils/message'; + +export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet { + const pageRequest = async (query: UserPageQuery) => { + const res = await api.GetList(query); + /** + * 处理crud警告:Invalid prop: type check failed for prop "name". Expected String with value "2", got Number with value 2. + */ + res.data.forEach((item: any) => { + if (item.role && Array.isArray(item.role) && item.role.length > 0) { + item.role = item.role.map((r: number) => String(r)); + } + }); + return res; + }; + const editRequest = async ({ form, row }: EditReq) => { + form.id = row.id; + return await api.UpdateObj(form); + }; + const delRequest = async ({ row }: DelReq) => { + return await api.DelObj(row.id); + }; + const addRequest = async ({ form }: AddReq) => { + return await api.AddObj(form); + }; + + const exportRequest = async (query: UserPageQuery) => { + return await api.exportData(query); + }; + + //权限判定 + const hasPermissions: any = inject('$hasPermissions'); + + return { + crudOptions: { + table: { + remove: { + confirmMessage: '是否删除该用户?', + }, + }, + request: { + pageRequest, + addRequest, + editRequest, + delRequest, + }, + actionbar: { + buttons: { + add: { + show: hasPermissions('user:Create'), + // show:true + }, + export: { + text: '导出', //按钮文字 + title: '导出', //鼠标停留显示的信息 + click() { + return exportRequest(crudExpose!.getSearchFormData()); + }, + }, + }, + }, + search: { + container: { + action: { + col: { + span: 6, + }, + }, + }, + }, + rowHandle: { + //固定右侧 + fixed: 'right', + width: 250, + buttons: { + view: { + show: false, + }, + edit: { + show: hasPermissions('user:Update'), + }, + remove: { + show: hasPermissions('user:Delete'), + }, + custom: { + text: '重设密码', + type: 'primary', + show: hasPermissions('user:ResetPassword'), + tooltip: { + placement: 'top', + content: '重设密码', + }, + click: (ctx: any) => { + const { row } = ctx; + }, + }, + }, + }, + columns: { + _index: { + title: '序号', + form: { show: false }, + column: { + type: 'index', + align: 'center', + width: '70px', + columnSetDisabled: true, //禁止在列设置中选择 + }, + }, + username: { + title: '账号', + search: { + show: true, + }, + type: 'input', + column: { + minWidth: 100, //最小列宽 + }, + form: { + rules: [ + // 表单校验规则 + { + required: true, + message: '账号必填项', + }, + ], + component: { + placeholder: '请输入账号', + }, + }, + }, + password: { + title: '密码', + type: 'input', + column: { + show: false, + }, + editForm: { + show: false, + }, + form: { + rules: [ + // 表单校验规则 + { + required: true, + message: '密码必填项', + }, + ], + component: { + span: 12, + showPassword: true, + placeholder: '请输入密码', + }, + // value: vm.systemConfig('base.default_password'), + }, + /* valueResolve(row, key) { + if (row.password) { + row.password = vm.$md5(row.password) + } + } */ + }, + name: { + title: '姓名', + search: { + show: true, + }, + type: 'input', + column: { + minWidth: 100, //最小列宽 + }, + form: { + rules: [ + // 表单校验规则 + { + required: true, + message: '姓名必填项', + }, + ], + component: { + span: 12, + placeholder: '请输入姓名', + }, + }, + }, + dept: { + title: '部门', + search: { + disabled: true, + }, + type: 'dict-tree', + dict: dict({ + isTree: true, + url: '/api/system/dept/all_dept/', + value: 'id', + label: 'name', + getData: async ({ url }: { url: string }) => { + return request({ + url: url, + }).then((ret: any) => { + return ret.data; + }); + }, + }), + column: { + minWidth: 150, //最小列宽 + }, + form: { + rules: [ + // 表单校验规则 + { + required: true, + message: '必填项', + }, + ], + component: { + filterable: true, + placeholder: '请选择', + props: { + props: { + value: 'id', + label: 'name', + }, + }, + }, + }, + }, + role: { + title: '角色', + search: { + disabled: true, + }, + type: 'dict-select', + dict: dict({ + url: '/api/system/role/', + value: 'id', + label: 'name', + isTree: true, + getData: async ({ url }: { url: string }) => { + return request({ + url: url, + params: { + page: 1, + limit: 10, + }, + }).then((ret: any) => { + return ret.data; + }); + }, + }), + column: { + minWidth: 100, //最小列宽 + }, + form: { + rules: [ + // 表单校验规则 + { + required: true, + message: '必填项', + }, + ], + component: { + multiple: true, + filterable: true, + placeholder: '请选择角色', + }, + }, + }, + mobile: { + title: '手机号码', + search: { + show: true, + }, + type: 'input', + column: { + minWidth: 120, //最小列宽 + }, + form: { + rules: [ + { + max: 20, + message: '请输入正确的手机号码', + trigger: 'blur', + }, + { + pattern: /^1[3-9]\d{9}$/, + message: '请输入正确的手机号码', + }, + ], + component: { + placeholder: '请输入手机号码', + }, + }, + }, + email: { + title: '邮箱', + column: { + width: 260, + }, + form: { + rules: [ + { + type: 'email', + message: '请输入正确的邮箱地址', + trigger: ['blur', 'change'], + }, + ], + component: { + placeholder: '请输入邮箱', + }, + }, + }, + gender: { + title: '性别', + type: 'dict-select', + dict: dict({ + data: dictionary('gender'), + }), + form: { + value: 1, + component: { + span: 12, + }, + }, + component: { props: { color: 'auto' } }, // 自动染色 + }, + user_type: { + title: '用户类型', + search: { + show: true, + }, + type: 'dict-select', + dict: dict({ + data: dictionary('user_type'), + }), + column: { + minWidth: 100, //最小列宽 + }, + form: { + show: false, + value: 0, + component: { + span: 12, + }, + }, + }, + is_active: { + title: '锁定', + search: { + show: true, + }, + type: 'dict-radio', + column: { + component: { + name: 'fs-dict-switch', + activeText: '', + inactiveText: '', + style: '--el-switch-on-color: var(--el-color-primary); --el-switch-off-color: #dcdfe6', + onChange: compute((context) => { + return () => { + api.UpdateObj(context.row).then((res: APIResponseData) => { + successMessage(res.msg as string); + }); + }; + }), + }, + }, + dict: dict({ + data: dictionary('button_status_bool'), + }), + }, + avatar: { + title: '头像', + type: 'avatar-cropper', + form: { + show: false, + }, + }, + }, + }, + }; +}; diff --git a/web/src/views/system/dept/components/DeptUserCom/index.vue b/web/src/views/system/dept/components/DeptUserCom/index.vue new file mode 100644 index 0000000..7cec118 --- /dev/null +++ b/web/src/views/system/dept/components/DeptUserCom/index.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/web/src/views/system/dept/components/TreeCom.vue b/web/src/views/system/dept/components/TreeCom.vue index 95049b4..ef869c6 100644 --- a/web/src/views/system/dept/components/TreeCom.vue +++ b/web/src/views/system/dept/components/TreeCom.vue @@ -67,7 +67,7 @@ import { ElTree } from 'element-plus'; import { getElementLabelLine } from "element-tree-line"; import { Search } from '@element-plus/icons-vue'; import { lazyLoadDept } from '../api'; -import { warningMessage } from '../../../../utils/message'; +import { warningNotification } from '../../../../utils/message'; import { TreeItemType, APIResponseData } from '../types'; import type Node from 'element-plus/es/components/tree/src/model/node'; @@ -85,7 +85,7 @@ const treeProps = { withDefaults(defineProps(), { treeData: () => [], }) -const emit = defineEmits(['setFormInitData', 'deleteDept', 'updateDept']) +const emit = defineEmits(['treeClick', 'deleteDept', 'updateDept']) let filterVal = ref(''); let showTotalNum = ref(false) @@ -96,11 +96,17 @@ watch(filterVal, (val) => { treeRef.value!.filter(val); }); +/** + * 部门树的搜索事件 + */ const handleFilterTreeNode = (value: string, data: TreeItemType) => { if (!value) return true; return toRaw(data).name?.indexOf(value) !== -1; }; +/** + * 部门树的懒加载 + */ const handleLoadNode = (node: Node, resolve: Function) => { if (node.level !== 0) { lazyLoadDept({ parent: node.data.id }).then((res: APIResponseData) => { @@ -109,9 +115,12 @@ const handleLoadNode = (node: Node, resolve: Function) => { } }; +/** + * 部门的点击事件 + */ const handleNodeClick = (data: TreeItemType) => { treeSelectDept.value = data - emit('setFormInitData', data) + emit('treeClick', data.id) }; /** @@ -120,7 +129,7 @@ const handleNodeClick = (data: TreeItemType) => { const handleUpdateMenu = (type: string) => { if (type === 'update') { if (!treeSelectDept.value.id) { - warningMessage('请选择菜单!') + warningNotification('请选择菜单!') return } emit('updateDept', type, treeSelectDept.value) @@ -134,7 +143,7 @@ const handleUpdateMenu = (type: string) => { */ const handleDeleteDept = () => { if (!treeSelectDept.value.id) { - warningMessage('请选择菜单!') + warningNotification('请选择菜单!') return } emit('deleteDept', treeSelectDept.value.id, () => { diff --git a/web/src/views/system/dept/crud.tsx b/web/src/views/system/dept/crud.tsx deleted file mode 100644 index 089d6fa..0000000 --- a/web/src/views/system/dept/crud.tsx +++ /dev/null @@ -1,251 +0,0 @@ -import * as api from './api'; -import { dict, UserPageQuery, AddReq, DelReq, EditReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'; -import { verifyPhone } from '/@/utils/toolsValidate'; -import { dictionary } from '/@/utils/dictionary'; -import { successMessage } from '/@/utils/message'; - -export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet { - const pageRequest = async (query: UserPageQuery) => { - return await api.GetList(query); - }; - const editRequest = async ({ form, row }: EditReq) => { - form.id = row.id; - return await api.UpdateObj(form); - }; - const delRequest = async ({ row }: DelReq) => { - return await api.DelObj(row.id); - }; - const addRequest = async ({ form }: AddReq) => { - return await api.AddObj(form); - }; - - const validatePhone = async (rule: any, value: any, callback: any) => { - if (value === '') { - throw new Error('请输入手机号码'); - } - if (verifyPhone(value)) { - callback(); - } else { - throw new Error('手机号码格式有误'); - } - }; - - /** - * 懒加载 - * @param row - * @returns {Promise} - */ - const loadContentMethod = (tree: any, treeNode: any, resolve: any) => { - api.GetList({ parent: tree.id }).then((res: any) => { - resolve(res.data); - }); - }; - - return { - crudOptions: { - request: { - pageRequest, - addRequest, - editRequest, - delRequest, - }, - pagination: { - show: false, - }, - table: { - rowKey: 'id', - lazy: true, - load: loadContentMethod, - treeProps: { children: 'children', hasChildren: 'hasChild' }, - }, - rowHandle: { - fiexd: 'right', - fixed: 'right', - width: 200, - buttons: { - view: { - show: false, - }, - edit: { - iconRight: 'Edit', - type: 'text', - }, - remove: { - iconRight: 'Delete', - type: 'text', - }, - addChildren: { - text: '添加子级', - type: 'text', - click(context) { - const rowId = context.row.id; - crudExpose!.openAdd({ row: { parent: rowId } }); - }, - }, - }, - }, - columns: { - _index: { - title: '序号', - form: { show: false }, - column: { - type: 'index', - align: 'center', - width: '70px', - columnSetDisabled: true, //禁止在列设置中选择 - }, - }, - search: { - title: '关键词', - column: { - show: false, - }, - search: { - show: true, - component: { - props: { - clearable: true, - }, - placeholder: '请输入关键词', - }, - }, - form: { - show: false, - component: { - props: { - clearable: true, - }, - }, - }, - }, - name: { - title: '部门名称', - sortable: true, - treeNode: true, // 设置为树形列 - search: { - disabled: false, - component: { - props: { - clearable: true, - }, - }, - }, - width: 180, - type: 'input', - form: { - rules: [ - // 表单校验规则 - { required: true, message: '部门名称必填项' }, - ], - component: { - span: 12, - props: { - clearable: true, - }, - placeholder: '请输入部门名称', - }, - }, - }, - key: { - title: '部门标识', - sortable: true, - form: { - component: { - props: { - clearable: true, - }, - placeholder: '请输入标识字符', - }, - }, - }, - owner: { - title: '负责人', - sortable: true, - form: { - component: { - span: 12, - props: { - clearable: true, - }, - placeholder: '请输入负责人', - }, - }, - }, - phone: { - title: '联系电话', - sortable: true, - form: { - rules: [{ validator: validatePhone, trigger: 'blur' }], - component: { - span: 12, - props: { - clearable: true, - }, - placeholder: '请输入联系电话', - }, - }, - }, - email: { - title: '邮箱', - sortable: true, - form: { - component: { - span: 12, - props: { - clearable: true, - }, - placeholder: '请输入邮箱', - }, - rules: [ - { - type: 'email', - message: '请输入正确的邮箱地址', - // @ts-ignore - trigger: ['blur', 'change'], - }, - ], - }, - }, - sort: { - title: '排序', - sortable: true, - width: 80, - type: 'number', - form: { - value: 1, - component: { - span: 12, - placeholder: '请选择序号', - }, - }, - }, - status: { - title: '状态', - sortable: true, - search: { - disabled: false, - }, - type: 'dict-radio', - column: { - component: { - name: 'fs-dict-switch', - activeText: '', - inactiveText: '', - style: '--el-switch-on-color: #409eff; --el-switch-off-color: #dcdfe6', - onChange: compute((context) => { - return () => { - api.UpdateObj(context.row).then((res: APIResponseData) => { - successMessage(res.msg as string); - }); - }; - }), - }, - }, - dict: dict({ - data: dictionary('button_status_bool'), - }), - }, - }, - }, - }; -}; diff --git a/web/src/views/system/dept/index.vue b/web/src/views/system/dept/index.vue index 9cc0018..d8c782e 100644 --- a/web/src/views/system/dept/index.vue +++ b/web/src/views/system/dept/index.vue @@ -3,71 +3,14 @@
-
-
- - - 部门配置 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 保存 - 新建 - - 删除部门 - - - - - +
+
@@ -80,36 +23,20 @@