feat: 用户管理-前端
This commit is contained in:
parent
87f7b3265d
commit
6cb7e97a5d
|
@ -1,9 +1,9 @@
|
|||
import MSR from '@/api/http/index';
|
||||
import { GetApiTestList, GetApiTestListUrl } from '@/api/requrls/api-test';
|
||||
import { QueryParams } from '@/models/common';
|
||||
import { TableQueryParams } from '@/models/common';
|
||||
import { CommonList } from '@/models/api-test';
|
||||
|
||||
export function getTableList(params: QueryParams) {
|
||||
export function getTableList(params: TableQueryParams) {
|
||||
const { current, pageSize, sort, filter, keyword } = params;
|
||||
return MSR.post<CommonList>({
|
||||
url: GetApiTestList,
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import MSR from '@/api/http/index';
|
||||
import { GetUserListUrl, CreateUserUrl, UpdateUserUrl } from '@/api/requrls/system';
|
||||
import type { UserListItem, CreateUserParams } from '@/models/system/user';
|
||||
import type { TableQueryParams } from '@/models/common';
|
||||
|
||||
export function getUserList(data: TableQueryParams) {
|
||||
return MSR.post<UserListItem[]>({ url: GetUserListUrl, data });
|
||||
}
|
||||
|
||||
export function batchCreateUser(data: CreateUserParams) {
|
||||
return MSR.post({ url: CreateUserUrl, data });
|
||||
}
|
||||
|
||||
export function updateUserInfo(data: UserListItem) {
|
||||
return MSR.post({ url: UpdateUserUrl, data });
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export const GetUserListUrl = '/user/page';
|
||||
export const CreateUserUrl = '/user/add';
|
||||
export const UpdateUserUrl = '/user/update';
|
|
@ -13,10 +13,9 @@
|
|||
}
|
||||
}
|
||||
.ms-table-row-disabled {
|
||||
td:not(.arco-table-col-fixed-right),
|
||||
td:not(.arco-table-col-fixed-right, .arco-table-checkbox),
|
||||
&:hover,
|
||||
td:not(.arco-table-col-fixed-right)::before,
|
||||
.arco-checkbox-icon,
|
||||
td:not(.arco-table-col-fixed-right, .arco-table-checkbox)::before,
|
||||
.arco-tag {
|
||||
color: var(--color-text-4);
|
||||
background-color: var(--color-text-n8) !important;
|
||||
|
@ -121,7 +120,7 @@
|
|||
background-color: rgb(var(--danger-2)) !important;
|
||||
}
|
||||
}
|
||||
.arco-btn-secondary {
|
||||
.arco-btn-secondary:not(.arco-btn-disabled) {
|
||||
color: var(--clolor-text-1) !important;
|
||||
background-color: var(--color-text-n8) !important;
|
||||
&:not(:disabled):hover {
|
||||
|
@ -275,3 +274,64 @@
|
|||
.arco-popover-content {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/** 链接 **/
|
||||
.arco-link-status-normal {
|
||||
color: rgb(var(--primary-5)) !important;
|
||||
&:not(:disabled):hover {
|
||||
color: rgb(var(--primary-4)) !important;
|
||||
background-color: rgb(var(--color-text-n9));
|
||||
}
|
||||
&:not(:disabled):active {
|
||||
color: rgb(var(--primary-7)) !important;
|
||||
}
|
||||
&:disabled {
|
||||
color: rgb(var(--primary-3)) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/** 穿梭框 **/
|
||||
.arco-transfer {
|
||||
@apply grid;
|
||||
|
||||
grid-template-columns: 4fr 1fr 4fr;
|
||||
.arco-transfer-view {
|
||||
@apply w-auto;
|
||||
|
||||
height: 370px;
|
||||
.arco-transfer-view-header {
|
||||
@apply bg-white;
|
||||
}
|
||||
}
|
||||
.arco-transfer-operations {
|
||||
.arco-btn-secondary {
|
||||
border-color: rgb(var(--primary-5));
|
||||
border-radius: var(--border-radius-small);
|
||||
background-color: rgb(var(--primary-1)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-5));
|
||||
}
|
||||
&:disabled {
|
||||
border-color: var(--color-text-input-border) !important;
|
||||
background-color: var(--color-text-n8) !important;
|
||||
.arco-btn-icon {
|
||||
color: var(--color-text-4);
|
||||
}
|
||||
}
|
||||
&:not(:disabled):hover {
|
||||
border-color: rgb(var(--primary-4)) !important;
|
||||
background-color: rgb(var(--primary-1)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-7));
|
||||
}
|
||||
}
|
||||
&:not(:disabled):active {
|
||||
border-color: rgb(var(--primary-7)) !important;
|
||||
background-color: rgb(var(--primary-9)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-7));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,3 +74,7 @@ body {
|
|||
.split-line {
|
||||
border-color: rgb(var(--gray-2));
|
||||
}
|
||||
.sub-text {
|
||||
font-size: 12px;
|
||||
color: rgb(var(--color-text-4));
|
||||
}
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
@border-radius-small: 4px;
|
||||
@border-radius-medium: 6px;
|
||||
@border-radius-large: 12px;
|
||||
|
||||
@color-white: #fff;
|
||||
|
|
|
@ -129,7 +129,7 @@
|
|||
};
|
||||
|
||||
function getRowClass(record: TableData) {
|
||||
if (record.disabled) {
|
||||
if (!record.raw.enable) {
|
||||
return 'ms-table-row-disabled';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import Mock from 'mockjs';
|
|||
import './user';
|
||||
import './message-box';
|
||||
import './api-test';
|
||||
import './system/user';
|
||||
|
||||
Mock.setup({
|
||||
timeout: '600-1000',
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
import Mock from 'mockjs';
|
||||
import setupMock, { successTableResponseWrap } from '@/utils/setup-mock';
|
||||
|
||||
const getUserList = () => {
|
||||
return [
|
||||
{
|
||||
id: '103423',
|
||||
name: '大家的',
|
||||
email: 'dehihu@kds.sd',
|
||||
enable: true,
|
||||
createTime: 1686905750716,
|
||||
updateTime: 0,
|
||||
lastOrganizationId: 'string',
|
||||
phone: '18473647583',
|
||||
source: 'string',
|
||||
lastProjectId: 'string',
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
organizationList: [
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 1',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 2',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 3',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 4',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
],
|
||||
userRoleList: [
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 1',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 2',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 3',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 4',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '103233',
|
||||
name: '发热发热',
|
||||
email: 'dehihu@kds.sd',
|
||||
enable: false,
|
||||
createTime: 1686905750716,
|
||||
updateTime: 0,
|
||||
lastOrganizationId: 'string',
|
||||
phone: '18473647583',
|
||||
source: 'string',
|
||||
lastProjectId: 'string',
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
organizationList: [
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 1',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 2',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 3',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
num: 0,
|
||||
name: '组织 4',
|
||||
description: 'blabla',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
updateUser: 'string',
|
||||
deleted: true,
|
||||
deleteUser: 'string',
|
||||
deleteTime: 0,
|
||||
enable: true,
|
||||
},
|
||||
],
|
||||
userRoleList: [
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 1',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 2',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 3',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
{
|
||||
id: 'string',
|
||||
name: '角色 4',
|
||||
description: 'sdadasd',
|
||||
internal: true,
|
||||
type: 'string',
|
||||
createTime: 0,
|
||||
updateTime: 0,
|
||||
createUser: 'string',
|
||||
scopeId: 'string',
|
||||
pos: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
setupMock({
|
||||
setup: () => {
|
||||
Mock.mock(new RegExp('/user/page'), () => {
|
||||
return successTableResponseWrap(getUserList());
|
||||
});
|
||||
},
|
||||
});
|
|
@ -7,16 +7,26 @@ export default interface CommonReponse<T> {
|
|||
}
|
||||
|
||||
// 表格查询
|
||||
export interface QueryParams {
|
||||
export interface TableQueryParams {
|
||||
// 当前页
|
||||
current: number;
|
||||
// 每页条数
|
||||
pageSize: number;
|
||||
// 排序仅针对单个字段
|
||||
sort?: object;
|
||||
// 排序仅针对单个字段
|
||||
sortString?: string;
|
||||
// 表头筛选
|
||||
filter?: object;
|
||||
// 查询条件
|
||||
keyword?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface TableResult<T> {
|
||||
[x: string]: any;
|
||||
pageSize: number;
|
||||
total: number;
|
||||
current: number;
|
||||
list: T[];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
export interface UserRoleListItem {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
internal: boolean;
|
||||
type: string;
|
||||
createTime: number;
|
||||
updateTime: number;
|
||||
createUser: string;
|
||||
scopeId: string;
|
||||
pos: number;
|
||||
}
|
||||
|
||||
export interface OrganizationList {
|
||||
id: string;
|
||||
num: number;
|
||||
name: string;
|
||||
description: string;
|
||||
createTime: number;
|
||||
updateTime: number;
|
||||
createUser: string;
|
||||
updateUser: string;
|
||||
deleted: boolean;
|
||||
deleteUser: string;
|
||||
deleteTime: number;
|
||||
enable: boolean;
|
||||
}
|
||||
|
||||
export interface UserListItem {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
enable: boolean;
|
||||
createTime: number;
|
||||
updateTime: number;
|
||||
language: string;
|
||||
lastOrganizationId: string;
|
||||
phone: string;
|
||||
source: string;
|
||||
lastProjectId: string;
|
||||
createUser: string;
|
||||
updateUser: string;
|
||||
organizationList: OrganizationList[];
|
||||
userRoleList: UserRoleListItem[];
|
||||
}
|
||||
|
||||
export interface Filter {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface Sort {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// 创建用户模型
|
||||
export interface CreateUserInfo {
|
||||
name: string;
|
||||
email: string;
|
||||
phone?: string;
|
||||
}
|
||||
|
||||
export interface CreateUserParams {
|
||||
userInfoList: CreateUserInfo[];
|
||||
userRoleIdList: string[];
|
||||
}
|
|
@ -18,6 +18,20 @@ export const successResponseWrap = (data: unknown) => {
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* mock- 表格接口成功返回结果结构体
|
||||
* @param data mock 返回结果
|
||||
* @returns
|
||||
*/
|
||||
export const successTableResponseWrap = (data: unknown) => {
|
||||
return {
|
||||
data: { list: data },
|
||||
status: 'ok',
|
||||
message: '请求成功',
|
||||
code: 0,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* mock- 失败返回结果结构体
|
||||
* @param data mock 返回结果
|
||||
|
|
|
@ -42,6 +42,9 @@ export default {
|
|||
'system.user.resetPassword': 'Reset PSW',
|
||||
'system.user.disable': 'Disable',
|
||||
'system.user.delete': 'Delete',
|
||||
'system.user.enable': 'Enable',
|
||||
'system.user.tableEnable': 'Enabled',
|
||||
'system.user.tableDisable': 'Disabled',
|
||||
'system.user.deleteUserStart': 'Are you sure to delete the user',
|
||||
'system.user.deleteUserEnd': '?',
|
||||
'system.user.deleteUserContent': "Only delete user information, does not handle the user's system data",
|
||||
|
@ -54,6 +57,12 @@ export default {
|
|||
'system.user.disableUserConfirm': 'Disabled',
|
||||
'system.user.disableUserCancel': 'Cancel',
|
||||
'system.user.disableUserSuccess': 'Disabled successful',
|
||||
'system.user.enableUserStart': 'Are you sure to enable the user',
|
||||
'system.user.enableUserEnd': '?',
|
||||
'system.user.enableUserContent': 'Enabled users can log in to the system',
|
||||
'system.user.enableUserConfirm': 'Enable',
|
||||
'system.user.enableUserCancel': 'Cancel',
|
||||
'system.user.enableUserSuccess': 'Enable successful',
|
||||
'system.user.resetPswStart': 'Reset the password of',
|
||||
'system.user.resetPswEnd': 'to its initial password?',
|
||||
'system.user.resetPswContent': "The initial password is the user's mailbox, which will take effect at the next login",
|
||||
|
@ -95,4 +104,31 @@ export default {
|
|||
'system.user.importModalCancel': 'Cancel',
|
||||
'system.user.importModalConfirm': 'Import',
|
||||
'system.user.importModalUploading': 'File is uploading...',
|
||||
'system.user.importSuccessTitle': 'Import user',
|
||||
'system.user.importSuccess': 'Import succeeded',
|
||||
'system.user.importFailTitle': 'Some user information failed to import',
|
||||
'system.user.importAllfailTitle': 'User information import failed',
|
||||
'system.user.importResultContentStart': 'Successfully imported user',
|
||||
'system.user.importResultContentCenter': 'items, failed to import',
|
||||
'system.user.importResultContentEnd': 'items;',
|
||||
'system.user.importResultContentSubStart': 'You can',
|
||||
'system.user.importResultContentDownload': 'Download bug report',
|
||||
'system.user.importResultContentSubEnd': ',re-import after modification',
|
||||
'system.user.importResultReturn': 'Return list',
|
||||
'system.user.importResultContinue': 'Continue importing',
|
||||
'system.user.importErrorFile': 'error report',
|
||||
'system.user.batchActionAddProject': 'Add to project',
|
||||
'system.user.batchActionAddUsergroup': 'Add to usergroup',
|
||||
'system.user.batchActionAddOrgnization': 'Add to org',
|
||||
'system.user.batchModalTip': 'Add project member usergroup as member by default',
|
||||
'system.user.batchModalSubTitleStart': '(Selected',
|
||||
'system.user.batchModalSubTitleEnd': 'users)',
|
||||
'system.user.batchModalCancel': 'Cancel',
|
||||
'system.user.batchModalConfirm': 'Add',
|
||||
'system.user.batchModalSuccess': 'Successfully added',
|
||||
'system.user.batchAddProject': 'Batch add to project',
|
||||
'system.user.batchAddUsergroup': 'Batch add to user group',
|
||||
'system.user.batchAddOrgnization': 'Batch add to organization',
|
||||
'system.user.batchOptional': 'Optional',
|
||||
'system.user.batchChosen': 'Chosen',
|
||||
};
|
||||
|
|
|
@ -42,6 +42,9 @@ export default {
|
|||
'system.user.resetPassword': '重置密码',
|
||||
'system.user.disable': '禁用',
|
||||
'system.user.delete': '删除',
|
||||
'system.user.enable': '启用',
|
||||
'system.user.tableEnable': '正常',
|
||||
'system.user.tableDisable': '禁用',
|
||||
'system.user.deleteUserStart': '确认删除',
|
||||
'system.user.deleteUserEnd': '这个用户吗?',
|
||||
'system.user.deleteUserContent': '仅删除用户信息,不处理该用户的系统数据',
|
||||
|
@ -54,6 +57,12 @@ export default {
|
|||
'system.user.disableUserConfirm': '确认禁用',
|
||||
'system.user.disableUserCancel': '取消',
|
||||
'system.user.disableUserSuccess': '禁用成功',
|
||||
'system.user.enableUserStart': '确认启用',
|
||||
'system.user.enableUserEnd': '这个用户吗?',
|
||||
'system.user.enableUserContent': '启用后用户可以登录系统',
|
||||
'system.user.enableUserConfirm': '确认启用',
|
||||
'system.user.enableUserCancel': '取消',
|
||||
'system.user.enableUserSuccess': '启用成功',
|
||||
'system.user.resetPswStart': '是否将',
|
||||
'system.user.resetPswEnd': '的密码重置为初始密码?',
|
||||
'system.user.resetPswContent': '初始的密码为用户邮箱,下次登录时生效',
|
||||
|
@ -96,4 +105,31 @@ export default {
|
|||
'system.user.importModalCancel': '取消',
|
||||
'system.user.importModalConfirm': '导入',
|
||||
'system.user.importModalUploading': '文件上传中...',
|
||||
'system.user.importSuccessTitle': '导入用户',
|
||||
'system.user.importSuccess': '导入成功',
|
||||
'system.user.importFailTitle': '部分用户信息导入失败',
|
||||
'system.user.importAllfailTitle': '用户信息导入失败',
|
||||
'system.user.importResultContentStart': '成功导入用户',
|
||||
'system.user.importResultContentCenter': '条,导入失败',
|
||||
'system.user.importResultContentEnd': '条',
|
||||
'system.user.importResultContentSubStart': '可',
|
||||
'system.user.importResultContentDownload': '下载错误报告',
|
||||
'system.user.importResultContentSubEnd': ',修改后重新导入',
|
||||
'system.user.importResultReturn': '返回列表',
|
||||
'system.user.importResultContinue': '继续导入',
|
||||
'system.user.importErrorFile': '错误报告',
|
||||
'system.user.batchActionAddProject': '添加至项目',
|
||||
'system.user.batchActionAddUsergroup': '添加至用户组',
|
||||
'system.user.batchActionAddOrgnization': '添加至组织',
|
||||
'system.user.batchModalTip': '默认为成员添加项目成员用户组',
|
||||
'system.user.batchModalSubTitleStart': '(已选',
|
||||
'system.user.batchModalSubTitleEnd': '个用户)',
|
||||
'system.user.batchModalCancel': '取消',
|
||||
'system.user.batchModalConfirm': '添加',
|
||||
'system.user.batchModalSuccess': '添加成功',
|
||||
'system.user.batchAddProject': '批量添加至项目',
|
||||
'system.user.batchAddUsergroup': '批量添加至用户组',
|
||||
'system.user.batchAddOrgnization': '批量添加至组织',
|
||||
'system.user.batchOptional': '可选',
|
||||
'system.user.batchChosen': '已选',
|
||||
};
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
<template>
|
||||
<a-modal
|
||||
v-model:visible="showBatchModal"
|
||||
title-align="start"
|
||||
class="ms-modal-upload ms-modal-medium"
|
||||
:loading="batchLoading"
|
||||
>
|
||||
<template #title>
|
||||
{{ batchTitle }}
|
||||
<div class="text-[var(--color-text-4)]">
|
||||
{{
|
||||
`${t('system.user.batchModalSubTitleStart')} ${props.tableSelected.length} ${t(
|
||||
'system.user.batchModalSubTitleEnd'
|
||||
)}`
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
<a-alert v-if="batchModalMode === 'project'" class="mb-[16px]">
|
||||
{{ t('system.user.batchModalTip') }}
|
||||
</a-alert>
|
||||
<a-transfer
|
||||
v-model="target"
|
||||
:title="[t('system.user.batchOptional'), t('system.user.batchChosen')]"
|
||||
:data="transferData"
|
||||
show-search
|
||||
>
|
||||
<template #source="{ data, selectedKeys, onSelect }">
|
||||
<a-tree
|
||||
:checkable="true"
|
||||
checked-strategy="child"
|
||||
:checked-keys="selectedKeys"
|
||||
:data="getTreeData(data)"
|
||||
block-node
|
||||
@check="onSelect"
|
||||
/>
|
||||
</template>
|
||||
</a-transfer>
|
||||
<template #footer>
|
||||
<a-button type="secondary" @click="cancelBatch">{{ t('system.user.batchModalCancel') }}</a-button>
|
||||
<a-button type="primary" @click="confirmBatch">
|
||||
{{ t('system.user.batchModalConfirm') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
interface TreeDataItem {
|
||||
key: string;
|
||||
title: string;
|
||||
children?: TreeDataItem[];
|
||||
}
|
||||
|
||||
interface TransferDataItem {
|
||||
value: string;
|
||||
label: string;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
tableSelected: (string | number)[];
|
||||
visible: boolean;
|
||||
action: string;
|
||||
treeData: TreeDataItem[];
|
||||
}>(),
|
||||
{
|
||||
visible: false,
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(['update:visible']);
|
||||
|
||||
const showBatchModal = ref(false);
|
||||
const batchLoading = ref(false);
|
||||
const batchTitle = ref('');
|
||||
const target = ref<string[]>([]);
|
||||
const batchModalMode = ref<'project' | 'usergroup' | 'organization'>('project');
|
||||
|
||||
function handelTableBatch(action: string) {
|
||||
switch (action) {
|
||||
case 'batchAddProject':
|
||||
batchModalMode.value = 'project';
|
||||
batchTitle.value = t('system.user.batchAddProject');
|
||||
break;
|
||||
case 'batchAddUsergroup':
|
||||
batchModalMode.value = 'usergroup';
|
||||
batchTitle.value = t('system.user.batchAddUsergroup');
|
||||
break;
|
||||
case 'batchAddOrgnization':
|
||||
batchModalMode.value = 'organization';
|
||||
batchTitle.value = t('system.user.batchAddOrgnization');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
showBatchModal.value = true;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
if (val) {
|
||||
handelTableBatch(props.action);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => showBatchModal.value,
|
||||
(val) => {
|
||||
emit('update:visible', val);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取穿梭框数据,根据树结构获取
|
||||
* @param _treeData 树结构
|
||||
* @param transferDataSource 穿梭框数组
|
||||
*/
|
||||
const getTransferData = (_treeData: TreeDataItem[], transferDataSource: TransferDataItem[]) => {
|
||||
_treeData.forEach((item) => {
|
||||
if (item.children) getTransferData(item.children, transferDataSource);
|
||||
else transferDataSource.push({ label: item.title, value: item.key, disabled: false });
|
||||
});
|
||||
return transferDataSource;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取树结构数据,根据穿梭框过滤的数据获取
|
||||
*/
|
||||
const getTreeData = (data: TransferDataItem[]) => {
|
||||
const values = data.map((item) => item.value);
|
||||
|
||||
const travel = (_treeData: TreeDataItem[]) => {
|
||||
const treeDataSource: TreeDataItem[] = [];
|
||||
_treeData.forEach((item) => {
|
||||
// 需要判断当前父节点下的子节点是否全部选中,若选中则不会 push 进穿梭框数组内,否则会出现空的节点无法选中
|
||||
const allSelected = item.children?.every((child) => target.value.includes(child.key));
|
||||
if (!allSelected && (item.children || values.includes(item.key))) {
|
||||
treeDataSource.push({
|
||||
title: item.title,
|
||||
key: item.key,
|
||||
children: item.children ? travel(item.children) : [],
|
||||
});
|
||||
}
|
||||
});
|
||||
return treeDataSource;
|
||||
};
|
||||
|
||||
return travel(props.treeData);
|
||||
};
|
||||
|
||||
const transferData = getTransferData(props.treeData, []);
|
||||
|
||||
function cancelBatch() {
|
||||
showBatchModal.value = false;
|
||||
target.value = [];
|
||||
}
|
||||
|
||||
async function batchAddProject() {}
|
||||
async function batchAddUsergroup() {}
|
||||
async function batchAddOrgnization() {}
|
||||
|
||||
async function confirmBatch() {
|
||||
batchLoading.value = true;
|
||||
try {
|
||||
switch (batchModalMode.value) {
|
||||
case 'project':
|
||||
await batchAddProject();
|
||||
break;
|
||||
case 'usergroup':
|
||||
await batchAddUsergroup();
|
||||
break;
|
||||
case 'organization':
|
||||
await batchAddOrgnization();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Message.success(t('system.user.batchModalSuccess'));
|
||||
showBatchModal.value = false;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
batchLoading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
|
@ -2,7 +2,7 @@
|
|||
<div class="p-6">
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<div>
|
||||
<a-button class="mr-3" type="primary" @click="showUserModal('batch')">{{
|
||||
<a-button class="mr-3" type="primary" @click="showUserModal('create')">{{
|
||||
t('system.user.createUser')
|
||||
}}</a-button>
|
||||
<a-button class="mr-3" type="outline" @click="showEmailInviteModal">{{
|
||||
|
@ -10,18 +10,68 @@
|
|||
}}</a-button>
|
||||
<a-button class="mr-3" type="outline" @click="showImportModal">{{ t('system.user.importUser') }}</a-button>
|
||||
</div>
|
||||
<div>
|
||||
<a-input-search
|
||||
:placeholder="t('system.user.searchUser')"
|
||||
class="w-[230px]"
|
||||
@search="searchUser"
|
||||
></a-input-search>
|
||||
</div>
|
||||
<a-input-search
|
||||
:placeholder="t('system.user.searchUser')"
|
||||
class="w-[230px]"
|
||||
@search="searchUser"
|
||||
></a-input-search>
|
||||
</div>
|
||||
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||
<ms-base-table
|
||||
v-bind="propsRes"
|
||||
:action-config="tableBatchActions"
|
||||
v-on="propsEvent"
|
||||
@selected-change="handleTableSelect"
|
||||
@batch-action="handelTableBatch"
|
||||
>
|
||||
<template #organization="{ record }">
|
||||
<a-tag
|
||||
v-for="org of record.organizationList.slice(0, 2)"
|
||||
:key="org.id"
|
||||
class="mr-[4px] bg-transparent"
|
||||
bordered
|
||||
>
|
||||
{{ org.name }}
|
||||
</a-tag>
|
||||
<a-tag v-show="record.organizationList.length > 2" class="mr-[4px] bg-transparent" bordered>
|
||||
+{{ record.organizationList.length - 2 }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #userRole="{ record }">
|
||||
<a-tag
|
||||
v-for="org of record.userRoleList.slice(0, 2)"
|
||||
:key="org.id"
|
||||
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
||||
bordered
|
||||
>
|
||||
{{ org.name }}
|
||||
</a-tag>
|
||||
<a-tag
|
||||
v-show="record.organizationList.length > 2"
|
||||
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
||||
bordered
|
||||
>
|
||||
+{{ record.organizationList.length - 2 }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #enable="{ record }">
|
||||
<div v-if="record.enable" class="flex items-center">
|
||||
<icon-check-circle-fill class="mr-[2px] text-[rgb(var(--success-6))]" />
|
||||
{{ t('system.user.tableEnable') }}
|
||||
</div>
|
||||
<div v-else class="flex items-center text-[var(--color-text-4)]">
|
||||
<icon-stop class="mr-[2px]" />
|
||||
{{ t('system.user.tableDisable') }}
|
||||
</div>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<MsButton @click="showUserModal('edit')">{{ t('system.user.editUser') }}</MsButton>
|
||||
<MsTableMoreAction :list="tableActions" @select="handleSelect($event, record)"></MsTableMoreAction>
|
||||
<template v-if="!record.enable">
|
||||
<MsButton @click="enableUser(record)">{{ t('system.user.enable') }}</MsButton>
|
||||
<MsButton @click="deleteUser(record)">{{ t('system.user.delete') }}</MsButton>
|
||||
</template>
|
||||
<template v-else>
|
||||
<MsButton @click="showUserModal('edit', record)">{{ t('system.user.editUser') }}</MsButton>
|
||||
<MsTableMoreAction :list="tableActions" @select="handleSelect($event, record)"></MsTableMoreAction>
|
||||
</template>
|
||||
</template>
|
||||
</ms-base-table>
|
||||
<a-modal
|
||||
|
@ -102,7 +152,7 @@
|
|||
</template>
|
||||
</div>
|
||||
</a-scrollbar>
|
||||
<div class="w-full">
|
||||
<div v-if="userFormMode === 'create'" class="w-full">
|
||||
<a-button class="px-0" type="text" @click="addUserField">
|
||||
<template #icon>
|
||||
<icon-plus class="text-[14px]" />
|
||||
|
@ -124,7 +174,7 @@
|
|||
</a-form>
|
||||
<template #footer>
|
||||
<a-button type="secondary" @click="cancelCreate">{{ t('system.user.editUserModalCancelCreate') }}</a-button>
|
||||
<a-button v-if="userFormMode === 'batch'" type="secondary" @click="saveAndContinue">{{
|
||||
<a-button v-if="userFormMode === 'create'" type="secondary" @click="saveAndContinue">{{
|
||||
t('system.user.editUserModalSaveAndContinue')
|
||||
}}</a-button>
|
||||
<a-button type="primary" @click="beforeCreateUser">{{
|
||||
|
@ -187,26 +237,90 @@
|
|||
</div>
|
||||
</template>
|
||||
</a-upload>
|
||||
<template #footer>
|
||||
<a-button type="secondary" @click="cancelImport">{{ t('system.user.importModalCancel') }}</a-button>
|
||||
<a-button type="primary" @click="importUser">
|
||||
{{ t('system.user.importModalConfirm') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
<a-modal v-model:visible="importResultVisible" title-align="start" class="ms-modal-upload">
|
||||
<template #title>
|
||||
<icon-exclamation-circle-fill
|
||||
v-if="importResult === 'fail'"
|
||||
class="mr-[8px] text-[20px] text-[rgb(var(--warning-6))]"
|
||||
/>
|
||||
<icon-close-circle-fill
|
||||
v-if="importResult === 'allFail'"
|
||||
class="mr-[8px] text-[20px] text-[rgb(var(--danger-6))]"
|
||||
/>
|
||||
{{ importResultTitle }}
|
||||
</template>
|
||||
<div v-if="importResult === 'success'" class="flex flex-col items-center justify-center">
|
||||
<icon-check-circle-fill class="text-[32px] text-[rgb(var(--success-6))]" />
|
||||
<div class="mb-[8px] mt-[16px] text-[16px] font-medium text-[var(--color-text-000)]">{{
|
||||
t('system.user.importSuccess')
|
||||
}}</div>
|
||||
<div class="sub-text">{{
|
||||
`${t('system.user.importResultContentStart')} ${importSuccessCount} ${t(
|
||||
'system.user.importResultContentEnd'
|
||||
)}`
|
||||
}}</div>
|
||||
</div>
|
||||
<template v-else>
|
||||
<div>{{
|
||||
`${t('system.user.importResultContentStart')} ${importSuccessCount} ${t(
|
||||
'system.user.importResultContentCenter'
|
||||
)} ${importFailCount} ${t('system.user.importResultContentEnd')};`
|
||||
}}</div>
|
||||
<div
|
||||
>{{ t('system.user.importResultContentSubStart')
|
||||
}}<a-link
|
||||
class="text-[rgb(var(--primary-5))]"
|
||||
:href="importErrorFileUrl"
|
||||
:download="`${t('system.user.importErrorFile')}.pdf`"
|
||||
>{{ t('system.user.importResultContentDownload') }}</a-link
|
||||
>{{ t('system.user.importResultContentSubEnd') }}</div
|
||||
>
|
||||
</template>
|
||||
<template #footer>
|
||||
<a-button type="text" class="!text-[var(--color-text-1)]" @click="cancelImport">{{
|
||||
t('system.user.importResultReturn')
|
||||
}}</a-button>
|
||||
<a-button type="text" @click="continueImport">
|
||||
{{ t('system.user.importResultContinue') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
<batchModal
|
||||
v-model:visible="showBatchModal"
|
||||
:table-selected="tableSelected"
|
||||
:action="batchAction"
|
||||
:tree-data="treeData"
|
||||
></batchModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||
import { getTableList } from '@/api/modules/api-test/index';
|
||||
import { getUserList, batchCreateUser, updateUserInfo } from '@/api/modules/system/user';
|
||||
import { validateEmail, validatePhone } from '@/utils/validate';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import batchModal from './components/batchModal.vue';
|
||||
|
||||
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||
import type { UserListItem } from '@/models/system/user';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const columns: MsTableColumn = [
|
||||
{
|
||||
|
@ -224,25 +338,45 @@
|
|||
},
|
||||
{
|
||||
title: '组织',
|
||||
dataIndex: 'organization',
|
||||
slotName: 'organization',
|
||||
dataIndex: 'organizationList',
|
||||
},
|
||||
{
|
||||
title: '用户组',
|
||||
dataIndex: 'userGroup',
|
||||
slotName: 'userRole',
|
||||
dataIndex: 'userRoleList',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
slotName: 'enable',
|
||||
dataIndex: 'enable',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slotName: 'action',
|
||||
fixed: 'right',
|
||||
width: 80,
|
||||
width: 90,
|
||||
},
|
||||
];
|
||||
|
||||
const { t } = useI18n();
|
||||
const { propsRes, propsEvent, loadList, setKeyword } = useTable(getUserList, {
|
||||
columns,
|
||||
scroll: { y: 'auto' },
|
||||
selectable: true,
|
||||
});
|
||||
|
||||
const keyword = ref('');
|
||||
|
||||
onMounted(async () => {
|
||||
setKeyword(keyword.value);
|
||||
await loadList();
|
||||
});
|
||||
|
||||
async function searchUser() {
|
||||
setKeyword(keyword.value);
|
||||
await loadList();
|
||||
}
|
||||
|
||||
const tableActions: ActionsItem[] = [
|
||||
{
|
||||
label: 'system.user.resetPassword',
|
||||
|
@ -262,8 +396,96 @@
|
|||
},
|
||||
];
|
||||
|
||||
const tableBatchActions = {
|
||||
baseAction: [
|
||||
{
|
||||
label: 'system.user.batchActionAddProject',
|
||||
eventTag: 'batchAddProject',
|
||||
},
|
||||
{
|
||||
label: 'system.user.batchActionAddUsergroup',
|
||||
eventTag: 'batchAddUsergroup',
|
||||
},
|
||||
{
|
||||
label: 'system.user.batchActionAddOrgnization',
|
||||
eventTag: 'batchAddOrgnization',
|
||||
},
|
||||
],
|
||||
moreAction: [
|
||||
{
|
||||
label: 'system.user.disable',
|
||||
eventTag: 'disabled',
|
||||
},
|
||||
{
|
||||
label: 'system.user.enable',
|
||||
eventTag: 'enable',
|
||||
},
|
||||
{
|
||||
isDivider: true,
|
||||
},
|
||||
{
|
||||
label: 'system.user.delete',
|
||||
eventTag: 'delete',
|
||||
danger: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const showBatchModal = ref(false);
|
||||
const batchAction = ref('');
|
||||
const treeData = ref([
|
||||
{
|
||||
title: 'Trunk 0-3',
|
||||
key: '0-3',
|
||||
},
|
||||
{
|
||||
title: 'Trunk 0-0',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{
|
||||
title: 'Leaf 0-0-1',
|
||||
key: '0-0-1',
|
||||
},
|
||||
{
|
||||
title: 'Branch 0-0-2',
|
||||
key: '0-0-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Trunk 0-1',
|
||||
key: '0-1',
|
||||
children: [
|
||||
{
|
||||
title: 'Branch 0-1-1',
|
||||
key: '0-1-1',
|
||||
},
|
||||
{
|
||||
title: 'Leaf 0-1-2',
|
||||
key: '0-1-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
function handelTableBatch() {
|
||||
batchAction.value = 'batchAddProject';
|
||||
showBatchModal.value = true;
|
||||
}
|
||||
|
||||
const tableSelected = ref<(string | number)[]>([]);
|
||||
|
||||
/**
|
||||
* 处理表格选中
|
||||
*/
|
||||
function handleTableSelect(arr: (string | number)[]) {
|
||||
tableSelected.value = arr;
|
||||
}
|
||||
const { openModal } = useModal();
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*/
|
||||
function resetPassword(record: any) {
|
||||
openModal({
|
||||
type: 'warning',
|
||||
|
@ -284,6 +506,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用用户
|
||||
*/
|
||||
function disabledUser(record: any) {
|
||||
openModal({
|
||||
type: 'warning',
|
||||
|
@ -291,6 +516,9 @@
|
|||
content: t('system.user.disableUserContent'),
|
||||
okText: t('system.user.disableUserConfirm'),
|
||||
cancelText: t('system.user.disableUserCancel'),
|
||||
okButtonProps: {
|
||||
status: 'danger',
|
||||
},
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
Message.success(t('system.user.disableUserSuccess'));
|
||||
|
@ -304,6 +532,32 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用用户
|
||||
*/
|
||||
function enableUser(record: any) {
|
||||
openModal({
|
||||
type: 'info',
|
||||
title: `${t('system.user.enableUserStart')} '${record.name}' ${t('system.user.enableUserEnd')}`,
|
||||
content: t('system.user.enableUserContent'),
|
||||
okText: t('system.user.enableUserConfirm'),
|
||||
cancelText: t('system.user.enableUserCancel'),
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
Message.success(t('system.user.enableUserSuccess'));
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
hideCancel: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
function deleteUser(record: any) {
|
||||
openModal({
|
||||
type: 'warning',
|
||||
|
@ -327,6 +581,10 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理表格更多按钮事件
|
||||
* @param item
|
||||
*/
|
||||
function handleSelect(item: ActionsItem, record: any) {
|
||||
switch (item.eventTag) {
|
||||
case 'resetPassword':
|
||||
|
@ -343,16 +601,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
const { propsRes, propsEvent, loadList } = useTable(getTableList, {
|
||||
columns,
|
||||
selectable: true,
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await loadList();
|
||||
});
|
||||
|
||||
type UserModalMode = 'create' | 'edit' | 'batch';
|
||||
type UserModalMode = 'create' | 'edit';
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
const userFormMode = ref<UserModalMode>('create');
|
||||
|
@ -387,6 +636,10 @@
|
|||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* 触发创建用户表单校验
|
||||
* @param cb 校验通过后执行回调
|
||||
*/
|
||||
function userFormValidate(cb: () => Promise<any>) {
|
||||
userFormRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
||||
if (errors) {
|
||||
|
@ -403,17 +656,25 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户表单项
|
||||
*/
|
||||
function addUserField() {
|
||||
userFormValidate(async () => {
|
||||
const lastIndex = userForm.value.list.length - 1;
|
||||
const lastOrder = userForm.value.list[lastIndex] + 1;
|
||||
userForm.value.list.push(lastOrder); // 序号自增
|
||||
userForm.value.list.push(lastOrder); // 序号自增,不会因为删除而重复
|
||||
userForm.value[`username${lastOrder}`] = '';
|
||||
userForm.value[`email${lastOrder}`] = '';
|
||||
userForm.value[`phone${lastOrder}`] = '';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除用户表单项
|
||||
* @param index 表单项的序号
|
||||
* @param i 表单项对应 list 的下标
|
||||
*/
|
||||
function removeUserField(index: number, i: number) {
|
||||
delete userForm.value[`username${index}`];
|
||||
delete userForm.value[`email${index}`];
|
||||
|
@ -421,6 +682,11 @@
|
|||
userForm.value.list.splice(i, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户姓名
|
||||
* @param value 输入的值
|
||||
* @param callback 失败回调,入参是提示信息
|
||||
*/
|
||||
function checkUerName(value: string | undefined, callback: (error?: string) => void) {
|
||||
if (value === '' || value === undefined) {
|
||||
callback(t('system.user.createUserNameNotNull'));
|
||||
|
@ -429,6 +695,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户邮箱
|
||||
* @param value 输入的值
|
||||
* @param callback 失败回调,入参是提示信息
|
||||
* @param index 当前输入的表单项对应 list 的下标,用于校验重复输入的时候排除自身
|
||||
*/
|
||||
function checkUerEmail(value: string | undefined, callback: (error?: string) => void, index: number) {
|
||||
if (value === '' || value === undefined) {
|
||||
callback(t('system.user.createUserEmailNotNull'));
|
||||
|
@ -447,12 +719,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户手机号
|
||||
* @param value 输入的值
|
||||
* @param callback 失败回调,入参是提示信息
|
||||
*/
|
||||
function checkUerPhone(value: string | undefined, callback: (error?: string) => void) {
|
||||
if (value !== '' && value !== undefined && !validatePhone(value)) {
|
||||
callback(t('system.user.createUserPhoneErr'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消创建,重置用户表单
|
||||
*/
|
||||
function cancelCreate() {
|
||||
visible.value = false;
|
||||
userFormRef.value?.resetFields();
|
||||
|
@ -460,13 +740,36 @@
|
|||
}
|
||||
|
||||
async function updateUser() {
|
||||
console.log('updateUser');
|
||||
const params = {
|
||||
userInfoList: [
|
||||
{
|
||||
name: userForm.value.username0,
|
||||
email: userForm.value.email0,
|
||||
phone: userForm.value.phone0,
|
||||
},
|
||||
],
|
||||
userRoleIdList: userForm.value.userGroup,
|
||||
};
|
||||
await updateUserInfo(params);
|
||||
}
|
||||
|
||||
async function createUser() {
|
||||
console.log('createUser');
|
||||
const params = {
|
||||
userInfoList: userForm.value.list.map((item: number) => {
|
||||
return {
|
||||
name: userForm.value[`username${item}`],
|
||||
email: userForm.value[`email${item}`],
|
||||
phone: userForm.value[`phone${item}`],
|
||||
};
|
||||
}),
|
||||
userRoleIdList: [],
|
||||
};
|
||||
await batchCreateUser(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建前的校验
|
||||
*/
|
||||
function beforeCreateUser() {
|
||||
if (userFormMode.value === 'create') {
|
||||
userFormValidate(createUser);
|
||||
|
@ -475,6 +778,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存并继续创建,重置用户表单
|
||||
*/
|
||||
function saveAndContinue() {
|
||||
userFormValidate(async () => {
|
||||
await createUser();
|
||||
|
@ -483,9 +789,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
function showUserModal(mode: UserModalMode) {
|
||||
function showUserModal(mode: UserModalMode, record?: UserListItem) {
|
||||
visible.value = true;
|
||||
userFormMode.value = mode;
|
||||
if (mode === 'edit' && record) {
|
||||
userForm.value.username0 = record.name;
|
||||
userForm.value.email0 = record.email;
|
||||
userForm.value.phone0 = record.phone;
|
||||
userForm.value.userGroup = record.userRoleList.map((e) => e.name);
|
||||
}
|
||||
}
|
||||
|
||||
const inviteVisible = ref(false);
|
||||
|
@ -513,14 +825,55 @@
|
|||
|
||||
const importVisible = ref(false);
|
||||
const importLoading = ref(false);
|
||||
const importResultVisible = ref(false);
|
||||
const importSuccessCount = ref(0);
|
||||
const importFailCount = ref(0);
|
||||
const importErrorFileUrl = ref('');
|
||||
const importResult = ref<'success' | 'allFail' | 'fail'>('success');
|
||||
const importResultTitle = ref(t('system.user.importSuccessTitle'));
|
||||
|
||||
function showImportModal() {
|
||||
importVisible.value = true;
|
||||
}
|
||||
|
||||
function importUser() {}
|
||||
function cancelImport() {
|
||||
importVisible.value = false;
|
||||
importResultVisible.value = false;
|
||||
}
|
||||
|
||||
async function searchUser() {}
|
||||
/**
|
||||
* 根据导入结果展示结果弹窗
|
||||
*/
|
||||
function showImportResult() {
|
||||
importLoading.value = false;
|
||||
importVisible.value = false;
|
||||
switch (importResult.value) {
|
||||
case 'success':
|
||||
importResultTitle.value = t('system.user.importSuccessTitle');
|
||||
break;
|
||||
case 'allFail':
|
||||
importResultTitle.value = t('system.user.importAllfailTitle');
|
||||
break;
|
||||
case 'fail':
|
||||
importResultTitle.value = t('system.user.importFailTitle');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
importResultVisible.value = true;
|
||||
}
|
||||
|
||||
function continueImport() {
|
||||
importResultVisible.value = false;
|
||||
importVisible.value = true;
|
||||
}
|
||||
|
||||
function importUser() {
|
||||
importResult.value = 'fail';
|
||||
importSuccessCount.value = 100;
|
||||
importFailCount.value = 20;
|
||||
showImportResult();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
Loading…
Reference in New Issue