feat(rvw): Complete RVW module development Phase 1-3
Summary: - Migrate backend to modules/rvw with v2 API routes (/api/v2/rvw) - Add new database fields: selectedAgents, editorialScore, methodologyStatus, picoExtract, isArchived - Create frontend module in frontend-v2/src/modules/rvw - Implement Dashboard with task list, filtering, batch operations - Implement ReportDetail with dual tabs (editorial/methodology) - Implement AgentModal for intelligent agent selection - Register RVW module in moduleRegistry.ts - Add navigation entry in TopNavigation - Update documentation for RVW module status (v3.0) - Update system status document (v2.9) Features: - User can select agents: editorial, methodology, or both - Support batch task execution - Task status filtering - Replace console.log with logger service - Maintain v1 API backward compatibility Tested: Frontend and backend verified locally Status: 85% complete (Phase 1-3 done)
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# AIclinicalresearch 系统当前状态与开发指南
|
||||
|
||||
> **文档版本:** v2.8
|
||||
> **文档版本:** v2.9
|
||||
> **创建日期:** 2025-11-28
|
||||
> **维护者:** 开发团队
|
||||
> **最后更新:** 2026-01-07
|
||||
> **重大进展:** 🎉 **PKB模块核心功能全部实现,具备生产可用性!** - 批处理完整流程验证通过
|
||||
> **重大进展:** 🎉 **RVW稿件审查模块开发完成(85%)!** - 后端迁移+数据库扩展+前端重构全部完成
|
||||
> **部署状态:** ✅ 生产环境运行中 | 公网地址:http://8.140.53.236/
|
||||
> **文档目的:** 快速了解系统当前状态,为新AI助手提供上下文
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
| **IIT** | IIT Manager Agent | AI驱动IIT研究助手 - 智能质控+REDCap集成 | ⭐⭐⭐⭐⭐ | 🎉 **Phase 1.5完成(60%)- AI对话+REDCap数据集成** | **P0** |
|
||||
| **SSA** | 智能统计分析 | 队列/预测模型/RCT分析 | ⭐⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **ST** | 统计分析工具 | 100+轻量化统计工具 | ⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **RVW** | 稿件审查系统 | 方法学评估、审稿流程 | ⭐⭐⭐⭐ | 📋 规划中 | P3 |
|
||||
| **RVW** | 稿件审查系统 | 方法学评估、审稿流程 | ⭐⭐⭐⭐ | ✅ **开发完成(85%)** | P3 |
|
||||
|
||||
---
|
||||
|
||||
@@ -661,6 +661,7 @@ AIclinicalresearch/
|
||||
| **2026-01-07 上午** | **PKB前端V3** 🎉 | ✅ PKB模块前端V3设计实现完成(Dashboard+Workspace+3种工作模式) |
|
||||
| **2026-01-07 下午** | **PKB批处理完善** 🏆 | ✅ 批处理完整流程调试通过(执行+进度+结果导出)+ 文档上传功能 + UI优化 |
|
||||
| **当前** | **PKB模块生产可用** | ✅ 核心功能全部实现(90%),具备生产环境部署条件 |
|
||||
| **2026-01-07 晚** | **RVW模块开发完成** 🎉 | ✅ Phase 1-3完成(后端迁移+数据库扩展+前端重构) |
|
||||
|
||||
---
|
||||
|
||||
@@ -814,9 +815,9 @@ npm run dev # http://localhost:3000
|
||||
- **总计**:约 85,000 行
|
||||
|
||||
### 模块完成度
|
||||
- ✅ **已完成**:AIA(100%)、平台基础层(100%)
|
||||
- 🚧 **开发中**:PKB(75%,前端V3设计完成)、ASL(80%)、DC(Tool C 98%,Tool B后端100%,Tool B前端0%)、IIT(60%,Phase 1.5完成)
|
||||
- 📋 **未开始**:SSA、ST、RVW
|
||||
- ✅ **已完成**:AIA(100%)、平台基础层(100%)、RVW(85%,Phase 1-3完成)
|
||||
- 🚧 **开发中**:PKB(90%,核心功能完成)、ASL(80%)、DC(Tool C 98%,Tool B后端100%,Tool B前端0%)、IIT(60%,Phase 1.5完成)
|
||||
- 📋 **未开始**:SSA、ST
|
||||
|
||||
### 部署完成度
|
||||
- ✅ **基础设施**:VPC(100%)、NAT网关(100%)、安全组(100%)
|
||||
@@ -952,9 +953,9 @@ if (items.length >= 50) {
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:v2.8
|
||||
**文档版本**:v2.9
|
||||
**最后更新**:2026-01-07
|
||||
**下次更新**:ASL智能文献筛选模块启动 或 IIT Manager Agent Phase 2
|
||||
**下次更新**:RVW生产环境部署 或 ASL智能文献筛选模块启动
|
||||
|
||||
---
|
||||
|
||||
@@ -1016,3 +1017,36 @@ if (items.length >= 50) {
|
||||
- ✅ 测试通过:查询test0102项目,ID 7患者详细信息
|
||||
|
||||
**模块进度**:60%完成(Phase 1.5)
|
||||
|
||||
---
|
||||
|
||||
**RVW稿件审查模块开发完成(2026-01-07)**:
|
||||
|
||||
### Phase 1:后端模块迁移与扩展
|
||||
- ✅ 创建 `backend/src/modules/rvw/` 模块结构
|
||||
- ✅ 迁移 reviewService、editorialService、methodologyService
|
||||
- ✅ 实现智能体选择(selectedAgents)
|
||||
- ✅ 实现批量运行API(batchRunReviewTasks)
|
||||
- ✅ 替换 console.log 为 logger 服务
|
||||
- ✅ 注册 v2 API路由(/api/v2/rvw)
|
||||
|
||||
### Phase 2:数据库字段扩展
|
||||
- ✅ 添加 selectedAgents、editorialScore、methodologyStatus 字段
|
||||
- ✅ 添加 picoExtract、isArchived、archivedAt 字段
|
||||
- ✅ 使用 prisma db push 同步到数据库
|
||||
|
||||
### Phase 3:前端重构(frontend-v2)
|
||||
- ✅ 创建 `frontend-v2/src/modules/rvw/index.tsx`(~503行)
|
||||
- ✅ 实现 Dashboard 组件(任务列表、筛选、批量操作)
|
||||
- ✅ 实现 ReportDetail 组件(双标签页切换)
|
||||
- ✅ 实现 AgentModal 组件(智能体选择弹窗)
|
||||
- ✅ 注册到 moduleRegistry.ts
|
||||
- ✅ 添加顶部导航"预审稿"入口
|
||||
|
||||
**技术亮点**:
|
||||
- 🔥 **新旧API兼容**:v1 + v2 API同时运行
|
||||
- 🔥 **智能体可选**:用户可选择运行稿约规范性/方法学/两者
|
||||
- 🔥 **批量操作**:支持多选任务批量运行
|
||||
- 🔥 **云原生改造**:使用 logger 服务,遵循开发规范
|
||||
|
||||
**模块进度**:85%完成(Phase 1-3)
|
||||
|
||||
@@ -606,5 +606,6 @@ async saveProcessedData(recordId, newData) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -793,5 +793,6 @@ export const AsyncProgressBar: React.FC<AsyncProgressBarProps> = ({
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1286,5 +1286,6 @@ interface FulltextScreeningResult {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -400,5 +400,6 @@ GET /api/v1/asl/fulltext-screening/tasks/:taskId/export
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -343,5 +343,6 @@ Linter错误:0个
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -502,5 +502,6 @@ Failed to open file '\\tmp\\extraction_service\\temp_10000_test.pdf'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -568,5 +568,6 @@ df['creatinine'] = pd.to_numeric(df['creatinine'], errors='coerce')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -406,5 +406,6 @@ npm run dev
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -983,5 +983,6 @@ export const aiController = new AIController();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1317,5 +1317,6 @@ npm install react-markdown
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -225,5 +225,6 @@ FMA___基线 | FMA___1个月 | FMA___2个月
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -383,5 +383,6 @@ formula = "FMA总分(0-100) / 100"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -217,5 +217,6 @@ async handleFillnaMice(request, reply) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -189,5 +189,6 @@ method: 'mean' | 'median' | 'mode' | 'constant' | 'ffill' | 'bfill'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -339,5 +339,6 @@ Changes:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -411,5 +411,6 @@ cd path; command
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -640,5 +640,6 @@ import { logger } from '../../../../common/logging/index.js';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -644,5 +644,6 @@ Content-Length: 45234
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -296,5 +296,6 @@ Response:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -449,5 +449,6 @@ Response:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -443,5 +443,6 @@ import { ChatContainer } from '@/shared/components/Chat';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -353,5 +353,6 @@ const initialMessages = defaultMessages.length > 0 ? defaultMessages : [{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -393,5 +393,6 @@ python main.py
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -641,5 +641,6 @@ http://localhost:5173/data-cleaning/tool-c
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -251,5 +251,6 @@ Day 5 (6-8小时):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -429,5 +429,6 @@ Docs: docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -404,5 +404,6 @@ const mockAssets: Asset[] = [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -388,5 +388,6 @@ frontend-v2/src/modules/dc/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -348,5 +348,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -302,5 +302,6 @@ ConflictDetectionService // 冲突检测(字段级对比)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -351,5 +351,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -314,5 +314,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -378,5 +378,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -466,5 +466,6 @@ Tool B后端代码**100%复用**了平台通用能力层,无任何重复开发
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -312,5 +312,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -243,5 +243,6 @@ $ node scripts/check-dc-tables.mjs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -476,5 +476,6 @@ ${fields.map((f, i) => `${i + 1}. ${f.name}:${f.desc}`).join('\n')}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -683,3 +683,4 @@ private async processMessageAsync(xmlData: any) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1077,3 +1077,4 @@ async function testIntegration() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -218,3 +218,4 @@ Content-Type: application/json
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -638,3 +638,4 @@ REDCap API: exportRecords success { recordCount: 1 }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -644,3 +644,4 @@ backend/src/modules/iit-manager/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -794,3 +794,4 @@ CREATE TABLE iit_schema.wechat_tokens (
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -551,3 +551,4 @@ Day 3 的开发工作虽然遇到了多个技术问题,但最终成功完成
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -318,3 +318,4 @@ AI: "出生日期:2017-01-04
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -262,3 +262,4 @@ Day 4: REDCap EM(Webhook推送)← 作为增强,而非核心
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -676,3 +676,4 @@ const answer = `根据研究方案[1]和CRF表格[2],纳入标准包括:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -356,3 +356,4 @@ const newResults = resultsData.map((docResult: any) => ({
|
||||
3. 增加更多模板和自定义能力
|
||||
4. 完善错误处理和用户反馈
|
||||
|
||||
|
||||
|
||||
@@ -229,3 +229,4 @@ const chatApi = axios.create({
|
||||
**下次更新**:批处理功能调试完成后
|
||||
|
||||
|
||||
|
||||
|
||||
338
docs/03-业务模块/RVW-稿件审查系统/00-模块当前状态与开发指南.md
Normal file
338
docs/03-业务模块/RVW-稿件审查系统/00-模块当前状态与开发指南.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# RVW稿件审查模块 - 当前状态与开发指南
|
||||
|
||||
> **文档版本:** v3.0
|
||||
> **创建日期:** 2026-01-07
|
||||
> **最后更新:** 2026-01-07
|
||||
> **维护者:** 开发团队
|
||||
> **当前状态:** ✅ **Phase 1-3 完成,前后端功能可用**
|
||||
> **文档目的:** 快速了解RVW模块状态,为新AI助手提供上下文
|
||||
|
||||
---
|
||||
|
||||
## 📊 模块概览
|
||||
|
||||
### 基本信息
|
||||
|
||||
| 项目 | 信息 |
|
||||
|------|------|
|
||||
| **模块名称** | RVW - 稿件审查系统 (Review) |
|
||||
| **模块定位** | 智能期刊审稿辅助系统(可独立销售) |
|
||||
| **商业价值** | ⭐⭐⭐⭐⭐ 极高 |
|
||||
| **独立性** | ⭐⭐⭐⭐⭐ 极高(用户群完全不同) |
|
||||
| **目标用户** | 期刊初审编辑 |
|
||||
| **开发状态** | ✅ **核心功能100%完成,已集成到 frontend-v2** |
|
||||
|
||||
### 核心目标
|
||||
|
||||
> 打造一个**"开箱即用"**的智能审稿工具。编辑上传稿件,系统自动运行双重检查(规范性+方法学),输出可供参考的审稿报告。
|
||||
>
|
||||
> **核心指标**:上传到出报告 < 2分钟;规范性问题检出率 > 80%
|
||||
|
||||
### 功能规格
|
||||
|
||||
#### 核心AI能力(已完成 ✅)
|
||||
|
||||
1. **稿约规范性评估**(11项标准)
|
||||
- 文题字数、摘要结构、参考文献、图片DPI等
|
||||
- 基于《中华医学超声杂志》稿约标准
|
||||
|
||||
2. **方法学评估**(3部分,20个检查点)
|
||||
- 科研设计评估(9个检查点)
|
||||
- 统计学方法描述评估(5个检查点)
|
||||
- 统计分析评估(6个检查点)
|
||||
|
||||
3. **综合评分 + PICO提取**
|
||||
- 规范性分数(0-100)
|
||||
- 方法学状态(🔴错误 🟡存疑 🟢通过)
|
||||
- PICO结构化提取(P/I/C/O)
|
||||
|
||||
#### 交互功能(✅ 已完成)
|
||||
|
||||
| 功能 | 旧版本 | 新版本 | 状态 |
|
||||
|------|--------|--------|------|
|
||||
| 单文件上传 | ✅ | ✅ | ✅ 已完成 |
|
||||
| 批量上传 | ❌ | ✅ | ✅ 已完成 |
|
||||
| 审稿工作台(宽表) | ❌ | ✅ | ✅ 已完成 |
|
||||
| 智能体选择 | 自动 | 用户可选 | ✅ 已完成 |
|
||||
| 批量操作 | ❌ | ✅ | ✅ 已完成 |
|
||||
| 状态筛选 | ❌ | ✅ | ✅ 已完成 |
|
||||
| 历史归档 | ❌ | ✅ | ⏸️ 数据库已支持,UI暂缓 |
|
||||
| 系统设置 | ❌ | ✅ | ⏸️ 暂不开发 |
|
||||
| 登录页面 | ❌ | ⏸️ | ⏸️ 复用平台登录 |
|
||||
| PICO卡片 | ❌ | ✅ | ⏸️ 数据库已支持,UI暂缓 |
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 架构状态
|
||||
|
||||
### ✅ 已完成迁移(Modules)
|
||||
|
||||
```
|
||||
后端(✅ 已完成):
|
||||
backend/src/modules/rvw/
|
||||
├── routes/index.ts # v2 API路由(/api/v2/rvw)
|
||||
├── controllers/reviewController.ts # 控制器(含批量操作、智能体选择)
|
||||
├── services/
|
||||
│ ├── reviewService.ts # 核心服务(任务创建、执行)
|
||||
│ ├── editorialService.ts # 稿约规范性评估
|
||||
│ ├── methodologyService.ts # 方法学评估
|
||||
│ └── utils.ts # 工具函数
|
||||
├── types/index.ts # TypeScript类型定义
|
||||
└── __tests__/ # API测试脚本
|
||||
|
||||
前端(✅ 已完成):
|
||||
frontend-v2/src/modules/rvw/
|
||||
└── index.tsx # 完整模块(~503行)
|
||||
├── Dashboard组件 # 审稿工作台(宽表、筛选、批量操作)
|
||||
├── ReportDetail组件 # 报告详情(双标签页切换)
|
||||
└── AgentModal组件 # 智能体选择弹窗
|
||||
|
||||
旧版本(保留兼容):
|
||||
backend/src/legacy/
|
||||
├── routes/reviewRoutes.ts # v1 API路由(保留)
|
||||
├── controllers/reviewController.ts
|
||||
└── services/reviewService.ts
|
||||
|
||||
Prompt(保持不变):
|
||||
backend/prompts/
|
||||
├── review_editorial_system.txt # 稿约评估(266行)
|
||||
└── review_methodology_system.txt # 方法学评估(257行)
|
||||
|
||||
数据库(✅ 已完成):
|
||||
- ReviewTask表已添加新字段:selectedAgents, editorialScore, methodologyStatus, picoExtract, isArchived, archivedAt
|
||||
- Schema迁移待后续执行(当前在public schema)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 开发进度
|
||||
|
||||
| Phase | 任务 | 状态 | 完成日期 |
|
||||
|-------|------|------|---------|
|
||||
| Phase 1 | 后端模块迁移与扩展 | ✅ 已完成 | 2026-01-07 |
|
||||
| Phase 2 | 数据库字段扩展 | ✅ 已完成 | 2026-01-07 |
|
||||
| Phase 3 | 前端重构(frontend-v2) | ✅ 已完成 | 2026-01-07 |
|
||||
| Phase 4 | 集成测试 | 🔧 基本通过 | 2026-01-07 |
|
||||
| Phase 5 | 系统设置与归档 | ⏸️ 暂缓 | - |
|
||||
| **总计** | - | **85%** | - |
|
||||
|
||||
### Phase 1-3 完成内容
|
||||
|
||||
**后端(Phase 1):**
|
||||
- ✅ 创建 `backend/src/modules/rvw/` 模块结构
|
||||
- ✅ 迁移并优化 reviewService、editorialService、methodologyService
|
||||
- ✅ 实现智能体选择(selectedAgents:editorial/methodology/both)
|
||||
- ✅ 实现批量运行API(batchRunReviewTasks)
|
||||
- ✅ 替换 console.log 为 logger 服务
|
||||
- ✅ 注册 v2 API路由(/api/v2/rvw)
|
||||
|
||||
**数据库(Phase 2):**
|
||||
- ✅ 添加 selectedAgents 字段(String[])
|
||||
- ✅ 添加 editorialScore 字段(Float?)
|
||||
- ✅ 添加 methodologyStatus 字段(String?)
|
||||
- ✅ 添加 picoExtract 字段(Json?)
|
||||
- ✅ 添加 isArchived、archivedAt 字段(归档支持)
|
||||
- ✅ 使用 prisma db push 同步到数据库
|
||||
|
||||
**前端(Phase 3):**
|
||||
- ✅ 创建 `frontend-v2/src/modules/rvw/index.tsx`(~503行)
|
||||
- ✅ 实现 Dashboard 组件(任务列表、筛选、批量操作)
|
||||
- ✅ 实现 ReportDetail 组件(双标签页:稿约规范性/方法学)
|
||||
- ✅ 实现 AgentModal 组件(智能体选择弹窗)
|
||||
- ✅ 注册到 moduleRegistry.ts
|
||||
- ✅ 添加顶部导航入口
|
||||
|
||||
详细任务清单见:[RVW模块迁移计划](./04-开发计划/RVW模块迁移计划.md)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术依赖
|
||||
|
||||
### 复用的平台能力
|
||||
|
||||
| 能力 | 位置 | 用途 |
|
||||
|------|------|------|
|
||||
| **LLM网关** | `@/common/llm/LLMFactory` | AI评估 |
|
||||
| **文档处理** | `ExtractionClient` | Word/PDF文本提取 |
|
||||
| **存储** | `@/common/storage` | 文件存储 |
|
||||
| **日志** | `@/common/logging` | 结构化日志 |
|
||||
| **任务队列** | `jobQueue` | 异步任务处理 |
|
||||
|
||||
### LLM模型
|
||||
|
||||
| 模型 | 用途 | 说明 |
|
||||
|------|------|------|
|
||||
| DeepSeek-V3 | 默认 | 性价比高,推理能力强 |
|
||||
| DeepSeek-R1 | 备选 | 深度推理 |
|
||||
| Qwen3-72B | 备选 | 中文理解好 |
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
### 需求文档
|
||||
|
||||
- [智能期刊审稿系统MVP PRD](./01-需求分析/智能期刊审稿系统%20MVP%20产品需求文档.md)
|
||||
- [智能审稿V7原型](./01-需求分析/智能审稿V7.html) - 可直接浏览器打开
|
||||
|
||||
### 开发文档
|
||||
|
||||
- [迁移计划(v2.0整合版)](./04-开发计划/RVW模块迁移计划.md) ⬅️ **主要开发文档**
|
||||
|
||||
### 参考文档
|
||||
|
||||
- [现有系统技术摸底报告](../../00-项目概述/现有系统技术摸底报告.md) - Line 578-748
|
||||
- [云原生开发规范](../../04-开发规范/08-云原生开发规范.md)
|
||||
- [系统架构分层设计](../../00-系统总体设计/01-系统架构分层设计.md)
|
||||
|
||||
### Prompt文件
|
||||
|
||||
- [稿约规范性评估标准](./稿约规范性评估标准.txt)
|
||||
- [稿件方法学评估标准](./稿件方法学评估标准.txt)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 快速开始
|
||||
|
||||
### 访问审稿模块
|
||||
|
||||
1. **启动后端**
|
||||
```bash
|
||||
cd backend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
2. **启动前端(新版 frontend-v2)**
|
||||
```bash
|
||||
cd frontend-v2
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3. **访问审稿页面**
|
||||
- 打开 `http://localhost:3000`
|
||||
- 点击顶部导航栏的 **"预审稿"** 标签
|
||||
- 或直接访问 `http://localhost:3000/rvw`
|
||||
|
||||
4. **测试流程**
|
||||
- 点击"上传稿件"按钮
|
||||
- 选择Word/PDF文档(≤5MB)
|
||||
- 选择智能体(稿约规范性/方法学/两者都选)
|
||||
- 点击"运行"按钮
|
||||
- 等待AI评估完成(约1-2分钟)
|
||||
- 查看评估报告
|
||||
|
||||
### API测试(新版 v2 API)
|
||||
|
||||
```http
|
||||
### 获取任务列表
|
||||
GET http://localhost:3001/api/v2/rvw/tasks
|
||||
|
||||
### 按状态筛选
|
||||
GET http://localhost:3001/api/v2/rvw/tasks?status=pending
|
||||
|
||||
### 上传稿件
|
||||
POST http://localhost:3001/api/v2/rvw/tasks
|
||||
Content-Type: multipart/form-data
|
||||
# file: 文件
|
||||
# selectedAgents: ["editorial", "methodology"]
|
||||
|
||||
### 运行单个任务
|
||||
POST http://localhost:3001/api/v2/rvw/tasks/{{taskId}}/run
|
||||
Content-Type: application/json
|
||||
{"selectedAgents": ["editorial", "methodology"]}
|
||||
|
||||
### 批量运行任务
|
||||
POST http://localhost:3001/api/v2/rvw/tasks/batch-run
|
||||
Content-Type: application/json
|
||||
{"taskIds": ["id1", "id2"], "selectedAgents": ["editorial"]}
|
||||
|
||||
### 获取任务详情
|
||||
GET http://localhost:3001/api/v2/rvw/tasks/{{taskId}}
|
||||
|
||||
### 获取报告
|
||||
GET http://localhost:3001/api/v2/rvw/tasks/{{taskId}}/report
|
||||
```
|
||||
|
||||
### 旧版API(保持兼容)
|
||||
|
||||
```http
|
||||
### 上传稿件(旧API)
|
||||
POST http://localhost:3001/api/v1/review/upload
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 对新AI助手
|
||||
|
||||
1. ✅ **核心功能已完成**:前后端已迁移到新架构,可正常使用
|
||||
2. ✅ **已集成到 frontend-v2**:通过顶部导航栏"预审稿"进入
|
||||
3. ✅ **v2 API 已就绪**:/api/v2/rvw/* 路由可用
|
||||
4. ✅ **遵循云原生规范**:使用 logger 服务替代 console.log
|
||||
5. ⚠️ **保留旧API**:v1路由保持兼容,支持旧前端
|
||||
|
||||
### 已完成改造
|
||||
|
||||
| 问题 | 改造前 | 改造后 | 状态 |
|
||||
|------|--------|--------|------|
|
||||
| 日志 | console.log | logger服务 | ✅ 已完成 |
|
||||
| 用户认证 | Mock用户ID | getUserId(request) | ✅ 已完成 |
|
||||
| 智能体选择 | 自动 | 用户可选 | ✅ 已完成 |
|
||||
| 批量操作 | 无 | batchRunReviewTasks | ✅ 已完成 |
|
||||
|
||||
### 待后续改造
|
||||
|
||||
| 问题 | 当前 | 目标 | 优先级 |
|
||||
|------|------|------|--------|
|
||||
| Schema位置 | public | review_schema | P2 |
|
||||
| 任务处理 | 直接异步 | jobQueue | P2 |
|
||||
| 报告导出 | 基础版 | PDF优化 | P3 |
|
||||
|
||||
---
|
||||
|
||||
## 📈 验收标准
|
||||
|
||||
根据MVP PRD,验收标准如下:
|
||||
|
||||
1. **流程通**:用户能成功上传5个PDF,勾选双模型运行,等待3分钟内,状态全部变为"已完成"
|
||||
|
||||
2. **报告准**:
|
||||
- 上传一篇故意删掉"摘要结论"的稿件,规范性智能体必须报错
|
||||
- 上传一篇故意混淆"t检验"和"卡方检验"的稿件,方法学智能体必须报"存疑"或"错误"
|
||||
|
||||
3. **无崩溃**:连续上传20个文件,系统不卡死,不白屏
|
||||
|
||||
---
|
||||
|
||||
## 🚀 未来规划
|
||||
|
||||
### ✅ 已完成(2026-01-07)
|
||||
|
||||
- [x] 架构迁移到 modules/rvw(后端)
|
||||
- [x] 架构迁移到 modules/rvw(前端 frontend-v2)
|
||||
- [x] 整合MVP新功能(批量上传、工作台、智能体选择)
|
||||
- [x] 云原生改造(logger服务)
|
||||
- [x] v2 API 路由注册
|
||||
- [x] 数据库字段扩展
|
||||
|
||||
### 后续版本
|
||||
|
||||
- [ ] Schema迁移到 review_schema
|
||||
- [ ] 任务队列改造(jobQueue)
|
||||
- [ ] PDF报告导出优化
|
||||
- [ ] PICO卡片UI实现
|
||||
- [ ] 历史归档UI实现
|
||||
- [ ] 登录页面(独立产品时)
|
||||
- [ ] 审稿人管理系统
|
||||
- [ ] 多轮审稿流程
|
||||
- [ ] 期刊库管理
|
||||
- [ ] 独立产品打包
|
||||
|
||||
---
|
||||
|
||||
**文档版本:** v3.0
|
||||
**最后更新:** 2026-01-07
|
||||
**当前状态:** ✅ Phase 1-3 完成,模块可用
|
||||
**下一步:** 生产环境部署测试 或 Schema隔离迁移
|
||||
529
docs/03-业务模块/RVW-稿件审查系统/01-需求分析/智能审稿V7.html
Normal file
529
docs/03-业务模块/RVW-稿件审查系统/01-需求分析/智能审稿V7.html
Normal file
@@ -0,0 +1,529 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>智能期刊审稿系统 - 中华脑血管病杂志专版</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- 引入 Lucide 图标 (UMD版) -->
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<style>
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background-color: #f8fafc; color: #334155; }
|
||||
|
||||
/* 状态标签 */
|
||||
.tag { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; line-height: 1.5; border: 1px solid transparent; }
|
||||
.tag-blue { background: #eff6ff; color: #1d4ed8; border-color: #dbeafe; }
|
||||
.tag-purple { background: #f5f3ff; color: #6d28d9; border-color: #ede9fe; }
|
||||
.tag-green { background: #f0fdf4; color: #15803d; border-color: #dcfce7; }
|
||||
.tag-amber { background: #fffbeb; color: #b45309; border-color: #fef3c7; }
|
||||
.tag-gray { background: #f8fafc; color: #64748b; border-color: #e2e8f0; }
|
||||
|
||||
/* 筛选 Chips */
|
||||
.filter-chip {
|
||||
padding: 4px 12px; border-radius: 9999px; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.2s; border: 1px solid transparent; color: #64748b;
|
||||
}
|
||||
.filter-chip:hover { background-color: #f1f5f9; color: #0f172a; }
|
||||
.filter-chip.active { background-color: #eff6ff; color: #2563eb; border-color: #bfdbfe; font-weight: 600; }
|
||||
|
||||
/* 选中行样式 */
|
||||
tr.selected { background-color: #eff6ff; }
|
||||
|
||||
/* Tab 激活样式 */
|
||||
.tab-btn { border-bottom: 2px solid transparent; color: #64748b; }
|
||||
.tab-btn:hover { color: #334155; }
|
||||
.tab-btn.active { color: #2563eb; border-bottom: 2px solid #2563eb; font-weight: 600; }
|
||||
|
||||
/* 动画 */
|
||||
.fade-in { animation: fadeIn 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
|
||||
.slide-up { animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes slideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
|
||||
|
||||
/* 侧边栏 Tooltip */
|
||||
.sidebar-btn:hover::after {
|
||||
content: attr(data-title); position: absolute; left: 100%; top: 50%; transform: translateY(-50%); margin-left: 12px; background: #1e293b; color: white; padding: 6px 10px; border-radius: 6px; font-size: 12px; white-space: nowrap; z-index: 50; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 评分环 */
|
||||
.score-circle {
|
||||
width: 80px; height: 80px; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; border: 6px solid #e2e8f0;
|
||||
}
|
||||
.score-circle.pass { border-color: #22c55e; background: #f0fdf4; color: #15803d; }
|
||||
.score-circle.warn { border-color: #f59e0b; background: #fffbeb; color: #b45309; }
|
||||
|
||||
/* 登录页背景 */
|
||||
.login-bg {
|
||||
background-image: radial-gradient(circle at 10% 20%, rgb(239, 246, 255) 0%, rgb(255, 255, 255) 90%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="h-screen overflow-hidden">
|
||||
|
||||
<!-- 视图 0: 登录页 (新增模块) -->
|
||||
<div id="view-login" class="fixed inset-0 z-50 login-bg flex flex-col items-center justify-center p-4">
|
||||
<div class="w-full max-w-md bg-white rounded-2xl shadow-xl p-8 slide-up border border-slate-100">
|
||||
<!-- 品牌 LOGO 区域 -->
|
||||
<div class="flex flex-col items-center mb-8">
|
||||
<div class="w-16 h-16 bg-indigo-600 rounded-2xl flex items-center justify-center text-white shadow-lg mb-4 transform rotate-3">
|
||||
<i data-lucide="brain-circuit" class="w-10 h-10"></i>
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-slate-800">中华脑血管病杂志</h1>
|
||||
<p class="text-sm text-slate-500 mt-2">智能审稿辅助系统 v1.0</p>
|
||||
</div>
|
||||
|
||||
<!-- 登录表单 -->
|
||||
<form onsubmit="handleLogin(event)" class="space-y-5">
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-1.5">账号</label>
|
||||
<div class="relative">
|
||||
<i data-lucide="user" class="absolute left-3 top-2.5 w-5 h-5 text-slate-400"></i>
|
||||
<input type="text" value="editor_admin" class="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition-all" placeholder="请输入编辑账号">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-1.5">密码</label>
|
||||
<div class="relative">
|
||||
<i data-lucide="lock" class="absolute left-3 top-2.5 w-5 h-5 text-slate-400"></i>
|
||||
<input type="password" value="123456" class="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition-all" placeholder="请输入密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<input type="checkbox" checked class="w-4 h-4 text-indigo-600 rounded border-gray-300">
|
||||
<span class="text-slate-600">记住我</span>
|
||||
</label>
|
||||
<a href="#" class="text-indigo-600 hover:underline font-medium">忘记密码?</a>
|
||||
</div>
|
||||
<button type="submit" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2.5 rounded-lg shadow-md transition-all hover:shadow-lg flex items-center justify-center gap-2">
|
||||
登录系统 <i data-lucide="arrow-right" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="text-center text-xs text-slate-400 mt-8">
|
||||
© 2025 AI审稿技术支持平台 · 技术支持
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主系统容器 (登录后显示) -->
|
||||
<div id="app-container" class="hidden h-full flex">
|
||||
|
||||
<!-- 侧边栏 -->
|
||||
<aside class="w-18 bg-slate-900 flex flex-col items-center py-6 gap-4 z-20 shadow-xl flex-shrink-0 relative">
|
||||
<!-- 客户 LOGO (侧边栏折叠版) -->
|
||||
<div class="w-10 h-10 bg-indigo-500 rounded-xl flex items-center justify-center text-white shadow-lg mb-4" title="中华脑血管病杂志">
|
||||
<i data-lucide="brain-circuit" class="w-6 h-6"></i>
|
||||
</div>
|
||||
|
||||
<button onclick="switchView('list')" class="sidebar-btn w-10 h-10 rounded-lg bg-white/10 text-white flex items-center justify-center hover:bg-indigo-600 transition-colors relative" data-title="审稿工作台">
|
||||
<i data-lucide="layout-grid" class="w-5 h-5"></i>
|
||||
</button>
|
||||
|
||||
<button onclick="alert('历史归档模式:此处将显示7天前已完成的稿件。')" class="sidebar-btn w-10 h-10 rounded-lg text-slate-400 flex items-center justify-center hover:bg-white/10 hover:text-white transition-colors relative" data-title="历史归档">
|
||||
<i data-lucide="archive" class="w-5 h-5"></i>
|
||||
</button>
|
||||
|
||||
<div class="mt-auto flex flex-col gap-4 relative">
|
||||
<button onclick="openSettings()" class="sidebar-btn w-10 h-10 rounded-lg text-slate-400 flex items-center justify-center hover:bg-white/10 hover:text-white transition-colors relative" data-title="系统设置">
|
||||
<i data-lucide="settings" class="w-5 h-5"></i>
|
||||
</button>
|
||||
|
||||
<!-- 用户头像 (点击触发菜单) -->
|
||||
<div class="relative">
|
||||
<div onclick="toggleUserMenu()" class="w-10 h-10 rounded-full bg-gradient-to-tr from-indigo-500 to-purple-500 flex items-center justify-center text-xs font-bold text-white border-2 border-slate-700 cursor-pointer hover:border-white transition-all shadow-md">
|
||||
主编
|
||||
</div>
|
||||
<!-- 用户悬浮菜单 -->
|
||||
<div id="user-menu" class="hidden absolute bottom-0 left-12 ml-2 w-48 bg-white rounded-lg shadow-xl border border-gray-100 py-1 z-50 animate-in fade-in zoom-in-95 origin-bottom-left">
|
||||
<div class="px-4 py-3 border-b border-gray-50 bg-slate-50">
|
||||
<p class="text-sm font-bold text-slate-800">王主编</p>
|
||||
<p class="text-xs text-slate-500 truncate">editor@chinastroke.com</p>
|
||||
</div>
|
||||
<button onclick="openChangePassword()" class="w-full text-left px-4 py-2 text-sm text-slate-700 hover:bg-indigo-50 hover:text-indigo-600 flex items-center gap-2">
|
||||
<i data-lucide="key" class="w-4 h-4"></i> 修改密码
|
||||
</button>
|
||||
<button onclick="handleLogout()" class="w-full text-left px-4 py-2 text-sm text-red-600 hover:bg-red-50 flex items-center gap-2">
|
||||
<i data-lucide="log-out" class="w-4 h-4"></i> 退出登录
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<main class="flex-1 flex flex-col min-w-0 bg-white">
|
||||
|
||||
<!-- 视图 1: 审稿列表 (Dashboard) -->
|
||||
<div id="view-list" class="flex-1 flex flex-col h-full relative fade-in">
|
||||
|
||||
<!-- 顶部核心操作区 -->
|
||||
<header class="bg-white px-8 pt-6 pb-4 border-b border-gray-100 flex-shrink-0 z-10">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<!-- 客户 LOGO 展示区 (新增) -->
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="bg-indigo-50 p-2 rounded-lg text-indigo-700">
|
||||
<i data-lucide="brain-circuit" class="w-6 h-6"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-xl font-bold text-slate-800">中华脑血管病杂志 · 智能审稿系统</h1>
|
||||
<p class="text-xs text-slate-500">当前工作区:编辑部初审组</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<input type="file" id="file-upload" multiple class="hidden" onchange="handleFileUpload(this)">
|
||||
<button onclick="document.getElementById('file-upload').click()" class="px-5 py-2.5 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg text-sm font-bold flex items-center gap-2 shadow-sm transition-all hover:-translate-y-0.5">
|
||||
<i data-lucide="upload-cloud" class="w-4 h-4"></i> 上传新稿件
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 筛选栏 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase tracking-wider mr-2">状态:</span>
|
||||
<div class="filter-chip active" onclick="activateFilter(this)">全部 <span class="ml-1 text-xs opacity-60 bg-black/10 px-1.5 rounded-full">3</span></div>
|
||||
<div class="filter-chip" onclick="activateFilter(this)">待处理 <span class="ml-1 text-xs opacity-60 bg-slate-200 px-1.5 rounded-full">1</span></div>
|
||||
<div class="filter-chip" onclick="activateFilter(this)">已完成</div>
|
||||
</div>
|
||||
|
||||
<div class="h-4 w-px bg-gray-200 mx-2"></div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase tracking-wider mr-2">时间:</span>
|
||||
<div class="filter-chip active" onclick="activateFilter(this)">不限</div>
|
||||
<div class="filter-chip" onclick="activateFilter(this)">今天</div>
|
||||
<div class="filter-chip" onclick="activateFilter(this)">近7天</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 批量操作栏 -->
|
||||
<div id="batch-toolbar" class="hidden absolute top-36 left-1/2 transform -translate-x-1/2 bg-slate-800 text-white px-5 py-3 rounded-full shadow-2xl flex items-center gap-6 z-30 fade-in border border-slate-700">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-5 h-5 rounded-full bg-indigo-500 flex items-center justify-center text-[10px] font-bold" id="selected-count">0</div>
|
||||
<span class="text-sm font-medium">个文件已选中</span>
|
||||
</div>
|
||||
<div class="h-4 w-px bg-slate-600"></div>
|
||||
<button onclick="openAgentModal()" class="text-sm font-bold text-white hover:text-indigo-300 flex items-center gap-2 transition-colors">
|
||||
<i data-lucide="play" class="w-4 h-4 text-green-400"></i> 运行智能审稿
|
||||
</button>
|
||||
<button onclick="clearSelection()" class="text-slate-400 hover:text-white ml-2">
|
||||
<i data-lucide="x" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 列表区域 -->
|
||||
<div class="flex-1 overflow-auto bg-slate-50/50 p-6">
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden min-h-[500px]">
|
||||
<table class="w-full text-left text-sm" id="file-table">
|
||||
<thead class="bg-gray-50 border-b border-gray-200 text-gray-500 font-semibold uppercase tracking-wider text-xs">
|
||||
<tr>
|
||||
<th class="px-6 py-4 w-12"><input type="checkbox" onchange="toggleSelectAll(this)" class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer"></th>
|
||||
<th class="px-6 py-4 w-1/3">文件名称 / 信息</th>
|
||||
<th class="px-6 py-4">上传时间</th>
|
||||
<th class="px-6 py-4">审稿维度</th>
|
||||
<th class="px-6 py-4">结果摘要</th>
|
||||
<th class="px-6 py-4 text-right">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100" id="table-body">
|
||||
<!-- 已完成示例 -->
|
||||
<tr class="hover:bg-slate-50 group transition-colors">
|
||||
<td class="px-6 py-4"><input type="checkbox" onchange="toggleRowSelection(this)" class="row-checkbox rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer"></td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="bg-red-50 text-red-600 p-2.5 rounded-lg border border-red-100">
|
||||
<i data-lucide="file-text" class="w-5 h-5"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-slate-800 text-base mb-0.5 cursor-pointer hover:text-indigo-600" onclick="viewReport(true)">
|
||||
替雷利珠单抗治疗非小细胞肺癌的临床研究.pdf
|
||||
</div>
|
||||
<div class="text-xs text-slate-400 flex items-center gap-2">
|
||||
<span class="bg-slate-100 px-1.5 rounded">12.5 MB</span> <span>•</span> <span>王某某</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-slate-500 font-mono text-xs">10:30</td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex gap-1.5">
|
||||
<span class="tag tag-blue">规范性</span>
|
||||
<span class="tag tag-purple">方法学</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<div class="flex items-center gap-2 text-xs">
|
||||
<div class="w-2 h-2 rounded-full bg-green-500"></div>
|
||||
<span class="text-slate-600">规范性:</span>
|
||||
<span class="font-bold text-green-700">92分</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 text-xs">
|
||||
<div class="w-2 h-2 rounded-full bg-amber-500"></div>
|
||||
<span class="text-slate-600">方法学:</span>
|
||||
<span class="font-bold text-amber-700">存疑</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-right">
|
||||
<button onclick="viewReport(true)" class="text-indigo-600 font-bold hover:bg-indigo-50 px-3 py-1.5 rounded-md transition-colors text-xs">查看</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 待处理示例 -->
|
||||
<tr class="hover:bg-slate-50 group transition-colors status-pending">
|
||||
<td class="px-6 py-4"><input type="checkbox" onchange="toggleRowSelection(this)" class="row-checkbox rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer"></td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="bg-blue-50 text-blue-600 p-2.5 rounded-lg border border-blue-100">
|
||||
<i data-lucide="file-type-2" class="w-5 h-5"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-slate-800 text-base mb-0.5">
|
||||
高血压药物多中心随机对照试验_V2.docx
|
||||
</div>
|
||||
<div class="text-xs text-slate-400 flex items-center gap-2">
|
||||
<span class="bg-slate-100 px-1.5 rounded">4.2 MB</span> <span>•</span> <span>李四</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-slate-500 font-mono text-xs">刚刚</td>
|
||||
<td class="px-6 py-4"><span class="tag tag-gray">未运行</span></td>
|
||||
<td class="px-6 py-4"><span class="text-xs text-slate-400 italic">等待发起...</span></td>
|
||||
<td class="px-6 py-4 text-right">
|
||||
<button onclick="selectRowAndOpenModal(this)" class="border border-indigo-200 text-indigo-600 hover:bg-indigo-50 px-3 py-1.5 rounded-md transition-colors text-xs font-medium flex items-center gap-1 ml-auto">
|
||||
<i data-lucide="play" class="w-3 h-3"></i> 开始
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 视图 2: 详情报告页 (保持 V6 的真实数据) -->
|
||||
<div id="view-detail" class="hidden flex-1 flex flex-col h-full bg-slate-50 relative animate-in fade-in slide-in-from-bottom-4">
|
||||
<header class="h-16 bg-white border-b border-gray-200 px-6 flex items-center justify-between sticky top-0 z-20 shadow-sm">
|
||||
<div class="flex items-center gap-4">
|
||||
<button onclick="switchView('list')" class="flex items-center gap-2 text-slate-500 hover:text-slate-800 transition-colors px-2 py-1 rounded hover:bg-slate-100">
|
||||
<i data-lucide="arrow-left" class="w-5 h-5"></i>
|
||||
<span class="text-sm font-medium">返回列表</span>
|
||||
</button>
|
||||
<div class="h-6 w-px bg-slate-200"></div>
|
||||
<div>
|
||||
<h1 class="text-base font-bold text-slate-800 flex items-center gap-2">
|
||||
替雷利珠单抗治疗非小细胞肺癌的临床研究.pdf
|
||||
<span class="tag tag-blue">V2 修回稿</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<button class="px-3 py-1.5 bg-indigo-600 text-white rounded text-sm font-medium hover:bg-indigo-700 transition shadow-sm flex items-center gap-2">
|
||||
<i data-lucide="file-check" class="w-4 h-4"></i> 导出报告
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex-1 overflow-auto p-8 max-w-5xl mx-auto w-full">
|
||||
<div class="flex gap-1 bg-slate-200/50 p-1 rounded-lg mb-8 w-fit mx-auto">
|
||||
<button onclick="switchTab('compliance')" id="tab-compliance" class="px-6 py-2 rounded-md text-sm font-bold bg-white text-indigo-600 shadow-sm transition-all">稿约规范性 (92分)</button>
|
||||
<button onclick="switchTab('methodology')" id="tab-methodology" class="px-6 py-2 rounded-md text-sm font-medium text-slate-500 hover:text-slate-700 transition-all">方法学评估 (存疑)</button>
|
||||
</div>
|
||||
|
||||
<!-- 规范性报告 -->
|
||||
<div id="content-compliance" class="space-y-6 fade-in">
|
||||
<div class="bg-white p-6 rounded-2xl shadow-sm border border-green-200 flex items-center gap-8">
|
||||
<div class="score-circle pass">
|
||||
<span class="text-2xl font-bold">92</span>
|
||||
<span class="text-[10px] font-bold uppercase">Pass</span>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h3 class="font-bold text-lg text-slate-800">基本符合稿约规范</h3>
|
||||
<p class="text-slate-600 text-sm mt-1">AI 已完成 11 项维度检查。主要问题集中在图片清晰度,其他格式(参考文献、伦理声明)均已合规。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="p-4 bg-slate-50 border-b border-gray-200 font-bold text-sm text-slate-700">检测详情</div>
|
||||
<div class="p-5 border-b border-gray-100 flex gap-4 bg-amber-50/50">
|
||||
<div class="mt-1 text-amber-500"><i data-lucide="alert-triangle" class="w-5 h-5"></i></div>
|
||||
<div class="flex-1">
|
||||
<div class="flex justify-between"><h4 class="font-bold text-sm text-slate-800">图片分辨率不足 (Figure 3)</h4><span class="tag tag-amber">警告</span></div>
|
||||
<p class="text-sm text-slate-600 mt-1">检测到病理切片图 DPI 为 150,低于期刊要求的 300 DPI。</p>
|
||||
<div class="mt-3 bg-white border border-amber-200 p-3 rounded-lg text-xs text-slate-600"><strong>建议:</strong> 请提供原始高清大图。</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 方法学报告 -->
|
||||
<div id="content-methodology" class="hidden space-y-6 fade-in">
|
||||
<div class="bg-indigo-900 text-white rounded-2xl p-6 shadow-lg">
|
||||
<div class="flex items-center gap-2 mb-4 opacity-80 text-xs font-bold uppercase tracking-wider"><i data-lucide="brain-circuit" class="w-4 h-4"></i> DeepSeek 智能提取</div>
|
||||
<div class="grid grid-cols-4 gap-4">
|
||||
<div class="bg-white/10 p-3 rounded-lg"><div class="text-indigo-300 text-xs uppercase mb-1 font-bold">P</div><div class="text-sm font-medium">非小细胞肺癌</div></div>
|
||||
<div class="bg-white/10 p-3 rounded-lg"><div class="text-indigo-300 text-xs uppercase mb-1 font-bold">I</div><div class="text-sm font-medium">替雷利珠单抗</div></div>
|
||||
<div class="bg-white/10 p-3 rounded-lg"><div class="text-indigo-300 text-xs uppercase mb-1 font-bold">C</div><div class="text-sm font-medium">传统化疗</div></div>
|
||||
<div class="bg-white/10 p-3 rounded-lg"><div class="text-indigo-300 text-xs uppercase mb-1 font-bold">O</div><div class="text-sm font-medium">OS, PFS</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl border border-red-200 shadow-sm overflow-hidden">
|
||||
<div class="p-4 bg-red-50 border-b border-red-100 text-red-700 font-bold text-sm flex items-center gap-2"><i data-lucide="x-circle" class="w-4 h-4"></i> 核心逻辑漏洞</div>
|
||||
<div class="p-6"><h5 class="font-bold text-slate-800 text-sm">统计检验方法缺失</h5><p class="text-sm text-slate-600 mt-1">比较 AUC 时未提及具体检验方法(如 Delong Test),仅给出 P 值不严谨。</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 弹窗:选择智能体 -->
|
||||
<div id="modal-agent" class="fixed inset-0 bg-slate-900/50 hidden z-50 flex items-center justify-center backdrop-blur-sm">
|
||||
<div class="bg-white rounded-2xl shadow-2xl w-[400px] overflow-hidden transform transition-all scale-100">
|
||||
<div class="bg-slate-900 p-5 text-white"><h3 class="font-bold text-lg flex items-center gap-2"><i data-lucide="play-circle" class="w-5 h-5 text-indigo-400"></i> 发起智能审稿</h3></div>
|
||||
<div class="p-6 space-y-4">
|
||||
<label class="flex items-start gap-3 p-3 border border-gray-200 rounded-xl hover:border-indigo-500 cursor-pointer transition-colors"><input type="checkbox" checked class="mt-1 w-4 h-4 text-indigo-600 rounded"><div><span class="block font-bold text-slate-800 text-sm">稿约规范性智能体</span><span class="block text-xs text-slate-500 mt-0.5">格式、参考文献、图片</span></div></label>
|
||||
<label class="flex items-start gap-3 p-3 border border-gray-200 rounded-xl hover:border-indigo-500 cursor-pointer transition-colors"><input type="checkbox" class="mt-1 w-4 h-4 text-indigo-600 rounded"><div><span class="block font-bold text-slate-800 text-sm">方法学统计智能体</span><span class="block text-xs text-slate-500 mt-0.5">DeepSeek 深度逻辑推理</span></div></label>
|
||||
</div>
|
||||
<div class="p-4 bg-slate-50 flex justify-end gap-3 border-t border-gray-100">
|
||||
<button onclick="closeModal()" class="px-4 py-2 text-sm text-slate-600 hover:bg-gray-200 rounded-lg">取消</button>
|
||||
<button onclick="runBatchTask()" class="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white text-sm font-bold rounded-lg shadow-sm">立即运行</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 弹窗:系统设置 -->
|
||||
<div id="modal-settings" class="fixed inset-0 bg-slate-900/50 hidden z-50 flex items-center justify-center backdrop-blur-sm">
|
||||
<div class="bg-white rounded-2xl shadow-2xl w-[400px] p-6">
|
||||
<h3 class="font-bold text-lg mb-4 text-slate-800">系统设置</h3>
|
||||
<div class="space-y-4">
|
||||
<div><label class="block text-sm font-bold text-slate-700 mb-1">期刊 Logo 上传</label><input type="file" class="block w-full text-sm text-slate-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100"/></div>
|
||||
<div><label class="block text-sm font-bold text-slate-700 mb-1">默认 AI 模型</label><select class="w-full border border-gray-300 rounded-lg p-2 text-sm"><option>DeepSeek V3</option><option>DeepSeek R1</option></select></div>
|
||||
</div>
|
||||
<div class="mt-6 pt-4 border-t border-gray-100 flex justify-end"><button onclick="closeSettings()" class="px-4 py-2 bg-indigo-600 text-white rounded-lg text-sm font-bold">保存设置</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 弹窗:修改密码 -->
|
||||
<div id="modal-password" class="fixed inset-0 bg-slate-900/50 hidden z-50 flex items-center justify-center backdrop-blur-sm">
|
||||
<div class="bg-white rounded-2xl shadow-2xl w-[400px] p-6">
|
||||
<h3 class="font-bold text-lg mb-4 text-slate-800">修改密码</h3>
|
||||
<div class="space-y-4">
|
||||
<div><label class="block text-sm font-bold text-slate-700 mb-1">旧密码</label><input type="password" class="w-full p-2 border rounded-lg"></div>
|
||||
<div><label class="block text-sm font-bold text-slate-700 mb-1">新密码</label><input type="password" class="w-full p-2 border rounded-lg"></div>
|
||||
<div><label class="block text-sm font-bold text-slate-700 mb-1">确认新密码</label><input type="password" class="w-full p-2 border rounded-lg"></div>
|
||||
</div>
|
||||
<div class="mt-6 pt-4 border-t border-gray-100 flex justify-end gap-2">
|
||||
<button onclick="closeChangePassword()" class="px-4 py-2 text-sm text-slate-600">取消</button>
|
||||
<button onclick="closeChangePassword(); alert('密码修改成功');" class="px-4 py-2 bg-indigo-600 text-white rounded-lg text-sm font-bold">确认修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
|
||||
// 1. 登录逻辑
|
||||
function handleLogin(e) {
|
||||
e.preventDefault();
|
||||
const btn = e.target.querySelector('button');
|
||||
const originalText = btn.innerHTML;
|
||||
btn.innerHTML = `<i data-lucide="loader-2" class="w-4 h-4 animate-spin"></i> 登录中...`;
|
||||
lucide.createIcons();
|
||||
|
||||
setTimeout(() => {
|
||||
document.getElementById('view-login').classList.add('hidden');
|
||||
document.getElementById('app-container').classList.remove('hidden');
|
||||
lucide.createIcons();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
if(confirm('确定要退出登录吗?')) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// 视图切换
|
||||
function switchView(viewId) {
|
||||
document.getElementById('view-list').classList.add('hidden');
|
||||
document.getElementById('view-detail').classList.add('hidden');
|
||||
document.getElementById('view-' + viewId).classList.remove('hidden');
|
||||
if(viewId === 'list') lucide.createIcons();
|
||||
}
|
||||
|
||||
function viewReport(isReal) { switchView('detail'); }
|
||||
|
||||
// Tab 切换
|
||||
function switchTab(tabId) {
|
||||
document.getElementById('content-compliance').classList.add('hidden');
|
||||
document.getElementById('content-methodology').classList.add('hidden');
|
||||
document.getElementById('tab-compliance').className = "px-6 py-2 rounded-md text-sm font-medium text-slate-500 hover:text-slate-700 transition-all";
|
||||
document.getElementById('tab-methodology').className = "px-6 py-2 rounded-md text-sm font-medium text-slate-500 hover:text-slate-700 transition-all";
|
||||
document.getElementById('content-' + tabId).classList.remove('hidden');
|
||||
document.getElementById('tab-' + tabId).className = "px-6 py-2 rounded-md text-sm font-bold bg-white text-indigo-600 shadow-sm transition-all";
|
||||
}
|
||||
|
||||
// 筛选逻辑 (Visual Only)
|
||||
function activateFilter(chip) {
|
||||
Array.from(chip.parentElement.children).forEach(c => c.classList.remove('active', 'bg-eff6ff', 'text-2563eb', 'border-bfdbfe', 'font-600'));
|
||||
chip.classList.add('active');
|
||||
}
|
||||
|
||||
// 弹窗逻辑
|
||||
function openAgentModal() { document.getElementById('modal-agent').classList.remove('hidden'); }
|
||||
function closeModal() { document.getElementById('modal-agent').classList.add('hidden'); }
|
||||
function openSettings() { document.getElementById('modal-settings').classList.remove('hidden'); }
|
||||
function closeSettings() { document.getElementById('modal-settings').classList.add('hidden'); }
|
||||
|
||||
// 用户菜单逻辑
|
||||
function toggleUserMenu() { document.getElementById('user-menu').classList.toggle('hidden'); }
|
||||
function openChangePassword() {
|
||||
toggleUserMenu();
|
||||
document.getElementById('modal-password').classList.remove('hidden');
|
||||
}
|
||||
function closeChangePassword() { document.getElementById('modal-password').classList.add('hidden'); }
|
||||
|
||||
// 点击外部关闭菜单
|
||||
document.addEventListener('click', function(e) {
|
||||
const menu = document.getElementById('user-menu');
|
||||
const avatar = document.querySelector('[onclick="toggleUserMenu()"]');
|
||||
if (!menu.classList.contains('hidden') && !menu.contains(e.target) && !avatar.contains(e.target)) {
|
||||
menu.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// 批量选择
|
||||
function toggleRowSelection(checkbox) { checkbox.checked ? checkbox.closest('tr').classList.add('selected') : checkbox.closest('tr').classList.remove('selected'); updateBatchToolbar(); }
|
||||
function toggleSelectAll(mainCheckbox) { document.querySelectorAll('.row-checkbox').forEach(cb => { cb.checked = mainCheckbox.checked; toggleRowSelection(cb); }); }
|
||||
function updateBatchToolbar() {
|
||||
const count = document.querySelectorAll('.row-checkbox:checked').length;
|
||||
const toolbar = document.getElementById('batch-toolbar');
|
||||
document.getElementById('selected-count').innerText = count;
|
||||
count > 0 ? toolbar.classList.remove('hidden') : toolbar.classList.add('hidden');
|
||||
}
|
||||
function clearSelection() { document.querySelectorAll('.row-checkbox').forEach(cb => cb.checked = false); document.querySelectorAll('tr').forEach(tr => tr.classList.remove('selected')); document.querySelector('thead input').checked = false; updateBatchToolbar(); }
|
||||
function selectRowAndOpenModal(btn) { clearSelection(); const cb = btn.closest('tr').querySelector('.row-checkbox'); cb.checked = true; toggleRowSelection(cb); openAgentModal(); }
|
||||
|
||||
// 模拟运行
|
||||
function runBatchTask() {
|
||||
closeModal();
|
||||
const btn = document.querySelector('.status-pending button');
|
||||
if(btn) {
|
||||
btn.innerHTML = `<i data-lucide="loader-2" class="w-3 h-3 animate-spin"></i> 运行中`;
|
||||
btn.className = "text-indigo-600 font-bold px-3 py-1.5 text-xs flex items-center gap-1";
|
||||
}
|
||||
clearSelection();
|
||||
alert("任务已提交!");
|
||||
}
|
||||
|
||||
function handleFileUpload(input) {
|
||||
if(input.files.length) alert(`已选择 ${input.files.length} 个文件`);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
135
docs/03-业务模块/RVW-稿件审查系统/01-需求分析/智能期刊审稿系统 MVP 产品需求文档.md
Normal file
135
docs/03-业务模块/RVW-稿件审查系统/01-需求分析/智能期刊审稿系统 MVP 产品需求文档.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# **智能期刊审稿系统 MVP 产品需求文档**
|
||||
|
||||
| 项目属性 | 内容 |
|
||||
| :---- | :---- |
|
||||
| **项目名称** | 智能期刊审稿辅助系统 (SmartReview MVP) |
|
||||
| **文档版本** | V1.0 (MVP) |
|
||||
| **优先级** | P0 (核心功能闭环) |
|
||||
| **目标用户** | 期刊初审编辑 |
|
||||
|
||||
## **1\. 产品目标 (Product Goal)**
|
||||
|
||||
打造一个\*\*“开箱即用”\*\*的智能审稿工具。编辑上传稿件,系统自动运行双重检查(规范性+方法学),输出可供参考的审稿报告。
|
||||
核心指标:上传到出报告 \< 2分钟;规范性问题检出率 \> 80%。
|
||||
|
||||
## **2\. 功能范围 (Scope)**
|
||||
|
||||
### **✅ MVP 包含 (In Scope)**
|
||||
|
||||
1. **账户体系**:简单的账号登录,支持期刊 Logo 定制。
|
||||
2. **文件处理**:批量上传 Word/PDF,列表展示状态。
|
||||
3. **审查流程**:用户手动选择智能体发起审查,后台异步运行。
|
||||
4. **规范性审查**:覆盖字数、摘要结构、参考文献、图片DPI等硬指标。
|
||||
5. **方法学审查**:PICO 提取、研究类型识别、基础统计逻辑校验。
|
||||
6. **报告与导出**:双视图报告展示,支持 PDF 导出。
|
||||
|
||||
### **❌ MVP 不包含 (Out of Scope)**
|
||||
|
||||
1. 在线文档编辑器 (Web Office)。
|
||||
2. 复杂的角色权限管理系统。
|
||||
3. 邮件自动发送功能。
|
||||
4. 高级历史归档与检索系统。
|
||||
5. 前端可视化的 Prompt 配置后台。
|
||||
|
||||
## **3\. 详细功能需求 (Requirements)**
|
||||
|
||||
### **3.1 登录页 (Login)**
|
||||
|
||||
* **功能**:账号密码验证。
|
||||
* **UI**:
|
||||
* 左/上侧展示期刊 Logo 与名称(支持配置)。
|
||||
* 输入框:账号、密码。
|
||||
* 登录按钮:点击校验,失败提示“账号或密码错误”。
|
||||
* **逻辑**:Session 保持 24 小时,避免频繁登录。
|
||||
|
||||
### **3.2 审稿工作台 (Dashboard)**
|
||||
|
||||
这是系统的主界面,采用\*\*“宽表”\*\*布局。
|
||||
|
||||
#### **3.2.1 顶部操作区**
|
||||
|
||||
* **品牌区**:展示“XX杂志社智能审稿系统”。
|
||||
* **筛选栏**:
|
||||
* 状态 (全部/待处理/已完成)。
|
||||
* 时间 (今天/近7天)。
|
||||
* **上传按钮**:
|
||||
* 点击触发文件选择器。
|
||||
* 支持多选。
|
||||
* 支持扩展名:.docx, .pdf。
|
||||
* 限制:单文件 \< 50MB。
|
||||
|
||||
#### **3.2.2 稿件列表**
|
||||
|
||||
列表包含以下列:
|
||||
|
||||
* 复选框:用于批量操作。
|
||||
* 文件信息:文件名(点击进入详情)、大小、上传时间。
|
||||
* 审稿维度:展示 Tags(规范性、方法学)。
|
||||
* 状态:
|
||||
* **待处理**:刚上传,未运行。
|
||||
* **运行中**:展示动态 Loading 图标。
|
||||
* **已完成**:
|
||||
* 若跑了规范性,显示分数(如:绿色 "90分")。
|
||||
* 若跑了方法学,显示结论(如:黄色 "存疑")。
|
||||
* 操作列:
|
||||
* \[开始审查\]:针对待处理状态。
|
||||
* \[查看报告\]:针对已完成状态。
|
||||
|
||||
#### **3.2.3 任务发起弹窗 (The Launcher)**
|
||||
|
||||
* **触发**:点击列表中的“开始审查”或底部批量操作栏的“运行”。
|
||||
* **内容**:
|
||||
* 标题:“发起智能审查”。
|
||||
* 复选框组:
|
||||
* \[x\] 稿约规范性智能体 (默认选中)。
|
||||
* \[ \] 方法学统计智能体。
|
||||
* **逻辑**:点击确定后,后端创建任务,列表状态变为“运行中”。
|
||||
|
||||
### **3.3 审稿详情页 (Report Detail)**
|
||||
|
||||
#### **3.3.1 头部信息**
|
||||
|
||||
* 展示文件名、作者(若能提取)、版本标签(MVP可暂不显示)。
|
||||
* 按钮:\[下载原稿\]、\[导出报告PDF\]。
|
||||
|
||||
#### **3.3.2 视图 A:稿约规范性报告**
|
||||
|
||||
* **总评卡片**:展示总分 (0-100) 和 结论 (Pass/Fail)。
|
||||
* **检查项列表**:
|
||||
* **文题字数**:提取字数,对比标准(如 \<20字)。
|
||||
* **摘要结构**:正则匹配“目的/方法/结果/结论”关键词。
|
||||
* **参考文献**:识别引用格式错误。
|
||||
* **图片质量**:显示低分辨率图片的页码和 DPI 值。
|
||||
* **交互**:每个报错项下方提供“建议修改意见”,支持点击复制。
|
||||
|
||||
#### **3.3.3 视图 B:方法学评估报告**
|
||||
|
||||
* **PICO 卡片**:结构化展示提取出的 P/I/C/O 内容。
|
||||
* **逻辑推理区**:
|
||||
* 展示模型对“研究类型”的判断(如:回顾性队列研究)。
|
||||
* 展示“统计方法”的合理性分析(如:发现多组比较未用 ANOVA)。
|
||||
* **红绿灯**:
|
||||
* 🔴 **错误**:明确的逻辑硬伤。
|
||||
* 🟡 **存疑**:模型不确定,需人工复核。
|
||||
* 🟢 **通过**:逻辑自洽。
|
||||
|
||||
## **4\. 技术与性能要求 (Non-functional)**
|
||||
|
||||
1. **响应速度**:
|
||||
* 列表加载 \< 1秒。
|
||||
* 文件上传速度取决于带宽,需有进度反馈。
|
||||
2. **并发处理**:
|
||||
* 支持至少 5 个任务并发运行(不需要排队太久)。
|
||||
3. **兼容性**:
|
||||
* 优先支持 Chrome / Edge 浏览器。
|
||||
4. **数据安全**:
|
||||
* 稿件文件存储需加密或隔离。
|
||||
* 审稿报告仅授权账号可见。
|
||||
|
||||
## **5\. 验收标准 (Acceptance Criteria)**
|
||||
|
||||
1. **流程通**:用户能成功上传 5 个 PDF,勾选双模型运行,等待 3 分钟内,状态全部变为“已完成”。
|
||||
2. **报告准**:
|
||||
* 上传一篇故意删掉“摘要结论”的稿件,规范性智能体必须报错。
|
||||
* 上传一篇故意混淆“t检验”和“卡方检验”的稿件,方法学智能体必须报“存疑”或“错误”。
|
||||
3. **无崩溃**:连续上传 20 个文件,系统不卡死,不白屏。
|
||||
829
docs/03-业务模块/RVW-稿件审查系统/04-开发计划/RVW模块迁移计划.md
Normal file
829
docs/03-业务模块/RVW-稿件审查系统/04-开发计划/RVW模块迁移计划.md
Normal file
@@ -0,0 +1,829 @@
|
||||
# RVW稿件审查模块迁移计划(v2.1 - 稳定迁移版)
|
||||
|
||||
> **文档版本:** v2.1
|
||||
> **创建日期:** 2026-01-07
|
||||
> **最后更新:** 2026-01-07
|
||||
> **维护者:** 开发团队
|
||||
> **文档目的:** 将稿件审查功能从旧架构安全迁移到新架构,同时整合MVP核心需求
|
||||
|
||||
---
|
||||
|
||||
## 📋 项目概述
|
||||
|
||||
### 1. 背景
|
||||
|
||||
稿件审查功能是2025-10-30(Day 30)独立开发的功能模块,目前位于 `backend/src/legacy/` 和 `frontend/` 目录中。现需要:
|
||||
|
||||
1. **架构迁移**:迁移到标准的模块目录结构(`modules/rvw`)
|
||||
2. **功能升级**:整合《智能期刊审稿系统MVP产品需求文档》的核心功能
|
||||
|
||||
### 2. 迁移原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **稳定优先** | 每个Phase完成后必须通过测试验证 |
|
||||
| **安全可靠** | 数据库迁移前必须备份,支持回滚 |
|
||||
| **阶段验证** | 每个Phase有明确的验收标准 |
|
||||
| **向后兼容** | 保留旧API过渡期,不影响现有功能 |
|
||||
| **渐进式** | 先核心后扩展,先后端后前端 |
|
||||
|
||||
### 3. 功能范围
|
||||
|
||||
| 功能 | 本次开发 | 数据库支撑 | 说明 |
|
||||
|------|:--------:|:----------:|------|
|
||||
| **核心AI评估** | ✅ | ✅ | 稿约规范性+方法学 |
|
||||
| **批量上传** | ✅ | ✅ | 多文件上传 |
|
||||
| **审稿工作台** | ✅ | ✅ | 宽表布局+筛选 |
|
||||
| **智能体选择** | ✅ | ✅ | 可选1个或2个 |
|
||||
| **批量操作** | ✅ | ✅ | 批量运行审查 |
|
||||
| **状态筛选** | ✅ | ✅ | 全部/待处理/已完成 |
|
||||
| PDF报告导出 | ✅ | ✅ | 优化现有功能 |
|
||||
| PICO卡片 | ⏸️ | ✅ | **暂不开发,数据库预留** |
|
||||
| 系统设置 | ⏸️ | ✅ | **暂不开发,数据库预留** |
|
||||
| 历史归档 | ⏸️ | ✅ | **暂不开发,数据库预留** |
|
||||
| 登录页面 | ⏸️ | - | 暂不开发 |
|
||||
|
||||
### 4. 智能体选择说明
|
||||
|
||||
用户可以灵活选择运行的智能体:
|
||||
|
||||
```
|
||||
选项 A: 只选择「稿约规范性智能体」 → 只运行规范性评估
|
||||
选项 B: 只选择「方法学统计智能体」 → 只运行方法学评估
|
||||
选项 C: 同时选择两个智能体 → 同时运行两项评估(默认)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据库设计(完整版,支撑未来扩展)
|
||||
|
||||
### 1. 期刊配置表(预留,暂不使用)
|
||||
|
||||
```prisma
|
||||
// review_schema
|
||||
|
||||
model JournalConfig {
|
||||
id String @id @default(uuid())
|
||||
name String // 期刊名称
|
||||
logoUrl String? @map("logo_url") // Logo URL(预留)
|
||||
defaultModel String @default("deepseek-v3") @map("default_model")
|
||||
settings Json? // 其他配置(预留)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
reviewTasks ReviewTask[]
|
||||
|
||||
@@map("journal_configs")
|
||||
@@schema("review_schema")
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 审稿任务表(扩展版)
|
||||
|
||||
```prisma
|
||||
model ReviewTask {
|
||||
id String @id @default(uuid())
|
||||
userId String @map("user_id")
|
||||
journalId String? @map("journal_id") // 预留:期刊关联
|
||||
|
||||
// 文件信息
|
||||
fileName String @map("file_name")
|
||||
fileSize Int @map("file_size")
|
||||
filePath String? @map("file_path")
|
||||
extractedText String @map("extracted_text")
|
||||
wordCount Int? @map("word_count")
|
||||
authorName String? @map("author_name") // 预留:作者提取
|
||||
|
||||
// 状态管理
|
||||
status String @default("pending")
|
||||
// ✅ 智能体选择:可选1个或2个
|
||||
selectedAgents String[] @default(["editorial", "methodology"]) @map("selected_agents")
|
||||
|
||||
// 评估结果
|
||||
editorialReview Json? @map("editorial_review")
|
||||
methodologyReview Json? @map("methodology_review")
|
||||
overallScore Float? @map("overall_score")
|
||||
|
||||
// 结果摘要(用于列表展示)
|
||||
editorialScore Float? @map("editorial_score")
|
||||
methodologyStatus String? @map("methodology_status") // pass/warn/fail
|
||||
|
||||
// 预留:PICO提取(暂不使用)
|
||||
picoExtract Json? @map("pico_extract")
|
||||
|
||||
// 元数据
|
||||
modelUsed String? @map("model_used")
|
||||
startedAt DateTime? @map("started_at")
|
||||
completedAt DateTime? @map("completed_at")
|
||||
durationSeconds Int? @map("duration_seconds")
|
||||
errorMessage String? @map("error_message")
|
||||
|
||||
// 预留:归档功能(暂不使用)
|
||||
isArchived Boolean @default(false) @map("is_archived")
|
||||
archivedAt DateTime? @map("archived_at")
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
// 关联
|
||||
user users @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
journal JournalConfig? @relation(fields: [journalId], references: [id])
|
||||
|
||||
@@index([userId])
|
||||
@@index([journalId])
|
||||
@@index([status])
|
||||
@@index([createdAt])
|
||||
@@index([isArchived])
|
||||
@@map("review_tasks")
|
||||
@@schema("review_schema")
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 字段说明
|
||||
|
||||
| 字段 | 本次使用 | 预留用途 |
|
||||
|------|:--------:|---------|
|
||||
| `journalId` | ❌ | 系统设置:期刊关联 |
|
||||
| `authorName` | ❌ | 自动提取作者名 |
|
||||
| `selectedAgents` | ✅ | 用户选择的智能体 |
|
||||
| `editorialScore` | ✅ | 列表显示规范性分数 |
|
||||
| `methodologyStatus` | ✅ | 列表显示方法学状态 |
|
||||
| `picoExtract` | ❌ | PICO卡片数据 |
|
||||
| `isArchived` | ❌ | 历史归档功能 |
|
||||
| `archivedAt` | ❌ | 归档时间 |
|
||||
|
||||
---
|
||||
|
||||
## 📋 安全迁移策略
|
||||
|
||||
### 1. 迁移前准备
|
||||
|
||||
```bash
|
||||
# 1. 备份数据库
|
||||
pg_dump -h localhost -U postgres -d airesearch -F c -f backup_before_rvw_migration.dump
|
||||
|
||||
# 2. 记录当前数据量
|
||||
SELECT COUNT(*) FROM public.review_tasks;
|
||||
|
||||
# 3. 导出关键数据(可选)
|
||||
COPY public.review_tasks TO '/tmp/review_tasks_backup.csv' WITH CSV HEADER;
|
||||
```
|
||||
|
||||
### 2. 回滚方案
|
||||
|
||||
```bash
|
||||
# 如果迁移失败,回滚数据库
|
||||
pg_restore -h localhost -U postgres -d airesearch -c backup_before_rvw_migration.dump
|
||||
|
||||
# 如果只需要回滚Schema迁移
|
||||
ALTER TABLE review_schema.review_tasks SET SCHEMA public;
|
||||
DROP SCHEMA review_schema;
|
||||
```
|
||||
|
||||
### 3. 阶段性验证
|
||||
|
||||
每个Phase完成后必须通过以下验证:
|
||||
|
||||
| Phase | 验证内容 | 验收标准 |
|
||||
|-------|---------|---------|
|
||||
| Phase 1 | 后端API测试 | 所有API返回正确,日志无ERROR |
|
||||
| Phase 2 | 数据库迁移 | 数据完整,查询正常,索引有效 |
|
||||
| Phase 3 | 前端功能测试 | 核心流程通顺,无白屏/报错 |
|
||||
| Phase 4 | 集成测试 | 端到端流程正常 |
|
||||
| Phase 5 | 验收测试 | 符合MVP验收标准 |
|
||||
|
||||
---
|
||||
|
||||
## 📋 开发任务清单
|
||||
|
||||
### Phase 1:后端模块迁移(2天)
|
||||
|
||||
#### Day 1 上午:创建模块结构 + 复用核心代码
|
||||
|
||||
**1.1 创建目录结构**
|
||||
|
||||
```
|
||||
backend/src/modules/rvw/
|
||||
├── routes/
|
||||
│ └── index.ts # 路由定义
|
||||
├── controllers/
|
||||
│ └── reviewController.ts # 控制器
|
||||
├── services/
|
||||
│ ├── reviewService.ts # 主服务(复用+扩展)
|
||||
│ ├── editorialService.ts # 稿约评估(复用)
|
||||
│ └── methodologyService.ts # 方法学评估(复用)
|
||||
├── types/
|
||||
│ └── index.ts # 类型定义
|
||||
├── prompts/
|
||||
│ ├── editorial_system.txt # 稿约Prompt
|
||||
│ └── methodology_system.txt # 方法学Prompt
|
||||
└── index.ts # 模块入口
|
||||
```
|
||||
|
||||
- [ ] **1.1.1** 创建目录结构
|
||||
- [ ] **1.1.2** 复制 `reviewEditorialStandards()` → `editorialService.ts`
|
||||
- [ ] **1.1.3** 复制 `reviewMethodology()` → `methodologyService.ts`
|
||||
- [ ] **1.1.4** 复制 `parseJSONFromLLMResponse()` → `utils.ts`
|
||||
- [ ] **1.1.5** 复制 Prompt 文件到模块内
|
||||
|
||||
**1.2 云原生改造**
|
||||
|
||||
- [ ] **1.2.1** 替换 `console.log` → `logger`
|
||||
- [ ] **1.2.2** 移除 Mock用户ID,集成JWT认证
|
||||
- [ ] **1.2.3** 使用 `process.env` 配置
|
||||
|
||||
#### Day 1 下午:智能体选择逻辑
|
||||
|
||||
**1.3 智能体选择实现**
|
||||
|
||||
```typescript
|
||||
// types/index.ts
|
||||
export type AgentType = 'editorial' | 'methodology';
|
||||
|
||||
export interface RunReviewParams {
|
||||
taskId: string;
|
||||
agents: AgentType[]; // 可选1个或2个
|
||||
}
|
||||
|
||||
// services/reviewService.ts
|
||||
async function runReview(params: RunReviewParams) {
|
||||
const { taskId, agents } = params;
|
||||
|
||||
// 验证:至少选择1个智能体
|
||||
if (agents.length === 0) {
|
||||
throw new Error('请至少选择一个智能体');
|
||||
}
|
||||
|
||||
// 更新任务状态
|
||||
await prisma.reviewTask.update({
|
||||
where: { id: taskId },
|
||||
data: {
|
||||
status: 'reviewing',
|
||||
selectedAgents: agents,
|
||||
startedAt: new Date()
|
||||
}
|
||||
});
|
||||
|
||||
// 只运行选中的智能体
|
||||
let editorialResult = null;
|
||||
let methodologyResult = null;
|
||||
|
||||
if (agents.includes('editorial')) {
|
||||
editorialResult = await editorialService.review(taskId);
|
||||
}
|
||||
|
||||
if (agents.includes('methodology')) {
|
||||
methodologyResult = await methodologyService.review(taskId);
|
||||
}
|
||||
|
||||
// 计算综合分数
|
||||
const overallScore = calculateOverallScore(editorialResult, methodologyResult, agents);
|
||||
|
||||
// 更新结果
|
||||
await prisma.reviewTask.update({
|
||||
where: { id: taskId },
|
||||
data: {
|
||||
status: 'completed',
|
||||
editorialReview: editorialResult,
|
||||
methodologyReview: methodologyResult,
|
||||
editorialScore: editorialResult?.overall_score,
|
||||
methodologyStatus: getMethodologyStatus(methodologyResult),
|
||||
overallScore,
|
||||
completedAt: new Date(),
|
||||
durationSeconds: calculateDuration(taskId)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 根据选择的智能体计算综合分数
|
||||
function calculateOverallScore(editorial: any, methodology: any, agents: AgentType[]) {
|
||||
if (agents.length === 2 && editorial && methodology) {
|
||||
// 两个都选:40% + 60%
|
||||
return editorial.overall_score * 0.4 + methodology.overall_score * 0.6;
|
||||
} else if (agents.includes('editorial') && editorial) {
|
||||
// 只选规范性
|
||||
return editorial.overall_score;
|
||||
} else if (agents.includes('methodology') && methodology) {
|
||||
// 只选方法学
|
||||
return methodology.overall_score;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **1.3.1** 实现智能体选择类型定义
|
||||
- [ ] **1.3.2** 实现 `runReview()` 函数
|
||||
- [ ] **1.3.3** 实现综合分数计算逻辑
|
||||
- [ ] **1.3.4** 实现方法学状态判断(pass/warn/fail)
|
||||
|
||||
#### Day 2 上午:批量操作 + API扩展
|
||||
|
||||
**1.4 批量运行实现**
|
||||
|
||||
```typescript
|
||||
// services/reviewService.ts
|
||||
async function batchRunReview(params: BatchRunParams) {
|
||||
const { taskIds, agents } = params;
|
||||
|
||||
// 限制并发数
|
||||
const MAX_CONCURRENT = 5;
|
||||
const results = [];
|
||||
|
||||
for (let i = 0; i < taskIds.length; i += MAX_CONCURRENT) {
|
||||
const batch = taskIds.slice(i, i + MAX_CONCURRENT);
|
||||
const batchResults = await Promise.allSettled(
|
||||
batch.map(taskId => runReview({ taskId, agents }))
|
||||
);
|
||||
results.push(...batchResults);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **1.4.1** 实现批量运行接口
|
||||
- [ ] **1.4.2** 实现并发控制(最多5个)
|
||||
- [ ] **1.4.3** 实现错误处理(单个失败不影响其他)
|
||||
|
||||
**1.5 API路由定义**
|
||||
|
||||
```typescript
|
||||
// routes/index.ts
|
||||
export default async function rvwRoutes(fastify: FastifyInstance) {
|
||||
// 任务管理
|
||||
fastify.post('/tasks', reviewController.createTask); // 创建/上传
|
||||
fastify.get('/tasks', reviewController.getTaskList); // 列表(筛选)
|
||||
fastify.get('/tasks/:taskId', reviewController.getTaskDetail); // 详情
|
||||
fastify.get('/tasks/:taskId/report', reviewController.getTaskReport); // 报告
|
||||
fastify.delete('/tasks/:taskId', reviewController.deleteTask); // 删除
|
||||
|
||||
// 运行审查(核心功能)
|
||||
fastify.post('/tasks/:taskId/run', reviewController.runReview); // 单个运行
|
||||
fastify.post('/tasks/batch/run', reviewController.batchRunReview); // 批量运行
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **1.5.1** 实现路由定义
|
||||
- [ ] **1.5.2** 实现控制器方法
|
||||
- [ ] **1.5.3** 添加请求验证
|
||||
|
||||
#### Day 2 下午:注册路由 + Phase 1 验证
|
||||
|
||||
**1.6 注册新路由**
|
||||
|
||||
```typescript
|
||||
// backend/src/index.ts
|
||||
import rvwRoutes from './modules/rvw/routes/index.js';
|
||||
|
||||
// 注册新路由(v2)
|
||||
await fastify.register(rvwRoutes, { prefix: '/api/v2/rvw' });
|
||||
logger.info('✅ RVW稿件审查路由已注册: /api/v2/rvw');
|
||||
|
||||
// 保留旧路由(兼容)
|
||||
await fastify.register(reviewRoutes, { prefix: '/api/v1' });
|
||||
logger.info('✅ Legacy审稿路由保留: /api/v1/review');
|
||||
```
|
||||
|
||||
- [ ] **1.6.1** 注册新路由
|
||||
- [ ] **1.6.2** 保留旧路由兼容
|
||||
|
||||
**1.7 Phase 1 验证测试**
|
||||
|
||||
```http
|
||||
### 1. 创建任务
|
||||
POST {{baseUrl}}/api/v2/rvw/tasks
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
# file: test.docx
|
||||
|
||||
### 2. 运行审查(只选规范性)
|
||||
POST {{baseUrl}}/api/v2/rvw/tasks/{{taskId}}/run
|
||||
Content-Type: application/json
|
||||
|
||||
{ "agents": ["editorial"] }
|
||||
|
||||
### 3. 运行审查(只选方法学)
|
||||
POST {{baseUrl}}/api/v2/rvw/tasks/{{taskId}}/run
|
||||
Content-Type: application/json
|
||||
|
||||
{ "agents": ["methodology"] }
|
||||
|
||||
### 4. 运行审查(两个都选)
|
||||
POST {{baseUrl}}/api/v2/rvw/tasks/{{taskId}}/run
|
||||
Content-Type: application/json
|
||||
|
||||
{ "agents": ["editorial", "methodology"] }
|
||||
|
||||
### 5. 批量运行
|
||||
POST {{baseUrl}}/api/v2/rvw/tasks/batch/run
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"taskIds": ["id1", "id2", "id3"],
|
||||
"agents": ["editorial", "methodology"]
|
||||
}
|
||||
|
||||
### 6. 获取任务列表
|
||||
GET {{baseUrl}}/api/v2/rvw/tasks?status=pending&limit=10
|
||||
|
||||
### 7. 获取报告
|
||||
GET {{baseUrl}}/api/v2/rvw/tasks/{{taskId}}/report
|
||||
```
|
||||
|
||||
**Phase 1 验收标准:**
|
||||
|
||||
| 测试项 | 预期结果 | 通过 |
|
||||
|--------|---------|:----:|
|
||||
| 创建任务 | 返回taskId,状态pending | ⬜ |
|
||||
| 只选规范性 | 只有editorialReview有值 | ⬜ |
|
||||
| 只选方法学 | 只有methodologyReview有值 | ⬜ |
|
||||
| 两个都选 | 两个Review都有值 | ⬜ |
|
||||
| 批量运行 | 多个任务都完成 | ⬜ |
|
||||
| 旧API兼容 | `/api/v1/review/*` 正常 | ⬜ |
|
||||
|
||||
- [ ] **1.7.1** 编写测试用例
|
||||
- [ ] **1.7.2** 执行测试
|
||||
- [ ] **1.7.3** 修复问题
|
||||
- [ ] **1.7.4** 确认Phase 1通过
|
||||
|
||||
---
|
||||
|
||||
### Phase 2:数据库Schema迁移(0.5天)
|
||||
|
||||
#### 迁移前:备份
|
||||
|
||||
- [ ] **2.1** 备份数据库
|
||||
```bash
|
||||
pg_dump -h localhost -U postgres -d airesearch -F c -f backup_phase2.dump
|
||||
```
|
||||
|
||||
- [ ] **2.2** 记录当前数据
|
||||
```sql
|
||||
SELECT COUNT(*) FROM public.review_tasks;
|
||||
```
|
||||
|
||||
#### 迁移执行
|
||||
|
||||
- [ ] **2.3** 创建迁移SQL
|
||||
```sql
|
||||
-- 1. 创建新Schema
|
||||
CREATE SCHEMA IF NOT EXISTS review_schema;
|
||||
|
||||
-- 2. 创建期刊配置表(预留)
|
||||
CREATE TABLE review_schema.journal_configs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
logo_url TEXT,
|
||||
default_model VARCHAR(50) DEFAULT 'deepseek-v3',
|
||||
settings JSONB,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 3. 迁移review_tasks表到新Schema
|
||||
ALTER TABLE public.review_tasks SET SCHEMA review_schema;
|
||||
|
||||
-- 4. 添加新字段(支持未来扩展)
|
||||
ALTER TABLE review_schema.review_tasks
|
||||
ADD COLUMN IF NOT EXISTS journal_id UUID REFERENCES review_schema.journal_configs(id),
|
||||
ADD COLUMN IF NOT EXISTS author_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS selected_agents TEXT[] DEFAULT ARRAY['editorial', 'methodology'],
|
||||
ADD COLUMN IF NOT EXISTS editorial_score FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS methodology_status VARCHAR(20),
|
||||
ADD COLUMN IF NOT EXISTS pico_extract JSONB,
|
||||
ADD COLUMN IF NOT EXISTS is_archived BOOLEAN DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS archived_at TIMESTAMPTZ;
|
||||
|
||||
-- 5. 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_review_tasks_journal ON review_schema.review_tasks(journal_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_review_tasks_archived ON review_schema.review_tasks(is_archived);
|
||||
|
||||
-- 6. 创建默认期刊配置
|
||||
INSERT INTO review_schema.journal_configs (name, default_model)
|
||||
VALUES ('默认期刊', 'deepseek-v3');
|
||||
```
|
||||
|
||||
- [ ] **2.4** 更新Prisma Schema
|
||||
- 修改 `@@schema("review_schema")`
|
||||
- 添加新字段
|
||||
|
||||
- [ ] **2.5** 执行迁移
|
||||
```bash
|
||||
npx prisma migrate dev --name rvw_schema_migration
|
||||
```
|
||||
|
||||
#### Phase 2 验证
|
||||
|
||||
- [ ] **2.6** 验证数据完整性
|
||||
```sql
|
||||
-- 确认数据量一致
|
||||
SELECT COUNT(*) FROM review_schema.review_tasks;
|
||||
|
||||
-- 确认字段可用
|
||||
SELECT id, selected_agents, editorial_score FROM review_schema.review_tasks LIMIT 5;
|
||||
|
||||
-- 确认外键关系
|
||||
SELECT rt.id, rt.user_id, u.email
|
||||
FROM review_schema.review_tasks rt
|
||||
JOIN public.users u ON rt.user_id = u.id
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
**Phase 2 验收标准:**
|
||||
|
||||
| 测试项 | 预期结果 | 通过 |
|
||||
|--------|---------|:----:|
|
||||
| 数据迁移 | 数据量一致 | ⬜ |
|
||||
| 新字段 | 字段存在且可用 | ⬜ |
|
||||
| 外键关系 | 关联正常 | ⬜ |
|
||||
| 索引有效 | 查询性能正常 | ⬜ |
|
||||
| API正常 | 后端API仍可用 | ⬜ |
|
||||
|
||||
- [ ] **2.7** 确认Phase 2通过
|
||||
|
||||
---
|
||||
|
||||
### Phase 3:前端重构(3天)
|
||||
|
||||
#### Day 3:模块结构 + API层
|
||||
|
||||
**3.1 创建模块结构**
|
||||
|
||||
```
|
||||
frontend-v2/src/modules/rvw/
|
||||
├── api/
|
||||
│ └── reviewApi.ts # API封装
|
||||
├── components/
|
||||
│ ├── ScoreCard.tsx # 复用
|
||||
│ ├── EditorialReview.tsx # 复用
|
||||
│ ├── MethodologyReview.tsx # 复用
|
||||
│ ├── AgentSelector.tsx # 🆕 智能体选择弹窗
|
||||
│ ├── BatchToolbar.tsx # 🆕 批量操作栏
|
||||
│ ├── TaskTable.tsx # 🆕 任务列表表格
|
||||
│ └── StatusFilter.tsx # 🆕 状态筛选
|
||||
├── pages/
|
||||
│ ├── ReviewDashboard.tsx # 🆕 审稿工作台
|
||||
│ └── ReviewDetail.tsx # 报告详情(优化)
|
||||
├── hooks/
|
||||
│ ├── useReviewTask.ts
|
||||
│ └── useBatchOperation.ts
|
||||
├── stores/
|
||||
│ └── useReviewStore.ts
|
||||
├── types/
|
||||
│ └── index.ts
|
||||
└── index.tsx
|
||||
```
|
||||
|
||||
- [ ] **3.1.1** 创建目录结构
|
||||
- [ ] **3.1.2** 复用现有组件(ScoreCard、EditorialReview、MethodologyReview)
|
||||
|
||||
**3.2 API封装**
|
||||
|
||||
```typescript
|
||||
// api/reviewApi.ts
|
||||
export type AgentType = 'editorial' | 'methodology';
|
||||
|
||||
// 运行审查(支持选择智能体)
|
||||
export async function runReview(taskId: string, agents: AgentType[]): Promise<void> {
|
||||
return axios.post(`/api/v2/rvw/tasks/${taskId}/run`, { agents });
|
||||
}
|
||||
|
||||
// 批量运行
|
||||
export async function batchRunReview(taskIds: string[], agents: AgentType[]): Promise<void> {
|
||||
return axios.post('/api/v2/rvw/tasks/batch/run', { taskIds, agents });
|
||||
}
|
||||
|
||||
// 获取任务列表(带筛选)
|
||||
export interface TaskListParams {
|
||||
status?: 'all' | 'pending' | 'completed';
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export async function getTaskList(params: TaskListParams): Promise<TaskListResponse> {
|
||||
return axios.get('/api/v2/rvw/tasks', { params });
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **3.2.1** 实现API封装
|
||||
- [ ] **3.2.2** 实现类型定义
|
||||
|
||||
#### Day 4:核心页面开发
|
||||
|
||||
**3.3 智能体选择弹窗**
|
||||
|
||||
```tsx
|
||||
// components/AgentSelector.tsx
|
||||
interface AgentSelectorProps {
|
||||
visible: boolean;
|
||||
taskIds: string[]; // 支持单个或多个
|
||||
onConfirm: (agents: AgentType[]) => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
// 弹窗内容:
|
||||
// ✅ 稿约规范性智能体(默认选中)
|
||||
// 格式、参考文献、图片检查
|
||||
// ☐ 方法学统计智能体
|
||||
// DeepSeek 深度逻辑推理
|
||||
//
|
||||
// 提示:可选择1个或同时选择2个智能体
|
||||
//
|
||||
// [取消] [立即运行]
|
||||
```
|
||||
|
||||
- [ ] **3.3.1** 实现智能体选择弹窗
|
||||
- [ ] **3.3.2** 支持单选和多选
|
||||
- [ ] **3.3.3** 默认选中规范性智能体
|
||||
|
||||
**3.4 审稿工作台**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Header: [Logo] 智能审稿系统 [上传新稿件] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Filter: [全部|待处理|已完成] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||||
│ │ ☐ 文件名称/信息 上传时间 审稿维度 结果摘要 操作 │ │
|
||||
│ │ ☐ 替雷利珠单抗...pdf 10:30 [规范][方法] 92分 [查看] │
|
||||
│ │ ☐ 高血压药物...docx 刚刚 [未运行] 等待... [开始] │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ [Batch Toolbar: 3个文件已选中 | 运行智能审稿 | ✕] │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- [ ] **3.4.1** 实现页面布局
|
||||
- [ ] **3.4.2** 实现任务列表表格
|
||||
- [ ] **3.4.3** 实现状态筛选
|
||||
- [ ] **3.4.4** 实现批量操作栏
|
||||
|
||||
#### Day 5:报告详情 + Phase 3 验证
|
||||
|
||||
**3.5 报告详情页**
|
||||
|
||||
- [ ] **3.5.1** 实现Tab切换(规范性/方法学)
|
||||
- [ ] **3.5.2** 复用评估详情组件
|
||||
- [ ] **3.5.3** 根据选择的智能体显示对应Tab
|
||||
- [ ] **3.5.4** 实现导出报告按钮
|
||||
|
||||
**3.6 路由配置**
|
||||
|
||||
```typescript
|
||||
// router/index.tsx
|
||||
{
|
||||
path: '/rvw',
|
||||
children: [
|
||||
{ path: '', element: <ReviewDashboard /> },
|
||||
{ path: ':taskId', element: <ReviewDetail /> }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **3.6.1** 配置路由
|
||||
- [ ] **3.6.2** 添加导航菜单
|
||||
|
||||
**Phase 3 验证测试**
|
||||
|
||||
| 测试项 | 预期结果 | 通过 |
|
||||
|--------|---------|:----:|
|
||||
| 页面加载 | 工作台正常显示 | ⬜ |
|
||||
| 文件上传 | 支持多文件 | ⬜ |
|
||||
| 智能体选择 | 可选1个或2个 | ⬜ |
|
||||
| 批量操作 | 批量运行成功 | ⬜ |
|
||||
| 状态筛选 | 筛选结果正确 | ⬜ |
|
||||
| 报告查看 | 显示对应评估结果 | ⬜ |
|
||||
|
||||
- [ ] **3.7** 确认Phase 3通过
|
||||
|
||||
---
|
||||
|
||||
### Phase 4:集成测试(1天)
|
||||
|
||||
**4.1 端到端测试**
|
||||
|
||||
| 测试场景 | 步骤 | 预期结果 |
|
||||
|---------|------|---------|
|
||||
| 单文件+单智能体 | 上传→选规范性→查看 | 只显示规范性报告 |
|
||||
| 单文件+双智能体 | 上传→选两个→查看 | 显示两个报告Tab |
|
||||
| 批量+双智能体 | 上传3个→批量运行 | 3个都完成 |
|
||||
| 状态筛选 | 上传→筛选待处理 | 正确过滤 |
|
||||
|
||||
- [ ] **4.1.1** 执行端到端测试
|
||||
- [ ] **4.1.2** 修复发现的问题
|
||||
|
||||
**4.2 性能测试**
|
||||
|
||||
| 指标 | 目标 | 实际 |
|
||||
|------|------|------|
|
||||
| 列表加载 | < 1秒 | ⬜ |
|
||||
| 单文件审查 | < 2分钟 | ⬜ |
|
||||
| 5文件并发 | < 5分钟 | ⬜ |
|
||||
|
||||
- [ ] **4.2.1** 执行性能测试
|
||||
|
||||
**4.3 兼容性测试**
|
||||
|
||||
- [ ] **4.3.1** Chrome浏览器测试
|
||||
- [ ] **4.3.2** Edge浏览器测试
|
||||
- [ ] **4.3.3** 旧API兼容性确认
|
||||
|
||||
---
|
||||
|
||||
### Phase 5:验收与上线(0.5天)
|
||||
|
||||
**5.1 MVP验收标准**
|
||||
|
||||
| 验收项 | 预期结果 | 通过 |
|
||||
|--------|---------|:----:|
|
||||
| 流程通 | 5个PDF,3分钟内全部完成 | ⬜ |
|
||||
| 规范性准确 | 删掉摘要结论必须报错 | ⬜ |
|
||||
| 方法学准确 | 混淆统计方法必须报存疑 | ⬜ |
|
||||
| 无崩溃 | 连续上传20个不卡死 | ⬜ |
|
||||
|
||||
- [ ] **5.1.1** 执行验收测试
|
||||
- [ ] **5.1.2** 编写验收报告
|
||||
|
||||
**5.2 上线准备**
|
||||
|
||||
- [ ] **5.2.1** 更新文档
|
||||
- [ ] **5.2.2** 通知相关人员
|
||||
- [ ] **5.2.3** 监控上线后状态
|
||||
|
||||
---
|
||||
|
||||
## 📅 时间估算
|
||||
|
||||
| Phase | 任务 | 预估工时 | 验证点 |
|
||||
|-------|------|---------|--------|
|
||||
| **Phase 1** | 后端模块迁移 | 2天 | ✓ API测试通过 |
|
||||
| **Phase 2** | 数据库迁移 | 0.5天 | ✓ 数据完整性验证 |
|
||||
| **Phase 3** | 前端重构 | 3天 | ✓ 功能测试通过 |
|
||||
| **Phase 4** | 集成测试 | 1天 | ✓ 端到端测试通过 |
|
||||
| **Phase 5** | 验收上线 | 0.5天 | ✓ MVP验收通过 |
|
||||
| **总计** | - | **7天** | - |
|
||||
|
||||
---
|
||||
|
||||
## ⏸️ 暂不开发的功能(数据库已预留)
|
||||
|
||||
| 功能 | 预留字段 | 后续计划 |
|
||||
|------|---------|---------|
|
||||
| **PICO卡片** | `pico_extract` | 方法学评估扩展 |
|
||||
| **系统设置** | `JournalConfig`表 | 期刊Logo/模型配置 |
|
||||
| **历史归档** | `is_archived`, `archived_at` | 自动归档7天前数据 |
|
||||
| **登录页面** | - | 独立产品时开发 |
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 风险控制
|
||||
|
||||
### 1. 数据库迁移风险
|
||||
|
||||
| 风险 | 概率 | 影响 | 控制措施 |
|
||||
|------|------|------|---------|
|
||||
| 数据丢失 | 低 | 高 | 迁移前备份 |
|
||||
| 迁移失败 | 中 | 中 | 准备回滚SQL |
|
||||
| 性能下降 | 低 | 中 | 验证索引有效性 |
|
||||
|
||||
### 2. 功能回归风险
|
||||
|
||||
| 风险 | 概率 | 影响 | 控制措施 |
|
||||
|------|------|------|---------|
|
||||
| 旧API中断 | 低 | 高 | 保留v1路由 |
|
||||
| 评估结果异常 | 低 | 高 | 对比测试结果 |
|
||||
| 前端白屏 | 中 | 中 | 阶段性测试 |
|
||||
|
||||
### 3. 回滚计划
|
||||
|
||||
```bash
|
||||
# 如果需要回滚到迁移前状态
|
||||
|
||||
# 1. 停止服务
|
||||
pm2 stop all
|
||||
|
||||
# 2. 回滚数据库
|
||||
pg_restore -h localhost -U postgres -d airesearch -c backup_phase2.dump
|
||||
|
||||
# 3. 切换到旧代码分支
|
||||
git checkout main
|
||||
|
||||
# 4. 重启服务
|
||||
pm2 start all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 参考文档
|
||||
|
||||
- [智能期刊审稿系统MVP PRD](../01-需求分析/智能期刊审稿系统%20MVP%20产品需求文档.md)
|
||||
- [智能审稿V7原型](../01-需求分析/智能审稿V7.html)
|
||||
- [云原生开发规范](../../04-开发规范/08-云原生开发规范.md)
|
||||
- [现有系统技术摸底报告](../../00-项目概述/现有系统技术摸底报告.md)
|
||||
|
||||
---
|
||||
|
||||
**文档版本:** v2.1
|
||||
**最后更新:** 2026-01-07
|
||||
**下一步:** 确认后开始Phase 1
|
||||
@@ -766,3 +766,4 @@ docker exec redcap-apache php /tmp/create-redcap-password.php
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -148,3 +148,4 @@ AIclinicalresearch/redcap-docker-dev/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -883,5 +883,6 @@ ACR镜像仓库:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1370,5 +1370,6 @@ SAE应用配置:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1186,5 +1186,6 @@ docker exec -e PGPASSWORD="密码" ai-clinical-postgres psql -h RDS地址 -U air
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -597,5 +597,6 @@ scripts/*.ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -286,4 +286,5 @@ Node.js后端部署成功后:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -509,4 +509,5 @@ Node.js后端 (SAE) ← http://172.17.173.88:3001
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -224,4 +224,5 @@ curl http://localhost:3001/health
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -262,4 +262,5 @@ npm run dev
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -486,4 +486,5 @@ pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1814,4 +1814,5 @@ curl http://8.140.53.236/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -362,4 +362,5 @@ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-se
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -684,4 +684,5 @@ docker login --username=gofeng117@163.com \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -494,5 +494,6 @@ NAT网关成本¥100/月,对初创团队是一笔开销
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -399,5 +399,6 @@ curl http://你的SAE地址:3001/health
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -731,5 +731,6 @@ const job = await queue.getJob(jobId);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -498,5 +498,6 @@ processLiteraturesInBackground(task.id, projectId, testLiteratures);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -975,5 +975,6 @@ ROI = (¥22,556 - ¥144) / ¥144 × 100% = 15,564%
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1032,5 +1032,6 @@ Redis 实例:¥500/月
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -490,5 +490,6 @@ import { ChatContainer } from '@/shared/components/Chat';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -410,3 +410,4 @@ frontend-v2/src/modules/pkb/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -272,3 +272,4 @@ npm run dev
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -787,3 +787,4 @@ AIA智能问答模块
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -932,3 +932,4 @@ CREATE INDEX idx_rvw_tasks_created_at ON rvw_schema.review_tasks(created_at);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -585,3 +585,4 @@ const typography = {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -897,3 +897,4 @@ app.use('/api/v1/knowledge', (req, res) => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -211,3 +211,4 @@ rm -rf src/modules/pkb
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -386,3 +386,4 @@ GET /api/v2/pkb/batch-tasks/batch/templates
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -30,3 +30,4 @@ import pkbRoutes from './modules/pkb/routes/index.js';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -299,3 +299,4 @@ backend/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -510,3 +510,4 @@ const response = await fetch('/api/v2/pkb/batch-tasks/batch/execute', {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user