diff --git a/admin-v2/src/pages/Knowledge.tsx b/admin-v2/src/pages/Knowledge.tsx index 09aa164..6a95a06 100644 --- a/admin-v2/src/pages/Knowledge.tsx +++ b/admin-v2/src/pages/Knowledge.tsx @@ -2,15 +2,18 @@ // 知识库管理 // ============================================================ -import { useState, useMemo } from 'react' +import { useState, useMemo, useEffect } 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, + Table, Tooltip, } from 'antd' import { PlusOutlined, SearchOutlined, BookOutlined, FolderOutlined, DeleteOutlined, EditOutlined, EyeOutlined, BarChartOutlined, + HistoryOutlined, RollbackOutlined, + WarningOutlined, } from '@ant-design/icons' import type { ProColumns } from '@ant-design/pro-components' import { ProTable } from '@ant-design/pro-components' @@ -25,7 +28,9 @@ const { Text, Title } = Typography function CategoriesPanel() { const queryClient = useQueryClient() const [createOpen, setCreateOpen] = useState(false) - const [form] = Form.useForm() + const [editItem, setEditItem] = useState(null) + const [createForm] = Form.useForm() + const [editForm] = Form.useForm() const { data: categories = [], isLoading } = useQuery({ queryKey: ['knowledge-categories'], @@ -39,7 +44,7 @@ function CategoriesPanel() { message.success('分类已创建') queryClient.invalidateQueries({ queryKey: ['knowledge-categories'] }) setCreateOpen(false) - form.resetFields() + createForm.resetFields() }, onError: (err: Error) => message.error(err.message || '创建失败'), }) @@ -53,6 +58,40 @@ function CategoriesPanel() { onError: (err: Error) => message.error(err.message || '删除失败'), }) + const updateMutation = useMutation({ + mutationFn: ({ id, ...data }: { id: string } & Record) => + knowledgeService.updateCategory(id, data), + onSuccess: () => { + message.success('分类已更新') + queryClient.invalidateQueries({ queryKey: ['knowledge-categories'] }) + setEditItem(null) + }, + onError: (err: Error) => message.error(err.message || '更新失败'), + }) + + // 编辑弹窗打开时同步表单值(Ant Design Form initialValues 仅首次挂载生效) + useEffect(() => { + if (editItem) { + editForm.setFieldsValue({ + name: editItem.name, + description: editItem.description, + parent_id: editItem.parent_id, + icon: editItem.icon, + }) + } + }, [editItem, editForm]) + + // 获取当前编辑分类及其所有后代的 ID(防止循环引用) + const getDescendantIds = (id: string, cats: CategoryResponse[]): string[] => { + const ids: string[] = [id] + for (const c of cats) { + if (c.parent_id === id) { + ids.push(...getDescendantIds(c.id, cats)) + } + } + return ids + } + const treeData = useMemo( () => buildTreeData(categories, (id) => { Modal.confirm({ @@ -61,6 +100,8 @@ function CategoriesPanel() { okType: 'danger', onOk: () => deleteMutation.mutate(id), }) + }, (id) => { + setEditItem(categories.find((c) => c.id === id) || null) }), [categories, deleteMutation], ) @@ -87,14 +128,15 @@ function CategoriesPanel() { /> )} + {/* 新建分类弹窗 */} setCreateOpen(false)} - onOk={() => form.submit()} + onCancel={() => { setCreateOpen(false); createForm.resetFields() }} + onOk={() => createForm.submit()} confirmLoading={createMutation.isPending} > -
createMutation.mutate(v)}> + createMutation.mutate(v)}> @@ -113,6 +155,40 @@ function CategoriesPanel() {
+ + {/* 编辑分类弹窗 */} + { setEditItem(null); editForm.resetFields() }} + onOk={() => editForm.submit()} + confirmLoading={updateMutation.isPending} + > +
editItem && updateMutation.mutate({ id: editItem.id, ...v })} + > + + + + +