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:
2026-01-06 22:15:42 +08:00
parent b31255031e
commit 5a17d096a7
226 changed files with 14899 additions and 224 deletions

View 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',
});
}
}