import { MEMBER_TYPE_COLORS, MEMBER_TYPE_LABELS, STATUS_DISABLED, STATUS_ENABLED, STATUS_OPTIONS, } from '@/defines'; import { BindRolesDrawer } from '@/pages/Admin/_shared/BindRolesDrawer'; import { UserPermDrawer } from '@/pages/Admin/_shared/UserPermDrawer'; import { useProductRolesBase, useUserProductRoles, } from '@/pages/Admin/_shared/useUserProductRoles'; import { fetchDeptTree } from '@/services/dept'; import { fetchResetPassword, fetchUpdateUserStatus, fetchUserCredentials, fetchUserList, } from '@/services/user'; import { unixTimeFormat } from '@/utils/timeUtils'; import { StopOutlined } from '@ant-design/icons'; import { ActionType, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components'; import { useIntl } from '@umijs/max'; import { Button, Popconfirm, Tag, message } from 'antd'; import { useEffect, useMemo, useRef, useState } from 'react'; import { UserForm } from './components/Form'; import { UserCredentialModal } from './components/UserCredentialModal'; const flattenDeptTree = (items: API.DeptItem[]): { label: string; value: number }[] => items.flatMap((d) => [ { label: d.name, value: d.id }, ...(d.children ? flattenDeptTree(d.children) : []), ]); export default function UserPage() { const intl = useIntl(); const actionRef = useRef(); const [pageUsers, setPageUsers] = useState([]); const [deptOptions, setDeptOptions] = useState<{ label: string; value: number }[]>([]); const [rolesDrawer, setRolesDrawer] = useState<{ open: boolean; userId: number }>({ open: false, userId: 0, }); const [permDrawer, setPermDrawer] = useState<{ open: boolean; userId: number }>({ open: false, userId: 0, }); const [refreshKey, setRefreshKey] = useState(0); const [credData, setCredData] = useState(null); const [credOpen, setCredOpen] = useState(false); useEffect(() => { fetchDeptTree().then((res) => { setDeptOptions([{ label: '无部门', value: 0 }, ...flattenDeptTree(res.data ?? [])]); }); }, []); const userIds = useMemo(() => pageUsers.map((u) => u.id), [pageUsers]); const productRolesBase = useProductRolesBase(); const { userProductInfo } = useUserProductRoles(userIds, productRolesBase, refreshKey); const handleToggleStatus = async (r: API.UserItem) => { const res = await fetchUpdateUserStatus({ id: r.id, status: r.status === STATUS_ENABLED ? STATUS_DISABLED : STATUS_ENABLED, }); if (!res.success) return; message.success('操作成功'); actionRef.current?.reload(); }; const showCredentials = async (ticket: string) => { const res = await fetchUserCredentials({ ticket }); if (!res.success || !res.data) return; setCredData(res.data); setCredOpen(true); }; const handleCreateSuccess = async (ticket?: string) => { actionRef.current?.reload(); if (ticket) await showCredentials(ticket); }; const handleResetPassword = async (r: API.UserItem) => { const res = await fetchResetPassword({ userId: r.id }); if (!res.success || !res.data) return; message.success('密码已重置'); await showCredentials(res.data.credentialsTicket); }; const columns: ProColumns[] = [ { title: '用户名', dataIndex: 'username', width: 200 }, { title: '昵称', dataIndex: 'nickname', width: 200 }, { title: '状态', dataIndex: 'status', width: 80, valueType: 'select', fieldProps: { options: STATUS_OPTIONS }, render: (_, r) => ( {r.status === STATUS_ENABLED ? '启用' : '禁用'} ), }, { title: '部门', dataIndex: 'deptId', width: 150, valueType: 'select', fieldProps: { options: deptOptions, showSearch: true }, render: (_, r) => { if (!r.deptId) return 无部门; const dept = deptOptions.find((d) => d.value === r.deptId); return ( dept?.label ?? 无部门 ); }, }, { title: '产品角色', key: 'productRoles', search: false, render: (_, r) => { const info = userProductInfo.get(r.id) ?? []; if (info.length === 0) return ; return (
{info.map((p) => (
{p.productName} {p.productStatus !== STATUS_ENABLED && ( )} {MEMBER_TYPE_LABELS[p.memberType ?? ''] ?? p.memberType}
{p.roleNames.length > 0 ? ( p.roleNames.map((name) => ( {name} )) ) : ( 无角色 )}
))}
); }, }, { title: '创建时间', dataIndex: 'createTime', width: 180, search: false, render: (_, r) => unixTimeFormat(r.createTime), }, { title: '操作', valueType: 'option', width: 320, render: (_, r) => [ 编辑} onSuccess={() => actionRef.current?.reload()} />, 复制} onSuccess={handleCreateSuccess} />, setRolesDrawer({ open: true, userId: r.id })}> 分配角色 , setPermDrawer({ open: true, userId: r.id })}> 设置权限 , handleResetPassword(r)} > 重置密码 , handleToggleStatus(r)} > {r.status === STATUS_ENABLED ? '冻结' : '解冻'} , ], }, ]; return ( actionRef={actionRef} columns={columns} rowKey="id" search={{ span: { xs: 24, sm: 12, md: 8, lg: 6, xl: 4, xxl: 4 } }} request={fetchUserList} onDataSourceChange={setPageUsers} scroll={{ x: 1280 }} tableLayout="fixed" pagination={{ defaultPageSize: 20, pageSizeOptions: [10, 20, 50, 100], showSizeChanger: true, }} toolBarRender={() => [ 新建用户} onSuccess={handleCreateSuccess} />, ]} /> setRolesDrawer((p) => ({ ...p, open: false }))} onSuccess={() => setRefreshKey((k) => k + 1)} /> setPermDrawer((p) => ({ ...p, open: false }))} /> setCredOpen(false)} /> ); }