diff --git a/src/api/knowledge.ts b/src/api/knowledge.ts index 8d03260..d92cf8a 100644 --- a/src/api/knowledge.ts +++ b/src/api/knowledge.ts @@ -13,4 +13,5 @@ export const knowledgeAPI = { sourceReferences(sourceId: string) { return api.get(`/admin-api/knowledge-bases/sources/${sourceId}/references`) }, allSources(params: string) { return api.get>(`/admin-api/knowledge-bases/all-sources?${params}`) }, search(params: string) { return api.get>(`/admin-api/knowledge-bases?${params}`) }, + verifyFiles() { return api.get<{ total: number; missing: number; missingFiles: { sourceId: string; filename: string; objectKey: string; exists: boolean }[] }>('/admin-api/knowledge-bases/verify-files') }, } diff --git a/src/pages/KnowledgeSources.tsx b/src/pages/KnowledgeSources.tsx index e6f088b..004c0ca 100644 --- a/src/pages/KnowledgeSources.tsx +++ b/src/pages/KnowledgeSources.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { Table, Tag, Space, Input, Select, Typography } from 'antd' +import { Table, Tag, Space, Input, Select, Typography, Tooltip } from 'antd' import { SearchOutlined } from '@ant-design/icons' import { useQuery } from '@tanstack/react-query' import { knowledgeAPI } from '@/api' @@ -71,9 +71,27 @@ export default function KnowledgeSourcesPage() { staleTime: 60_000, }) + const { data: fileCheck } = useQuery({ + queryKey: ['admin', 'verify-files'], + queryFn: () => knowledgeAPI.verifyFiles(), + staleTime: 30_000, + refetchOnMount: true, + }) + + const missingMap = new Set((fileCheck?.missingFiles || []).map(f => f.sourceId)) + const columns = [ { title: '文件名', dataIndex: 'originalFilename', width: 220, ellipsis: true, render: (v: string, r: KnowledgeSourceItem) => v || r.title || '-' }, { title: '知识库', dataIndex: 'kbName', width: 140, ellipsis: true, render: (v: string, r: KnowledgeSourceItem) => v || r.knowledgeBaseId }, + { + title: '文件', dataIndex: 'id', width: 60, + render: (id: string) => { + if (!fileCheck) return null + return missingMap.has(id) + ? + : + }, + }, { title: '类型', dataIndex: 'mimeType', width: 80, render: (v: string) => mimeLabels[v] || v?.split('/').pop() || '-' }, { title: '大小', dataIndex: 'sizeBytes', width: 80, render: (v: number) => v ? `${(v / 1024).toFixed(1)} KB` : '-' }, { title: '字数', dataIndex: 'textLength', width: 70, render: (v: number | undefined) => v != null ? v : '-' },