// ============================================================ // 角色与权限模板管理 // ============================================================ import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Button, message, Tag, Modal, Form, Input, Select, Space, Popconfirm, Tabs, Tooltip, } from 'antd' import { PlusOutlined, SafetyOutlined, CheckCircleOutlined } from '@ant-design/icons' import type { ProColumns } from '@ant-design/pro-components' import { ProTable } from '@ant-design/pro-components' import { roleService } from '@/services/roles' import { PageHeader } from '@/components/PageHeader' import type { Role, PermissionTemplate, CreateRoleRequest, UpdateRoleRequest, CreateTemplateRequest, } from '@/types' // ============================================================ // 常见权限选项 // ============================================================ const permissionOptions = [ { value: 'account:admin', label: 'account:admin' }, { value: 'provider:manage', label: 'provider:manage' }, { value: 'model:read', label: 'model:read' }, { value: 'model:write', label: 'model:write' }, { value: 'relay:use', label: 'relay:use' }, { value: 'knowledge:read', label: 'knowledge:read' }, { value: 'knowledge:write', label: 'knowledge:write' }, { value: 'billing:read', label: 'billing:read' }, { value: 'billing:write', label: 'billing:write' }, { value: 'config:read', label: 'config:read' }, { value: 'config:write', label: 'config:write' }, { value: 'prompt:read', label: 'prompt:read' }, { value: 'prompt:write', label: 'prompt:write' }, { value: 'admin:full', label: 'admin:full' }, ] // ============================================================ // Roles Tab // ============================================================ function RolesTab() { const queryClient = useQueryClient() const [form] = Form.useForm() const [modalOpen, setModalOpen] = useState(false) const [editingId, setEditingId] = useState(null) const { data, isLoading } = useQuery({ queryKey: ['roles'], queryFn: ({ signal }) => roleService.list(signal), }) const createMutation = useMutation({ mutationFn: (data: CreateRoleRequest) => roleService.create(data), onSuccess: () => { message.success('角色已创建') queryClient.invalidateQueries({ queryKey: ['roles'] }) setModalOpen(false) form.resetFields() }, onError: (err: Error) => message.error(err.message || '创建失败'), }) const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: UpdateRoleRequest }) => roleService.update(id, data), onSuccess: () => { message.success('角色已更新') queryClient.invalidateQueries({ queryKey: ['roles'] }) setModalOpen(false) }, onError: (err: Error) => message.error(err.message || '更新失败'), }) const deleteMutation = useMutation({ mutationFn: (id: string) => roleService.delete(id), onSuccess: () => { message.success('角色已删除') queryClient.invalidateQueries({ queryKey: ['roles'] }) }, onError: (err: Error) => message.error(err.message || '删除失败'), }) const handleSave = async () => { const values = await form.validateFields() if (editingId) { updateMutation.mutate({ id: editingId, data: values }) } else { createMutation.mutate(values) } } const openEdit = async (record: Role) => { setEditingId(record.id) const permissions = await roleService.getPermissions(record.id).catch(() => record.permissions) form.setFieldsValue({ ...record, permissions }) setModalOpen(true) } const openCreate = () => { setEditingId(null) form.resetFields() setModalOpen(true) } const closeModal = () => { setModalOpen(false) setEditingId(null) form.resetFields() } const columns: ProColumns[] = [ { title: '角色名称', dataIndex: 'name', width: 160, render: (_, record) => ( {record.name} ), }, { title: '描述', dataIndex: 'description', width: 240, ellipsis: true, render: (_, record) => record.description || '-', }, { title: '权限数', dataIndex: 'permissions', width: 100, render: (_, record) => ( {record.permissions?.length ?? 0} 项 ), }, { title: '关联账号', dataIndex: 'account_count', width: 100, render: (_, record) => record.account_count ?? 0, }, { title: '创建时间', dataIndex: 'created_at', width: 180, render: (_, record) => record.created_at ? new Date(record.created_at).toLocaleString('zh-CN') : '-', }, { title: '操作', width: 160, render: (_, record) => ( deleteMutation.mutate(record.id)} > ), }, ] return (
columns={columns} dataSource={data ?? []} loading={isLoading} rowKey="id" search={false} toolBarRender={() => [ , ]} pagination={{ showSizeChanger: false }} />