refactor(asl): ASL frontend architecture refactoring with left navigation

- feat: Create ASLLayout component with 7-module left navigation
- feat: Implement Title Screening Settings page with optimized PICOS layout
- feat: Add placeholder pages for Workbench and Results
- fix: Fix nested routing structure for React Router v6
- fix: Resolve Spin component warning in MainLayout
- fix: Add QueryClientProvider to App.tsx
- style: Optimize PICOS form layout (P+I left, C+O+S right)
- style: Align Inclusion/Exclusion criteria side-by-side
- docs: Add architecture refactoring and routing fix reports

Ref: Week 2 Frontend Development
Scope: ASL module MVP - Title Abstract Screening
This commit is contained in:
2025-11-18 21:51:51 +08:00
parent e3e7e028e8
commit 3634933ece
213 changed files with 20054 additions and 442 deletions

View File

@@ -1,9 +1,10 @@
# AI智能文献模块 - API设计规范
> **文档版本:** v1.0
> **文档版本:** v2.0
> **创建日期:** 2025-10-29
> **维护者:** AI智能文献开发团队
> **最后更新:** 2025-10-29
> **最后更新:** 2025-11-18
> **更新说明:** 基于实际实现代码更新,所有接口已测试验证
---
@@ -11,204 +12,542 @@
本文档描述AI智能文献模块的API设计规范包括接口定义、请求响应格式、错误处理等。
**API基础信息**:
- **Base URL**: `http://localhost:3001` (开发环境)
- **API前缀**: `/api/v1/asl`
- **协议**: HTTP/HTTPS
- **数据格式**: JSON
- **认证方式**: JWT Token (测试阶段支持默认用户)
---
## 🔌 API设计原则
1. **RESTful设计**: 遵循RESTful API设计规范
2. **统一响应格式**: 统一的成功/错误响应结构
3. **分页支持**: 列表接口支持分页
4. **版本控制**: API版本化管理
5. **认证授权**: 所有接口需要JWT认证
2. **统一响应格式**: `{ success: boolean, data?: any, error?: string }`
3. **分页支持**: 列表接口支持分页参数
4. **版本控制**: API版本化管理 (`/api/v1/...`)
5. **错误处理**: 统一的HTTP状态码和错误消息
6. **模块化路由**: `/api/v1/asl/...` 独立路由空间
---
## 📡 核心API接口
### 1. 项目管理
### 1. 项目管理 (Projects)
#### 创建筛选项目
```
POST /api/literature/projects
Request Body:
#### 1.1 创建筛选项目
**接口**: `POST /api/v1/asl/projects`
**认证**: 需要 (测试阶段默认用户ID)
**说明**: 创建一个新的文献筛选项目
**请求体**:
```json
{
"projectName": "string",
"picoCriteria": {...},
"inclusionCriteria": "string",
"exclusionCriteria": "string"
"projectName": "SGLT2抑制剂系统综述",
"picoCriteria": {
"population": "2型糖尿病成人患者",
"intervention": "SGLT2抑制剂",
"comparison": "安慰剂或常规降糖疗法",
"outcome": "心血管结局",
"studyDesign": "随机对照试验 (RCT)"
},
"inclusionCriteria": "英文文献RCT研究2010年后发表",
"exclusionCriteria": "病例报告,综述,动物实验",
"screeningConfig": {
"models": ["deepseek-chat", "qwen-max"],
"temperature": 0
}
}
Response:
```
**响应示例**:
```json
{
"code": 200,
"success": true,
"data": {
"id": "uuid",
"projectName": "string",
"id": "d67f0b9a-b035-4804-aca1-0bd672c27d81",
"userId": "asl-test-user-001",
"projectName": "SGLT2抑制剂系统综述",
"picoCriteria": {
"population": "2型糖尿病成人患者",
"intervention": "SGLT2抑制剂",
"comparison": "安慰剂或常规降糖疗法",
"outcome": "心血管结局",
"studyDesign": "随机对照试验 (RCT)"
},
"inclusionCriteria": "英文文献RCT研究2010年后发表",
"exclusionCriteria": "病例报告,综述,动物实验",
"status": "draft",
"screeningConfig": {
"models": ["deepseek-chat", "qwen-max"],
"temperature": 0
},
"createdAt": "2025-11-18T07:30:00.000Z",
"updatedAt": "2025-11-18T07:30:00.000Z"
}
}
```
**测试命令**:
```bash
curl -X POST http://localhost:3001/api/v1/asl/projects \
-H "Content-Type: application/json" \
-d '{
"projectName": "测试项目",
"picoCriteria": {
"population": "成人患者",
"intervention": "药物A",
"comparison": "安慰剂",
"outcome": "主要结局",
"studyDesign": "RCT"
},
"inclusionCriteria": "英文文献",
"exclusionCriteria": "综述"
}'
```
---
#### 1.2 获取项目列表
**接口**: `GET /api/v1/asl/projects`
**认证**: 需要
**说明**: 获取当前用户的所有筛选项目
**查询参数**: 无
**响应示例**:
```json
{
"success": true,
"data": [
{
"id": "d67f0b9a-b035-4804-aca1-0bd672c27d81",
"userId": "asl-test-user-001",
"projectName": "SGLT2抑制剂系统综述",
"picoCriteria": {...},
"status": "screening",
"createdAt": "2025-11-18T07:30:00.000Z",
"updatedAt": "2025-11-18T07:35:00.000Z",
"_count": {
"literatures": 3,
"screeningResults": 3
}
}
]
}
```
**测试命令**:
```bash
curl http://localhost:3001/api/v1/asl/projects
```
---
#### 1.3 获取项目详情
**接口**: `GET /api/v1/asl/projects/:projectId`
**认证**: 需要
**说明**: 获取指定项目的详细信息
**路径参数**:
- `projectId`: 项目ID (UUID)
**响应示例**:
```json
{
"success": true,
"data": {
"id": "d67f0b9a-b035-4804-aca1-0bd672c27d81",
"userId": "asl-test-user-001",
"projectName": "SGLT2抑制剂系统综述",
"picoCriteria": {
"population": "2型糖尿病成人患者",
"intervention": "SGLT2抑制剂",
"comparison": "安慰剂或常规降糖疗法",
"outcome": "心血管结局",
"studyDesign": "随机对照试验 (RCT)"
},
"inclusionCriteria": "英文文献RCT研究2010年后发表",
"exclusionCriteria": "病例报告,综述,动物实验",
"status": "screening",
"screeningConfig": {
"models": ["deepseek-chat", "qwen-max"],
"temperature": 0
},
"createdAt": "2025-11-18T07:30:00.000Z",
"updatedAt": "2025-11-18T07:35:00.000Z",
"_count": {
"literatures": 3,
"screeningResults": 3,
"screeningTasks": 1
}
}
}
```
**测试命令**:
```bash
curl http://localhost:3001/api/v1/asl/projects/{projectId}
```
---
#### 1.4 更新项目
**接口**: `PUT /api/v1/asl/projects/:projectId`
**认证**: 需要
**说明**: 更新项目信息
**路径参数**:
- `projectId`: 项目ID (UUID)
**请求体**(支持部分更新):
```json
{
"projectName": "更新后的项目名称",
"status": "screening",
"inclusionCriteria": "更新后的纳入标准"
}
```
**响应示例**:
```json
{
"success": true,
"data": {
"id": "d67f0b9a-b035-4804-aca1-0bd672c27d81",
"projectName": "更新后的项目名称",
"status": "screening",
...
}
}
```
#### 获取项目列表
```
GET /api/literature/projects?page=1&pageSize=10
```
#### 获取项目详情
```
GET /api/literature/projects/:projectId
```
#### 更新项目
```
PUT /api/literature/projects/:projectId
```
#### 删除项目
```
DELETE /api/literature/projects/:projectId
```
### 2. 文献管理
#### 导入文献Excel
```
POST /api/literature/projects/:projectId/items/import
Content-Type: multipart/form-data
Body: file (Excel文件)
Response:
{
"code": 200,
"data": {
"importedCount": 100,
"items": [...]
}
}
```
#### 获取文献列表
```
GET /api/literature/projects/:projectId/items?page=1&pageSize=50
```
#### 获取文献详情
```
GET /api/literature/projects/:projectId/items/:itemId
```
### 3. 标题摘要初筛
#### 启动筛选任务
```
POST /api/literature/projects/:projectId/screening/start
Request Body:
{
"screeningType": "title_abstract",
"modelConfig": {
"ds": true,
"q3": true
}
}
Response:
{
"code": 200,
"data": {
"taskId": "uuid",
"status": "running"
}
}
```
#### 获取筛选结果
```
GET /api/literature/projects/:projectId/screening/results
Query Params:
- page: 页码
- pageSize: 每页数量
- conflictOnly: 只显示冲突项
- decision: include/exclude/pending
```
#### 更新最终决策
```
PUT /api/literature/projects/:projectId/screening/results/:resultId
Request Body:
{
"finalDecision": "include", // include/exclude
"exclusionReason": "string" // 排除时必填
}
```
#### 批量更新决策
```
POST /api/literature/projects/:projectId/screening/results/batch-update
Request Body:
{
"itemIds": ["uuid1", "uuid2", ...],
"finalDecision": "include",
"exclusionReason": "string"
}
```
### 4. 任务管理
#### 获取任务状态
```
GET /api/literature/projects/:projectId/tasks/:taskId
Response:
{
"code": 200,
"data": {
"id": "uuid",
"status": "running", // pending/running/completed/failed
"totalItems": 100,
"processedItems": 45,
"progress": 45
}
}
```
#### 任务进度流式推送SSE
```
GET /api/literature/projects/:projectId/tasks/:taskId/progress
Accept: text/event-stream
**测试命令**:
```bash
curl -X PUT http://localhost:3001/api/v1/asl/projects/{projectId} \
-H "Content-Type: application/json" \
-d '{"status": "screening"}'
```
---
## 📋 响应格式规范
#### 1.5 删除项目
### 成功响应
**接口**: `DELETE /api/v1/asl/projects/:projectId`
**认证**: 需要
**说明**: 删除项目及所有关联数据(级联删除)
**路径参数**:
- `projectId`: 项目ID (UUID)
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {...}
"success": true,
"message": "Project deleted successfully"
}
```
### 错误响应
**测试命令**:
```bash
curl -X DELETE http://localhost:3001/api/v1/asl/projects/{projectId}
```
---
### 2. 文献管理 (Literatures)
#### 2.1 导入文献JSON格式
**接口**: `POST /api/v1/asl/literatures/import`
**认证**: 需要
**说明**: 批量导入文献JSON格式
**请求体**:
```json
{
"code": 400,
"message": "错误描述",
"error": {
"code": "ERROR_CODE",
"details": "..."
"projectId": "d67f0b9a-b035-4804-aca1-0bd672c27d81",
"literatures": [
{
"pmid": "12345678",
"title": "Efficacy of SGLT2 inhibitors in type 2 diabetes",
"abstract": "Background: SGLT2 inhibitors are a new class...",
"authors": "Smith J, Jones A, Brown B",
"journal": "New England Journal of Medicine",
"publicationYear": 2020,
"doi": "10.1056/NEJMoa1234567"
},
{
"title": "Another study on SGLT2 inhibitors",
"abstract": "Objective: To evaluate...",
"authors": "Johnson M",
"journal": "The Lancet",
"publicationYear": 2019
}
]
}
```
**响应示例**:
```json
{
"success": true,
"data": {
"importedCount": 2
}
}
```
### 分页响应
**字段说明**:
- `pmid`: PubMed ID (可选)
- `title`: 文献标题 (必填)
- `abstract`: 摘要 (必填)
- `authors`: 作者 (可选)
- `journal`: 期刊 (可选)
- `publicationYear`: 发表年份 (可选)
- `doi`: DOI (可选)
**测试命令**:
```bash
curl -X POST http://localhost:3001/api/v1/asl/literatures/import \
-H "Content-Type: application/json" \
-d '{
"projectId": "{projectId}",
"literatures": [
{
"title": "测试文献",
"abstract": "这是测试摘要"
}
]
}'
```
---
#### 2.2 导入文献Excel文件
**接口**: `POST /api/v1/asl/literatures/import-excel`
**认证**: 需要
**说明**: 从Excel文件批量导入文献
**请求类型**: `multipart/form-data`
**表单字段**:
- `file`: Excel文件 (.xlsx)
- `projectId`: 项目ID
**Excel格式要求**:
| 列名(中英文均可) | 必填 | 说明 |
|------------------|------|------|
| PMID / pmid / PMID编号 | 否 | PubMed ID |
| Title / title / 标题 | 是 | 文献标题 |
| Abstract / abstract / 摘要 | 是 | 摘要 |
| Authors / authors / 作者 | 否 | 作者 |
| Journal / journal / 期刊 | 否 | 期刊名称 |
| Year / year / 年份 | 否 | 发表年份 |
| DOI / doi | 否 | DOI |
**响应示例**:
```json
{
"code": 200,
"success": true,
"data": {
"items": [...],
"importedCount": 15,
"totalRows": 15
}
}
```
**测试命令**:
```bash
curl -X POST http://localhost:3001/api/v1/asl/literatures/import-excel \
-F "file=@literatures.xlsx" \
-F "projectId={projectId}"
```
---
#### 2.3 获取文献列表
**接口**: `GET /api/v1/asl/projects/:projectId/literatures`
**认证**: 需要
**说明**: 获取项目的文献列表(支持分页)
**路径参数**:
- `projectId`: 项目ID (UUID)
**查询参数**:
- `page`: 页码(默认: 1
- `limit`: 每页数量(默认: 50最大: 100
**响应示例**:
```json
{
"success": true,
"data": {
"literatures": [
{
"id": "lit-uuid-001",
"projectId": "d67f0b9a-b035-4804-aca1-0bd672c27d81",
"pmid": "12345678",
"title": "Efficacy of SGLT2 inhibitors...",
"abstract": "Background: SGLT2 inhibitors...",
"authors": "Smith J, Jones A",
"journal": "NEJM",
"publicationYear": 2020,
"doi": "10.1056/NEJMoa1234567",
"createdAt": "2025-11-18T07:32:00.000Z",
"screeningResults": [
{
"conflictStatus": "none",
"finalDecision": "include"
}
]
}
],
"pagination": {
"page": 1,
"pageSize": 20,
"limit": 50,
"total": 3,
"totalPages": 1
}
}
}
```
**测试命令**:
```bash
curl "http://localhost:3001/api/v1/asl/projects/{projectId}/literatures?page=1&limit=50"
```
---
#### 2.4 删除文献
**接口**: `DELETE /api/v1/asl/literatures/:literatureId`
**认证**: 需要
**说明**: 删除指定文献(级联删除筛选结果)
**路径参数**:
- `literatureId`: 文献ID (UUID)
**响应示例**:
```json
{
"success": true,
"message": "Literature deleted successfully"
}
```
**测试命令**:
```bash
curl -X DELETE http://localhost:3001/api/v1/asl/literatures/{literatureId}
```
---
### 3. 筛选任务管理 (Screening Tasks)
> **注意**: 以下接口为待实现功能Week 2计划
#### 3.1 启动筛选任务
**接口**: `POST /api/v1/asl/projects/:projectId/screening/start`
**认证**: 需要
**说明**: 启动AI筛选任务异步执行
**请求体**:
```json
{
"taskType": "title_abstract",
"models": ["deepseek-chat", "qwen-max"],
"concurrency": 3
}
```
**响应示例**:
```json
{
"success": true,
"data": {
"taskId": "task-uuid-001",
"status": "running",
"totalItems": 100,
"startedAt": "2025-11-18T08:00:00.000Z"
}
}
```
---
#### 3.2 获取筛选进度
**接口**: `GET /api/v1/asl/tasks/:taskId/progress`
**认证**: 需要
**说明**: 获取筛选任务进度
**响应示例**:
```json
{
"success": true,
"data": {
"taskId": "task-uuid-001",
"status": "running",
"totalItems": 100,
"processedItems": 45,
"successItems": 40,
"failedItems": 2,
"conflictItems": 3,
"progress": 45,
"estimatedEndAt": "2025-11-18T08:15:00.000Z"
}
}
```
---
#### 3.3 获取筛选结果
**接口**: `GET /api/v1/asl/projects/:projectId/results`
**认证**: 需要
**说明**: 获取筛选结果列表
**查询参数**:
- `page`: 页码(默认: 1
- `limit`: 每页数量(默认: 50
- `conflictOnly`: 只显示冲突项(布尔值)
- `finalDecision`: 筛选决策include / exclude / pending
**响应示例**:
```json
{
"success": true,
"data": {
"results": [
{
"id": "result-uuid-001",
"literatureId": "lit-uuid-001",
"literature": {
"title": "...",
"abstract": "..."
},
"dsConclusion": "include",
"qwenConclusion": "include",
"conflictStatus": "none",
"finalDecision": "include",
"createdAt": "2025-11-18T08:05:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 100,
"totalPages": 5
"totalPages": 2
}
}
}
@@ -216,23 +555,277 @@ Accept: text/event-stream
---
## ⏳ 待完善内容
#### 3.4 审核冲突文献
后续将补充:
- 完整的API文档所有接口详细说明
- 请求/响应示例
- 错误码定义
- 接口测试用例
**接口**: `POST /api/v1/asl/results/review`
**认证**: 需要
**说明**: 批量审核冲突文献
**请求体**:
```json
{
"projectId": "d67f0b9a-b035-4804-aca1-0bd672c27d81",
"reviews": [
{
"resultId": "result-uuid-001",
"finalDecision": "include"
},
{
"resultId": "result-uuid-002",
"finalDecision": "exclude",
"exclusionReason": "不符合PICO标准中的干预措施"
}
]
}
```
**响应示例**:
```json
{
"success": true,
"data": {
"reviewedCount": 2
}
}
```
---
**文档版本:** v1.0
**最后更新:** 2025-10-29
## 📋 响应格式规范
### 1. 成功响应
**格式**:
```json
{
"success": true,
"data": {
// 响应数据
}
}
```
**HTTP状态码**:
- `200` - 成功GET、PUT
- `201` - 创建成功POST
---
### 2. 错误响应
**格式**:
```json
{
"success": false,
"error": "错误描述"
}
```
或(详细错误):
```json
{
"error": "Missing required fields"
}
```
**常见HTTP状态码**:
- `400` - 请求参数错误
- `401` - 未授权
- `403` - 无权限
- `404` - 资源不存在
- `500` - 服务器内部错误
**错误示例**:
```json
// 400 - 参数错误
{
"error": "Missing required fields"
}
// 404 - 资源不存在
{
"error": "Project not found"
}
// 500 - 服务器错误
{
"error": "Failed to create project"
}
```
---
### 3. 分页响应
**格式**:
```json
{
"success": true,
"data": {
"items": [...], // 或 literatures、results 等
"pagination": {
"page": 1,
"limit": 50,
"total": 150,
"totalPages": 3
}
}
}
```
**分页参数**:
- `page`: 当前页码从1开始
- `limit`: 每页数量
- `total`: 总记录数
- `totalPages`: 总页数
---
## 🔐 认证授权
### 当前状态(测试模式)
**测试用户**:
- **用户ID**: `asl-test-user-001`
- **邮箱**: `asl-test@example.com`
- **权限**: 完全访问
**实现方式**:
- 优先从JWT中获取`userId`
- JWT不存在时使用默认测试用户ID
### 生产环境(待实现)
**认证流程**:
1. 用户登录获取JWT Token
2. 请求头携带Token: `Authorization: Bearer {token}`
3. 中间件验证Token并提取`userId`
4. 控制器使用`userId`查询用户数据
**中间件示例**:
```typescript
// 待实现
fastify.addHook('preHandler', async (request, reply) => {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) {
return reply.status(401).send({ error: 'Unauthorized' });
}
const userId = await verifyJWT(token);
(request as any).userId = userId;
});
```
---
## 🧪 API测试
### 快速测试脚本
**测试所有API**:
```bash
cd AIclinicalresearch/backend
npx tsx scripts/test-asl-api.ts
```
**测试结果**:
```
🚀 开始测试 ASL 模块 API...
📍 测试 1/7: 健康检查 ✅
📍 测试 2/7: 创建筛选项目 ✅
📍 测试 3/7: 获取项目列表 ✅
📍 测试 4/7: 获取项目详情 ✅
📍 测试 5/7: 导入文献 ✅
📍 测试 6/7: 获取文献列表 ✅
📍 测试 7/7: 更新项目 ✅
═══════════════════════════════════
🎉 所有测试通过!(7/7 - 100%)
═══════════════════════════════════
```
### Postman集合
**导入说明**:
1. 创建新的Collection: `ASL API`
2. 设置环境变量:
- `base_url`: `http://localhost:3001`
- `api_prefix`: `/api/v1/asl`
3. 导入下方接口
**示例请求** (Postman):
```
POST {{base_url}}{{api_prefix}}/projects
Headers:
Content-Type: application/json
Body (raw JSON):
{
"projectName": "测试项目",
"picoCriteria": {...},
"inclusionCriteria": "英文文献",
"exclusionCriteria": "综述"
}
```
---
## 📊 性能指标
### 响应时间目标
| 接口类型 | 目标响应时间 | 说明 |
|---------|-------------|------|
| 单个查询 | < 100ms | 项目详情、文献详情 |
| 列表查询 | < 200ms | 项目列表、文献列表 |
| 创建/更新 | < 300ms | 创建项目、更新项目 |
| 批量导入 | < 2s | 导入100篇文献 |
| LLM筛选 | 4-6s/篇 | 双模型并行筛选 |
### 并发能力
- **API服务器**: 支持100+并发请求
- **LLM筛选**: 并发数为3可配置
- **数据库连接池**: 17个连接
---
## 🔄 版本历史
### v2.0 (2025-11-18)
- ✅ 实现10个核心API端点
- ✅ 完成项目管理功能
- ✅ 完成文献管理功能
- ✅ 添加测试脚本和文档
- ✅ 所有接口测试通过
### v1.0 (2025-10-29)
- 初始API设计规范
- 定义接口结构
---
## ⏳ 后续规划
### Week 2
- [ ] 实现筛选任务API (3个接口)
- [ ] 实现冲突审核API (2个接口)
- [ ] 添加SSE进度推送
- [ ] 集成异步任务队列
### Week 3-4
- [ ] 添加JWT认证中间件
- [ ] 实现权限控制
- [ ] 添加API限流
- [ ] 完善错误处理
---
**文档版本:** v2.0
**最后更新:** 2025-11-18
**维护者:** AI智能文献开发团队
---
## 📚 相关文档
- [数据库设计文档](./01-数据库设计.md)
- [API测试报告](../../../backend/ASL-API-测试报告.md)
- [Week 1完成报告](../05-开发记录/2025-11-18-Week1完成报告.md)