| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import { MEMBER_TYPE_COLORS, MEMBER_TYPE_LABELS, STATUS_DISABLED, STATUS_ENABLED } 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 { fetchUpdateUserStatus, 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 { useMemo, useRef, useState } from 'react';
- import { UserForm } from './components/Form';
- export default function UserPage() {
- const intl = useIntl();
- const actionRef = useRef<ActionType>();
- const [pageUsers, setPageUsers] = useState<API.UserItem[]>([]);
- 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 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 columns: ProColumns<API.UserItem>[] = [
- { title: '用户名', dataIndex: 'username', width: 200 },
- { title: '昵称', dataIndex: 'nickname', width: 200 },
- {
- title: '状态',
- dataIndex: 'status',
- width: 80,
- render: (_, r) => (
- <Tag color={r.status === STATUS_ENABLED ? 'success' : 'error'}>
- {r.status === STATUS_ENABLED ? '启用' : '禁用'}
- </Tag>
- ),
- },
- {
- title: '产品角色',
- key: 'productRoles',
- render: (_, r) => {
- const info = userProductInfo.get(r.id) ?? [];
- if (info.length === 0)
- return <span className="text-(--ant-color-text-quaternary) text-xs">无</span>;
- return (
- <div className="flex flex-col gap-1">
- {info.map((p) => (
- <div
- key={p.productName}
- className="flex flex-row gap-1 rounded border border-dashed border-(--ant-color-border) bg-(--ant-color-fill-quaternary) px-2 py-2"
- >
- <Tag color="purple" className="mr-0 self-center">
- {p.productName}
- {p.productStatus !== STATUS_ENABLED && (
- <StopOutlined className="ml-1 text-(--ant-color-error)!" />
- )}
- </Tag>
- <Tag
- color={MEMBER_TYPE_COLORS[p.memberType ?? ''] ?? 'default'}
- className="mr-0 self-center"
- >
- {MEMBER_TYPE_LABELS[p.memberType ?? ''] ?? p.memberType}
- </Tag>
- <div className="flex flex-row flex-wrap gap-1 items-center">
- {p.roleNames.length > 0 ? (
- p.roleNames.map((name) => (
- <Tag key={name} className="mr-0">
- {name}
- </Tag>
- ))
- ) : (
- <span className="text-(--ant-color-text-quaternary) text-xs whitespace-nowrap">
- 无角色
- </span>
- )}
- </div>
- </div>
- ))}
- </div>
- );
- },
- },
- {
- title: '创建时间',
- dataIndex: 'createTime',
- width: 180,
- render: (_, r) => unixTimeFormat(r.createTime),
- },
- {
- title: '操作',
- valueType: 'option',
- width: 260,
- render: (_, r) => [
- <UserForm
- key="edit"
- mode="edit"
- initialValues={r}
- trigger={<a>编辑</a>}
- onSuccess={() => actionRef.current?.reload()}
- />,
- <UserForm
- key="copy"
- mode="copy"
- initialValues={r}
- trigger={<a>复制</a>}
- onSuccess={() => actionRef.current?.reload()}
- />,
- <a key="roles" onClick={() => setRolesDrawer({ open: true, userId: r.id })}>
- 分配角色
- </a>,
- <a key="perms" onClick={() => setPermDrawer({ open: true, userId: r.id })}>
- 设置权限
- </a>,
- <Popconfirm
- key="status"
- title={
- r.status === STATUS_ENABLED
- ? `确认冻结「${r.username}」?`
- : `确认解冻「${r.username}」?`
- }
- onConfirm={() => handleToggleStatus(r)}
- >
- <a className={r.status === STATUS_ENABLED ? 'text-(--ant-color-error)' : ''}>
- {r.status === STATUS_ENABLED ? '冻结' : '解冻'}
- </a>
- </Popconfirm>,
- ],
- },
- ];
- return (
- <PageContainer title={intl.formatMessage({ id: 'admin.user.title' })}>
- <ProTable<API.UserItem>
- actionRef={actionRef}
- columns={columns}
- rowKey="id"
- search={false}
- request={fetchUserList}
- onDataSourceChange={setPageUsers}
- scroll={{ x: 1220 }}
- tableLayout="fixed"
- pagination={{
- defaultPageSize: 20,
- pageSizeOptions: [10, 20, 50, 100],
- showSizeChanger: true,
- }}
- toolBarRender={() => [
- <UserForm
- key="create"
- mode="add"
- trigger={<Button type="primary">新建用户</Button>}
- onSuccess={() => actionRef.current?.reload()}
- />,
- ]}
- />
- <BindRolesDrawer
- {...rolesDrawer}
- onClose={() => setRolesDrawer((p) => ({ ...p, open: false }))}
- onSuccess={() => setRefreshKey((k) => k + 1)}
- />
- <UserPermDrawer
- {...permDrawer}
- onClose={() => setPermDrawer((p) => ({ ...p, open: false }))}
- />
- </PageContainer>
- );
- }
|