refactor(web): 系统设置模块页面表单一致性重构
- 新增 useCrudDrawer hook 封装 CRUD Drawer 通用模式(状态管理/提交/错误处理) - 新增 useListData hook 封装非分页列表数据获取 - 11 个页面统一迁移到 DrawerForm + 共享 hooks,消除重复代码 - 错误处理统一使用 useApiRequest.execute(),移除内联 try-catch - Modal 全部替换为 DrawerForm,保持 UI 一致性 - 净减少 ~1300 行代码(858 增 / 2136 删)
This commit is contained in:
@@ -1,19 +1,16 @@
|
||||
import { useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import {
|
||||
Table,
|
||||
Button,
|
||||
Space,
|
||||
Modal,
|
||||
Form,
|
||||
Input,
|
||||
Tag,
|
||||
Popconfirm,
|
||||
Checkbox,
|
||||
message,
|
||||
} from 'antd';
|
||||
import {
|
||||
PlusOutlined,
|
||||
SearchOutlined,
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
UserOutlined,
|
||||
@@ -32,311 +29,132 @@ import {
|
||||
} from '../api/users';
|
||||
import { listRoles, type RoleInfo } from '../api/roles';
|
||||
import type { UserInfo } from '../api/auth';
|
||||
import { handleApiError } from '../api/client';
|
||||
import { PageContainer } from '../components/PageContainer';
|
||||
import { DrawerForm } from '../components/DrawerForm';
|
||||
import { useCrudDrawer } from '../hooks/useCrudDrawer';
|
||||
import { usePaginatedData } from '../hooks/usePaginatedData';
|
||||
import { useApiRequest } from '../hooks/useApiRequest';
|
||||
import { useThemeMode } from '../hooks/useThemeMode';
|
||||
|
||||
const STATUS_COLOR_MAP: Record<string, string> = {
|
||||
active: '#059669',
|
||||
disabled: '#dc2626',
|
||||
locked: '#d97706',
|
||||
};
|
||||
|
||||
const STATUS_BG_MAP: Record<string, string> = {
|
||||
active: '#ECFDF5',
|
||||
disabled: '#FEF2F2',
|
||||
locked: '#FFFBEB',
|
||||
};
|
||||
|
||||
const STATUS_LABEL_MAP: Record<string, string> = {
|
||||
active: '正常',
|
||||
disabled: '禁用',
|
||||
locked: '锁定',
|
||||
};
|
||||
const STATUS_COLOR_MAP: Record<string, string> = { active: '#059669', disabled: '#dc2626', locked: '#d97706' };
|
||||
const STATUS_BG_MAP: Record<string, string> = { active: '#ECFDF5', disabled: '#FEF2F2', locked: '#FFFBEB' };
|
||||
const STATUS_LABEL_MAP: Record<string, string> = { active: '正常', disabled: '禁用', locked: '锁定' };
|
||||
|
||||
export default function Users() {
|
||||
const [users, setUsers] = useState<UserInfo[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [page, setPage] = useState(1);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [createModalOpen, setCreateModalOpen] = useState(false);
|
||||
const [editUser, setEditUser] = useState<UserInfo | null>(null);
|
||||
const [roleModalOpen, setRoleModalOpen] = useState(false);
|
||||
const [selectedUser, setSelectedUser] = useState<UserInfo | null>(null);
|
||||
const [allRoles, setAllRoles] = useState<RoleInfo[]>([]);
|
||||
const [selectedRoleIds, setSelectedRoleIds] = useState<string[]>([]);
|
||||
const [form] = Form.useForm();
|
||||
const isDark = useThemeMode();
|
||||
const { execute } = useApiRequest();
|
||||
|
||||
const fetchUsers = useCallback(async (p = page) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const result = await listUsers(p, 20, searchText);
|
||||
setUsers(result.data);
|
||||
setTotal(result.total);
|
||||
} catch {
|
||||
message.error('加载用户列表失败');
|
||||
}
|
||||
setLoading(false);
|
||||
}, [page, searchText]);
|
||||
const {
|
||||
data: users, total, page, loading, refresh,
|
||||
} = usePaginatedData<UserInfo>(async (p, pageSize, search) => {
|
||||
const result = await listUsers(p, pageSize, search);
|
||||
return { data: result.data, total: result.total };
|
||||
}, 20);
|
||||
|
||||
// 搜索防抖:输入后 300ms 才触发查询
|
||||
const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const debouncedSearch = useCallback((_text: string) => {
|
||||
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
||||
debounceTimer.current = setTimeout(() => {
|
||||
setPage(1);
|
||||
}, 300);
|
||||
}, []);
|
||||
const [allRoles, setAllRoles] = useState<RoleInfo[]>([]);
|
||||
const [roleDrawerOpen, setRoleDrawerOpen] = useState(false);
|
||||
const [selectedUser, setSelectedUser] = useState<UserInfo | null>(null);
|
||||
const [selectedRoleIds, setSelectedRoleIds] = useState<string[]>([]);
|
||||
|
||||
const fetchRoles = useCallback(async () => {
|
||||
try {
|
||||
const result = await listRoles();
|
||||
setAllRoles(result.data);
|
||||
} catch {
|
||||
// 静默处理
|
||||
}
|
||||
} catch { /* silent */ }
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUsers();
|
||||
fetchRoles();
|
||||
}, [fetchUsers, fetchRoles]);
|
||||
useEffect(() => { fetchRoles(); }, [fetchRoles]);
|
||||
|
||||
const handleCreateOrEdit = async (values: {
|
||||
username: string;
|
||||
password?: string;
|
||||
display_name?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
}) => {
|
||||
try {
|
||||
if (editUser) {
|
||||
const req: UpdateUserRequest = {
|
||||
display_name: values.display_name,
|
||||
email: values.email,
|
||||
phone: values.phone,
|
||||
version: editUser.version,
|
||||
};
|
||||
await updateUser(editUser.id, req);
|
||||
message.success('用户更新成功');
|
||||
} else {
|
||||
const req: CreateUserRequest = {
|
||||
username: values.username,
|
||||
password: values.password ?? '',
|
||||
display_name: values.display_name,
|
||||
email: values.email,
|
||||
phone: values.phone,
|
||||
};
|
||||
await createUser(req);
|
||||
message.success('用户创建成功');
|
||||
}
|
||||
setCreateModalOpen(false);
|
||||
setEditUser(null);
|
||||
form.resetFields();
|
||||
fetchUsers();
|
||||
} catch (err: unknown) {
|
||||
handleApiError(err, '操作失败');
|
||||
}
|
||||
};
|
||||
const userDrawer = useCrudDrawer<UserInfo>({
|
||||
getId: (r) => r.id,
|
||||
onCreate: async (values) => {
|
||||
await createUser(values as unknown as CreateUserRequest);
|
||||
},
|
||||
onUpdate: async (id, values) => {
|
||||
await updateUser(id, values as unknown as UpdateUserRequest);
|
||||
},
|
||||
onSuccess: refresh,
|
||||
});
|
||||
|
||||
const handleDelete = async (id: string) => {
|
||||
try {
|
||||
await deleteUser(id);
|
||||
message.success('用户已删除');
|
||||
fetchUsers();
|
||||
} catch {
|
||||
message.error('删除失败');
|
||||
}
|
||||
await execute(() => deleteUser(id), '用户已删除');
|
||||
refresh();
|
||||
};
|
||||
|
||||
const handleToggleStatus = async (id: string, status: string) => {
|
||||
try {
|
||||
const user = users.find(u => u.id === id);
|
||||
if (!user) return;
|
||||
await updateUser(id, { status, version: user.version });
|
||||
message.success(status === 'disabled' ? '用户已禁用' : '用户已启用');
|
||||
fetchUsers();
|
||||
} catch {
|
||||
message.error('状态更新失败');
|
||||
}
|
||||
const user = users.find(u => u.id === id);
|
||||
if (!user) return;
|
||||
await execute(() => updateUser(id, { status, version: user.version }), status === 'disabled' ? '用户已禁用' : '用户已启用');
|
||||
refresh();
|
||||
};
|
||||
|
||||
const handleAssignRoles = async () => {
|
||||
if (!selectedUser) return;
|
||||
try {
|
||||
await assignRoles(selectedUser.id, selectedRoleIds);
|
||||
message.success('角色分配成功');
|
||||
setRoleModalOpen(false);
|
||||
fetchUsers();
|
||||
} catch {
|
||||
message.error('角色分配失败');
|
||||
}
|
||||
await execute(() => assignRoles(selectedUser.id, selectedRoleIds), '角色分配成功');
|
||||
setRoleDrawerOpen(false);
|
||||
refresh();
|
||||
};
|
||||
|
||||
const openCreateModal = () => {
|
||||
setEditUser(null);
|
||||
form.resetFields();
|
||||
setCreateModalOpen(true);
|
||||
};
|
||||
|
||||
const openEditModal = (user: UserInfo) => {
|
||||
setEditUser(user);
|
||||
form.setFieldsValue({
|
||||
username: user.username,
|
||||
display_name: user.display_name,
|
||||
email: user.email,
|
||||
phone: user.phone,
|
||||
});
|
||||
setCreateModalOpen(true);
|
||||
};
|
||||
|
||||
const closeCreateModal = () => {
|
||||
setCreateModalOpen(false);
|
||||
setEditUser(null);
|
||||
form.resetFields();
|
||||
};
|
||||
|
||||
const openRoleModal = (user: UserInfo) => {
|
||||
const openRoleDrawer = (user: UserInfo) => {
|
||||
setSelectedUser(user);
|
||||
setSelectedRoleIds(user.roles.map((r) => r.id));
|
||||
setRoleModalOpen(true);
|
||||
setRoleDrawerOpen(true);
|
||||
};
|
||||
|
||||
const filteredUsers = users;
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '用户',
|
||||
dataIndex: 'username',
|
||||
key: 'username',
|
||||
title: '用户', dataIndex: 'username', key: 'username',
|
||||
render: (v: string, record: UserInfo) => (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
||||
<div
|
||||
style={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 8,
|
||||
background: 'linear-gradient(135deg, #2563eb, #60a5fa)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: '#fff',
|
||||
fontSize: 13,
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
width: 32, height: 32, borderRadius: 8,
|
||||
background: 'linear-gradient(135deg, #2563eb, #60a5fa)',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
color: '#fff', fontSize: 13, fontWeight: 600,
|
||||
}}>
|
||||
{(record.display_name?.[0] || v?.[0] || 'U').toUpperCase()}
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ fontWeight: 500, fontSize: 14 }}>{v}</div>
|
||||
{record.display_name && (
|
||||
<div style={{ fontSize: 12, color: isDark ? '#475569' : '#94a3b8' }}>
|
||||
{record.display_name}
|
||||
</div>
|
||||
)}
|
||||
{record.display_name && <div style={{ fontSize: 12, color: isDark ? '#475569' : '#94a3b8' }}>{record.display_name}</div>}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{ title: '邮箱', dataIndex: 'email', key: 'email', render: (v?: string) => v || '-' },
|
||||
{ title: '电话', dataIndex: 'phone', key: 'phone', render: (v?: string) => v || '-' },
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
key: 'email',
|
||||
render: (v: string | undefined) => v || '-',
|
||||
},
|
||||
{
|
||||
title: '电话',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
render: (v: string | undefined) => v || '-',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
title: '状态', dataIndex: 'status', key: 'status', width: 100,
|
||||
render: (status: string) => (
|
||||
<Tag
|
||||
style={{
|
||||
color: STATUS_COLOR_MAP[status] || '#62625b',
|
||||
background: STATUS_BG_MAP[status] || '#f8fafc',
|
||||
border: 'none',
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
<Tag style={{ color: STATUS_COLOR_MAP[status] || '#62625b', background: STATUS_BG_MAP[status] || '#f8fafc', border: 'none', fontWeight: 500 }}>
|
||||
{STATUS_LABEL_MAP[status] || status}
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '角色',
|
||||
dataIndex: 'roles',
|
||||
key: 'roles',
|
||||
title: '角色', dataIndex: 'roles', key: 'roles',
|
||||
render: (roles: RoleInfo[]) =>
|
||||
roles.length > 0
|
||||
? roles.map((r) => (
|
||||
<Tag key={r.id} style={{
|
||||
background: isDark ? '#0f172a' : '#f8fafc',
|
||||
border: 'none',
|
||||
color: isDark ? '#CBD5E1' : '#475569',
|
||||
}}>
|
||||
{r.name}
|
||||
</Tag>
|
||||
))
|
||||
? roles.map((r) => <Tag key={r.id} style={{ background: isDark ? '#0f172a' : '#f8fafc', border: 'none', color: isDark ? '#CBD5E1' : '#475569' }}>{r.name}</Tag>)
|
||||
: <span style={{ color: isDark ? '#475569' : '#CBD5E1' }}>-</span>,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 240,
|
||||
title: '操作', key: 'actions', width: 240,
|
||||
render: (_: unknown, record: UserInfo) => (
|
||||
<Space size={4}>
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => openEditModal(record)}
|
||||
style={{ color: isDark ? '#94a3b8' : '#475569' }}
|
||||
/>
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<SafetyCertificateOutlined />}
|
||||
onClick={() => openRoleModal(record)}
|
||||
style={{ color: isDark ? '#94a3b8' : '#475569' }}
|
||||
/>
|
||||
<Button size="small" type="text" icon={<EditOutlined />} onClick={() => userDrawer.openEdit(record, (r) => ({
|
||||
username: r.username, display_name: r.display_name, email: r.email, phone: r.phone,
|
||||
}))} style={{ color: isDark ? '#94a3b8' : '#475569' }} />
|
||||
<Button size="small" type="text" icon={<SafetyCertificateOutlined />} onClick={() => openRoleDrawer(record)} style={{ color: isDark ? '#94a3b8' : '#475569' }} />
|
||||
{record.status === 'active' ? (
|
||||
<Popconfirm
|
||||
title="确定禁用此用户?"
|
||||
onConfirm={() => handleToggleStatus(record.id, 'disabled')}
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<StopOutlined />}
|
||||
danger
|
||||
/>
|
||||
<Popconfirm title="确定禁用此用户?" onConfirm={() => handleToggleStatus(record.id, 'disabled')}>
|
||||
<Button size="small" type="text" icon={<StopOutlined />} danger />
|
||||
</Popconfirm>
|
||||
) : (
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<CheckCircleOutlined />}
|
||||
onClick={() => handleToggleStatus(record.id, 'active')}
|
||||
style={{ color: '#059669' }}
|
||||
/>
|
||||
<Button size="small" type="text" icon={<CheckCircleOutlined />} onClick={() => handleToggleStatus(record.id, 'active')} style={{ color: '#059669' }} />
|
||||
)}
|
||||
<Popconfirm
|
||||
title="确定删除此用户?"
|
||||
onConfirm={() => handleDelete(record.id)}
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<DeleteOutlined />}
|
||||
danger
|
||||
/>
|
||||
<Popconfirm title="确定删除此用户?" onConfirm={() => handleDelete(record.id)}>
|
||||
<Button size="small" type="text" icon={<DeleteOutlined />} danger />
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
),
|
||||
@@ -344,112 +162,59 @@ export default function Users() {
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* 页面标题和工具栏 */}
|
||||
<div className="erp-page-header">
|
||||
<div>
|
||||
<h4>用户管理</h4>
|
||||
<div className="erp-page-subtitle">管理系统用户账户、角色分配和状态</div>
|
||||
</div>
|
||||
<Space size={8}>
|
||||
<Input
|
||||
placeholder="搜索用户名..."
|
||||
prefix={<SearchOutlined style={{ color: '#94a3b8' }} />}
|
||||
value={searchText}
|
||||
onChange={(e) => {
|
||||
setSearchText(e.target.value);
|
||||
debouncedSearch(e.target.value);
|
||||
}}
|
||||
allowClear
|
||||
style={{ width: 220, borderRadius: 8 }}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={openCreateModal}
|
||||
>
|
||||
新建用户
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
<PageContainer
|
||||
title="用户管理"
|
||||
subtitle="管理系统用户账户、角色分配和状态"
|
||||
actions={<Button type="primary" icon={<PlusOutlined />} onClick={() => userDrawer.openCreate()}>新建用户</Button>}
|
||||
>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={users}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{
|
||||
current: page, total, pageSize: 20,
|
||||
onChange: (p) => refresh(p),
|
||||
showTotal: (t) => `共 ${t} 条记录`,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 表格容器 */}
|
||||
<div style={{
|
||||
background: isDark ? '#111827' : '#FFFFFF',
|
||||
borderRadius: 12,
|
||||
border: `1px solid ${isDark ? '#0f172a' : '#f8fafc'}`,
|
||||
overflow: 'hidden',
|
||||
}}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={filteredUsers}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{
|
||||
current: page,
|
||||
total,
|
||||
pageSize: 20,
|
||||
onChange: (p) => {
|
||||
setPage(p);
|
||||
fetchUsers(p);
|
||||
},
|
||||
showTotal: (t) => `共 ${t} 条记录`,
|
||||
style: { padding: '12px 16px', margin: 0 },
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 新建/编辑用户弹窗 */}
|
||||
<Modal
|
||||
title={editUser ? '编辑用户' : '新建用户'}
|
||||
open={createModalOpen}
|
||||
onCancel={closeCreateModal}
|
||||
onOk={() => form.submit()}
|
||||
{/* 新建/编辑用户 Drawer */}
|
||||
<DrawerForm
|
||||
title={userDrawer.editingRecord ? '编辑用户' : '新建用户'}
|
||||
open={userDrawer.open}
|
||||
onClose={userDrawer.close}
|
||||
onSubmit={userDrawer.handleSubmit}
|
||||
initialValues={userDrawer.initialValues}
|
||||
loading={userDrawer.loading}
|
||||
width={480}
|
||||
columns={1}
|
||||
>
|
||||
<Form form={form} onFinish={handleCreateOrEdit} layout="vertical" style={{ marginTop: 16 }}>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="用户名"
|
||||
rules={[{ required: true, message: '请输入用户名' }]}
|
||||
>
|
||||
<Input prefix={<UserOutlined style={{ color: '#94a3b8' }} />} disabled={!!editUser} />
|
||||
<Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }]}>
|
||||
<Input prefix={<UserOutlined style={{ color: '#94a3b8' }} />} disabled={!!userDrawer.editingRecord} />
|
||||
</Form.Item>
|
||||
{!userDrawer.editingRecord && (
|
||||
<Form.Item name="password" label="密码" rules={[{ required: true, message: '请输入密码' }, { min: 6, message: '密码至少6位' }]}>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
{!editUser && (
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="密码"
|
||||
rules={[
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ min: 6, message: '密码至少6位' },
|
||||
]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item name="display_name" label="显示名">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="email"
|
||||
label="邮箱"
|
||||
rules={[{ type: 'email', message: '请输入有效的邮箱地址' }]}
|
||||
>
|
||||
<Input type="email" />
|
||||
</Form.Item>
|
||||
<Form.Item name="phone" label="电话">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
)}
|
||||
<Form.Item name="display_name" label="显示名"><Input /></Form.Item>
|
||||
<Form.Item name="email" label="邮箱" rules={[{ type: 'email', message: '请输入有效的邮箱地址' }]}>
|
||||
<Input type="email" />
|
||||
</Form.Item>
|
||||
<Form.Item name="phone" label="电话"><Input /></Form.Item>
|
||||
</DrawerForm>
|
||||
|
||||
{/* 角色分配弹窗 */}
|
||||
<Modal
|
||||
{/* 角色分配 Drawer */}
|
||||
<DrawerForm
|
||||
title={`分配角色 - ${selectedUser?.username || ''}`}
|
||||
open={roleModalOpen}
|
||||
onCancel={() => setRoleModalOpen(false)}
|
||||
onOk={handleAssignRoles}
|
||||
width={480}
|
||||
open={roleDrawerOpen}
|
||||
onClose={() => setRoleDrawerOpen(false)}
|
||||
onSubmit={async () => { await handleAssignRoles(); }}
|
||||
initialValues={{}}
|
||||
loading={false}
|
||||
width={520}
|
||||
columns={1}
|
||||
>
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Checkbox.Group
|
||||
@@ -458,26 +223,20 @@ export default function Users() {
|
||||
style={{ display: 'flex', flexDirection: 'column', gap: 12 }}
|
||||
>
|
||||
{allRoles.map((r) => (
|
||||
<div
|
||||
key={r.id}
|
||||
style={{
|
||||
padding: '10px 14px',
|
||||
borderRadius: 8,
|
||||
border: `1px solid ${isDark ? '#0f172a' : '#E2E8F0'}`,
|
||||
background: isDark ? '#0B0F1A' : '#f1f5f9',
|
||||
}}
|
||||
>
|
||||
<div key={r.id} style={{
|
||||
padding: '10px 14px', borderRadius: 8,
|
||||
border: `1px solid ${isDark ? '#0f172a' : '#E2E8F0'}`,
|
||||
background: isDark ? '#0B0F1A' : '#f1f5f9',
|
||||
}}>
|
||||
<Checkbox value={r.id}>
|
||||
<span style={{ fontWeight: 500 }}>{r.name}</span>
|
||||
<span style={{ color: isDark ? '#475569' : '#94a3b8', marginLeft: 8, fontSize: 12 }}>
|
||||
{r.code}
|
||||
</span>
|
||||
<span style={{ color: isDark ? '#475569' : '#94a3b8', marginLeft: 8, fontSize: 12 }}>{r.code}</span>
|
||||
</Checkbox>
|
||||
</div>
|
||||
))}
|
||||
</Checkbox.Group>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</DrawerForm>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user