import React, { useEffect, useState } from 'react'; import { Card, Tag, Input, Space, Spin, Empty } from 'antd'; import api from '../../api'; import { message } from '../../ui/app-message'; interface PermissionItem { id: number; code: string; name: string; group: string; description: string; } const PermissionsPage: React.FC = () => { const [permTree, setPermTree] = useState<{ group: string; permissions: PermissionItem[] }[]>([]); const [loading, setLoading] = useState(false); const [search, setSearch] = useState(''); const groupNames: Record = { dashboard: '数据面板', student: '学生管理', 'student-scope': '学生数据范围', teacher: '教师管理', 'teacher-workspace': '教师工作台', 'attendance-scope': '考勤数据范围', room: '宿舍管理', occupancy: '入住管理', expense: '费用管理', bill: '账单管理', deposit: '押金管理', classroom: '教室管理', organization: '机构管理', rental: '租赁订单', log: '操作日志', user: '用户管理', role: '角色管理', class: '班级管理', schedule: '排课管理', attendance: '考勤管理', learning: '学习记录', exam: '考试管理', sync: '数据同步', integration: '集成配置', department: '部门管理', notification: '通知中心', profile: '个人资料', ai: 'AI 模型配置', }; useEffect(() => { setLoading(true); api .get('/rbac/permissions/tree') .then((res: any) => setPermTree(res)) .catch((e: unknown) => { const err = e as { message?: string }; message.error(err?.message || '加载权限失败'); }) .finally(() => setLoading(false)); }, []); const filteredTree = search ? permTree .map((g) => ({ ...g, permissions: g.permissions.filter( (p) => p.name.includes(search) || p.code.includes(search), ), })) .filter((g) => g.permissions.length > 0) : permTree; if (loading) return ; return (

权限一览

!e.target.value && setSearch('')} />
{filteredTree.map((group) => ( {groupNames[group.group] || group.group} ({group.permissions.length}) } size="small" > {group.permissions.map((p) => ( {p.name}{' '} {p.code} ))} ))} {filteredTree.length === 0 && }
); }; export default PermissionsPage;