feat: 新增用户管理页面
This commit is contained in:
parent
aec8444121
commit
768bde6e14
@ -63,6 +63,10 @@ const SUPPORTED_ADMIN_MENU_NAMES = new Set([
|
||||
'SystemRoleCreate',
|
||||
'SystemRoleDelete',
|
||||
'SystemRoleEdit',
|
||||
'SystemUser',
|
||||
'SystemUserCreate',
|
||||
'SystemUserDelete',
|
||||
'SystemUserEdit',
|
||||
]);
|
||||
|
||||
export function isSupportedAdminMenuName(name?: null | string | symbol) {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './dept';
|
||||
export * from './menu';
|
||||
export * from './role';
|
||||
export * from './user';
|
||||
|
||||
74
apps/web-antdv-next/src/api/system/user.ts
Normal file
74
apps/web-antdv-next/src/api/system/user.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace SystemUserApi {
|
||||
export interface SystemUser {
|
||||
[key: string]: any;
|
||||
createTime?: string;
|
||||
dept?: null | {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
deptId?: null | string;
|
||||
deptName?: string;
|
||||
homePath: string;
|
||||
id: string;
|
||||
password?: string;
|
||||
realName: string;
|
||||
roleIds: string[];
|
||||
roleNames: string[];
|
||||
roles?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
roleCode: string;
|
||||
status: 0 | 1;
|
||||
}>;
|
||||
status: 0 | 1;
|
||||
timezone: string;
|
||||
updateTime?: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export type SystemUserInput = Partial<Omit<SystemUser, 'id' | 'roles'>> & {
|
||||
roleIds?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户列表数据
|
||||
* @param params 用户查询参数
|
||||
*/
|
||||
async function getUserList(params: Recordable<any>) {
|
||||
return requestClient.get<Array<SystemUserApi.SystemUser>>(
|
||||
'/system/user/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
* @param data 用户数据
|
||||
*/
|
||||
async function createUser(data: SystemUserApi.SystemUserInput) {
|
||||
return requestClient.post('/system/user', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户
|
||||
* @param id 用户 ID
|
||||
* @param data 用户数据
|
||||
*/
|
||||
async function updateUser(id: string, data: SystemUserApi.SystemUserInput) {
|
||||
return requestClient.put(`/system/user/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
* @param id 用户 ID
|
||||
*/
|
||||
async function deleteUser(id: string) {
|
||||
return requestClient.delete(`/system/user/${id}`);
|
||||
}
|
||||
|
||||
export { createUser, deleteUser, getUserList, updateUser };
|
||||
@ -1,5 +1,22 @@
|
||||
{
|
||||
"title": "System Management",
|
||||
"user": {
|
||||
"allDept": "All",
|
||||
"createTime": "Create Time",
|
||||
"dept": "Department",
|
||||
"deptTree": "Department Tree",
|
||||
"homePath": "Home Path",
|
||||
"list": "User List",
|
||||
"name": "User",
|
||||
"password": "Password",
|
||||
"passwordPlaceholder": "Leave blank when editing to keep the current password; blank new users default to 123456",
|
||||
"realName": "Real Name",
|
||||
"roles": "Roles",
|
||||
"status": "Status",
|
||||
"timezone": "Timezone",
|
||||
"title": "User Management",
|
||||
"username": "Username"
|
||||
},
|
||||
"dept": {
|
||||
"name": "Department",
|
||||
"title": "Department Management",
|
||||
|
||||
@ -1,5 +1,22 @@
|
||||
{
|
||||
"title": "系统管理",
|
||||
"user": {
|
||||
"allDept": "全部",
|
||||
"createTime": "创建时间",
|
||||
"dept": "所属部门",
|
||||
"deptTree": "部门树",
|
||||
"homePath": "首页路径",
|
||||
"list": "用户列表",
|
||||
"name": "用户",
|
||||
"password": "密码",
|
||||
"passwordPlaceholder": "编辑时留空则不修改密码;新增留空默认 123456",
|
||||
"realName": "真实姓名",
|
||||
"roles": "角色",
|
||||
"status": "状态",
|
||||
"timezone": "时区",
|
||||
"title": "用户管理",
|
||||
"username": "用户名"
|
||||
},
|
||||
"dept": {
|
||||
"list": "部门列表",
|
||||
"createTime": "创建时间",
|
||||
|
||||
@ -12,6 +12,15 @@ const routes: RouteRecordRaw[] = [
|
||||
name: 'System',
|
||||
path: '/system',
|
||||
children: [
|
||||
{
|
||||
path: '/system/user',
|
||||
name: 'SystemUser',
|
||||
meta: {
|
||||
icon: 'mdi:account',
|
||||
title: $t('system.user.title'),
|
||||
},
|
||||
component: () => import('#/views/system/user/list.vue'),
|
||||
},
|
||||
{
|
||||
path: '/system/role',
|
||||
name: 'SystemRole',
|
||||
|
||||
150
apps/web-antdv-next/src/views/system/user/data.ts
Normal file
150
apps/web-antdv-next/src/views/system/user/data.ts
Normal file
@ -0,0 +1,150 @@
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
import { getDeptList } from '#/api/system/dept';
|
||||
import { getRoleList } from '#/api/system/role';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const statusOptions = [
|
||||
{ label: $t('common.enabled'), value: 1 },
|
||||
{ label: $t('common.disabled'), value: 0 },
|
||||
];
|
||||
|
||||
async function getRoleOptions() {
|
||||
const res = await getRoleList({
|
||||
page: 1,
|
||||
pageSize: 1000,
|
||||
status: 1,
|
||||
});
|
||||
const items = (res as any)?.items || [];
|
||||
return items.map((role: any) => ({
|
||||
label: role.name,
|
||||
value: role.id,
|
||||
}));
|
||||
}
|
||||
|
||||
export function useFormSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'username',
|
||||
label: $t('system.user.username'),
|
||||
rules: z
|
||||
.string()
|
||||
.min(2, $t('ui.formRules.minLength', [$t('system.user.username'), 2]))
|
||||
.max(
|
||||
30,
|
||||
$t('ui.formRules.maxLength', [$t('system.user.username'), 30]),
|
||||
),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: $t('system.user.passwordPlaceholder'),
|
||||
},
|
||||
fieldName: 'password',
|
||||
label: $t('system.user.password'),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'realName',
|
||||
label: $t('system.user.realName'),
|
||||
rules: z
|
||||
.string()
|
||||
.min(2, $t('ui.formRules.minLength', [$t('system.user.realName'), 2]))
|
||||
.max(
|
||||
30,
|
||||
$t('ui.formRules.maxLength', [$t('system.user.realName'), 30]),
|
||||
),
|
||||
},
|
||||
{
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: getRoleOptions,
|
||||
mode: 'multiple',
|
||||
},
|
||||
fieldName: 'roleIds',
|
||||
label: $t('system.user.roles'),
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'ApiTreeSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
api: getDeptList,
|
||||
childrenField: 'children',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
fieldName: 'deptId',
|
||||
label: $t('system.user.dept'),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '/workspace',
|
||||
},
|
||||
defaultValue: '/workspace',
|
||||
fieldName: 'homePath',
|
||||
label: $t('system.user.homePath'),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: 'Asia/Shanghai',
|
||||
},
|
||||
defaultValue: 'Asia/Shanghai',
|
||||
fieldName: 'timezone',
|
||||
label: $t('system.user.timezone'),
|
||||
},
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
buttonStyle: 'solid',
|
||||
options: statusOptions,
|
||||
optionType: 'button',
|
||||
},
|
||||
defaultValue: 1,
|
||||
fieldName: 'status',
|
||||
label: $t('system.user.status'),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function useGridFormSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'username',
|
||||
label: $t('system.user.username'),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'realName',
|
||||
label: $t('system.user.realName'),
|
||||
},
|
||||
{
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
options: statusOptions,
|
||||
},
|
||||
fieldName: 'status',
|
||||
label: $t('system.user.status'),
|
||||
},
|
||||
{
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
api: getRoleOptions,
|
||||
},
|
||||
fieldName: 'roleId',
|
||||
label: $t('system.user.roles'),
|
||||
},
|
||||
{
|
||||
component: 'RangePicker',
|
||||
fieldName: 'createTime',
|
||||
label: $t('system.user.createTime'),
|
||||
},
|
||||
];
|
||||
}
|
||||
353
apps/web-antdv-next/src/views/system/user/list.vue
Normal file
353
apps/web-antdv-next/src/views/system/user/list.vue
Normal file
@ -0,0 +1,353 @@
|
||||
<script lang="ts" setup>
|
||||
import type { TableColumnType } from 'antdv-next';
|
||||
import type { DataNode } from 'antdv-next/dist/tree/index';
|
||||
|
||||
import type { SystemUserApi } from '#/api';
|
||||
import type { SystemDeptApi } from '#/api/system/dept';
|
||||
import type {
|
||||
KtTableApi,
|
||||
KtTableButton,
|
||||
KtTableContext,
|
||||
KtTableRowAction,
|
||||
} from '#/components/ktTable';
|
||||
|
||||
import { computed, h, onMounted, ref } from 'vue';
|
||||
|
||||
import { useAccess } from '@vben/access';
|
||||
import { Page, useVbenDrawer } from '@vben/common-ui';
|
||||
import { Plus } from '@vben/icons';
|
||||
|
||||
import { Button, message, Spin, Switch, Tag, Tree } from 'antdv-next';
|
||||
|
||||
import { deleteUser, getUserList, updateUser } from '#/api';
|
||||
import { getDeptList } from '#/api/system/dept';
|
||||
import { KtTable, useKtTable } from '#/components/ktTable';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useGridFormSchema } from './data';
|
||||
import Form from './modules/form.vue';
|
||||
|
||||
const [FormDrawer, formDrawerApi] = useVbenDrawer({
|
||||
connectedComponent: Form,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
const { hasAccessByCodes } = useAccess();
|
||||
const deptTree = ref<SystemDeptApi.SystemDept[]>([]);
|
||||
const deptLoading = ref(false);
|
||||
const selectedDeptId = ref<string>();
|
||||
const selectedDeptKeys = computed(() =>
|
||||
selectedDeptId.value ? [selectedDeptId.value] : [],
|
||||
);
|
||||
const deptTreeData = computed<DataNode[]>(() => mapDeptTree(deptTree.value));
|
||||
|
||||
function hasPermission(code: string) {
|
||||
return hasAccessByCodes([code]);
|
||||
}
|
||||
|
||||
const columns: Array<TableColumnType<SystemUserApi.SystemUser>> = [
|
||||
{
|
||||
dataIndex: 'username',
|
||||
fixed: 'left',
|
||||
key: 'username',
|
||||
title: $t('system.user.username'),
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
title: $t('system.user.realName'),
|
||||
width: 160,
|
||||
},
|
||||
{
|
||||
dataIndex: 'roleNames',
|
||||
key: 'roleNames',
|
||||
title: $t('system.user.roles'),
|
||||
width: 220,
|
||||
},
|
||||
{
|
||||
dataIndex: 'deptName',
|
||||
key: 'deptName',
|
||||
title: $t('system.user.dept'),
|
||||
width: 160,
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
title: $t('system.user.status'),
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
dataIndex: 'homePath',
|
||||
key: 'homePath',
|
||||
title: $t('system.user.homePath'),
|
||||
width: 160,
|
||||
},
|
||||
{
|
||||
dataIndex: 'timezone',
|
||||
key: 'timezone',
|
||||
title: $t('system.user.timezone'),
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
title: $t('system.user.createTime'),
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
|
||||
const api: KtTableApi<SystemUserApi.SystemUser> = {
|
||||
list: async (params) => {
|
||||
const { pageNo, pageSize, ...formValues } = params;
|
||||
|
||||
return await getUserList({
|
||||
page: pageNo,
|
||||
pageSize,
|
||||
...(selectedDeptId.value ? { deptId: selectedDeptId.value } : {}),
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const buttons: Array<KtTableButton<SystemUserApi.SystemUser>> = [
|
||||
{
|
||||
icon: () => h(Plus, { class: 'kt-table__button-icon' }),
|
||||
key: 'create',
|
||||
label: $t('ui.actionTitle.create', [$t('system.user.name')]),
|
||||
onClick: onCreate,
|
||||
permissionCodes: ['System:User:Create'],
|
||||
type: 'primary',
|
||||
},
|
||||
];
|
||||
|
||||
const rowActions: Array<KtTableRowAction<SystemUserApi.SystemUser>> = [
|
||||
{
|
||||
key: 'edit',
|
||||
label: $t('common.edit'),
|
||||
onClick: onEdit,
|
||||
permissionCodes: ['System:User:Edit'],
|
||||
},
|
||||
{
|
||||
confirm: (row) => `确认删除「${row.username}」吗?`,
|
||||
danger: true,
|
||||
disabled: (row) => row.username === 'admin',
|
||||
key: 'delete',
|
||||
label: $t('common.delete'),
|
||||
onClick: onDelete,
|
||||
permissionCodes: ['System:User:Delete'],
|
||||
},
|
||||
];
|
||||
|
||||
const [registerTable, tableApi] = useKtTable<SystemUserApi.SystemUser>({
|
||||
api,
|
||||
buttons,
|
||||
columns,
|
||||
formOptions: {
|
||||
fieldMappingTime: [['createTime', ['startTime', 'endTime']]],
|
||||
schema: useGridFormSchema(),
|
||||
},
|
||||
rowActions,
|
||||
tableTitle: $t('system.user.list'),
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
loadDeptTree();
|
||||
});
|
||||
|
||||
async function loadDeptTree() {
|
||||
deptLoading.value = true;
|
||||
try {
|
||||
deptTree.value = await getDeptList();
|
||||
} finally {
|
||||
deptLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onDeptSelect(keys: Array<number | string>) {
|
||||
selectedDeptId.value = keys.length > 0 ? String(keys[0]) : undefined;
|
||||
tableApi.reload();
|
||||
}
|
||||
|
||||
function clearDeptFilter() {
|
||||
selectedDeptId.value = undefined;
|
||||
tableApi.reload();
|
||||
}
|
||||
|
||||
function mapDeptTree(depts: SystemDeptApi.SystemDept[]): DataNode[] {
|
||||
return depts.map((dept) => ({
|
||||
children: dept.children ? mapDeptTree(dept.children) : undefined,
|
||||
key: dept.id,
|
||||
title: dept.name,
|
||||
}));
|
||||
}
|
||||
|
||||
async function onStatusSwitchChange(
|
||||
checked: boolean | number | string,
|
||||
row: SystemUserApi.SystemUser,
|
||||
) {
|
||||
const nextStatus = Number(checked) as SystemUserApi.SystemUser['status'];
|
||||
if (nextStatus === row.status) return;
|
||||
|
||||
await updateUser(row.id, { status: nextStatus });
|
||||
await tableApi.reload();
|
||||
}
|
||||
|
||||
function onEdit(row: SystemUserApi.SystemUser) {
|
||||
formDrawerApi.setData(row).open();
|
||||
}
|
||||
|
||||
async function onDelete(
|
||||
row: SystemUserApi.SystemUser,
|
||||
context?: KtTableContext<SystemUserApi.SystemUser>,
|
||||
) {
|
||||
const hideLoading = message.loading({
|
||||
content: $t('ui.actionMessage.deleting', [row.username]),
|
||||
duration: 0,
|
||||
key: 'action_process_msg',
|
||||
});
|
||||
|
||||
try {
|
||||
await deleteUser(row.id);
|
||||
message.success({
|
||||
content: $t('ui.actionMessage.deleteSuccess', [row.username]),
|
||||
key: 'action_process_msg',
|
||||
});
|
||||
await (context || tableApi).reload();
|
||||
} catch {
|
||||
hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
function onRefresh() {
|
||||
tableApi.reload();
|
||||
}
|
||||
|
||||
function onCreate() {
|
||||
formDrawerApi.setData({ deptId: selectedDeptId.value }).open();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<FormDrawer @success="onRefresh" />
|
||||
<div class="system-user-page">
|
||||
<aside class="system-user-page__dept">
|
||||
<div class="system-user-page__dept-header">
|
||||
<span class="system-user-page__dept-title">
|
||||
{{ $t('system.user.deptTree') }}
|
||||
</span>
|
||||
<Button size="small" type="link" @click="clearDeptFilter">
|
||||
{{ $t('system.user.allDept') }}
|
||||
</Button>
|
||||
</div>
|
||||
<Spin :spinning="deptLoading">
|
||||
<Tree
|
||||
block-node
|
||||
:selected-keys="selectedDeptKeys"
|
||||
:tree-data="deptTreeData"
|
||||
default-expand-all
|
||||
@select="onDeptSelect"
|
||||
/>
|
||||
</Spin>
|
||||
</aside>
|
||||
<main class="system-user-page__table">
|
||||
<KtTable @register="registerTable">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'roleNames'">
|
||||
<div class="system-user-list__roles">
|
||||
<Tag
|
||||
v-for="roleName in record.roleNames || []"
|
||||
:key="roleName"
|
||||
color="processing"
|
||||
>
|
||||
{{ roleName }}
|
||||
</Tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'deptName'">
|
||||
{{ record.deptName || '-' }}
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<Switch
|
||||
v-if="record && hasPermission('System:User:Edit')"
|
||||
:checked="record.status"
|
||||
:checked-value="1"
|
||||
:un-checked-value="0"
|
||||
@change="(checked) => onStatusSwitchChange(checked, record)"
|
||||
/>
|
||||
<Tag v-else :color="record.status === 1 ? 'success' : 'default'">
|
||||
{{
|
||||
record.status === 1
|
||||
? $t('common.enabled')
|
||||
: $t('common.disabled')
|
||||
}}
|
||||
</Tag>
|
||||
</template>
|
||||
</template>
|
||||
</KtTable>
|
||||
</main>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.system-user-page {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
|
||||
&__dept {
|
||||
display: flex;
|
||||
flex: 0 0 240px;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
&__dept-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
}
|
||||
|
||||
&__dept-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
&__table {
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.ant-spin-nested-loading),
|
||||
:deep(.ant-spin-container) {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.ant-spin-container) {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.system-user-list {
|
||||
&__roles {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
77
apps/web-antdv-next/src/views/system/user/modules/form.vue
Normal file
77
apps/web-antdv-next/src/views/system/user/modules/form.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<script lang="ts" setup>
|
||||
import type { SystemUserApi } from '#/api/system/user';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenDrawer } from '@vben/common-ui';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { createUser, updateUser } from '#/api/system/user';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useFormSchema } from '../data';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
|
||||
const formData = ref<SystemUserApi.SystemUser>();
|
||||
const id = ref<string>();
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
schema: useFormSchema(),
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
const [Drawer, drawerApi] = useVbenDrawer({
|
||||
async onConfirm() {
|
||||
const { valid } = await formApi.validate();
|
||||
if (!valid) return;
|
||||
|
||||
const values = await formApi.getValues();
|
||||
if (id.value && !values.password) {
|
||||
delete values.password;
|
||||
}
|
||||
|
||||
drawerApi.lock();
|
||||
try {
|
||||
await (id.value ? updateUser(id.value, values) : createUser(values));
|
||||
emit('success');
|
||||
drawerApi.close();
|
||||
} finally {
|
||||
drawerApi.lock(false);
|
||||
}
|
||||
},
|
||||
onOpenChange(isOpen) {
|
||||
if (!isOpen) return;
|
||||
|
||||
const data = drawerApi.getData<SystemUserApi.SystemUser>();
|
||||
formData.value = data || undefined;
|
||||
id.value = data?.id;
|
||||
formApi.resetForm();
|
||||
formApi.setValues({
|
||||
...data,
|
||||
homePath: data?.homePath || '/workspace',
|
||||
password: '',
|
||||
status: data?.status ?? 1,
|
||||
timezone: data?.timezone || 'Asia/Shanghai',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const getDrawerTitle = computed(() => {
|
||||
return formData.value?.id
|
||||
? $t('ui.actionTitle.edit', [$t('system.user.name')])
|
||||
: $t('ui.actionTitle.create', [$t('system.user.name')]);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Drawer :title="getDrawerTitle">
|
||||
<Form class="system-user-form" />
|
||||
</Drawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.system-user-form {
|
||||
padding: 0 8px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user