diff --git a/.gitignore b/.gitignore index 7ceb59f..c8ef453 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ dist-ssr *.sln *.sw? .env +uploads/ diff --git a/src/api/imports.ts b/src/api/imports.ts index 4d9a7ab..2f1d5fb 100644 --- a/src/api/imports.ts +++ b/src/api/imports.ts @@ -6,4 +6,5 @@ export const importsAdminAPI = { detail: (id: string) => api.get(`/admin-api/imports/${id}`), retry: (id: string) => api.post(`/admin-api/imports/${id}/retry`), batchRetry: (ids: string[]) => api.post('/admin-api/imports/batch-retry', { ids }), + remove: (id: string) => api.delete<{ success: boolean; deletedId: string; deletedSource: boolean }>(`/admin-api/imports/${id}`), } diff --git a/src/api/knowledge.ts b/src/api/knowledge.ts index d92cf8a..bcd14f9 100644 --- a/src/api/knowledge.ts +++ b/src/api/knowledge.ts @@ -1,5 +1,5 @@ import { api } from '@/lib/api-client' -import type { KnowledgeBase, KnowledgeSource, PaginatedResult, SourceReference, KnowledgeCandidate, KnowledgeChunk } from '@/types' +import type { KnowledgeBase, KnowledgeSource, PaginatedResult, SourceReference, KnowledgeChunk } from '@/types' export const knowledgeAPI = { list(page = 1, limit = 20) { @@ -7,7 +7,6 @@ export const knowledgeAPI = { }, getById(id: string) { return api.get(`/admin-api/knowledge-bases/${id}`) }, remove(id: string) { return api.delete(`/admin-api/knowledge-bases/${id}`) }, - candidates() { return api.get('/admin-api/knowledge-bases/candidates?limit=50') }, chunks(sourceId: string) { return api.get(`/admin-api/knowledge-bases/chunks?sourceId=${sourceId}&limit=50`) }, sources(kbId: string) { return api.get(`/admin-api/knowledge-bases/${kbId}/sources`) }, sourceReferences(sourceId: string) { return api.get(`/admin-api/knowledge-bases/sources/${sourceId}/references`) }, diff --git a/src/constants/labels.ts b/src/constants/labels.ts index dc2d683..03aa434 100644 --- a/src/constants/labels.ts +++ b/src/constants/labels.ts @@ -91,7 +91,6 @@ export const importStatusLabels: Record = { CHUNKING: '分段中', EMBEDDING: '向量化中', INDEXING: '索引中', - GENERATING_CANDIDATES: '生成候选中', COMPLETED: '已完成', FAILED: '失败', FAILED_RETRYABLE: '失败(可重试)', @@ -109,7 +108,6 @@ export const importStepLabels: Record = { CHUNKING: '文本分段', EMBEDDING: '向量化', INDEXING: '写入索引', - GENERATING_CANDIDATES: 'AI 生成候选', COMPLETED: '已完成', FAILED: '失败', FAILED_RETRYABLE: '失败(可重试)', @@ -130,11 +128,6 @@ export const userStatusLabels: Record = { // ── Knowledge ── export const kbStatusLabels: Record = { active: '正常' }; -export const candidateStatusLabels: Record = { - PENDING: '待审核', - ACCEPTED: '已通过', - REJECTED: '已拒绝', -}; // ── Hermes / Agent ── export const agentTaskStatusLabels: Record = { diff --git a/src/pages/ImportMonitor.tsx b/src/pages/ImportMonitor.tsx index b26aff0..393f7bc 100644 --- a/src/pages/ImportMonitor.tsx +++ b/src/pages/ImportMonitor.tsx @@ -1,7 +1,7 @@ import { useState, useCallback, useRef } from 'react' import { useQuery, useQueryClient } from '@tanstack/react-query' import { Table, Tag, Typography, Button, App, Drawer, Space, Select, Popconfirm, Row, Col, Checkbox } from 'antd' -import { ReloadOutlined, RetweetOutlined, ImportOutlined, EyeOutlined } from '@ant-design/icons' +import { ReloadOutlined, RetweetOutlined, ImportOutlined, EyeOutlined, DeleteOutlined } from '@ant-design/icons' import { importsAdminAPI, knowledgeAPI } from '@/api' import { importStatusLabels, importStepLabels } from '@/constants/labels' import type { TablePaginationConfig } from 'antd' @@ -73,6 +73,17 @@ export default function ImportMonitorPage() { qc.invalidateQueries({ queryKey: ['admin-imports', 'list'] }) } + const handleDelete = async (id: string) => { + try { + await importsAdminAPI.remove(id) + message.success('已删除') + refreshList() + } catch (err: unknown) { + const e = err as { response?: { data?: { message?: string } }; message?: string } + message.error(e?.response?.data?.message || e?.message || '删除失败') + } + } + const handleRetry = async (id: string, sourceDeleted?: boolean) => { if (sourceDeleted) { message.warning('关联的资料来源已删除,无法重新解析。请删除此导入记录后重新上传文件。') @@ -135,7 +146,7 @@ export default function ImportMonitorPage() { const statusColor: Record = { COMPLETED: 'green', QUEUED: 'default', CLAIMED: 'blue', DOWNLOADING: 'processing', PARSING: 'processing', CHUNKING: 'processing', - EMBEDDING: 'processing', INDEXING: 'processing', GENERATING_CANDIDATES: 'processing', + EMBEDDING: 'processing', INDEXING: 'processing', FAILED: 'red', FAILED_RETRYABLE: 'orange', CANCELLED: 'default', } @@ -155,6 +166,9 @@ export default function ImportMonitorPage() { + handleDelete(r.id)}> + + ) }, ] @@ -198,8 +212,13 @@ export default function ImportMonitorPage() { size="small" onChange={(_pagination: TablePaginationConfig, _filters: Record, sorter: SorterResult | SorterResult[]) => { const s = Array.isArray(sorter) ? sorter[0] : sorter - if (s.columnKey) setSortBy(String(s.columnKey)) - setSortOrder(s.order || 'descend') + if (s.order) { + setSortBy(String(s.columnKey || 'createdAt')) + setSortOrder(s.order) + } else { + setSortBy('createdAt') + setSortOrder('descend') + } }} /> { setDrawerOpen(false); setSelectedJob(null) }} width={700}> diff --git a/src/pages/KnowledgeOps.tsx b/src/pages/KnowledgeOps.tsx index b11809d..8639436 100644 --- a/src/pages/KnowledgeOps.tsx +++ b/src/pages/KnowledgeOps.tsx @@ -3,8 +3,6 @@ import { useQuery, useQueryClient } from '@tanstack/react-query' import { Table, Tag, Typography, Button, App, Tabs, Input, Card, Space } from 'antd' import { ReloadOutlined, SearchOutlined, ExperimentOutlined } from '@ant-design/icons' import { knowledgeAPI, vectorAPI } from '@/api' -import { candidateStatusLabels } from '@/constants/labels' -import dayjs from 'dayjs' const { Title, Text } = Typography @@ -14,11 +12,6 @@ export default function KnowledgeOpsPage() { const [sourceId, setSourceId] = useState('') const [debugQuery, setDebugQuery] = useState('') - const { data: candidates } = useQuery({ - queryKey: ['ops', 'candidates'], - queryFn: () => knowledgeAPI.candidates(), - }) - const { data: chunks } = useQuery({ queryKey: ['ops', 'chunks', sourceId], queryFn: () => knowledgeAPI.chunks(sourceId), @@ -31,15 +24,6 @@ export default function KnowledgeOpsPage() { message.info(JSON.stringify(res.data)) } - const candidateCols = [ - { title: '标题', dataIndex: 'title', width: 200, ellipsis: true }, - { title: '用户', dataIndex: 'userId', width: 120, ellipsis: true, render: (_: any, r: any) => r.userName || r.userId }, - { title: '状态', dataIndex: 'status', width: 80, render: (s: string) => {candidateStatusLabels[s] || s} }, - { title: '置信度', dataIndex: 'confidence', width: 80, align: 'center' as const, render: (v: any) => v ? `${(Number(v)*100).toFixed(0)}%` : '-' }, - { title: '难度', dataIndex: 'difficulty', width: 70 }, - { title: '时间', dataIndex: 'createdAt', width: 130, render: (d: string) => dayjs(d).format('MM-DD HH:mm') }, - ] - const chunkCols = [ { title: '#', dataIndex: 'chunkIndex', width: 50 }, { title: '内容', dataIndex: 'content', ellipsis: true, render: (v: string) => {v?.slice(0, 150)} }, @@ -57,10 +41,6 @@ export default function KnowledgeOpsPage() { , - }, { key: 'chunks', label: 'Chunk 管理', children: ( diff --git a/src/types/index.ts b/src/types/index.ts index b562c07..22c7eb6 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -22,7 +22,6 @@ export type { ImportStepLog, ImportJobDetail, KnowledgeChunk, - KnowledgeCandidate, } from './knowledge' export type { ServerInfo, diff --git a/src/types/knowledge.ts b/src/types/knowledge.ts index 773c6e0..f038444 100644 --- a/src/types/knowledge.ts +++ b/src/types/knowledge.ts @@ -9,7 +9,6 @@ export interface KnowledgeBase { user?: { nickname?: string; email?: string } sourceCount?: number chunkCount?: number - candidateCount?: number createdAt: string updatedAt?: string } @@ -63,7 +62,6 @@ export type ImportJobStatus = | 'CHUNKING' | 'EMBEDDING' | 'INDEXING' - | 'GENERATING_CANDIDATES' | 'COMPLETED' | 'FAILED' | 'FAILED_RETRYABLE' @@ -95,16 +93,3 @@ export interface KnowledgeChunk { tokenCount?: number confidence?: number } - -// ── 候选知识点 ── - -export interface KnowledgeCandidate { - id: string - knowledgeBaseId: string - sourceId: string - importId?: string - title: string - content?: string - confidence?: number - status?: string -}