feat(knowledge): add chunk management and document processing features

This commit is contained in:
2025-10-16 16:23:53 +08:00
parent 4f956e79ba
commit 5a0a9ef2a1
17 changed files with 1655 additions and 366 deletions

107
src/hooks/chunk-hooks.ts Normal file
View File

@@ -0,0 +1,107 @@
import { useState, useEffect, useCallback } from 'react';
import knowledgeService from '@/services/knowledge_service';
import type { IChunk, IChunkListResult } from '@/interfaces/database/knowledge';
import type { IFetchChunkListRequestBody } from '@/interfaces/request/knowledge';
// Chunk列表Hook状态接口
export interface UseChunkListState {
chunks: IChunk[];
total: number;
loading: boolean;
error: string | null;
currentPage: number;
pageSize: number;
keywords: string;
}
// Chunk列表Hook返回值接口
export interface UseChunkListReturn extends UseChunkListState {
fetchChunks: (params?: IFetchChunkListRequestBody) => Promise<void>;
setKeywords: (keywords: string) => void;
setCurrentPage: (page: number) => void;
setPageSize: (size: number) => void;
refresh: () => Promise<void>;
}
/**
* Chunk列表数据管理Hook
* 支持关键词搜索、分页等功能
*/
export const useChunkList = (
docId: string,
initialParams?: IFetchChunkListRequestBody
): UseChunkListReturn => {
const [chunks, setChunks] = useState<IChunk[]>([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [currentPage, setCurrentPage] = useState(initialParams?.page || 1);
const [pageSize, setPageSize] = useState(initialParams?.size || 10);
const [keywords, setKeywords] = useState(initialParams?.keywords || '');
/**
* 获取chunk列表
*/
const fetchChunks = useCallback(async (params?: IFetchChunkListRequestBody) => {
if (!docId) return;
try {
setLoading(true);
setError(null);
// 合并参数
const queryParams = {
doc_id: docId,
keywords: params?.keywords ?? keywords,
page: params?.page ?? currentPage,
size: params?.size ?? pageSize,
};
const response = await knowledgeService.getChunkList(queryParams);
// 检查响应状态
if (response.data.code === 0) {
const data: IChunkListResult = response.data.data;
setChunks(data.chunks || []);
setTotal(data.total || 0);
} else {
throw new Error(response.data.message || '获取chunk列表失败');
}
} catch (err: any) {
const errorMessage = err.response?.data?.message || err.message || '获取chunk列表失败';
setError(errorMessage);
console.error('Failed to fetch chunks:', err);
} finally {
setLoading(false);
}
}, [docId, keywords, currentPage, pageSize]);
/**
* 刷新数据
*/
const refresh = useCallback(async () => {
await fetchChunks();
}, [fetchChunks]);
// 初始化加载数据
useEffect(() => {
if (docId) {
fetchChunks();
}
}, [docId, fetchChunks]);
return {
chunks,
total,
loading,
error,
currentPage,
pageSize,
keywords,
fetchChunks,
setKeywords,
setCurrentPage,
setPageSize,
refresh,
};
};

View File

@@ -2,6 +2,7 @@ import { useState, useEffect, useCallback } from 'react';
import knowledgeService from '@/services/knowledge_service';
import type { IKnowledgeFile } from '@/interfaces/database/knowledge';
import type { IFetchKnowledgeListRequestParams, IFetchDocumentListRequestBody } from '@/interfaces/request/knowledge';
import type { IDocumentInfoFilter } from '@/interfaces/database/document';
// 文档列表Hook状态接口
export interface UseDocumentListState {
@@ -17,7 +18,7 @@ export interface UseDocumentListState {
// 文档列表Hook返回值接口
export interface UseDocumentListReturn extends UseDocumentListState {
fetchDocuments: (params?: IFetchKnowledgeListRequestParams) => Promise<void>;
fetchDocumentsFilter: () => Promise<void>;
fetchDocumentsFilter: () => Promise<IDocumentInfoFilter | undefined>;
setKeywords: (keywords: string) => void;
setCurrentPage: (page: number) => void;
setPageSize: (size: number) => void;
@@ -107,7 +108,8 @@ export const useDocumentList = (
kb_id: kbId,
});
if (response.data.code === 0) {
const data = response.data.data;
const data: IDocumentInfoFilter = response.data.data;
return data;
} else {
throw new Error(response.data.message || '获取文档过滤器失败');
}
@@ -324,7 +326,7 @@ export const useDocumentOperations = () => {
setLoading(true);
setError(null);
const response = await knowledgeService.changeDocumentStatus({ doc_id: docIds, status });
const response = await knowledgeService.changeDocumentStatus({ doc_ids: docIds, status });
if (response.data.code === 0) {
return response.data.data;
@@ -349,7 +351,7 @@ export const useDocumentOperations = () => {
setLoading(true);
setError(null);
const response = await knowledgeService.runDocument({ doc_id: docIds });
const response = await knowledgeService.runDocument({ doc_ids: docIds, run: 1, delete: false });
if (response.data.code === 0) {
return response.data.data;
@@ -366,6 +368,31 @@ export const useDocumentOperations = () => {
}
}, []);
/**
* 取消文档处理
*/
const cancelRunDocuments = useCallback(async (docIds: string[]) => {
try {
setLoading(true);
setError(null);
const response = await knowledgeService.runDocument({ doc_ids: docIds, run: 2, delete: false });
if (response.data.code === 0) {
return response.data.data;
} else {
throw new Error(response.data.message || '取消文档处理失败');
}
} catch (err: any) {
const errorMessage = err.response?.data?.message || err.message || '取消文档处理失败';
setError(errorMessage);
console.error('Failed to cancel documents:', err);
throw err;
} finally {
setLoading(false);
}
}, []);
/**
* 清除错误状态
*/
@@ -383,6 +410,7 @@ export const useDocumentOperations = () => {
createDocument,
changeDocumentStatus,
runDocuments,
cancelRunDocuments,
clearError,
};
};
@@ -435,7 +463,7 @@ export const useDocumentBatchOperations = () => {
setLoading(true);
setError(null);
const response = await knowledgeService.changeDocumentStatus({ doc_id: docIds, status });
const response = await knowledgeService.changeDocumentStatus({ doc_ids: docIds, status });
if (response.data.code === 0) {
return response.data.data;
@@ -460,7 +488,7 @@ export const useDocumentBatchOperations = () => {
setLoading(true);
setError(null);
const response = await knowledgeService.runDocument({ doc_id: docIds });
const response = await knowledgeService.runDocument({ doc_ids: docIds, run: 1, delete: false });
if (response.data.code === 0) {
return response.data.data;