2024-10-13 19:49:48 +08:00
|
|
|
import { useFormReset } from "@/hooks/useFormReset";
|
|
|
|
|
import TemplateContainer from "@/pages/TemplateContainer";
|
|
|
|
|
import { QueryRoleOption } from "@/services/services/role";
|
2025-02-06 15:09:29 +08:00
|
|
|
import { UserInfo } from "@/services/services/user";
|
2024-10-13 19:49:48 +08:00
|
|
|
import { FormatDate } from "@/util/time";
|
|
|
|
|
import { useAccess, useModel } from "@umijs/max";
|
2024-12-27 21:49:11 +08:00
|
|
|
import { Button, Dropdown, Form, Input, InputNumber, message, Modal, Select, SelectProps, Table, Tag, Tooltip } from "antd";
|
2024-10-13 19:49:48 +08:00
|
|
|
import { ColumnsType, TablePaginationConfig } from "antd/es/table";
|
|
|
|
|
import { FilterValue, SorterResult, TableCurrentDataSource } from "antd/es/table/interface";
|
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
import ModifyUser from "../ModifyUser";
|
2025-02-06 15:09:29 +08:00
|
|
|
import Icon, { DeleteOutlined, EditOutlined, KeyOutlined, MenuOutlined, SyncOutlined } from "@ant-design/icons";
|
2024-12-27 21:49:11 +08:00
|
|
|
import { SoftwareControl } from "@/services/services/software";
|
2025-02-06 15:09:29 +08:00
|
|
|
import { CustomIconComponentProps } from "@ant-design/icons/lib/components/Icon";
|
|
|
|
|
import DiceIcon from "@/components/Icon/DiceIcon";
|
|
|
|
|
import { generateRandomPassword } from "@/util/password";
|
|
|
|
|
import ResetUserPassword from "./ResetUserPassword";
|
2024-10-13 19:49:48 +08:00
|
|
|
|
|
|
|
|
const UserManagement: React.FC = () => {
|
|
|
|
|
type TagRender = SelectProps['tagRender'];
|
|
|
|
|
|
|
|
|
|
const { initialState } = useModel('@@initialState');
|
|
|
|
|
const [data, setData] = useState<UserModel.UserCollection[]>(); // 数据
|
|
|
|
|
const [messageApi, messageHolder] = message.useMessage();
|
|
|
|
|
const [form] = Form.useForm();
|
|
|
|
|
const access = useAccess();
|
|
|
|
|
const { setFormRef, resetForm } = useFormReset();
|
|
|
|
|
const [tableParams, setTableParams] = useState<TableModel.TableParams>({
|
|
|
|
|
pagination: {
|
|
|
|
|
current: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
showQuickJumper: true,
|
|
|
|
|
totalBoundaryShowSizeChanger: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
const [loading, setLoading] = useState<boolean>(true);
|
|
|
|
|
const [userId, setUserId] = useState<number>(0);
|
|
|
|
|
const [openModal, setOpenModal] = useState<boolean>(false);
|
|
|
|
|
const [roleNames, setRoleNames] = useState<SelectProps['options']>([]);
|
2025-02-06 15:09:29 +08:00
|
|
|
const [modal, modaltHolder] = Modal.useModal();
|
2024-10-13 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
QueryRoleOption().then((res: string[]) => {
|
|
|
|
|
let temRoleNames = res.filter(item => item !== "Super Admin").map((item) => {
|
|
|
|
|
return {
|
|
|
|
|
value: item
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
setRoleNames(temRoleNames);
|
|
|
|
|
}).catch((error: any) => {
|
|
|
|
|
messageApi.error(error.message);
|
|
|
|
|
})
|
|
|
|
|
|
2025-02-06 15:09:29 +08:00
|
|
|
UserInfo.QueryUserList(tableParams, form.getFieldsValue())
|
2024-10-13 19:49:48 +08:00
|
|
|
.then((res) => {
|
|
|
|
|
setData(res.collection);
|
|
|
|
|
setTableParams({
|
|
|
|
|
pagination: {
|
|
|
|
|
...tableParams.pagination,
|
|
|
|
|
total: res.total
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
setLoading(false);
|
|
|
|
|
})
|
|
|
|
|
.catch((error: any) => {
|
|
|
|
|
messageApi.error(error.message);
|
|
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
})
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
async function QueryUserBasic(params: UserModel.QueryUserParams | null, pagination: TablePaginationConfig | null): Promise<void> {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
try {
|
|
|
|
|
let tableParamsParams = pagination ? { pagination } : tableParams;
|
2025-02-06 15:09:29 +08:00
|
|
|
let res = await UserInfo.QueryUserList(tableParamsParams, params ?? form.getFieldsValue());
|
2024-10-13 19:49:48 +08:00
|
|
|
setData(res.collection);
|
|
|
|
|
setTableParams({
|
|
|
|
|
pagination: {
|
|
|
|
|
...tableParams.pagination,
|
|
|
|
|
total: res.total
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
message.error(error.message);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleTableChange(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>, sorter: SorterResult<UserModel.UserCollection> | SorterResult<UserModel.UserCollection>[], extra: TableCurrentDataSource<UserModel.UserCollection>): Promise<void> {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
try {
|
2025-02-06 15:09:29 +08:00
|
|
|
let queryUser = await UserInfo.QueryUserList({ pagination }, form.getFieldsValue());
|
2024-10-13 19:49:48 +08:00
|
|
|
setData(queryUser.collection);
|
|
|
|
|
setTableParams({
|
|
|
|
|
pagination: {
|
|
|
|
|
...pagination,
|
|
|
|
|
total: queryUser.total
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
message.error(error.message);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function modalCancel(): Promise<void> {
|
|
|
|
|
setOpenModal(false);
|
|
|
|
|
setUserId(0);
|
|
|
|
|
resetForm();
|
|
|
|
|
// 这边调用加载数据的方法
|
|
|
|
|
await QueryUserBasic(null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function QueryUserListByCondition(values: any): Promise<void> {
|
|
|
|
|
await QueryUserBasic(values, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const tagRender: TagRender = (props) => {
|
|
|
|
|
const { label, value, closable, onClose } = props;
|
|
|
|
|
const onPreventMouseDown = (event: React.MouseEvent<HTMLSpanElement>) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
};
|
|
|
|
|
return (
|
|
|
|
|
<Tag
|
|
|
|
|
color="cyan"
|
|
|
|
|
onMouseDown={onPreventMouseDown}
|
|
|
|
|
closable={closable}
|
|
|
|
|
onClose={onClose}
|
|
|
|
|
style={{ marginInlineEnd: 4 }}
|
|
|
|
|
>
|
|
|
|
|
{label}
|
|
|
|
|
</Tag>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2025-02-06 15:09:29 +08:00
|
|
|
|
|
|
|
|
async function ResetUserPasswordFunc(userId: number) {
|
|
|
|
|
modal.info({
|
|
|
|
|
title: '重置密码',
|
|
|
|
|
width: 500,
|
|
|
|
|
closable: true,
|
|
|
|
|
content: <ResetUserPassword userId={userId} />,
|
|
|
|
|
footer: null
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-27 21:49:11 +08:00
|
|
|
/**
|
|
|
|
|
* 给指定用户申请软件控制权限
|
|
|
|
|
* @param userId 用户ID
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
async function ApplySoftwareControlHandle(userId: number) {
|
|
|
|
|
if (!access.isAdminOrSuperAdmin) {
|
|
|
|
|
messageApi.error("您没有权限执行此操作");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
let userCanApplyCount = await SoftwareControl.GetUserSoftwareControlCount(userId);
|
|
|
|
|
if (userCanApplyCount <= 0) {
|
|
|
|
|
messageApi.warning("用户已经没有可申请的软件控制权限了");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 开始申请
|
|
|
|
|
await SoftwareControl.ApplyUserSoftwareControl(userId);
|
|
|
|
|
messageApi.success("用户软件控制权限申请成功");
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
messageApi.error(error.message);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-13 19:49:48 +08:00
|
|
|
const columns: ColumnsType<UserModel.UserCollection> = [
|
|
|
|
|
{
|
|
|
|
|
title: 'ID',
|
|
|
|
|
dataIndex: 'id',
|
|
|
|
|
sorter: true,
|
|
|
|
|
width: '60px',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '用户名',
|
|
|
|
|
dataIndex: 'userName',
|
|
|
|
|
width: '140px',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '用户昵称',
|
|
|
|
|
dataIndex: 'nickName',
|
|
|
|
|
width: '140px',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '邀请人',
|
|
|
|
|
dataIndex: 'parentId',
|
|
|
|
|
width: '140px',
|
|
|
|
|
hidden: !access.isAdminOrSuperAdmin,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '角色',
|
|
|
|
|
dataIndex: 'roleNames',
|
|
|
|
|
render: (text, record) => {
|
|
|
|
|
let res = record.roleNames.map((item) => {
|
|
|
|
|
return <Tag key={item} color="cyan">{item}</Tag>
|
|
|
|
|
});
|
|
|
|
|
return res;
|
|
|
|
|
},
|
|
|
|
|
width: '260px',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '创建时间',
|
|
|
|
|
dataIndex: 'createdDate',
|
|
|
|
|
render: (text, record) => FormatDate(record.createdDate),
|
2024-10-30 15:36:49 +08:00
|
|
|
width: '160px',
|
2024-10-13 19:49:48 +08:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '上次登录时间',
|
|
|
|
|
dataIndex: 'lastLoginDate',
|
|
|
|
|
render: (text, record) => FormatDate(record.lastLoginDate),
|
2024-10-30 15:36:49 +08:00
|
|
|
width: '160px',
|
2024-10-13 19:49:48 +08:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '上次登录IP',
|
|
|
|
|
dataIndex: 'lastLoginIp',
|
2024-10-30 15:36:49 +08:00
|
|
|
width: '120px',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '备注',
|
|
|
|
|
dataIndex: 'remark',
|
|
|
|
|
hidden: !access.isAdminOrSuperAdmin,
|
|
|
|
|
ellipsis: {
|
|
|
|
|
showTitle: false,
|
|
|
|
|
},
|
|
|
|
|
render: (remark) => (
|
|
|
|
|
<Tooltip placement="topLeft" title={remark}>
|
|
|
|
|
{remark}
|
|
|
|
|
</Tooltip>
|
|
|
|
|
),
|
2024-10-13 19:49:48 +08:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '操作',
|
2024-12-27 21:49:11 +08:00
|
|
|
width: '80px',
|
|
|
|
|
hidden: !access.isAdminOrSuperAdmin,
|
2024-10-13 19:49:48 +08:00
|
|
|
render: (text, record) => (
|
2024-12-27 21:49:11 +08:00
|
|
|
<Dropdown
|
|
|
|
|
menu={{
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
key: 'edit',
|
|
|
|
|
label: '编辑',
|
|
|
|
|
icon: <EditOutlined />,
|
|
|
|
|
hidden: !access.canEditUser,
|
|
|
|
|
primary: true,
|
|
|
|
|
onClick: () => {
|
|
|
|
|
setUserId(record.id);
|
|
|
|
|
setOpenModal(true);
|
|
|
|
|
}
|
|
|
|
|
},
|
2025-02-06 15:09:29 +08:00
|
|
|
{
|
|
|
|
|
key: 'resetPassword',
|
|
|
|
|
label: '重置密码',
|
|
|
|
|
icon: <KeyOutlined />,
|
|
|
|
|
hidden: !access.isSuperAdmin,
|
|
|
|
|
onClick: async () => {
|
|
|
|
|
await ResetUserPasswordFunc(record.id);
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-12-27 21:49:11 +08:00
|
|
|
{
|
|
|
|
|
key: 'apply',
|
|
|
|
|
label: '初始化权限',
|
|
|
|
|
icon: <SyncOutlined />,
|
|
|
|
|
hidden: !access.canApplySoftwareControl,
|
|
|
|
|
primary: true,
|
|
|
|
|
onClick: async () => {
|
|
|
|
|
await ApplySoftwareControlHandle(record.id);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'delete',
|
|
|
|
|
label: '删除',
|
|
|
|
|
icon: <DeleteOutlined />,
|
|
|
|
|
hidden: !access.canDeleteUser,
|
|
|
|
|
danger: true,
|
|
|
|
|
onClick: () => {
|
|
|
|
|
messageApi.error("暂不支持删除用户");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
].filter(item => !item.hidden)
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Button color="primary" variant="filled" icon={<MenuOutlined />} />
|
|
|
|
|
</Dropdown>
|
2024-10-13 19:49:48 +08:00
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
|
|
|
|
|
<div>
|
|
|
|
|
<Form
|
|
|
|
|
layout='inline'
|
|
|
|
|
form={form}
|
|
|
|
|
onFinish={QueryUserListByCondition}
|
|
|
|
|
>
|
|
|
|
|
<Form.Item label="用户ID" name='userId' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Input placeholder="请输入用户ID" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item label="用户名称" name='userName' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Input placeholder="请输入用户名称" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item label="用户昵称" name='nickName' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Input placeholder="请输入用户昵称" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
{access.isAdminOrSuperAdmin ?
|
|
|
|
|
<Form.Item label="所属用户ID" name='parentId' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Input />
|
|
|
|
|
</Form.Item> :
|
|
|
|
|
null}
|
|
|
|
|
<Form.Item label="电话号码" name='phoneNumber' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Input placeholder="请输入电话号码" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item label="邮箱" name='email' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Input placeholder="请输入邮箱号" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
{
|
|
|
|
|
access.isAdminOrSuperAdmin ?
|
|
|
|
|
<Form.Item label="角色分组" name='roleNames' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Select
|
|
|
|
|
mode="multiple"
|
|
|
|
|
tagRender={tagRender}
|
|
|
|
|
style={{ width: '260px' }}
|
|
|
|
|
options={roleNames}
|
|
|
|
|
placeholder="请选择角色分组"
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item> :
|
|
|
|
|
null
|
|
|
|
|
|
2024-10-30 15:36:49 +08:00
|
|
|
}
|
|
|
|
|
<Form.Item>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
{
|
|
|
|
|
access.isAdminOrSuperAdmin ?
|
|
|
|
|
<Form.Item label="备注" name='remark' style={{ marginBottom: 5 }}>
|
|
|
|
|
<Input placeholder="请输入备注" />
|
|
|
|
|
</Form.Item> :
|
|
|
|
|
null
|
|
|
|
|
|
2024-10-13 19:49:48 +08:00
|
|
|
}
|
|
|
|
|
<Form.Item>
|
|
|
|
|
<Button type="primary" htmlType='submit'>查询</Button>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
<Table<UserModel.UserCollection>
|
|
|
|
|
columns={columns}
|
|
|
|
|
rowKey={(record) => record.id}
|
|
|
|
|
dataSource={data}
|
|
|
|
|
pagination={tableParams.pagination}
|
|
|
|
|
loading={loading}
|
|
|
|
|
onChange={handleTableChange}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<Modal width={840} title="编辑用户" maskClosable={false} open={openModal} footer={null} onCancel={modalCancel}>
|
|
|
|
|
<ModifyUser setFormRef={setFormRef} open={openModal} userId={userId} />
|
|
|
|
|
</Modal>
|
|
|
|
|
{messageHolder}
|
2025-02-06 15:09:29 +08:00
|
|
|
{modaltHolder}
|
2024-10-13 19:49:48 +08:00
|
|
|
</TemplateContainer>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default UserManagement;
|