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,292 @@
/**
* 验证PKB和RVW的数据库Schema状态
*
* 目的:
* 1. 检查pkb_schema是否存在及其表结构
* 2. 检查rvw_schema是否存在
* 3. 检查ReviewTask在哪个Schema中
* 4. 检查是否有旧数据需要迁移
*
* 运行方式:
* npx tsx scripts/verify-pkb-rvw-schema.ts
*/
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
interface SchemaInfo {
schema_name: string;
}
interface TableInfo {
table_schema: string;
table_name: string;
}
interface ColumnInfo {
column_name: string;
data_type: string;
is_nullable: string;
column_default: string | null;
}
interface RowCount {
count: bigint;
}
async function verifySchemas() {
console.log('🔍 开始验证PKB和RVW的数据库Schema状态...\n');
console.log('='.repeat(80));
try {
// ========================================
// 1. 检查所有Schema
// ========================================
console.log('\n📦 1. 检查数据库中所有的Schema');
console.log('='.repeat(80));
const schemas = await prisma.$queryRaw<SchemaInfo[]>`
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name IN ('pkb_schema', 'rvw_schema', 'public', 'platform_schema')
ORDER BY schema_name
`;
console.log('✅ 找到以下Schema');
schemas.forEach(s => console.log(` - ${s.schema_name}`));
const hasRvwSchema = schemas.some(s => s.schema_name === 'rvw_schema');
const hasPkbSchema = schemas.some(s => s.schema_name === 'pkb_schema');
console.log(`\n📊 Schema存在性检查`);
console.log(` pkb_schema: ${hasPkbSchema ? '✅ 存在' : '❌ 不存在'}`);
console.log(` rvw_schema: ${hasRvwSchema ? '✅ 存在' : '❌ 不存在'}`);
// ========================================
// 2. 检查PKB相关表
// ========================================
console.log('\n');
console.log('='.repeat(80));
console.log('📚 2. 检查PKB相关表在pkb_schema中');
console.log('='.repeat(80));
if (hasPkbSchema) {
const pkbTables = await prisma.$queryRaw<TableInfo[]>`
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_schema = 'pkb_schema'
ORDER BY table_name
`;
console.log(`✅ pkb_schema中共有 ${pkbTables.length} 个表:`);
pkbTables.forEach(t => console.log(` - ${t.table_name}`));
// 检查每个表的行数
console.log('\n📊 PKB表数据统计');
for (const table of pkbTables) {
try {
const result = await prisma.$queryRaw<RowCount[]>`
SELECT COUNT(*) as count FROM pkb_schema.${prisma.$queryRawUnsafe(table.table_name)}
`;
const count = Number(result[0]?.count || 0);
console.log(` - ${table.table_name}: ${count}`);
} catch (error) {
console.log(` - ${table.table_name}: 查询失败`);
}
}
} else {
console.log('❌ pkb_schema不存在需要创建');
}
// ========================================
// 3. 检查RVW相关表
// ========================================
console.log('\n');
console.log('='.repeat(80));
console.log('📝 3. 检查RVW相关表review_tasks');
console.log('='.repeat(80));
// 查找review_tasks表在哪个schema
const reviewTaskLocation = await prisma.$queryRaw<TableInfo[]>`
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_name = 'review_tasks'
`;
if (reviewTaskLocation.length > 0) {
console.log('✅ 找到review_tasks表');
reviewTaskLocation.forEach(t => {
console.log(` - 位置: ${t.table_schema}.${t.table_name}`);
});
// 查看review_tasks表结构
const reviewSchema = reviewTaskLocation[0].table_schema;
console.log(`\n📋 review_tasks表结构${reviewSchema}中):`);
const reviewColumns = await prisma.$queryRaw<ColumnInfo[]>`
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = ${reviewSchema}
AND table_name = 'review_tasks'
ORDER BY ordinal_position
`;
console.log('='.repeat(80));
console.log(
'Column Name'.padEnd(25) +
'Data Type'.padEnd(20) +
'Nullable'.padEnd(12) +
'Default'
);
console.log('='.repeat(80));
reviewColumns.forEach(col => {
const colName = col.column_name.padEnd(25);
const dataType = col.data_type.padEnd(20);
const nullable = (col.is_nullable === 'YES' ? 'YES' : 'NO').padEnd(12);
const defaultVal = col.column_default || '';
console.log(`${colName}${dataType}${nullable}${defaultVal}`);
});
console.log('='.repeat(80));
console.log(`总计: ${reviewColumns.length} 个字段`);
// 查询数据量
const reviewCount = await prisma.$queryRaw<RowCount[]>`
SELECT COUNT(*) as count FROM ${prisma.$queryRawUnsafe(reviewSchema)}.review_tasks
`;
const count = Number(reviewCount[0]?.count || 0);
console.log(`\n📊 review_tasks表数据量: ${count}`);
if (reviewSchema === 'public') {
console.log('\n⚠ WARNING: review_tasks当前在public schema中');
console.log(' 建议迁移到rvw_schema以保持架构一致性');
}
} else {
console.log('❌ 未找到review_tasks表');
}
// ========================================
// 4. 检查rvw_schema状态
// ========================================
console.log('\n');
console.log('='.repeat(80));
console.log('🔍 4. 检查rvw_schema状态');
console.log('='.repeat(80));
if (hasRvwSchema) {
const rvwTables = await prisma.$queryRaw<TableInfo[]>`
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_schema = 'rvw_schema'
ORDER BY table_name
`;
if (rvwTables.length > 0) {
console.log(`✅ rvw_schema中共有 ${rvwTables.length} 个表:`);
rvwTables.forEach(t => console.log(` - ${t.table_name}`));
} else {
console.log('⚠️ rvw_schema存在但为空未创建任何表');
}
} else {
console.log('❌ rvw_schema不存在需要创建');
}
// ========================================
// 5. 检查User表状态
// ========================================
console.log('\n');
console.log('='.repeat(80));
console.log('👤 5. 检查User表状态');
console.log('='.repeat(80));
const userTables = await prisma.$queryRaw<TableInfo[]>`
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_name = 'users'
AND table_schema IN ('public', 'platform_schema')
`;
console.log('✅ 找到以下users表');
for (const userTable of userTables) {
console.log(` - ${userTable.table_schema}.${userTable.table_name}`);
const userCount = await prisma.$queryRaw<RowCount[]>`
SELECT COUNT(*) as count FROM ${prisma.$queryRawUnsafe(userTable.table_schema)}.users
`;
const count = Number(userCount[0]?.count || 0);
console.log(` 数据量: ${count}`);
}
// ========================================
// 6. 总结和建议
// ========================================
console.log('\n');
console.log('='.repeat(80));
console.log('📋 6. 迁移建议总结');
console.log('='.repeat(80));
console.log('\n✅ PKB模块迁移建议');
if (hasPkbSchema && pkbTables.length > 0) {
console.log(' 1. ✅ pkb_schema已存在且有表');
console.log(' 2. ✅ 可以直接迁移代码到新架构');
console.log(' 3. ⚠️ 注意检查旧代码是否连接到正确的schema');
} else {
console.log(' 1. ❌ 需要先创建pkb_schema和相关表');
console.log(' 2. ❌ 需要运行Prisma迁移');
}
console.log('\n⚠ RVW模块迁移建议');
if (reviewTaskLocation.length > 0) {
const currentSchema = reviewTaskLocation[0].table_schema;
if (currentSchema === 'public') {
console.log(' 1. ⚠️ review_tasks当前在public schema');
console.log(' 2. 🔄 建议先完整迁移功能后续再迁移Schema');
console.log(' 3. 📋 迁移步骤:');
console.log(' a. 创建rvw_schema如果不存在');
console.log(' b. 在rvw_schema中创建新表');
console.log(' c. 迁移数据');
console.log(' d. 更新代码');
console.log(' e. 删除旧表');
} else if (currentSchema === 'rvw_schema') {
console.log(' 1. ✅ review_tasks已在rvw_schema中');
console.log(' 2. ✅ 可以直接迁移代码');
}
} else {
console.log(' 1. ❌ review_tasks表不存在');
console.log(' 2. ❌ 需要从头创建');
}
console.log('\n💡 推荐迁移策略:');
console.log(' 【方案A渐进式迁移推荐】');
console.log(' 1. PKB: 直接迁移代码到新架构Schema已就绪');
console.log(' 2. RVW: 先迁移代码保持在public schema');
console.log(' 3. 验证功能完整性');
console.log(' 4. 后续独立任务将RVW迁移到rvw_schema');
console.log('');
console.log(' 【方案B一步到位风险较高】');
console.log(' 1. 同时迁移代码+Schema');
console.log(' 2. 需要数据迁移脚本');
console.log(' 3. 需要更长的测试时间');
console.log('\n='.repeat(80));
console.log('✅ 验证完成!');
console.log('='.repeat(80));
} catch (error) {
console.error('❌ 验证过程中出错:', error);
throw error;
} finally {
await prisma.$disconnect();
}
}
// 运行验证
verifySchemas()
.catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
});