Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/06-技术债务/技术债务清单.md
HaHafeng 66255368b7 feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
2026-01-16 13:42:10 +08:00

33 KiB
Raw Blame History

AI智能文献模块 - 技术债务清单

文档版本: v1.2
创建日期: 2025-11-21
维护者: AI智能文献开发团队
最后更新: 2025-11-23
文档目的: 记录MVP完成后需要优化的技术问题


📋 文档说明

本文档记录AI智能文献模块在MVP开发完成后发现的需要优化但不影响核心功能的技术问题。这些问题将在MVP稳定运行后按优先级逐步解决。

当前MVP状态

  • 核心功能完整(上传→筛选→复核)
  • 双模型筛选可用DeepSeek + Qwen
  • 前后端联调通过
  • ⚠️ 准确率60%低于目标85%
  • ⚠️ 性能较慢199篇约33-66分钟

🔴 优先级1质量优化准确率

问题描述

当前状态

  • 准确率60%
  • 目标≥85%
  • 差距25%

影响范围

  • 直接影响用户对AI筛选结果的信任度
  • 增加人工复核工作量
  • 可能导致漏筛或误筛

根本原因基于2025-11-18测试报告

  1. Prompt不够清晰AI对"边界情况"的理解与人类不一致
  2. 缺少Few-shot示例:模型没有参考案例,难以把握标准
  3. PICOS标准模糊:用户输入的标准可能含糊不清
  4. 冲突检测不敏感只检测结论不一致忽略了置信度和PICO差异

优化方案1Few-shot示例

目标在Prompt中添加3-5个高质量示例

实施步骤

Step 1: 设计示例结构

每个示例包含:
1. 文献标题和摘要(精简版)
2. PICOS标准
3. 纳入/排除标准
4. 正确的判断结果include/exclude
5. 详细的推理过程

Step 2: 选择示例类型

示例1明确应纳入 - 完美匹配所有PICOS
示例2明确应排除 - 人群不匹配
示例3明确应排除 - 研究设计不符
示例4边界情况 - 部分匹配,但应纳入
示例5边界情况 - 看似匹配,但应排除

Step 3: 编写示例

参考真实测试案例中的成功和失败案例
确保示例覆盖常见的判断场景

Step 4: 集成到Prompt

位置backend/prompts/asl/screening/v1.1.0-fewshot.txt
格式:
---
## 示例1明确纳入
【文献】:...
【PICOS】...
【判断】include
【原因】:...
---

预计提升:准确率 +10-15%60% → 70-75%

预计耗时1天


优化方案2PICOS标准明确化

目标帮助AI更准确理解用户的PICOS标准

实施步骤

Step 1: 增强PICOS输入

// 当前输入
picoCriteria: {
  P: "2型糖尿病成人患者",
  I: "SGLT2抑制剂",
  ...
}

// 优化后输入
picoCriteria: {
  P: {
    description: "2型糖尿病成人患者",
    keywords: ["2型糖尿病", "成人", "T2DM"],
    mustInclude: ["糖尿病"],
    mustExclude: ["1型", "儿童", "青少年"]
  },
  ...
}

Step 2: 在Prompt中明确要求

在Prompt中添加
- 明确哪些关键词必须出现
- 明确哪些关键词不能出现
- 部分匹配的判断标准(如"部分匹配"意味着什么)

Step 3: 调整前端表单

在TitleScreeningSettings.tsx中
- 为每个PICO字段添加"关键词提取"功能
- 添加"必须包含"和"必须排除"的高级选项
- 提供标准模板

预计提升:准确率 +5-10%75% → 80-85%

预计耗时2天


优化方案3置信度阈值调优

目标:提高模型判断的置信度,减少不确定性

实施步骤

Step 1: 分析置信度分布

-- 查询置信度分布
SELECT 
  ROUND(ds_confidence * 10) / 10 as confidence_range,
  COUNT(*) as count
FROM asl_schema.screening_results
GROUP BY confidence_range
ORDER BY confidence_range;

Step 2: 调整Prompt要求

在Prompt中明确
- 什么情况下应该给出高置信度0.8-1.0
- 什么情况下应该给出中置信度0.5-0.8
- 什么情况下应该给出低置信度0-0.5
- 低于0.7的自动标记为"需要人工复核"

Step 3: 优化冲突检测

// 当前:只检测结论不一致
hasConflict = (dsConclusion !== qwenConclusion);

// 优化:增加置信度差异检测
hasConflict = 
  (dsConclusion !== qwenConclusion) || // 结论不一致
  (Math.abs(dsConfidence - qwenConfidence) > 0.3) || // 置信度差异大
  (dsJudgments.P !== qwenJudgments.P && important.includes('P')); // 关键PICO不一致

预计提升:冲突检测准确率 +10%,减少漏检

预计耗时0.5天


优化方案4测试与迭代

目标持续测试和优化直到准确率≥85%

实施步骤

Step 1: 使用现有测试脚本

cd backend
npm run test:llm

# 或直接运行
npx ts-node scripts/test-llm-screening.ts

Step 2: 分析失败案例

对于每个失败案例:
1. 记录AI的判断结果
2. 记录正确答案
3. 分析差异原因
4. 调整Prompt或示例

Step 3: A/B测试

测试不同版本的Prompt
- v1.0.0-mvp当前60%
- v1.1.0-fewshot+Few-shot
- v1.2.0-picos-enhanced+PICOS明确化
- v1.3.0-confidence+置信度优化)

Step 4: 记录测试结果

创建测试报告:
- 准确率变化曲线
- 各版本对比
- 失败案例分析
- 最终推荐版本

预计耗时1-2天迭代


质量优化总计

预计提升60% → 85-90%

预计总耗时4-5天

负责人AI工程师 + 医学专家

验收标准

  • 准确率 ≥ 85%
  • 双模型一致率 ≥ 80%
  • 人工复核队列 ≤ 20%
  • 置信度分布合理高置信度占60%+

🟡 优先级2性能优化并发处理

问题描述

当前状态

  • 处理方式:串行(一篇接一篇)
  • 处理速度10-20秒/篇DeepSeek + Qwen并行
  • 总耗时199篇约33-66分钟

目标

  • 处理方式3-5并发
  • 总耗时199篇约10-20分钟提速3倍

影响范围

  • 用户体验(等待时间长)
  • 云服务成本(长时间占用资源)

优化方案:并发处理

实施步骤

Step 1: 安装并发控制库

cd backend
npm install p-limit

Step 2: 修改筛选服务

// 文件backend/src/modules/asl/services/screeningService.ts

import pLimit from 'p-limit';

// 在 processLiteraturesInBackground 中修改

// ❌ 当前:串行处理
for (const literature of literatures) {
  await llmScreeningService.dualModelScreening(...);
}

// ✅ 优化后:并发处理
const concurrency = 3; // 3个并发
const limit = pLimit(concurrency);

const tasks = literatures.map((literature, index) =>
  limit(async () => {
    try {
      console.log(`\n🔍 开始处理文献 ${index + 1}/${literatures.length}`);
      
      // 调用LLM筛选
      const screeningResult = await llmScreeningService.dualModelScreening(...);
      
      // 保存结果
      await prisma.aslScreeningResult.create({ data: screeningResult });
      
      // 更新进度
      await updateTaskProgress(...);
      
      console.log(`✅ 文献 ${index + 1}/${literatures.length} 处理成功`);
    } catch (error) {
      console.error(`❌ 文献 ${index + 1}/${literatures.length} 处理失败:`, error);
      // 继续处理其他文献
    }
  })
);

await Promise.all(tasks);

Step 3: 添加进度更新优化

// 当前问题:高并发下频繁更新数据库
// 解决方案:批量更新或使用内存计数器

let processedCount = 0;
let successCount = 0;
let conflictCount = 0;
let failedCount = 0;

// 每5篇或每10秒更新一次数据库
const updateInterval = setInterval(async () => {
  await prisma.aslScreeningTask.update({
    where: { id: taskId },
    data: {
      processedItems: processedCount,
      successItems: successCount,
      conflictItems: conflictCount,
      failedItems: failedCount,
    }
  });
}, 10000); // 10秒更新一次

// 处理完成后清理
clearInterval(updateInterval);

Step 4: 添加限流保护

// 防止API限流
const API_RATE_LIMITS = {
  'deepseek-chat': { rpm: 30, tpm: 100000 }, // 每分钟30次
  'qwen-max': { rpm: 60, tpm: 200000 },
};

// 动态调整并发数
function calculateOptimalConcurrency(model: string): number {
  const limit = API_RATE_LIMITS[model];
  // 保守估计使用限制的50%
  return Math.floor(limit.rpm / 20); // DeepSeek: 1-2, Qwen: 3
}

const concurrency = Math.min(
  calculateOptimalConcurrency('deepseek-chat'),
  calculateOptimalConcurrency('qwen-max')
); // 取最小值约3

Step 5: 添加错误重试

async function processWithRetry(
  literature: any,
  maxRetries: number = 2
): Promise<any> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await llmScreeningService.dualModelScreening(...);
    } catch (error) {
      console.error(`❌ 尝试 ${attempt}/${maxRetries} 失败:`, error);
      if (attempt === maxRetries) throw error;
      // 等待后重试(指数退避)
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
  }
}

预计提升

  • 处理速度3倍提升
  • 199篇文献33-66分钟 → 10-20分钟
  • 用户体验:显著改善

预计耗时0.5-1天

负责人:后端开发

验收标准

  • 199篇文献筛选 ≤ 20分钟
  • API调用不触发限流
  • 错误率不增加
  • 进度显示正常

🟢 优先级3用户体验优化

问题清单

1. 浏览器性能警告

[Violation]'setTimeout' handler took 72ms

问题原因

  • React组件渲染耗时
  • 表格数据量大

解决方案

  • 使用虚拟滚动(react-window
  • 优化表格渲染减少不必要的re-render
  • 使用useMemo缓存计算结果

预计耗时0.5天


2. 无估计剩余时间

问题:用户不知道还需要等多久

解决方案

// 计算预估时间
const avgTimePerLit = (Date.now() - task.startedAt) / task.processedItems;
const remainingLits = task.totalItems - task.processedItems;
const estimatedTimeRemaining = avgTimePerLit * remainingLits;

// 显示
<div>
  预计剩余时间: {formatDuration(estimatedTimeRemaining)}
</div>

预计耗时0.5天


3. 无当前处理文献显示

问题用户不知道AI正在处理哪篇文献

解决方案

// 在 screeningService.ts 中
await prisma.aslScreeningTask.update({
  where: { id: taskId },
  data: {
    currentLiteratureTitle: literature.title, // 新增字段
    currentLiteratureId: literature.id,
  }
});

// 前端显示
<div>
  当前处理: {task.currentLiteratureTitle}
</div>

预计耗时0.5天


4. 表格小屏幕适配

问题:小屏幕上表格列宽度不适配

解决方案

  • 使用响应式布局
  • 添加"紧凑模式"切换
  • 移动端使用卡片布局代替表格

预计耗时1天


🟣 优先级4Excel导出优化

问题描述

当前状态

  • 导出方式:前端生成(xlsx库)
  • 适用数据量:<5000条
  • 生成速度:<1000条约2-3秒

目标状态(当数据量>5000条或需要复杂格式时

  • 导出方式:后端生成 + OSS存储
  • 适用数据量:无限制
  • 支持复杂格式多Sheet、图表、样式定制

触发条件

  • 单次导出数据量 >5000条
  • 需要复杂Excel格式多Sheet、图表等
  • 用户反馈前端导出卡顿

优化方案:后端导出+OSS存储

实施步骤

Step 1: 后端安装Excel生成库

cd backend
npm install exceljs

Step 2: 实现后端导出服务

// backend/src/modules/asl/services/exportService.ts
import ExcelJS from 'exceljs';
import { storage } from '@/common/storage';
import { logger } from '@/common/logging';

export async function exportScreeningResults(projectId: string, filter: string) {
  // 1. 查询数据
  const results = await prisma.aslScreeningResult.findMany({
    where: buildWhereClause(projectId, filter),
    include: { literature: true },
  });

  // 2. 生成Excel内存中
  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('筛选结果');

  // 设置表头
  worksheet.columns = [
    { header: '序号', key: 'index', width: 6 },
    { header: '文献标题', key: 'title', width: 50 },
    // ... 更多列
  ];

  // 填充数据
  results.forEach((result, idx) => {
    worksheet.addRow({
      index: idx + 1,
      title: result.literature.title,
      // ... 更多字段
    });
  });

  // 3. 转为Buffer
  const buffer = await workbook.xlsx.writeBuffer();

  // 4. ⭐ 上传到OSS使用平台存储服务
  const key = `asl/exports/${projectId}/${Date.now()}.xlsx`;
  const url = await storage.upload(key, Buffer.from(buffer));

  // 5. 记录日志
  logger.info('Excel exported', { projectId, recordCount: results.length, url });

  return {
    url,
    filename: `screening-results-${Date.now()}.xlsx`,
    recordCount: results.length,
  };
}

Step 3: 实现导出API

// backend/src/modules/asl/controllers/exportController.ts
export async function exportResults(
  request: FastifyRequest<{
    Params: { projectId: string };
    Querystring: { filter?: string };
  }>,
  reply: FastifyReply
) {
  try {
    const { projectId } = request.params;
    const filter = request.query.filter || 'all';

    // 导出并上传到OSS
    const result = await exportService.exportScreeningResults(projectId, filter);

    return reply.send({
      success: true,
      data: result,
    });
  } catch (error) {
    logger.error('Export failed', { error });
    return reply.status(500).send({
      success: false,
      error: '导出失败',
    });
  }
}

Step 4: 前端调用

// 前端
const handleExportLarge = async () => {
  try {
    message.loading('正在生成Excel请稍候...', 0);

    // 调用后端导出API
    const { data } = await aslApi.exportResults(projectId, { filter: 'all' });

    message.destroy();
    message.success(`成功导出 ${data.recordCount} 条记录`);

    // 通过OSS URL下载
    window.open(data.url, '_blank');
  } catch (error) {
    message.destroy();
    message.error('导出失败');
  }
};

Step 5: OSS文件清理可选

// 定时任务清理7天前的导出文件
import { jobQueue } from '@/common/jobs';

jobQueue.schedule('cleanup-exports', '0 2 * * *', async () => {
  const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
  
  // 列出并删除过期文件
  const files = await storage.list('asl/exports/');
  for (const file of files) {
    if (file.lastModified < sevenDaysAgo) {
      await storage.delete(file.key);
    }
  }
  
  logger.info('Cleaned up old export files');
});

预计提升

  • 支持无限数据量
  • 支持复杂格式多Sheet、图表、样式
  • 不占用前端资源

预计耗时1-2天

负责人:后端开发

验收标准

  • 可导出>5000条数据
  • 文件上传到OSS
  • 前端通过URL下载
  • 符合云原生规范(使用平台存储服务)

🔵 优先级5架构优化云原生

问题清单

1. 异步任务未使用消息队列

当前状态

  • 筛选任务在后台线程中执行
  • 服务重启会丢失任务

目标状态

  • 使用Bull队列Redis
  • 任务持久化
  • 支持分布式处理

解决方案

// 使用平台提供的jobQueue
import { jobQueue } from '@/common/jobs';

// 创建任务
await jobQueue.push('asl:screening', {
  projectId,
  literatures,
  config,
});

// Worker处理
jobQueue.process('asl:screening', async (job) => {
  await screeningService.processLiteratures(job.data);
});

预计耗时1-2天


2. 无断点续传

问题:任务中断后需要重新开始

解决方案

// 检查是否有未完成的任务
const existingTask = await prisma.aslScreeningTask.findFirst({
  where: {
    projectId,
    status: 'running',
  }
});

if (existingTask) {
  // 恢复任务
  const processedLiteratureIds = await getProcessedLiteratureIds(existingTask.id);
  const remainingLiteratures = literatures.filter(
    lit => !processedLiteratureIds.includes(lit.id)
  );
  await resumeTask(existingTask.id, remainingLiteratures);
} else {
  // 创建新任务
  await startNewTask(projectId, literatures);
}

预计耗时1天


3. 无成本控制

问题无法控制API调用成本

解决方案

// 添加成本估算
interface CostEstimate {
  totalTokens: number;
  estimatedCost: number; // USD
  processingTime: number; // seconds
}

function estimateCost(literatures: Literature[]): CostEstimate {
  const avgTokensPerLit = 1500; // 标题+摘要约1500 tokens
  const totalTokens = literatures.length * avgTokensPerLit * 2; // 2个模型
  
  const deepseekCost = (totalTokens / 1000) * 0.001; // $0.001/1K tokens
  const qwenCost = (totalTokens / 1000) * 0.002; // $0.002/1K tokens
  
  return {
    totalTokens,
    estimatedCost: deepseekCost + qwenCost,
    processingTime: literatures.length * 15, // 15秒/篇
  };
}

// 前端显示
const estimate = estimateCost(literatures);
<Alert>
  预计消耗: {estimate.totalTokens} tokens
  预计费用: ${estimate.estimatedCost.toFixed(2)}
  预计时间: {formatDuration(estimate.processingTime)}
</Alert>

预计耗时0.5天


📊 技术债务优先级矩阵

债务项 影响范围 紧迫性 预计耗时 ROI 优先级
Prompt优化 核心质量 4-5天 P1 🔴
并发处理 用户体验 0.5-1天 P2 🟡
估计剩余时间 用户体验 0.5天 P3 🟢
当前文献显示 用户体验 0.5天 P3 🟢
浏览器性能 用户体验 0.5天 P4 🔵
消息队列 架构稳定性 1-2天 P4 🔵
断点续传 用户体验 1天 P4 🔵
成本控制 运营 0.5天 P4 🔵
小屏幕适配 用户体验 1天 P4 🔵

🗓️ 建议的解决顺序

阶段1质量优化必须

时间1周
任务:
  1. Few-shot示例设计1天
  2. PICOS标准明确化2天
  3. 置信度优化0.5天)
  4. 测试迭代1-2天
目标:准确率 60% → 85%

阶段2性能优化推荐

时间1-2天
任务:
  1. 并发处理0.5-1天
  2. 进度优化0.5天)
目标199篇 33-66分钟 → 10-20分钟

阶段3体验优化可选

时间2-3天
任务:
  1. 估计剩余时间0.5天)
  2. 当前文献显示0.5天)
  3. 浏览器性能0.5天)
  4. 小屏幕适配1天
目标:提升用户体验

阶段4架构优化长期

时间3-4天
任务:
  1. 消息队列集成1-2天
  2. 断点续传1天
  3. 成本控制0.5天)
目标:生产环境就绪

📝 决策记录

2025-11-21推迟质量优化优先完成Week 4功能

决策人:用户

决策内容

  • 将Prompt优化、并发处理等优化任务记录为技术债务
  • 优先完成Week 4功能结果展示、统计、导出
  • 待Week 4完成后再根据实际需要处理技术债务

理由

  1. MVP核心功能已可用可以先完成功能闭环
  2. 统计和导出功能是用户强需求
  3. 质量优化可以在功能完整后迭代

后续计划

  • Week 4功能完成后评估
  • 根据用户反馈决定优化优先级


🟠 优先级6全文复筛技术债务NEW

更新日期2025-11-22
当前状态Day 1-3已完成通用能力层核心

债务1Nougat质量检测机制缺失

问题描述

  • 当前Nougat提取后质量评分为undefined
  • 导致所有PDF都降级到PyMuPDF无法充分利用Nougat的结构化优势

影响

  • 无法获得Markdown格式的结构化全文
  • Section-Aware Prompt策略效果打折扣
  • 可能影响准确率(结构化信息丢失)

根本原因

  • Python extraction_service返回的Nougat结果缺少quality字段
  • 或质量评分逻辑未实现

解决方案

  1. 检查extraction_service/services/pdf_processor.py的Nougat处理逻辑
  2. 实现质量评分机制基于识别置信度、Markdown完整性等
  3. 测试并调优质量阈值

优先级:中
预计耗时:半天
风险:低


债务2MVP未实施全文验证Full-text Validation

问题描述

  • 质量保障策略中设计了"分段提取 + 全文验证"
  • MVP采用"一次性全文提取"策略,跳过了全文验证步骤

影响

  • 可能存在"Lost in the Middle"现象导致的遗漏
  • 关键字段的准确率可能未达到92%目标

建议

  1. MVP上线后收集准确率数据
  2. 如果关键字段准确率<90%,实施全文验证
  3. 优先针对3个核心字段随机化方法、盲法、结果完整性

优先级待MVP测试验证
预计耗时2天
条件触发:关键字段准确率<90%


债务3Cochrane标准未加载MVP简化

问题描述

  • MVP为了减少Prompt长度和成本未加载Cochrane RoB 2.0标准
  • 可能影响"质量评估"字段的判断准确性

影响

  • 质量评估字段可能不够严谨
  • 缺少统一的评判标准

建议

  1. MVP测试后评估准确率
  2. 如果"质量评估"字段准确率<85%重新加载Cochrane标准
  3. 通过配置开关灵活控制PromptBuilder已支持

优先级待MVP测试验证
预计耗时:半天(已有代码,仅需配置)
条件触发:质量评估字段准确率<85%


债务4Few-shot Examples被移除

问题描述

  • 为了优化Prompt长度从74KB降至52KB移除了Few-shot examples
  • 可能影响模型对"Lost in the Middle"场景的处理能力

影响

  • 模型缺少参考案例,面对复杂场景时可能表现不稳定

建议

  1. MVP测试后分析失败案例
  2. 如果发现特定模式的失败案例如信息在中间位置重新添加Few-shot
  3. 采用精简版Few-shot1-2个核心案例而非原来的完整案例

优先级待MVP测试验证
预计耗时1天
条件触发:特定场景失败率>30%


债务5批处理服务未实现Day 4待开发

问题描述

  • 当前只有单篇PDF的LLM处理服务
  • 缺少批量处理、进度跟踪、并发控制

影响

  • 无法批量处理多篇文献
  • 缺少任务队列和进度管理

解决方案

  • Day 4开发AsyncTaskServiceFulltextScreeningService
  • 集成p-queue实现并发控制
  • 实现进度回调和失败重试

优先级Day 4计划中
预计耗时1天
状态:计划中


债务6前端UI未开发Day 5-6待开发

问题描述

  • 全文复筛的前端UI完全未开发
  • 包括设置页、工作台页、结果页、双视图审阅弹窗

影响

  • 后端服务无法被用户使用
  • MVP无法交付

解决方案

  • Day 5-6开发前端UI
  • 参考标题摘要初筛的UI设计
  • 适配12字段模板的展示需求

优先级Day 5-6计划中
预计耗时2天
状态:计划中


债务7数据库表未创建 已解决

问题描述

  • AslFulltextScreeningTaskAslFulltextScreeningResult表未创建
  • 无法存储全文复筛的任务和结果

影响

  • 后端服务无法持久化数据

解决方案

  • Day 4执行Prisma迁移
  • 创建两个新表并建立关联

优先级Day 4计划中
预计耗时:半天
状态 已完成2025-11-23

解决详情

  • 使用手动SQL脚本完成迁移避免影响public schema
  • 创建了 fulltext_screening_tasksfulltext_screening_results
  • 修改 literatures添加13个全文相关字段
  • 详见:2025-11-23_数据库迁移状态说明.md

债务8API端点未实现

问题描述

  • 全文复筛相关的RESTful API未实现
  • 前端无法调用后端服务

影响

  • 前后端无法集成

解决方案

  • Day 4开发API控制器
  • 实现任务创建、进度查询、结果查询、人工复核等接口

优先级Day 4计划中
预计耗时:半天
状态:计划中


债务9成本优化空间

问题描述

  • 单篇PDF处理成本约¥0.10DeepSeek + Qwen
  • System Prompt仍有6,601字符有优化空间

潜在优化

  1. 精简System Prompt保留核心指引移除冗余说明
  2. 调整JSON Schema减少description字段
  3. 考虑单模型模式仅DeepSeek成本降低75%

预期效果

  • 成本降低30-50%(双模型)
  • 或降低75%(单模型)

优先级MVP稳定后
预计耗时1-2天


债务10容错机制待增强

问题描述

  • 虽然已实现3层JSON解析策略但缺少"LLM重试"层
  • 如果3层解析都失败任务直接失败

建议

  • 在生产环境中监控JSON解析失败率
  • 如果失败率>5%实施第4层LLM重试带强化Prompt

优先级:低(待生产数据验证)
预计耗时1天
条件触发JSON解析失败率>5%


🎨 全文复筛 - 前端技术债务

模块:全文复筛前端
创建时间2025-11-23
状态:待开发


债务11PDF标注功能

问题描述

  • MVP版本只支持PDF预览翻页、缩放
  • 无法在PDF上进行标注、高亮、添加批注
  • 用户希望在审核时标记关键信息

使用场景

  • 审核工作台查看原文时,标记关键证据
  • 高亮冲突的文本片段
  • 添加个人审核笔记

建议方案

  • 集成PDF标注库如 react-pdf-highlighter
  • 支持文本高亮、下划线、批注
  • 标注数据保存到数据库,可导出

优先级:中
预计耗时3-4天
依赖PDF预览功能完成
用户价值


债务12文献笔记功能

问题描述

  • 无法为每篇文献添加审核笔记
  • 人工复核时的思考过程无法记录
  • 不便于后续回溯决策依据

使用场景

  • 记录为什么纳入/排除某篇文献
  • 记录需要进一步核查的问题
  • 团队协作时的沟通记录

建议方案

  • 在文献详情抽屉添加"笔记"Tab
  • 支持富文本编辑器Markdown
  • 支持@提及团队成员
  • 笔记保存到数据库

优先级:中
预计耗时2-3天
依赖:详情抽屉完成
用户价值


债务13从知识库选择文献

问题描述

  • MVP版本只支持本地上传PDF
  • 无法从已有知识库中选择文献
  • 需要重复上传已存在的PDF

使用场景

  • 用户在个人知识库中已保存大量文献
  • 希望直接选择现有文献进行全文复筛
  • 避免重复上传和存储

建议方案

  • 在"添加文献"弹窗添加"知识库"Tab
  • 显示用户的所有PDF文献列表
  • 支持搜索、筛选、多选
  • 选中后自动关联到当前任务

优先级:低
预计耗时2天
依赖个人知识库模块PKB
用户价值


债务14通过PMID/DOI自动获取全文

问题描述

  • 用户只有PMID或DOI没有PDF文件
  • 需要手动去PubMed等网站下载PDF
  • 增加操作成本和时间

使用场景

  • 用户有文献的PMID列表
  • 希望系统自动获取全文PDF
  • 自动批量下载并关联

建议方案

  • 在"添加文献"弹窗添加"自动获取"Tab
  • 输入PMID/DOI列表支持批量
  • 调用第三方APIPubMed、Unpaywall、Sci-Hub镜像
  • 自动下载PDF并添加到任务

优先级:低
预计耗时3-5天
依赖第三方PDF获取API
用户价值
法律风险⚠️ 需评估版权问题


债务15高亮AI引用的原文片段

问题描述

  • AI判断时引用了原文证据
  • 但在PDF预览中无法自动定位和高亮
  • 用户需要手动查找对应的文本

使用场景

  • 查看AI判断依据时希望看到原文位置
  • 点击证据文本PDF自动跳转并高亮
  • 验证AI提取是否准确

建议方案

  • 在AI判断对比中证据文本变为可点击
  • 点击后PDF预览自动跳转到对应页面
  • 高亮匹配的文本片段(需要坐标信息)
  • 后端需要返回文本在PDF中的位置坐标

优先级:中
预计耗时4-5天
依赖PDF提取服务返回文本坐标
用户价值
技术难度


债务16WebSocket实时推送替代轮询

问题描述

  • 当前使用轮询机制每3秒请求一次
  • 增加服务器负载和网络流量
  • 进度更新有延迟最多3秒

使用场景

  • 任务进度监控页面
  • 长时间运行的LLM任务
  • 希望实时看到处理日志

建议方案

  • 后端实现WebSocket服务
  • 前端建立WebSocket连接
  • 任务进度变化时主动推送
  • 降级策略WebSocket不可用时回退到轮询

优先级:低
预计耗时3-4天
依赖后端WebSocket实现
用户价值
性能提升


债务17虚拟滚动优化大列表性能

问题描述

  • 当文献数量>100篇时表格渲染变慢
  • 所有行都渲染到DOM占用大量内存
  • 滚动时可能出现卡顿

使用场景

  • 大规模全文复筛200+篇文献)
  • 审核工作台和结果页面
  • 需要流畅的滚动体验

建议方案

  • 使用虚拟滚动库react-window / react-virtualized
  • 只渲染可见区域的行
  • 优化Ant Design Table性能
  • 添加性能监控

优先级:低
预计耗时2天
条件触发:文献数量>100篇
用户价值
性能提升


债务18批量操作功能

问题描述

  • 结果页面只能单个文献操作
  • 无法批量修改决策
  • 无法批量导出选中的文献

使用场景

  • 批量标记为"纳入"或"排除"
  • 批量导出选中文献的PDF
  • 批量删除错误上传的文献

建议方案

  • 表格添加复选框列
  • 添加批量操作工具栏
  • 支持:批量修改决策、批量导出、批量删除
  • 添加操作确认提示

优先级:低
预计耗时2天
用户价值


债务19离线PDF预览支持

问题描述

  • PDF预览依赖在线CDN加载pdf.js worker
  • 网络不好时加载失败
  • 内网环境无法使用

使用场景

  • 内网部署环境
  • 网络不稳定的用户
  • 需要完全离线使用

建议方案

  • 将pdf.js worker打包到项目中
  • 支持本地加载和CDN加载两种模式
  • 自动检测网络并选择最优方式

优先级:低
预计耗时1天
条件触发:内网部署需求
用户价值


债务20响应式设计适配移动端

问题描述

  • 当前设计只考虑桌面端1920x1080
  • 在平板和手机上显示效果差
  • 表格宽度固定,小屏幕下无法使用

使用场景

  • 用户希望在平板上审核文献
  • 移动场景下查看任务进度
  • 外出时临时处理审核

建议方案

  • 使用响应式布局Tailwind CSS
  • 小屏幕下表格改为卡片视图
  • 优化触摸交互体验
  • 添加移动端导航

优先级:极低
预计耗时5-7天
条件触发:用户明确需求
用户价值


📚 相关文档

标题摘要初筛:

全文复筛:


文档维护

  • 每次发现新的技术债务时更新
  • 每次解决技术债务后标记状态
  • 定期评估优先级(每月)

最后更新2025-11-23v1.2
本次更新新增全文复筛前端技术债务10项债务11-20
下次评估全文复筛前端MVP完成后