diff --git a/admin-v2/src/layouts/AdminLayout.tsx b/admin-v2/src/layouts/AdminLayout.tsx index a2d065c..c4555b4 100644 --- a/admin-v2/src/layouts/AdminLayout.tsx +++ b/admin-v2/src/layouts/AdminLayout.tsx @@ -16,6 +16,7 @@ import { SunOutlined, MoonOutlined, ApiOutlined, + BookOutlined, } from '@ant-design/icons' import { Avatar, Dropdown, Tooltip, Drawer } from 'antd' import { useAuthStore } from '@/stores/authStore' @@ -42,6 +43,7 @@ const navItems: NavItem[] = [ { path: '/api-keys', name: 'API 密钥', icon: , permission: 'provider:manage', group: '资源管理' }, { path: '/usage', name: '用量统计', icon: , permission: 'admin:full', group: '运维' }, { path: '/relay', name: '中转任务', icon: , permission: 'relay:use', group: '运维' }, + { path: '/knowledge', name: '知识库', icon: , permission: 'knowledge:read', group: '资源管理' }, { path: '/logs', name: '操作日志', icon: , permission: 'admin:full', group: '运维' }, { path: '/config', name: '系统配置', icon: , permission: 'config:read', group: '系统' }, { path: '/prompts', name: '提示词管理', icon: , permission: 'prompt:read', group: '系统' }, @@ -204,6 +206,7 @@ const breadcrumbMap: Record = { '/agent-templates': 'Agent 模板', '/usage': '用量统计', '/relay': '中转任务', + '/knowledge': '知识库', '/config': '系统配置', '/prompts': '提示词管理', '/logs': '操作日志', diff --git a/admin-v2/src/pages/Knowledge.tsx b/admin-v2/src/pages/Knowledge.tsx new file mode 100644 index 0000000..09aa164 --- /dev/null +++ b/admin-v2/src/pages/Knowledge.tsx @@ -0,0 +1,503 @@ +// ============================================================ +// 知识库管理 +// ============================================================ + +import { useState, useMemo } from 'react' +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' +import { + Button, message, Tag, Modal, Form, Input, Select, Space, Popconfirm, + Card, Statistic, Row, Col, Tabs, Tree, Typography, Empty, Spin, InputNumber, +} from 'antd' +import { + PlusOutlined, SearchOutlined, BookOutlined, FolderOutlined, + DeleteOutlined, EditOutlined, EyeOutlined, BarChartOutlined, +} from '@ant-design/icons' +import type { ProColumns } from '@ant-design/pro-components' +import { ProTable } from '@ant-design/pro-components' +import { knowledgeService } from '@/services/knowledge' +import type { CategoryResponse, KnowledgeItem, SearchResult } from '@/services/knowledge' + +const { TextArea } = Input +const { Text, Title } = Typography + +// === 分类树 + 条目列表 Tab === + +function CategoriesPanel() { + const queryClient = useQueryClient() + const [createOpen, setCreateOpen] = useState(false) + const [form] = Form.useForm() + + const { data: categories = [], isLoading } = useQuery({ + queryKey: ['knowledge-categories'], + queryFn: ({ signal }) => knowledgeService.listCategories(signal), + }) + + const createMutation = useMutation({ + mutationFn: (data: Parameters[0]) => + knowledgeService.createCategory(data), + onSuccess: () => { + message.success('分类已创建') + queryClient.invalidateQueries({ queryKey: ['knowledge-categories'] }) + setCreateOpen(false) + form.resetFields() + }, + onError: (err: Error) => message.error(err.message || '创建失败'), + }) + + const deleteMutation = useMutation({ + mutationFn: (id: string) => knowledgeService.deleteCategory(id), + onSuccess: () => { + message.success('分类已删除') + queryClient.invalidateQueries({ queryKey: ['knowledge-categories'] }) + }, + onError: (err: Error) => message.error(err.message || '删除失败'), + }) + + const treeData = useMemo( + () => buildTreeData(categories, (id) => { + Modal.confirm({ + title: '确认删除', + content: '删除后无法恢复,请确保分类下没有子分类和条目。', + okType: 'danger', + onOk: () => deleteMutation.mutate(id), + }) + }), + [categories, deleteMutation], + ) + + return ( +
+
+ 分类管理 + +
+ + {isLoading ? ( +
+ ) : categories.length === 0 ? ( + + ) : ( + + )} + + setCreateOpen(false)} + onOk={() => form.submit()} + confirmLoading={createMutation.isPending} + > +
createMutation.mutate(v)}> + + + + +