feat(pkb): Complete PKB module frontend migration with V3 design
Summary: - Implement PKB Dashboard and Workspace pages based on V3 prototype - Add single-layer header with integrated Tab navigation - Implement 3 work modes: Full Text, Deep Read, Batch Processing - Integrate Ant Design X Chat component for AI conversations - Create BatchModeComplete with template selection and document processing - Add compact work mode selector with dropdown design Backend: - Migrate PKB controllers and services to /modules/pkb structure - Register v2 API routes at /api/v2/pkb/knowledge - Maintain dual API routes for backward compatibility Technical details: - Use Zustand for state management - Handle SSE streaming responses for AI chat - Support document selection for Deep Read mode - Implement batch processing with progress tracking Known issues: - Batch processing API integration pending - Knowledge assets page navigation needs optimization Status: Frontend functional, pending refinement
This commit is contained in:
217
frontend-v2/src/modules/pkb/api/knowledgeBaseApi.ts
Normal file
217
frontend-v2/src/modules/pkb/api/knowledgeBaseApi.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* PKB个人知识库 API(v2版本)
|
||||
* 更新API路径为 /api/v2/pkb/knowledge
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000';
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: `${API_BASE_URL}/api/v2/pkb/knowledge`,
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 知识库类型定义
|
||||
*/
|
||||
export interface KnowledgeBase {
|
||||
id: string;
|
||||
userId: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
difyDatasetId: string;
|
||||
fileCount: number;
|
||||
totalSizeBytes: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
_count?: {
|
||||
documents: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface Document {
|
||||
id: string;
|
||||
kbId: string;
|
||||
userId: string;
|
||||
filename: string;
|
||||
fileType: string;
|
||||
fileSizeBytes: number;
|
||||
fileUrl: string;
|
||||
difyDocumentId: string;
|
||||
status: 'uploading' | 'parsing' | 'indexing' | 'completed' | 'error';
|
||||
progress: number;
|
||||
errorMessage?: string;
|
||||
segmentsCount?: number;
|
||||
tokensCount?: number;
|
||||
uploadedAt: string;
|
||||
processedAt?: string;
|
||||
}
|
||||
|
||||
export interface CreateKnowledgeBaseRequest {
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface UpdateKnowledgeBaseRequest {
|
||||
name?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeBaseStats {
|
||||
totalDocuments: number;
|
||||
completedDocuments: number;
|
||||
processingDocuments: number;
|
||||
errorDocuments: number;
|
||||
totalSizeBytes: number;
|
||||
totalTokens: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 知识库管理API
|
||||
*/
|
||||
export const knowledgeBaseApi = {
|
||||
/**
|
||||
* 获取知识库列表
|
||||
*/
|
||||
async getList(): Promise<KnowledgeBase[]> {
|
||||
const response = await api.get('/knowledge-bases');
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取知识库详情
|
||||
*/
|
||||
async getById(id: string): Promise<KnowledgeBase> {
|
||||
const response = await api.get(`/knowledge-bases/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建知识库
|
||||
*/
|
||||
async create(data: CreateKnowledgeBaseRequest): Promise<KnowledgeBase> {
|
||||
const response = await api.post('/knowledge-bases', data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新知识库
|
||||
*/
|
||||
async update(id: string, data: UpdateKnowledgeBaseRequest): Promise<KnowledgeBase> {
|
||||
const response = await api.put(`/knowledge-bases/${id}`, data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除知识库
|
||||
*/
|
||||
async delete(id: string): Promise<void> {
|
||||
await api.delete(`/knowledge-bases/${id}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取知识库统计信息
|
||||
*/
|
||||
async getStats(id: string): Promise<KnowledgeBaseStats> {
|
||||
const response = await api.get(`/knowledge-bases/${id}/stats`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 检索知识库(RAG)
|
||||
*/
|
||||
async search(id: string, query: string, topK: number = 3): Promise<any> {
|
||||
const response = await api.get(`/knowledge-bases/${id}/search`, {
|
||||
params: { query, top_k: topK },
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 文档管理API
|
||||
*/
|
||||
export const documentApi = {
|
||||
/**
|
||||
* 获取文档列表
|
||||
*/
|
||||
async getList(kbId: string): Promise<Document[]> {
|
||||
const response = await api.get(`/knowledge-bases/${kbId}/documents`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取文档详情
|
||||
*/
|
||||
async getById(id: string): Promise<Document> {
|
||||
const response = await api.get(`/documents/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 上传文档
|
||||
*/
|
||||
async upload(kbId: string, file: File, onProgress?: (progress: number) => void): Promise<Document> {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
const response = await api.post(`/knowledge-bases/${kbId}/documents`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
onUploadProgress: (progressEvent) => {
|
||||
if (progressEvent.total && onProgress) {
|
||||
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
onProgress(percentCompleted);
|
||||
}
|
||||
},
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除文档
|
||||
*/
|
||||
async delete(id: string): Promise<void> {
|
||||
await api.delete(`/documents/${id}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 重新处理文档
|
||||
*/
|
||||
async reprocess(id: string): Promise<void> {
|
||||
await api.post(`/documents/${id}/reprocess`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取文档全文(用于逐篇精读模式)
|
||||
*/
|
||||
async getFullText(id: string): Promise<any> {
|
||||
const response = await api.get(`/documents/${id}/full-text`);
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 文档选择API(用于全文阅读模式)
|
||||
*/
|
||||
export const documentSelectionApi = {
|
||||
/**
|
||||
* 获取知识库的文档选择结果
|
||||
*/
|
||||
async getSelection(kbId: string, maxFiles?: number, maxTokens?: number): Promise<any> {
|
||||
const params = new URLSearchParams();
|
||||
if (maxFiles) params.append('max_files', maxFiles.toString());
|
||||
if (maxTokens) params.append('max_tokens', maxTokens.toString());
|
||||
|
||||
const url = `/knowledge-bases/${kbId}/document-selection${params.toString() ? '?' + params.toString() : ''}`;
|
||||
const response = await api.get(url);
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user