'use client' import { useState, useEffect } from 'react' import { Card, Button, Table, Badge, Modal, Input } from '@/components/ui' import { Plus, Pencil, Trash2 } from 'lucide-react' interface Role { id: number name: string display_name: string permissions: string created_at: string } const allPermissions = [ { key: 'tickets:read', label: '查看工单' }, { key: 'tickets:write', label: '编辑工单' }, { key: 'reports:read', label: '查看报告' }, { key: 'reports:write', label: '编辑报告' }, { key: 'users:read', label: '查看用户' }, { key: 'users:write', label: '编辑用户' }, { key: 'roles:read', label: '查看角色' }, { key: 'roles:write', label: '编辑角色' }, ] export default function RolesPage() { const [roles, setRoles] = useState([]) const [loading, setLoading] = useState(true) const [modalOpen, setModalOpen] = useState(false) const [editRole, setEditRole] = useState(null) const [form, setForm] = useState({ name: '', display_name: '', permissions: [] as string[] }) const [error, setError] = useState('') const fetchRoles = () => { fetch('/api/roles').then(r => r.json()).then(d => { if (d.roles) setRoles(d.roles) }).catch(() => {}).finally(() => setLoading(false)) } useEffect(() => { fetchRoles() }, []) const openCreate = () => { setEditRole(null) setForm({ name: '', display_name: '', permissions: [] }) setError('') setModalOpen(true) } const openEdit = (r: Role) => { setEditRole(r) let perms: string[] = [] try { perms = JSON.parse(r.permissions) } catch {} setForm({ name: r.name, display_name: r.display_name, permissions: perms }) setError('') setModalOpen(true) } const togglePermission = (key: string) => { setForm(prev => ({ ...prev, permissions: prev.permissions.includes(key) ? prev.permissions.filter(p => p !== key) : [...prev.permissions, key], })) } const handleSave = async () => { setError('') try { if (editRole) { const res = await fetch(`/api/roles/${editRole.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ display_name: form.display_name, permissions: form.permissions }) }) if (!res.ok) { const d = await res.json(); setError(d.error || '更新失败'); return } } else { if (!form.name || !form.display_name) { setError('请填写必填项'); return } const res = await fetch('/api/roles', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(form) }) if (!res.ok) { const d = await res.json(); setError(d.error || '创建失败'); return } } setModalOpen(false) fetchRoles() } catch { setError('操作失败') } } const handleDelete = async (id: number) => { if (!confirm('确定删除此角色?')) return const res = await fetch(`/api/roles/${id}`, { method: 'DELETE' }) if (res.ok) fetchRoles() else { const d = await res.json(); alert(d.error || '删除失败') } } const formatPermissions = (permStr: string) => { try { const perms: string[] = JSON.parse(permStr) if (perms.includes('*')) return '全部权限' return perms.map(p => { const f = allPermissions.find(a => a.key === p); return f ? f.label : p }).join(', ') || '无权限' } catch { return '无权限' } } const builtinRoles = ['admin', 'operator', 'viewer'] return (

角色权限

角色与权限配置

{loading ? (
加载中...
) : ( {roles.map(r => ( ))}
{r.name} {r.display_name} {formatPermissions(r.permissions)}
{!builtinRoles.includes(r.name) && ( )}
)} setModalOpen(false)} title={editRole ? '编辑角色' : '新建角色'}>
{!editRole && setForm(p => ({ ...p, name: e.target.value }))} placeholder="e.g. supervisor" />} setForm(p => ({ ...p, display_name: e.target.value }))} />
{allPermissions.map(p => ( ))}
{error &&

{error}

}
) }