|
|
@@ -1,11 +1,19 @@
|
|
|
-import { MEMBER_TYPE_LABELS, MEMBER_TYPE_OPTIONS, STATUS_OPTIONS } from '@/defines';
|
|
|
+import {
|
|
|
+ MEMBER_TYPE_COLORS,
|
|
|
+ MEMBER_TYPE_LABELS,
|
|
|
+ MEMBER_TYPE_OPTIONS,
|
|
|
+ STATUS_OPTIONS,
|
|
|
+} from '@/defines';
|
|
|
+import { BindRolesDrawer } from '@/pages/Admin/_shared/BindRolesDrawer';
|
|
|
+import { UserPermDrawer } from '@/pages/Admin/_shared/UserPermDrawer';
|
|
|
import {
|
|
|
fetchAddMember,
|
|
|
fetchMemberList,
|
|
|
fetchRemoveMember,
|
|
|
fetchUpdateMember,
|
|
|
} from '@/services/member';
|
|
|
-import { fetchUserList } from '@/services/user';
|
|
|
+import { fetchRoleList } from '@/services/role';
|
|
|
+import { fetchUserDetail, fetchUserList } from '@/services/user';
|
|
|
import {
|
|
|
ActionType,
|
|
|
DrawerForm,
|
|
|
@@ -23,6 +31,18 @@ interface MemberTabProps {
|
|
|
export const MemberTab = ({ productCode }: MemberTabProps) => {
|
|
|
const actionRef = useRef<ActionType>();
|
|
|
const [userOptions, setUserOptions] = useState<{ label: string; value: number }[]>([]);
|
|
|
+ const [roleMap, setRoleMap] = useState<Map<number, string>>(new Map());
|
|
|
+ const [userRoleIds, setUserRoleIds] = useState<Map<number, number[]>>(new Map());
|
|
|
+ const [pageMembers, setPageMembers] = useState<API.MemberItem[]>([]);
|
|
|
+ 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 loadUsers = async () => {
|
|
|
const res = await fetchUserList({ pageSize: 9999 });
|
|
|
@@ -35,8 +55,30 @@ export const MemberTab = ({ productCode }: MemberTabProps) => {
|
|
|
};
|
|
|
|
|
|
useEffect(() => {
|
|
|
- loadUsers();
|
|
|
- }, []);
|
|
|
+ fetchRoleList({ productCode, pageSize: 9999 }).then((res) => {
|
|
|
+ const map = new Map<number, string>();
|
|
|
+ (res.data ?? []).forEach((r: API.RoleItem) => map.set(r.id, r.name));
|
|
|
+ setRoleMap(map);
|
|
|
+ });
|
|
|
+ }, [productCode]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (pageMembers.length === 0) {
|
|
|
+ setUserRoleIds(new Map());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const load = async () => {
|
|
|
+ const details = await Promise.all(
|
|
|
+ pageMembers.map((m) => fetchUserDetail({ id: m.userId, productCode })),
|
|
|
+ );
|
|
|
+ const map = new Map<number, number[]>();
|
|
|
+ details.forEach((res, i) => {
|
|
|
+ map.set(pageMembers[i].userId, res.data?.roleIds ?? []);
|
|
|
+ });
|
|
|
+ setUserRoleIds(map);
|
|
|
+ };
|
|
|
+ load();
|
|
|
+ }, [pageMembers, refreshKey]);
|
|
|
|
|
|
const columns: ProColumns<API.MemberItem>[] = [
|
|
|
{ title: '用户名', dataIndex: 'username', width: 200 },
|
|
|
@@ -45,7 +87,29 @@ export const MemberTab = ({ productCode }: MemberTabProps) => {
|
|
|
title: '成员类型',
|
|
|
dataIndex: 'memberType',
|
|
|
width: 100,
|
|
|
- render: (_, r) => <Tag>{MEMBER_TYPE_LABELS[r.memberType] ?? r.memberType}</Tag>,
|
|
|
+ render: (_, r) => (
|
|
|
+ <Tag color={MEMBER_TYPE_COLORS[r.memberType] ?? 'default'}>
|
|
|
+ {MEMBER_TYPE_LABELS[r.memberType] ?? r.memberType}
|
|
|
+ </Tag>
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '角色',
|
|
|
+ key: 'roles',
|
|
|
+ render: (_, r) => {
|
|
|
+ const roleIds = userRoleIds.get(r.userId) ?? [];
|
|
|
+ const names = roleIds.map((id) => roleMap.get(id)).filter(Boolean) as string[];
|
|
|
+ if (names.length === 0) return <span className="text-gray-400 text-xs">无</span>;
|
|
|
+ return (
|
|
|
+ <div className="flex flex-row flex-wrap gap-1">
|
|
|
+ {names.map((name) => (
|
|
|
+ <Tag key={name} className="mr-0">
|
|
|
+ {name}
|
|
|
+ </Tag>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
title: '状态',
|
|
|
@@ -58,7 +122,7 @@ export const MemberTab = ({ productCode }: MemberTabProps) => {
|
|
|
{
|
|
|
title: '操作',
|
|
|
valueType: 'option',
|
|
|
- width: 120,
|
|
|
+ width: 220,
|
|
|
render: (_, r) => [
|
|
|
<DrawerForm
|
|
|
key="edit"
|
|
|
@@ -66,11 +130,12 @@ export const MemberTab = ({ productCode }: MemberTabProps) => {
|
|
|
trigger={<a>编辑</a>}
|
|
|
initialValues={{ memberType: r.memberType, status: r.status }}
|
|
|
onFinish={async (values) => {
|
|
|
- await fetchUpdateMember({
|
|
|
+ const res = await fetchUpdateMember({
|
|
|
id: r.id,
|
|
|
memberType: values.memberType,
|
|
|
status: values.status,
|
|
|
});
|
|
|
+ if (!res.success) return false;
|
|
|
actionRef.current?.reload();
|
|
|
return true;
|
|
|
}}
|
|
|
@@ -89,11 +154,18 @@ export const MemberTab = ({ productCode }: MemberTabProps) => {
|
|
|
rules={[{ required: true }]}
|
|
|
/>
|
|
|
</DrawerForm>,
|
|
|
+ <a key="roles" onClick={() => setRolesDrawer({ open: true, userId: r.userId })}>
|
|
|
+ 分配角色
|
|
|
+ </a>,
|
|
|
+ <a key="perms" onClick={() => setPermDrawer({ open: true, userId: r.userId })}>
|
|
|
+ 设置权限
|
|
|
+ </a>,
|
|
|
<Popconfirm
|
|
|
key="remove"
|
|
|
title="确认移除该成员?"
|
|
|
onConfirm={async () => {
|
|
|
- await fetchRemoveMember({ id: r.id });
|
|
|
+ const res = await fetchRemoveMember({ id: r.id });
|
|
|
+ if (!res.success) return;
|
|
|
message.success('已移除');
|
|
|
actionRef.current?.reload();
|
|
|
}}
|
|
|
@@ -105,53 +177,68 @@ export const MemberTab = ({ productCode }: MemberTabProps) => {
|
|
|
];
|
|
|
|
|
|
return (
|
|
|
- <ProTable<API.MemberItem>
|
|
|
- actionRef={actionRef}
|
|
|
- columns={columns}
|
|
|
- rowKey="id"
|
|
|
- search={false}
|
|
|
- request={async (params, sorter, filter) => {
|
|
|
- return fetchMemberList({ ...params, productCode }, sorter, filter);
|
|
|
- }}
|
|
|
- scroll={{ x: 700 }}
|
|
|
- tableLayout="fixed"
|
|
|
- pagination={{
|
|
|
- defaultPageSize: 20,
|
|
|
- pageSizeOptions: [10, 20, 50, 100],
|
|
|
- showSizeChanger: true,
|
|
|
- }}
|
|
|
- toolBarRender={() => [
|
|
|
- <DrawerForm
|
|
|
- key="add"
|
|
|
- title="添加成员"
|
|
|
- trigger={<Button type="primary">添加成员</Button>}
|
|
|
- onFinish={async (values) => {
|
|
|
- await fetchAddMember({
|
|
|
- productCode,
|
|
|
- userId: values.userId,
|
|
|
- memberType: values.memberType,
|
|
|
- });
|
|
|
- actionRef.current?.reload();
|
|
|
- return true;
|
|
|
- }}
|
|
|
- drawerProps={{ destroyOnClose: true }}
|
|
|
- >
|
|
|
- <ProFormSelect
|
|
|
- name="userId"
|
|
|
- label="选择用户"
|
|
|
- options={userOptions}
|
|
|
- showSearch
|
|
|
- fieldProps={{ onSearch: loadUsers, filterOption: false }}
|
|
|
- rules={[{ required: true }]}
|
|
|
- />
|
|
|
- <ProFormSelect
|
|
|
- name="memberType"
|
|
|
- label="成员类型"
|
|
|
- options={MEMBER_TYPE_OPTIONS}
|
|
|
- rules={[{ required: true }]}
|
|
|
- />
|
|
|
- </DrawerForm>,
|
|
|
- ]}
|
|
|
- />
|
|
|
+ <>
|
|
|
+ <ProTable<API.MemberItem>
|
|
|
+ actionRef={actionRef}
|
|
|
+ columns={columns}
|
|
|
+ rowKey="id"
|
|
|
+ search={false}
|
|
|
+ request={async (params, sorter, filter) => {
|
|
|
+ return fetchMemberList({ ...params, productCode }, sorter, filter);
|
|
|
+ }}
|
|
|
+ onDataSourceChange={setPageMembers}
|
|
|
+ scroll={{ x: 1000 }}
|
|
|
+ tableLayout="fixed"
|
|
|
+ pagination={{
|
|
|
+ defaultPageSize: 20,
|
|
|
+ pageSizeOptions: [10, 20, 50, 100],
|
|
|
+ showSizeChanger: true,
|
|
|
+ }}
|
|
|
+ toolBarRender={() => [
|
|
|
+ <DrawerForm
|
|
|
+ key="add"
|
|
|
+ title="添加成员"
|
|
|
+ trigger={<Button type="primary">添加成员</Button>}
|
|
|
+ onFinish={async (values) => {
|
|
|
+ const res = await fetchAddMember({
|
|
|
+ productCode,
|
|
|
+ userId: values.userId,
|
|
|
+ memberType: values.memberType,
|
|
|
+ });
|
|
|
+ if (!res.success) return false;
|
|
|
+ actionRef.current?.reload();
|
|
|
+ return true;
|
|
|
+ }}
|
|
|
+ drawerProps={{ destroyOnClose: true }}
|
|
|
+ >
|
|
|
+ <ProFormSelect
|
|
|
+ name="userId"
|
|
|
+ label="选择用户"
|
|
|
+ options={userOptions}
|
|
|
+ showSearch
|
|
|
+ fieldProps={{ onSearch: loadUsers, filterOption: false }}
|
|
|
+ rules={[{ required: true }]}
|
|
|
+ />
|
|
|
+ <ProFormSelect
|
|
|
+ name="memberType"
|
|
|
+ label="成员类型"
|
|
|
+ options={MEMBER_TYPE_OPTIONS}
|
|
|
+ rules={[{ required: true }]}
|
|
|
+ />
|
|
|
+ </DrawerForm>,
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ <BindRolesDrawer
|
|
|
+ {...rolesDrawer}
|
|
|
+ onClose={() => setRolesDrawer((p) => ({ ...p, open: false }))}
|
|
|
+ onSuccess={() => setRefreshKey((k) => k + 1)}
|
|
|
+ defaultProductCode={productCode}
|
|
|
+ />
|
|
|
+ <UserPermDrawer
|
|
|
+ {...permDrawer}
|
|
|
+ onClose={() => setPermDrawer((p) => ({ ...p, open: false }))}
|
|
|
+ defaultProductCode={productCode}
|
|
|
+ />
|
|
|
+ </>
|
|
|
);
|
|
|
};
|