feat(用户管理): 新增用户管理页面
- 实现用户列表展示功能 - 添加用户搜索和筛选 - 集成表格分页组件 - 支持用户查看、编辑、删除操作
This commit is contained in:
parent
d5dcd6780c
commit
a44b06cc15
117
src/pages/user-management/constants.tsx
Normal file
117
src/pages/user-management/constants.tsx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Button, Typography, Badge, Space } from '@arco-design/web-react';
|
||||||
|
import { IconEye, IconEdit, IconDelete } from '@arco-design/web-react/icon';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const { Text } = Typography;
|
||||||
|
|
||||||
|
export const RoleType = ['管理员', '普通用户', '访客'];
|
||||||
|
export const Status = ['禁用', '启用'];
|
||||||
|
|
||||||
|
export function getColumns(
|
||||||
|
t: any,
|
||||||
|
callback: (record: Record<string, any>, type: string) => Promise<void>
|
||||||
|
) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.id'],
|
||||||
|
dataIndex: 'id',
|
||||||
|
width: 100,
|
||||||
|
render: (value) => <Text copyable>{value}</Text>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.name'],
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.username'],
|
||||||
|
dataIndex: 'username',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.email'],
|
||||||
|
dataIndex: 'email',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.phone'],
|
||||||
|
dataIndex: 'phone',
|
||||||
|
width: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.role'],
|
||||||
|
dataIndex: 'role',
|
||||||
|
width: 100,
|
||||||
|
render: (value) => {
|
||||||
|
const roleMap = {
|
||||||
|
0: { text: t['userManagement.role.admin'], color: 'red' },
|
||||||
|
1: { text: t['userManagement.role.user'], color: 'blue' },
|
||||||
|
2: { text: t['userManagement.role.guest'], color: 'gray' },
|
||||||
|
};
|
||||||
|
const role = roleMap[value] || roleMap[1];
|
||||||
|
return <Badge color={role.color} text={role.text} />;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.department'],
|
||||||
|
dataIndex: 'department',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.createdTime'],
|
||||||
|
dataIndex: 'createdTime',
|
||||||
|
width: 180,
|
||||||
|
render: (x) => dayjs().subtract(x, 'days').format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
sorter: (a, b) => b.createdTime - a.createdTime,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.status'],
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 100,
|
||||||
|
render: (x) => {
|
||||||
|
if (x === 0) {
|
||||||
|
return <Badge status="error" text={Status[x]}></Badge>;
|
||||||
|
}
|
||||||
|
return <Badge status="success" text={Status[x]}></Badge>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['userManagement.columns.operations'],
|
||||||
|
dataIndex: 'operations',
|
||||||
|
width: 240,
|
||||||
|
fixed: 'right' as const,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<IconEye />}
|
||||||
|
onClick={() => callback(record, 'view')}
|
||||||
|
>
|
||||||
|
{t['userManagement.columns.operations.view']}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<IconEdit />}
|
||||||
|
onClick={() => callback(record, 'edit')}
|
||||||
|
>
|
||||||
|
{t['userManagement.columns.operations.edit']}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
status="danger"
|
||||||
|
icon={<IconDelete />}
|
||||||
|
onClick={() => callback(record, 'delete')}
|
||||||
|
>
|
||||||
|
{t['userManagement.columns.operations.delete']}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => RoleType;
|
||||||
160
src/pages/user-management/form.tsx
Normal file
160
src/pages/user-management/form.tsx
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
DatePicker,
|
||||||
|
Button,
|
||||||
|
Grid,
|
||||||
|
} from '@arco-design/web-react';
|
||||||
|
import { GlobalContext } from '@/context';
|
||||||
|
import locale from './locale';
|
||||||
|
import useLocale from '@/utils/useLocale';
|
||||||
|
import { IconRefresh, IconSearch } from '@arco-design/web-react/icon';
|
||||||
|
import { RoleType, Status } from './constants';
|
||||||
|
import styles from './style/index.module.less';
|
||||||
|
|
||||||
|
const { Row, Col } = Grid;
|
||||||
|
const { useForm } = Form;
|
||||||
|
|
||||||
|
function SearchForm(props: {
|
||||||
|
onSearch: (values: Record<string, any>) => void;
|
||||||
|
}) {
|
||||||
|
const { lang } = useContext(GlobalContext);
|
||||||
|
|
||||||
|
const t = useLocale(locale);
|
||||||
|
const [form] = useForm();
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
const values = form.getFieldsValue();
|
||||||
|
props.onSearch(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
form.resetFields();
|
||||||
|
props.onSearch({});
|
||||||
|
};
|
||||||
|
|
||||||
|
const colSpan = lang === 'zh-CN' ? 8 : 12;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles['search-form-wrapper']}>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
className={styles['search-form']}
|
||||||
|
labelAlign="left"
|
||||||
|
labelCol={{ span: 5 }}
|
||||||
|
wrapperCol={{ span: 19 }}
|
||||||
|
>
|
||||||
|
<Row gutter={24}>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item label={t['userManagement.columns.id']} field="id">
|
||||||
|
<Input
|
||||||
|
placeholder={t['userManagement.form.id.placeholder']}
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item label={t['userManagement.columns.name']} field="name">
|
||||||
|
<Input
|
||||||
|
allowClear
|
||||||
|
placeholder={t['userManagement.form.name.placeholder']}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item
|
||||||
|
label={t['userManagement.columns.username']}
|
||||||
|
field="username"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
allowClear
|
||||||
|
placeholder={t['userManagement.form.username.placeholder']}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item label={t['userManagement.columns.email']} field="email">
|
||||||
|
<Input
|
||||||
|
allowClear
|
||||||
|
placeholder={t['userManagement.form.email.placeholder']}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item label={t['userManagement.columns.phone']} field="phone">
|
||||||
|
<Input
|
||||||
|
allowClear
|
||||||
|
placeholder={t['userManagement.form.phone.placeholder']}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item label={t['userManagement.columns.role']} field="role">
|
||||||
|
<Select
|
||||||
|
placeholder={t['userManagement.form.all.placeholder']}
|
||||||
|
options={RoleType.map((item, index) => ({
|
||||||
|
label: item,
|
||||||
|
value: index,
|
||||||
|
}))}
|
||||||
|
mode="multiple"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item
|
||||||
|
label={t['userManagement.columns.department']}
|
||||||
|
field="department"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
allowClear
|
||||||
|
placeholder={t['userManagement.form.department.placeholder']}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item
|
||||||
|
label={t['userManagement.columns.status']}
|
||||||
|
field="status"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder={t['userManagement.form.all.placeholder']}
|
||||||
|
options={Status.map((item, index) => ({
|
||||||
|
label: item,
|
||||||
|
value: index,
|
||||||
|
}))}
|
||||||
|
mode="multiple"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={colSpan}>
|
||||||
|
<Form.Item
|
||||||
|
label={t['userManagement.columns.createdTime']}
|
||||||
|
field="createdTime"
|
||||||
|
>
|
||||||
|
<DatePicker.RangePicker
|
||||||
|
allowClear
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
disabledDate={(date) => dayjs(date).isAfter(dayjs())}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form>
|
||||||
|
<div className={styles['right-button']}>
|
||||||
|
<Button type="primary" icon={<IconSearch />} onClick={handleSubmit}>
|
||||||
|
{t['userManagement.form.search']}
|
||||||
|
</Button>
|
||||||
|
<Button icon={<IconRefresh />} onClick={handleReset}>
|
||||||
|
{t['userManagement.form.reset']}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SearchForm;
|
||||||
171
src/pages/user-management/index.tsx
Normal file
171
src/pages/user-management/index.tsx
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import React, { useState, useEffect, useMemo } from 'react';
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
Card,
|
||||||
|
PaginationProps,
|
||||||
|
Button,
|
||||||
|
Space,
|
||||||
|
Typography,
|
||||||
|
Message,
|
||||||
|
} from '@arco-design/web-react';
|
||||||
|
import PermissionWrapper from '@/components/PermissionWrapper';
|
||||||
|
import Pagination from '@/components/Pagination';
|
||||||
|
import {
|
||||||
|
IconDownload,
|
||||||
|
IconPlus,
|
||||||
|
IconDelete,
|
||||||
|
} from '@arco-design/web-react/icon';
|
||||||
|
import axios from 'axios';
|
||||||
|
import useLocale from '@/utils/useLocale';
|
||||||
|
import SearchForm from './form';
|
||||||
|
import locale from './locale';
|
||||||
|
import styles from './style/index.module.less';
|
||||||
|
import './mock';
|
||||||
|
import { getColumns } from './constants';
|
||||||
|
|
||||||
|
const { Title } = Typography;
|
||||||
|
|
||||||
|
function UserManagement() {
|
||||||
|
const t = useLocale(locale);
|
||||||
|
|
||||||
|
const tableCallback = async (record, type) => {
|
||||||
|
console.log(record, type);
|
||||||
|
|
||||||
|
// 简单的操作提示
|
||||||
|
if (type === 'view') {
|
||||||
|
Message.info(`查看用户: ${record.name}`);
|
||||||
|
} else if (type === 'edit') {
|
||||||
|
Message.info(`编辑用户: ${record.name}`);
|
||||||
|
} else if (type === 'delete') {
|
||||||
|
Message.warning(`删除用户: ${record.name}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = useMemo(() => getColumns(t, tableCallback), [t]);
|
||||||
|
|
||||||
|
const [data, setData] = useState([]);
|
||||||
|
const [pagination, setPagination] = useState<PaginationProps>({
|
||||||
|
sizeCanChange: true,
|
||||||
|
showTotal: true,
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1,
|
||||||
|
pageSizeChangeResetCurrent: true,
|
||||||
|
});
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [formParams, setFormParams] = useState({});
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchData();
|
||||||
|
}, [pagination.current, pagination.pageSize, JSON.stringify(formParams)]);
|
||||||
|
|
||||||
|
function fetchData() {
|
||||||
|
const { current, pageSize } = pagination;
|
||||||
|
setLoading(true);
|
||||||
|
axios
|
||||||
|
.get('/api/user-management', {
|
||||||
|
params: {
|
||||||
|
page: current,
|
||||||
|
pageSize,
|
||||||
|
...formParams,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
setData(res.data.list);
|
||||||
|
setPagination({
|
||||||
|
...pagination,
|
||||||
|
current,
|
||||||
|
pageSize,
|
||||||
|
total: res.data.total,
|
||||||
|
});
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChangeTable(current: number, pageSize: number) {
|
||||||
|
setPagination({
|
||||||
|
...pagination,
|
||||||
|
current,
|
||||||
|
pageSize,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSearch(params) {
|
||||||
|
setPagination({ ...pagination, current: 1 });
|
||||||
|
setFormParams(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
Message.info(t['userManagement.operations.add']);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBatchDelete() {
|
||||||
|
if (selectedRowKeys.length === 0) {
|
||||||
|
Message.warning('请选择要删除的用户');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Message.warning(`批量删除 ${selectedRowKeys.length} 个用户`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleExport() {
|
||||||
|
Message.info(t['userManagement.operations.export']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<Title heading={6}>{t['menu.list.userManagement']}</Title>
|
||||||
|
<SearchForm onSearch={handleSearch} />
|
||||||
|
<PermissionWrapper
|
||||||
|
requiredPermissions={[
|
||||||
|
{ resource: 'menu.list.userManagement', actions: ['write'] },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<div className={styles['button-group']}>
|
||||||
|
<Space>
|
||||||
|
<Button type="primary" icon={<IconPlus />} onClick={handleAdd}>
|
||||||
|
{t['userManagement.operations.add']}
|
||||||
|
</Button>
|
||||||
|
<Button icon={<IconDelete />} onClick={handleBatchDelete}>
|
||||||
|
{t['userManagement.operations.batchDelete']}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
<Space>
|
||||||
|
<Button icon={<IconDownload />} onClick={handleExport}>
|
||||||
|
{t['userManagement.operations.export']}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
</PermissionWrapper>
|
||||||
|
<Table
|
||||||
|
rowKey="id"
|
||||||
|
loading={loading}
|
||||||
|
pagination={false}
|
||||||
|
columns={columns}
|
||||||
|
data={data}
|
||||||
|
rowSelection={{
|
||||||
|
type: 'checkbox',
|
||||||
|
selectedRowKeys,
|
||||||
|
onChange: (selectedRowKeys) => {
|
||||||
|
setSelectedRowKeys(selectedRowKeys);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
scroll={{ x: 1640 }}
|
||||||
|
/>
|
||||||
|
<Pagination
|
||||||
|
total={pagination.total}
|
||||||
|
current={pagination.current}
|
||||||
|
pageSize={pagination.pageSize}
|
||||||
|
sizeCanChange={pagination.sizeCanChange}
|
||||||
|
onChange={onChangeTable}
|
||||||
|
onPageSizeChange={(pageSize) => {
|
||||||
|
setPagination({ ...pagination, current: 1, pageSize });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserManagement;
|
||||||
74
src/pages/user-management/locale/index.ts
Normal file
74
src/pages/user-management/locale/index.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
const i18n = {
|
||||||
|
'en-US': {
|
||||||
|
'menu.list.userManagement': 'User Management',
|
||||||
|
'userManagement.form.search': 'Search',
|
||||||
|
'userManagement.form.reset': 'Reset',
|
||||||
|
'userManagement.columns.id': 'User ID',
|
||||||
|
'userManagement.columns.name': 'Name',
|
||||||
|
'userManagement.columns.username': 'Username',
|
||||||
|
'userManagement.columns.email': 'Email',
|
||||||
|
'userManagement.columns.phone': 'Phone',
|
||||||
|
'userManagement.columns.role': 'Role',
|
||||||
|
'userManagement.columns.department': 'Department',
|
||||||
|
'userManagement.columns.status': 'Status',
|
||||||
|
'userManagement.columns.createdTime': 'Created Time',
|
||||||
|
'userManagement.columns.operations': 'Operations',
|
||||||
|
'userManagement.columns.operations.view': 'View',
|
||||||
|
'userManagement.columns.operations.edit': 'Edit',
|
||||||
|
'userManagement.columns.operations.delete': 'Delete',
|
||||||
|
'userManagement.columns.operations.enable': 'Enable',
|
||||||
|
'userManagement.columns.operations.disable': 'Disable',
|
||||||
|
'userManagement.operations.add': 'Add User',
|
||||||
|
'userManagement.operations.batchDelete': 'Batch Delete',
|
||||||
|
'userManagement.operations.export': 'Export',
|
||||||
|
'userManagement.role.admin': 'Administrator',
|
||||||
|
'userManagement.role.user': 'User',
|
||||||
|
'userManagement.role.guest': 'Guest',
|
||||||
|
'userManagement.status.enabled': 'Enabled',
|
||||||
|
'userManagement.status.disabled': 'Disabled',
|
||||||
|
'userManagement.form.id.placeholder': 'Please enter user ID',
|
||||||
|
'userManagement.form.name.placeholder': 'Please enter name',
|
||||||
|
'userManagement.form.username.placeholder': 'Please enter username',
|
||||||
|
'userManagement.form.email.placeholder': 'Please enter email',
|
||||||
|
'userManagement.form.phone.placeholder': 'Please enter phone',
|
||||||
|
'userManagement.form.department.placeholder': 'Please enter department',
|
||||||
|
'userManagement.form.all.placeholder': 'All',
|
||||||
|
},
|
||||||
|
'zh-CN': {
|
||||||
|
'menu.list.userManagement': '用户管理',
|
||||||
|
'userManagement.form.search': '查询',
|
||||||
|
'userManagement.form.reset': '重置',
|
||||||
|
'userManagement.columns.id': '用户ID',
|
||||||
|
'userManagement.columns.name': '姓名',
|
||||||
|
'userManagement.columns.username': '用户名',
|
||||||
|
'userManagement.columns.email': '邮箱',
|
||||||
|
'userManagement.columns.phone': '手机号',
|
||||||
|
'userManagement.columns.role': '角色',
|
||||||
|
'userManagement.columns.department': '部门',
|
||||||
|
'userManagement.columns.status': '状态',
|
||||||
|
'userManagement.columns.createdTime': '创建时间',
|
||||||
|
'userManagement.columns.operations': '操作',
|
||||||
|
'userManagement.columns.operations.view': '查看',
|
||||||
|
'userManagement.columns.operations.edit': '编辑',
|
||||||
|
'userManagement.columns.operations.delete': '删除',
|
||||||
|
'userManagement.columns.operations.enable': '启用',
|
||||||
|
'userManagement.columns.operations.disable': '禁用',
|
||||||
|
'userManagement.operations.add': '新建用户',
|
||||||
|
'userManagement.operations.batchDelete': '批量删除',
|
||||||
|
'userManagement.operations.export': '导出',
|
||||||
|
'userManagement.role.admin': '管理员',
|
||||||
|
'userManagement.role.user': '普通用户',
|
||||||
|
'userManagement.role.guest': '访客',
|
||||||
|
'userManagement.status.enabled': '启用',
|
||||||
|
'userManagement.status.disabled': '禁用',
|
||||||
|
'userManagement.form.id.placeholder': '请输入用户ID',
|
||||||
|
'userManagement.form.name.placeholder': '请输入姓名',
|
||||||
|
'userManagement.form.username.placeholder': '请输入用户名',
|
||||||
|
'userManagement.form.email.placeholder': '请输入邮箱',
|
||||||
|
'userManagement.form.phone.placeholder': '请输入手机号',
|
||||||
|
'userManagement.form.department.placeholder': '请输入部门',
|
||||||
|
'userManagement.form.all.placeholder': '全部',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default i18n;
|
||||||
134
src/pages/user-management/mock/index.ts
Normal file
134
src/pages/user-management/mock/index.ts
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import Mock from 'mockjs';
|
||||||
|
import qs from 'query-string';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import setupMock from '@/utils/setupMock';
|
||||||
|
|
||||||
|
const { list } = Mock.mock({
|
||||||
|
'list|100': [
|
||||||
|
{
|
||||||
|
id: /[0-9]{8}/,
|
||||||
|
name: () => Mock.Random.cname(),
|
||||||
|
username: () => Mock.Random.word(5, 10),
|
||||||
|
email: () => Mock.Random.email(),
|
||||||
|
phone: /1[3-9]\d{9}/,
|
||||||
|
'role|0-2': 0,
|
||||||
|
department: () =>
|
||||||
|
Mock.Random.pick([
|
||||||
|
'技术部',
|
||||||
|
'产品部',
|
||||||
|
'运营部',
|
||||||
|
'市场部',
|
||||||
|
'人力资源部',
|
||||||
|
'财务部',
|
||||||
|
]),
|
||||||
|
'status|0-1': 0,
|
||||||
|
'createdTime|1-365': 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const filterData = (
|
||||||
|
rest: {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
username?: string;
|
||||||
|
email?: string;
|
||||||
|
phone?: string;
|
||||||
|
'role[]'?: string[];
|
||||||
|
department?: string;
|
||||||
|
'status[]'?: string[];
|
||||||
|
'createdTime[]'?: string[];
|
||||||
|
} = {}
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
phone,
|
||||||
|
'role[]': role,
|
||||||
|
department,
|
||||||
|
'status[]': status,
|
||||||
|
'createdTime[]': createdTime,
|
||||||
|
} = rest;
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
return list.filter((item) => item.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = [...list];
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
result = result.filter((item) => {
|
||||||
|
return (item.name as string).toLowerCase().includes(name.toLowerCase());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username) {
|
||||||
|
result = result.filter((item) => {
|
||||||
|
return (item.username as string)
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(username.toLowerCase());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (email) {
|
||||||
|
result = result.filter((item) => {
|
||||||
|
return (item.email as string).toLowerCase().includes(email.toLowerCase());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phone) {
|
||||||
|
result = result.filter((item) => {
|
||||||
|
return (item.phone as string).includes(phone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role && role.length > 0) {
|
||||||
|
result = result.filter((item) => role.includes(item.role.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (department) {
|
||||||
|
result = result.filter((item) => {
|
||||||
|
return (item.department as string).includes(department);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status && status.length > 0) {
|
||||||
|
result = result.filter((item) => status.includes(item.status.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createdTime && createdTime.length === 2) {
|
||||||
|
const [begin, end] = createdTime;
|
||||||
|
result = result.filter((item) => {
|
||||||
|
const time = dayjs()
|
||||||
|
.subtract(item.createdTime, 'days')
|
||||||
|
.format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
return (
|
||||||
|
!dayjs(time).isBefore(dayjs(begin)) && !dayjs(time).isAfter(dayjs(end))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
setupMock({
|
||||||
|
setup: () => {
|
||||||
|
Mock.mock(new RegExp('/api/user-management'), (params) => {
|
||||||
|
const {
|
||||||
|
page = 1,
|
||||||
|
pageSize = 10,
|
||||||
|
...rest
|
||||||
|
} = qs.parseUrl(params.url).query;
|
||||||
|
const p = page as number;
|
||||||
|
const ps = pageSize as number;
|
||||||
|
|
||||||
|
const result = filterData(rest);
|
||||||
|
return {
|
||||||
|
list: result.slice((p - 1) * ps, p * ps),
|
||||||
|
total: result.length,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
41
src/pages/user-management/style/index.module.less
Normal file
41
src/pages/user-management/style/index.module.less
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
.toolbar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operations {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form-wrapper {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid var(--color-border-1);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.right-button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-left: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-left: 1px solid var(--color-border-2);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
padding-right: 20px;
|
||||||
|
|
||||||
|
:global(.arco-form-label-item-left) {
|
||||||
|
> label {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user