import React, { useEffect, useState } from 'react'; import { Table, Modal, Form, Input, Space, Tag, Popconfirm, message, Card, Checkbox, } from 'antd'; import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; import api from '../../api'; import PermissionButton from '../../components/PermissionButton'; interface PermissionItem { id: number; code: string; name: string; group: string; } interface RoleItem { id: number; name: string; description: string; isSystem: boolean; status: number; permissions: PermissionItem[]; } const RolesPage: React.FC = () => { const [data, setData] = useState([]); const [loading, setLoading] = useState(false); const [modalOpen, setModalOpen] = useState(false); const [editing, setEditing] = useState(null); const [allPerms, setAllPerms] = useState<{ group: string; permissions: PermissionItem[] }[]>([]); const [form] = Form.useForm(); const [selectedPermIds, setSelectedPermIds] = useState([]); const fetchData = async () => { setLoading(true); try { const [roles, permTree] = await Promise.all([ api.get('/rbac/roles') as Promise, api.get('/rbac/permissions/tree') as Promise< { group: string; permissions: PermissionItem[] }[] >, ]); setData(roles); setAllPerms(permTree); } catch (e) { console.error(e); } setLoading(false); }; useEffect(() => { fetchData(); }, []); const handleAdd = () => { setEditing(null); form.resetFields(); setSelectedPermIds([]); setModalOpen(true); }; const handleEdit = (record: RoleItem) => { setEditing(record); form.setFieldsValue({ name: record.name, description: record.description }); setSelectedPermIds(record.permissions.map((p) => p.id)); setModalOpen(true); }; const handleSubmit = async () => { const values = await form.validateFields(); try { if (editing) { await api.put(`/rbac/roles/${editing.id}`, { name: values.name, description: values.description, permissionIds: selectedPermIds, }); message.success('角色更新成功'); } else { await api.post('/rbac/roles', { name: values.name, description: values.description, permissionIds: selectedPermIds, }); message.success('角色创建成功'); } setModalOpen(false); fetchData(); } catch (e: any) { message.error(e.message || '操作失败'); } }; const handleDelete = async (id: number) => { try { await api.delete(`/rbac/roles/${id}`); message.success('角色已删除'); fetchData(); } catch (e: any) { message.error(e.message || '删除失败'); } }; const groupNames: Record = { dashboard: '数据面板', student: '学生管理', room: '宿舍管理', occupancy: '入住管理', expense: '费用管理', bill: '账单管理', deposit: '押金管理', classroom: '教室管理', tenant: '租赁方', rental: '租赁订单', log: '操作日志', user: '用户管理', role: '角色管理', }; const columns = [ { title: 'ID', dataIndex: 'id', width: 60 }, { title: '名称', dataIndex: 'name', width: 120 }, { title: '描述', dataIndex: 'description', width: 200, ellipsis: true }, { title: '权限标签', dataIndex: 'permissions', width: 150, ellipsis: true, render: (perms: PermissionItem[]) => perms?.length > 0 ? ( {perms.length} 个权限 ) : ( 无权限 ), }, { title: '系统', dataIndex: 'isSystem', width: 70, render: (v: boolean) => (v ? 系统 : null), }, { title: '操作', width: 160, fixed: 'right' as const, render: (_: any, record: RoleItem) => ( } onClick={() => handleEdit(record)} > 编辑 {!record.isSystem && ( handleDelete(record.id)}> }> 删除 )} ), }, ]; const handleGroupCheckAll = (group: string, checked: boolean) => { const groupPermIds = allPerms.find((g) => g.group === group)?.permissions.map((p) => p.id) || []; if (checked) { setSelectedPermIds((prev) => [...new Set([...prev, ...groupPermIds])]); } else { setSelectedPermIds((prev) => prev.filter((id) => !groupPermIds.includes(id))); } }; const isGroupAllChecked = (group: string) => { const groupPermIds = allPerms.find((g) => g.group === group)?.permissions.map((p) => p.id) || []; return groupPermIds.length > 0 && groupPermIds.every((id) => selectedPermIds.includes(id)); }; const isGroupIndeterminate = (group: string) => { const groupPermIds = allPerms.find((g) => g.group === group)?.permissions.map((p) => p.id) || []; const checkedCount = groupPermIds.filter((id) => selectedPermIds.includes(id)).length; return checkedCount > 0 && checkedCount < groupPermIds.length; }; return (

角色管理

} onClick={handleAdd} > 新增角色
setModalOpen(false)} width={700} destroyOnHidden >
{allPerms.map((group) => ( handleGroupCheckAll(group.group, e.target.checked)} > {groupNames[group.group] || group.group} } style={{ marginBottom: 8 }} > setSelectedPermIds(vals as number[])} > {group.permissions.map((p) => ( {p.name} ))} ))}
); }; export default RolesPage;