diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index e0c18bf..7ffe36d 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -46,7 +46,6 @@ const AiPromptList = lazy(() => import('./pages/health/AiPromptList')); const AiAnalysisList = lazy(() => import('./pages/health/AiAnalysisList')); const AiUsageDashboard = lazy(() => import('./pages/health/AiUsageDashboard')); const AiConfigPage = lazy(() => import('./pages/health/AiConfigPage')); -const AiKnowledgePage = lazy(() => import('./pages/health/AiKnowledgePage')); const KnowledgeV2Page = lazy(() => import('./pages/ai/KnowledgeV2Page')); const AiChatPage = lazy(() => import('./pages/ai/ChatPage')); const AlertList = lazy(() => import('./pages/health/AlertList')); @@ -258,7 +257,7 @@ export default function App() { "/health/follow-up-records", "/health/consultations", "/health/points-rules", "/health/points-products", "/health/points-orders", "/health/offline-events", "/health/ai-prompts", "/health/ai-analysis", - "/health/ai-usage", "/health/ai-config", "/health/ai-knowledge", "/health/ai-knowledge-v2", "/health/alerts", "/health/alert-dashboard", + "/health/ai-usage", "/health/ai-config", "/health/ai-knowledge", "/health/alerts", "/health/alert-dashboard", "/ai/chat", "/health/alert-rules", "/health/devices", "/health/realtime-monitor", "/health/oauth-clients", "/health/dialysis", "/health/action-inbox", @@ -331,8 +330,7 @@ export default function App() { } /> } /> } /> - } /> - } /> + } /> } /> } /> } /> diff --git a/apps/web/src/api/ai/knowledge.ts b/apps/web/src/api/ai/knowledge.ts deleted file mode 100644 index 40bf9c0..0000000 --- a/apps/web/src/api/ai/knowledge.ts +++ /dev/null @@ -1,110 +0,0 @@ -import client from '../client'; - -// === Types === - -export interface KnowledgeReference { - id: string; - tenant_id: string; - title: string; - analysis_type: string; - source_name: string; - content_summary: string; - tags: Record | null; - is_enabled: boolean; - created_at: string; - updated_at: string; -} - -export interface KnowledgeGuide { - id: string; - tenant_id: string; - title: string; - analysis_type: string; - content: string; - category: string | null; - is_enabled: boolean; - created_at: string; - updated_at: string; -} - -export interface CreateReferenceReq { - title: string; - analysis_type: string; - source_name: string; - content_summary: string; - tags?: Record; - is_enabled?: boolean; -} - -export interface UpdateReferenceReq { - title?: string; - analysis_type?: string; - source_name?: string; - content_summary?: string; - tags?: Record; - is_enabled?: boolean; -} - -export interface CreateGuideReq { - title: string; - analysis_type: string; - content: string; - category?: string; - is_enabled?: boolean; -} - -export interface UpdateGuideReq { - title?: string; - analysis_type?: string; - content?: string; - category?: string; - is_enabled?: boolean; -} - -// === API === - -export const knowledgeApi = { - // References - listReferences: async (params?: { analysis_type?: string }) => { - const resp = await client.get('/ai/knowledge/references', { params }); - return resp.data.data as { data: KnowledgeReference[]; total: number }; - }, - createReference: async (data: CreateReferenceReq) => { - const resp = await client.post('/ai/knowledge/references', data); - return resp.data.data as { id: string }; - }, - updateReference: async (id: string, data: UpdateReferenceReq) => { - const resp = await client.put(`/ai/knowledge/references/${id}`, data); - return resp.data.data as { id: string }; - }, - deleteReference: async (id: string) => { - const resp = await client.delete(`/ai/knowledge/references/${id}`); - return resp.data.data as { id: string }; - }, - reEmbedReference: async (id: string) => { - const resp = await client.post(`/ai/knowledge/references/${id}/re-embed`); - return resp.data.data as { id: string }; - }, - - // Guides - listGuides: async (params?: { analysis_type?: string }) => { - const resp = await client.get('/ai/knowledge/guides', { params }); - return resp.data.data as { data: KnowledgeGuide[]; total: number }; - }, - createGuide: async (data: CreateGuideReq) => { - const resp = await client.post('/ai/knowledge/guides', data); - return resp.data.data as { id: string }; - }, - updateGuide: async (id: string, data: UpdateGuideReq) => { - const resp = await client.put(`/ai/knowledge/guides/${id}`, data); - return resp.data.data as { id: string }; - }, - deleteGuide: async (id: string) => { - const resp = await client.delete(`/ai/knowledge/guides/${id}`); - return resp.data.data as { id: string }; - }, - reEmbedGuide: async (id: string) => { - const resp = await client.post(`/ai/knowledge/guides/${id}/re-embed`); - return resp.data.data as { id: string }; - }, -}; diff --git a/apps/web/src/pages/health/AiKnowledgePage.tsx b/apps/web/src/pages/health/AiKnowledgePage.tsx deleted file mode 100644 index 418ecb7..0000000 --- a/apps/web/src/pages/health/AiKnowledgePage.tsx +++ /dev/null @@ -1,508 +0,0 @@ -import { useCallback, useEffect, useState } from 'react'; -import { - Card, - Table, - Button, - Space, - Modal, - Form, - Input, - Select, - Switch, - message, - Popconfirm, - Tabs, - Tag, - Tooltip, -} from 'antd'; -import { - PlusOutlined, - EditOutlined, - DeleteOutlined, - ReloadOutlined, - ThunderboltOutlined, -} from '@ant-design/icons'; -import { - knowledgeApi, - type KnowledgeReference, - type KnowledgeGuide, - type CreateReferenceReq, - type UpdateReferenceReq, - type CreateGuideReq, - type UpdateGuideReq, -} from '../../api/ai/knowledge'; -import { AuthButton } from '../../components/AuthButton'; - -const ANALYSIS_TYPES = [ - { value: 'lab_report', label: '化验报告' }, - { value: 'trend', label: '趋势分析' }, - { value: 'report_summary', label: '报告摘要' }, - { value: 'dialysis_risk', label: '透析风险' }, - { value: 'checkup_plan', label: '体检计划' }, - { value: 'follow_up', label: '随访总结' }, -]; - -export default function AiKnowledgePage() { - return ( - - }, - { key: 'guides', label: '临床指南', children: }, - ]} - /> - - ); -} - -// === References Tab === - -function ReferencesTab() { - const [data, setData] = useState([]); - const [loading, setLoading] = useState(false); - const [modalOpen, setModalOpen] = useState(false); - const [editing, setEditing] = useState(null); - const [filterType, setFilterType] = useState(); - const [form] = Form.useForm(); - - const fetchData = useCallback(async () => { - setLoading(true); - try { - const result = await knowledgeApi.listReferences( - filterType ? { analysis_type: filterType } : undefined, - ); - setData(result.data); - } catch { - message.error('加载参考资料失败'); - } finally { - setLoading(false); - } - }, [filterType]); - - useEffect(() => { - fetchData(); - }, [fetchData]); - - const openCreate = () => { - setEditing(null); - form.resetFields(); - form.setFieldsValue({ is_enabled: true }); - setModalOpen(true); - }; - - const openEdit = (record: KnowledgeReference) => { - setEditing(record); - form.setFieldsValue({ - title: record.title, - analysis_type: record.analysis_type, - source_name: record.source_name, - content_summary: record.content_summary, - is_enabled: record.is_enabled, - }); - setModalOpen(true); - }; - - const handleSubmit = async () => { - const values = await form.validateFields(); - try { - if (editing) { - const req: UpdateReferenceReq = { - title: values.title, - analysis_type: values.analysis_type, - source_name: values.source_name, - content_summary: values.content_summary, - is_enabled: values.is_enabled, - }; - await knowledgeApi.updateReference(editing.id, req); - message.success('更新成功'); - } else { - const req: CreateReferenceReq = { - title: values.title, - analysis_type: values.analysis_type, - source_name: values.source_name, - content_summary: values.content_summary, - is_enabled: values.is_enabled, - }; - await knowledgeApi.createReference(req); - message.success('创建成功'); - } - setModalOpen(false); - fetchData(); - } catch { - message.error(editing ? '更新失败' : '创建失败'); - } - }; - - const handleDelete = async (id: string) => { - try { - await knowledgeApi.deleteReference(id); - message.success('删除成功'); - fetchData(); - } catch { - message.error('删除失败'); - } - }; - - const handleReEmbed = async (id: string) => { - try { - await knowledgeApi.reEmbedReference(id); - message.success('向量重新生成已触发'); - } catch { - message.error('向量重新生成失败'); - } - }; - - const columns = [ - { title: '标题', dataIndex: 'title', key: 'title', ellipsis: true }, - { - title: '分析类型', - dataIndex: 'analysis_type', - key: 'analysis_type', - width: 120, - render: (v: string) => { - const found = ANALYSIS_TYPES.find((t) => t.value === v); - return {found?.label ?? v}; - }, - }, - { title: '来源', dataIndex: 'source_name', key: 'source_name', width: 150, ellipsis: true }, - { - title: '状态', - dataIndex: 'is_enabled', - key: 'is_enabled', - width: 80, - render: (v: boolean) => ( - {v ? '启用' : '禁用'} - ), - }, - { - title: '更新时间', - dataIndex: 'updated_at', - key: 'updated_at', - width: 170, - render: (v: string) => (v ? new Date(v).toLocaleString() : '-'), - }, - { - title: '操作', - key: 'actions', - width: 200, - render: (_: unknown, record: KnowledgeReference) => ( - - -