+
+ :tree-data="departmentList"
+ :field-names="{ key: 'id', title: 'deptName' }"
+ :load-data="onLoadDeptList"
+ @select="onSelect"
+ >
+
+
+
+
diff --git a/src/views/system/user/ResetPwdModal.vue b/src/views/system/user/UserFormModal.vue
similarity index 50%
rename from src/views/system/user/ResetPwdModal.vue
rename to src/views/system/user/UserFormModal.vue
index dff86ff..0b8db65 100644
--- a/src/views/system/user/ResetPwdModal.vue
+++ b/src/views/system/user/UserFormModal.vue
@@ -1,41 +1,41 @@
-
+
diff --git a/src/views/system/user/UserModal.vue b/src/views/system/user/UserModal.vue
deleted file mode 100644
index 1f71df1..0000000
--- a/src/views/system/user/UserModal.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/views/system/user/UserRoleModal.vue b/src/views/system/user/UserRoleModal.vue
deleted file mode 100644
index 93c6664..0000000
--- a/src/views/system/user/UserRoleModal.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/views/system/user/data.ts b/src/views/system/user/data.ts
new file mode 100644
index 0000000..8c753c1
--- /dev/null
+++ b/src/views/system/user/data.ts
@@ -0,0 +1,309 @@
+import type { Ref } from 'vue'
+import { h } from 'vue'
+import { Avatar } from 'ant-design-vue'
+import { getRoleTree } from '@/api/system/role'
+import type { BasicColumn, FormSchema } from '@/components/Table'
+import { getAllTenants } from '@/api/system/tenant'
+import { getDeptTree, lazyGetDeptList } from '@/api/system/dept'
+
+export const columns: BasicColumn[] = [
+ {
+ title: '登陆账号',
+ dataIndex: 'account',
+ width: 180,
+ },
+ {
+ title: '所属租户',
+ dataIndex: 'tenantName',
+ width: 100,
+ },
+ {
+ title: '用户姓名',
+ dataIndex: 'realName',
+ width: 120,
+ customRender({ record, value }) {
+ return h('div', [
+ h(
+ Avatar,
+ {
+ src: /^https?/.test(record.avatar) ? record.avatar : undefined,
+ size: 'small',
+ style: { marginRight: '10px' },
+ },
+ () => value?.slice(0, 1),
+ ),
+ value,
+ ])
+ },
+ },
+ {
+ title: '手机号码',
+ dataIndex: 'mobile',
+ width: 120,
+ },
+ {
+ title: '用户邮箱',
+ dataIndex: 'email',
+ width: 120,
+ },
+ {
+ title: '所属角色',
+ dataIndex: 'roleName',
+ width: 120,
+ },
+ {
+ title: '所属部门',
+ dataIndex: 'deptName',
+ width: 120,
+ },
+]
+
+export const searchFormSchema: FormSchema[] = [
+ {
+ label: '账号',
+ field: 'account',
+ component: 'Input',
+ colProps: { span: 6 },
+ },
+ {
+ label: '手机号码',
+ field: 'mobile',
+ component: 'InputNumber',
+ componentProps: {
+ controls: false,
+ precision: 0,
+ },
+ colProps: { span: 6 },
+ },
+ {
+ label: '所属部门',
+ field: 'tenantId',
+ component: 'ApiTreeSelect',
+ componentProps: {
+ async api() {
+ try {
+ const res = await lazyGetDeptList()
+ return res.map(item => ({ ...item, isLeaf: !item.hasChildren }))
+ }
+ catch {
+ return []
+ }
+ },
+ async loadData(treeNode) {
+ try {
+ const res = await lazyGetDeptList({ parentId: treeNode.id })
+ return res.map(item => ({ ...item, isLeaf: !item.hasChildren }))
+ }
+ catch {
+ return []
+ }
+ },
+ valueField: 'id',
+ labelField: 'deptName',
+ },
+ colProps: { span: 6 },
+ },
+]
+
+export function getFormSchema(isUpdate: Ref
): FormSchema[] {
+ return [
+ {
+ field: 'id',
+ show: false,
+ component: 'Input',
+ },
+ {
+ field: 'BaseInfo',
+ label: '基本信息',
+ component: 'Divider',
+ componentProps: {
+ plain: false,
+ },
+ },
+ {
+ label: '账号',
+ field: 'account',
+ required: true,
+ component: 'Input',
+ ifShow: () => !isUpdate.value,
+ },
+ {
+ label: '密码',
+ field: 'password',
+ required: true,
+ component: 'InputPassword',
+ ifShow: () => !isUpdate.value,
+ },
+ {
+ label: '确认密码',
+ field: 'confirmPassword',
+ required: true,
+ component: 'InputPassword',
+ ifShow: () => !isUpdate.value,
+ dynamicRules: ({ values }) => {
+ return [
+ {
+ required: true,
+ validator: (_, value) => {
+ if (value !== values.password)
+ // eslint-disable-next-line prefer-promise-reject-errors
+ return Promise.reject('两次输入的密码不一致!')
+
+ return Promise.resolve()
+ },
+ },
+ ]
+ },
+ },
+ {
+ label: '所属租户',
+ field: 'tenantId',
+ required: true,
+ component: 'ApiSelect',
+ defaultValue: undefined,
+ dynamicDisabled: () => isUpdate.value,
+ componentProps({ formActionType, formModel }) {
+ return {
+ api: getAllTenants,
+ valueField: 'tenantId',
+ labelField: 'tenantName',
+ onChange(value?: string) {
+ function updateRole(treeData: { id: string, title: string }[]) {
+ if (!isUpdate)
+ formModel.roleId && formActionType.setFieldsValue({ roleId: undefined })
+
+ formActionType.updateSchema({
+ field: 'roleId',
+ componentProps: {
+ treeData,
+ },
+ })
+ }
+ function updateDept(treeData: { id: string, title: string }[]) {
+ if (!isUpdate)
+ formModel.deptId && formActionType.setFieldsValue({ deptId: undefined })
+
+ formActionType.updateSchema({
+ field: 'deptId',
+ componentProps: {
+ treeData,
+ },
+ })
+ }
+
+ if (!value) {
+ updateRole([])
+ updateDept([])
+ return
+ }
+
+ getRoleTree({ tenantId: value })
+ .then((res) => {
+ updateRole(res)
+ })
+
+ getDeptTree({ tenantId: value })
+ .then((res) => {
+ updateDept(res)
+ })
+ },
+ }
+ },
+ },
+ {
+ label: '所属部门',
+ field: 'deptId',
+ required: true,
+ component: 'TreeSelect',
+ componentProps: {
+ treeData: [],
+ fieldNames: {
+ label: 'title',
+ value: 'id',
+ },
+ },
+ },
+ {
+ label: '所属角色',
+ field: 'roleId',
+ required: true,
+ component: 'TreeSelect',
+ componentProps: {
+ treeData: [],
+ fieldNames: {
+ label: 'title',
+ value: 'id',
+ },
+ },
+ },
+ {
+ field: 'UserInfo',
+ label: '用户信息',
+ component: 'Divider',
+ componentProps: {
+ plain: false,
+ },
+ },
+ {
+ label: '用户姓名',
+ field: 'realName',
+ component: 'Input',
+ required: true,
+ },
+ {
+ label: '用户头像',
+ field: 'avatar',
+ component: 'FileUpload',
+ componentProps: {
+ maxCount: 1,
+ fileType: 'image',
+ },
+ },
+ {
+ label: '用户邮箱',
+ field: 'email',
+ component: 'Input',
+ rules: [
+ { type: 'email', message: '邮箱格式不正确' },
+ ],
+ },
+ {
+ label: '手机号码',
+ field: 'mobile',
+ component: 'InputNumber',
+ componentProps: {
+ controls: false,
+ precision: 0,
+ },
+ rules: [
+ { pattern: /^1[3-9]\d{9}$/, message: '手机号码格式不正确' },
+ ],
+ },
+ {
+ label: '用户性别',
+ field: 'sex',
+ component: 'Select',
+ componentProps: {
+ options: [
+ {
+ label: '男',
+ value: 0,
+ },
+ {
+ label: '女',
+ value: 1,
+ },
+ {
+ label: '未知',
+ value: 2,
+ },
+ ],
+ },
+ },
+ {
+ label: '备注',
+ field: 'remark',
+ component: 'InputTextArea',
+ },
+ ]
+}
diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue
index 4f55b3f..c3aee41 100644
--- a/src/views/system/user/index.vue
+++ b/src/views/system/user/index.vue
@@ -1,39 +1,33 @@
-
-
-
-
-
+
+
+
+
+
{{ t('action.create') }}
-
- {{ t('action.export') }}
-
+
-
-
-
+
+
diff --git a/src/views/system/user/user.data.ts b/src/views/system/user/user.data.ts
deleted file mode 100644
index 150a669..0000000
--- a/src/views/system/user/user.data.ts
+++ /dev/null
@@ -1,283 +0,0 @@
-/* eslint-disable prefer-promise-reject-errors */
-import { h } from 'vue'
-import { Switch } from 'ant-design-vue'
-import dayjs from 'dayjs'
-import { useMessage } from '@/hooks/web/useMessage'
-import { listSimpleDept } from '@/api/system/dept'
-import { listSimplePosts } from '@/api/system/post'
-import type { BasicColumn, FormSchema } from '@/components/Table'
-import { useRender } from '@/components/Table'
-import { DICT_TYPE, getDictOptions } from '@/utils/dict'
-import { updateUserStatus } from '@/api/system/user'
-import { listSimpleRoles } from '@/api/system/role'
-
-export const columns: BasicColumn[] = [
- {
- title: '用户编号',
- dataIndex: 'id',
- width: 100,
- },
- {
- title: '用户名称',
- dataIndex: 'username',
- width: 180,
- },
- {
- title: '用户昵称',
- dataIndex: 'nickname',
- width: 100,
- },
- {
- title: '部门',
- dataIndex: 'deptId',
- width: 120,
- customRender: ({ record }) => {
- return useRender.renderTag(record.dept && record.dept.name)
- },
- },
- {
- title: '手机号码',
- dataIndex: 'mobile',
- width: 120,
- },
- {
- title: '状态',
- dataIndex: 'status',
- width: 180,
- // customRender: ({ text }) => {
- // return useRender.renderDict(text, DICT_TYPE.COMMON_STATUS)
- // }
- customRender: ({ record }) => {
- if (!Reflect.has(record, 'pendingStatus'))
- record.pendingStatus = false
-
- return h(Switch, {
- checked: record.status === 0,
- checkedChildren: '已启用',
- unCheckedChildren: '已禁用',
- loading: record.pendingStatus,
- onChange(checked: boolean) {
- record.pendingStatus = true
- const newStatus = checked ? 0 : 1
- const { createMessage } = useMessage()
- updateUserStatus(record.id, newStatus)
- .then(() => {
- record.status = newStatus
- createMessage.success('已成功修改用户状态')
- })
- .catch(() => {
- createMessage.error('修改用户状态失败')
- })
- .finally(() => {
- record.pendingStatus = false
- })
- },
- })
- },
- },
- {
- title: '创建时间',
- dataIndex: 'createTime',
- width: 180,
- customRender: ({ text }) => {
- return useRender.renderDate(text)
- },
- },
-]
-
-export const searchFormSchema: FormSchema[] = [
- {
- label: '用户名称',
- field: 'username',
- component: 'Input',
- colProps: { span: 8 },
- },
- {
- label: '手机号码',
- field: 'mobile',
- component: 'Input',
- colProps: { span: 8 },
- },
- {
- label: '状态',
- field: 'status',
- component: 'Select',
- componentProps: {
- options: getDictOptions(DICT_TYPE.COMMON_STATUS),
- },
- colProps: { span: 8 },
- },
- {
- label: '创建时间',
- field: 'createTime',
- component: 'RangePicker',
- componentProps: {
- showTime: {
- defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')],
- },
- },
- colProps: { span: 8 },
- },
-]
-
-export const formSchema: FormSchema[] = [
- {
- label: '编号',
- field: 'id',
- show: false,
- component: 'Input',
- },
- {
- label: '用户昵称',
- field: 'nickname',
- required: true,
- component: 'Input',
- },
- {
- label: '用户头像',
- field: 'avatar',
- component: 'FileUpload',
- componentProps: {
- maxCount: 1,
- fileType: 'image',
- },
- },
- {
- label: '归属部门',
- field: 'deptId',
- required: true,
- component: 'ApiTreeSelect',
- componentProps: {
- api: () => listSimpleDept(),
- handleTree: 'id',
- },
- },
- {
- label: '手机号码',
- field: 'mobile',
- required: true,
- defaultValue: 0,
- component: 'InputNumber',
- },
- {
- label: '邮箱',
- field: 'email',
- required: true,
- component: 'Input',
- },
- {
- label: '用户名称',
- field: 'username',
- component: 'Input',
- dynamicDisabled: ({ values }) => !!values.id,
- },
- {
- label: '用户密码',
- field: 'password',
- component: 'InputPassword',
- ifShow: ({ values }) => !values.id,
- },
- {
- label: '用户性别',
- field: 'sex',
- component: 'Select',
- componentProps: {
- options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX),
- },
- },
- {
- label: '岗位',
- field: 'postIds',
- component: 'ApiSelect',
- defaultValue: [],
- componentProps: {
- api: () => listSimplePosts(),
- labelField: 'name',
- valueField: 'id',
- mode: 'tags',
- },
- },
- {
- label: '状态',
- field: 'status',
- component: 'Select',
- componentProps: {
- options: getDictOptions(DICT_TYPE.COMMON_STATUS),
- },
- },
- {
- label: '备注',
- field: 'remark',
- component: 'InputTextArea',
- },
-]
-
-export const userRoleFormSchema: FormSchema[] = [
- {
- label: '编号',
- field: 'id',
- show: false,
- component: 'Input',
- },
- {
- label: '用户名称',
- field: 'username',
- component: 'Input',
- dynamicDisabled: () => true,
- },
- {
- label: '用户昵称',
- field: 'nickname',
- component: 'Input',
- dynamicDisabled: () => true,
- },
- {
- label: '角色',
- field: 'roleIds',
- component: 'ApiSelect',
- componentProps: {
- api: () => listSimpleRoles(),
- labelField: 'name',
- valueField: 'id',
- mode: 'tags',
- },
- },
-]
-
-export const userPwdFormSchema: FormSchema[] = [
- {
- field: 'newPassword',
- label: '新密码',
- component: 'StrengthMeter',
- componentProps: {
- placeholder: '新密码',
- },
- rules: [
- {
- required: true,
- message: '请输入新密码',
- },
- ],
- },
- {
- field: 'confirmPassword',
- label: '确认密码',
- component: 'InputPassword',
- dynamicRules: ({ values }) => {
- return [
- {
- required: true,
- validator: (_, value) => {
- if (!value)
- return Promise.reject('密码不能为空')
-
- if (value !== values.newPassword)
- return Promise.reject('两次输入的密码不一致!')
-
- return Promise.resolve()
- },
- },
- ]
- },
- },
-]