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:
341
backend/src/modules/pkb/controllers/knowledgeBaseController.ts
Normal file
341
backend/src/modules/pkb/controllers/knowledgeBaseController.ts
Normal file
@@ -0,0 +1,341 @@
|
||||
import type { FastifyRequest, FastifyReply } from 'fastify';
|
||||
import * as knowledgeBaseService from '../services/knowledgeBaseService.js';
|
||||
|
||||
// Mock用户ID(实际应从JWT token中获取)
|
||||
const MOCK_USER_ID = 'user-mock-001';
|
||||
|
||||
/**
|
||||
* 创建知识库
|
||||
*/
|
||||
export async function createKnowledgeBase(
|
||||
request: FastifyRequest<{
|
||||
Body: {
|
||||
name: string;
|
||||
description?: string;
|
||||
};
|
||||
}>,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const { name, description } = request.body;
|
||||
|
||||
if (!name || name.trim().length === 0) {
|
||||
return reply.status(400).send({
|
||||
success: false,
|
||||
message: 'Knowledge base name is required',
|
||||
});
|
||||
}
|
||||
|
||||
const knowledgeBase = await knowledgeBaseService.createKnowledgeBase(
|
||||
MOCK_USER_ID,
|
||||
name,
|
||||
description
|
||||
);
|
||||
|
||||
return reply.status(201).send({
|
||||
success: true,
|
||||
data: knowledgeBase,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to create knowledge base:', error);
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to create knowledge base',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识库列表
|
||||
*/
|
||||
export async function getKnowledgeBases(
|
||||
_request: FastifyRequest,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const knowledgeBases = await knowledgeBaseService.getKnowledgeBases(
|
||||
MOCK_USER_ID
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
data: knowledgeBases,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to get knowledge bases:', error);
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to get knowledge bases',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识库详情
|
||||
*/
|
||||
export async function getKnowledgeBaseById(
|
||||
request: FastifyRequest<{
|
||||
Params: {
|
||||
id: string;
|
||||
};
|
||||
}>,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
|
||||
const knowledgeBase = await knowledgeBaseService.getKnowledgeBaseById(
|
||||
MOCK_USER_ID,
|
||||
id
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
data: knowledgeBase,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to get knowledge base:', error);
|
||||
|
||||
if (error.message.includes('not found')) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to get knowledge base',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新知识库
|
||||
*/
|
||||
export async function updateKnowledgeBase(
|
||||
request: FastifyRequest<{
|
||||
Params: {
|
||||
id: string;
|
||||
};
|
||||
Body: {
|
||||
name?: string;
|
||||
description?: string;
|
||||
};
|
||||
}>,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const updateData = request.body;
|
||||
|
||||
const knowledgeBase = await knowledgeBaseService.updateKnowledgeBase(
|
||||
MOCK_USER_ID,
|
||||
id,
|
||||
updateData
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
data: knowledgeBase,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to update knowledge base:', error);
|
||||
|
||||
if (error.message.includes('not found')) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to update knowledge base',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除知识库
|
||||
*/
|
||||
export async function deleteKnowledgeBase(
|
||||
request: FastifyRequest<{
|
||||
Params: {
|
||||
id: string;
|
||||
};
|
||||
}>,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
|
||||
await knowledgeBaseService.deleteKnowledgeBase(MOCK_USER_ID, id);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
message: 'Knowledge base deleted successfully',
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to delete knowledge base:', error);
|
||||
|
||||
if (error.message.includes('not found')) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to delete knowledge base',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检索知识库
|
||||
*/
|
||||
export async function searchKnowledgeBase(
|
||||
request: FastifyRequest<{
|
||||
Params: {
|
||||
id: string;
|
||||
};
|
||||
Querystring: {
|
||||
query: string;
|
||||
top_k?: string;
|
||||
};
|
||||
}>,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const { query, top_k } = request.query;
|
||||
|
||||
if (!query || query.trim().length === 0) {
|
||||
return reply.status(400).send({
|
||||
success: false,
|
||||
message: 'Query parameter is required',
|
||||
});
|
||||
}
|
||||
|
||||
const topK = top_k ? parseInt(top_k, 10) : 15; // Phase 1优化:默认从3增加到15
|
||||
|
||||
const results = await knowledgeBaseService.searchKnowledgeBase(
|
||||
MOCK_USER_ID,
|
||||
id,
|
||||
query,
|
||||
topK
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
data: results,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to search knowledge base:', error);
|
||||
|
||||
if (error.message.includes('not found')) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to search knowledge base',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识库统计信息
|
||||
*/
|
||||
export async function getKnowledgeBaseStats(
|
||||
request: FastifyRequest<{
|
||||
Params: {
|
||||
id: string;
|
||||
};
|
||||
}>,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
|
||||
const stats = await knowledgeBaseService.getKnowledgeBaseStats(
|
||||
MOCK_USER_ID,
|
||||
id
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
data: stats,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to get knowledge base stats:', error);
|
||||
|
||||
if (error.message.includes('not found')) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to get knowledge base stats',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识库文档选择(Phase 2: 全文阅读模式)
|
||||
*/
|
||||
export async function getDocumentSelection(
|
||||
request: FastifyRequest<{
|
||||
Params: {
|
||||
id: string;
|
||||
};
|
||||
Querystring: {
|
||||
max_files?: string;
|
||||
max_tokens?: string;
|
||||
};
|
||||
}>,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const { max_files, max_tokens } = request.query;
|
||||
|
||||
const maxFiles = max_files ? parseInt(max_files, 10) : undefined;
|
||||
const maxTokens = max_tokens ? parseInt(max_tokens, 10) : undefined;
|
||||
|
||||
const selection = await knowledgeBaseService.getDocumentSelection(
|
||||
MOCK_USER_ID,
|
||||
id,
|
||||
maxFiles,
|
||||
maxTokens
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
data: selection,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Failed to get document selection:', error);
|
||||
|
||||
if (error.message.includes('not found')) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: error.message || 'Failed to get document selection',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user