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 @@
-
-