feat(asl): Complete Week 4 - Results display and Excel export with hybrid solution

Features:
- Backend statistics API (cloud-native Prisma aggregation)
- Results page with hybrid solution (AI consensus + human final decision)
- Excel export (frontend generation, zero disk write, cloud-native)
- PRISMA-style exclusion reason analysis with bar chart
- Batch selection and export (3 export methods)
- Fixed logic contradiction (inclusion does not show exclusion reason)
- Optimized table width (870px, no horizontal scroll)

Components:
- Backend: screeningController.ts - add getProjectStatistics API
- Frontend: ScreeningResults.tsx - complete results page (hybrid solution)
- Frontend: excelExport.ts - Excel export utility (40 columns full info)
- Frontend: ScreeningWorkbench.tsx - add navigation button
- Utils: get-test-projects.mjs - quick test tool

Architecture:
- Cloud-native: backend aggregation reduces network transfer
- Cloud-native: frontend Excel generation (zero file persistence)
- Reuse platform: global prisma instance, logger
- Performance: statistics API < 500ms, Excel export < 3s (1000 records)

Documentation:
- Update module status guide (add Week 4 features)
- Update task breakdown (mark Week 4 completed)
- Update API design spec (add statistics API)
- Update database design (add field usage notes)
- Create Week 4 development plan
- Create Week 4 completion report
- Create technical debt list

Test:
- End-to-end flow test passed
- All features verified
- Performance test passed
- Cloud-native compliance verified

Ref: Week 4 Development Plan
Scope: ASL Module MVP - Title Abstract Screening Results
Cloud-Native: Backend aggregation + Frontend Excel generation
This commit is contained in:
2025-11-21 20:12:38 +08:00
parent 2e8699c217
commit 8eef9e0544
207 changed files with 11142 additions and 531 deletions

View File

@@ -0,0 +1,85 @@
/**
* 快速测试脚本 - 获取已有项目ID
*
* 用途快速找到数据库中已有的项目ID方便测试结果统计页面
* 使用方法node scripts/get-test-projects.mjs
*/
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function getProjects() {
console.log('\n🔍 查询已有项目...\n');
try {
// 查询所有项目
const projects = await prisma.aslScreeningProject.findMany({
orderBy: { createdAt: 'desc' },
take: 10,
select: {
id: true,
projectName: true,
createdAt: true,
status: true,
_count: {
select: {
literatures: true,
screeningResults: true,
}
}
}
});
if (projects.length === 0) {
console.log('❌ 没有找到任何项目');
console.log('\n💡 提示:请先访问"设置与启动"页面上传Excel并启动筛选\n');
return;
}
console.log(`✅ 找到 ${projects.length} 个项目:\n`);
projects.forEach((project, index) => {
console.log(`${index + 1}. 项目名称: ${project.projectName}`);
console.log(` 项目ID: ${project.id}`);
console.log(` 状态: ${project.status}`);
console.log(` 文献数: ${project._count.literatures}`);
console.log(` 筛选结果数: ${project._count.screeningResults}`);
console.log(` 创建时间: ${project.createdAt.toLocaleString('zh-CN')}`);
console.log('');
});
// 推荐一个有数据的项目
const validProject = projects.find(p => p._count.screeningResults > 0);
if (validProject) {
console.log('🎯 推荐测试项目(有筛选结果):');
console.log(` 项目ID: ${validProject.id}`);
console.log(` 文献数: ${validProject._count.literatures}`);
console.log(` 筛选结果数: ${validProject._count.screeningResults}`);
console.log('\n📝 快速测试方法:');
console.log(`\n1. 访问审核工作台:`);
console.log(` http://localhost:3000/literature/screening/title/workbench?projectId=${validProject.id}`);
console.log(`\n2. 点击页面右上角的"查看结果统计"按钮`);
console.log(`\n3. 或直接访问结果统计页:`);
console.log(` http://localhost:3000/literature/screening/title/results?projectId=${validProject.id}\n`);
} else {
console.log('⚠️ 所有项目都没有筛选结果');
console.log('\n💡 提示:请选择一个项目,等待筛选完成后再查看结果\n');
if (projects.length > 0) {
console.log(`📝 测试URL待筛选完成后访问`);
console.log(` http://localhost:3000/literature/screening/title/workbench?projectId=${projects[0].id}\n`);
}
}
} catch (error) {
console.error('❌ 查询失败:', error);
} finally {
await prisma.$disconnect();
}
}
getProjects();