Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/02-技术设计/02-API设计规范.md
HaHafeng 8eef9e0544 feat(asl): Complete Week 4 - Results display and Excel export with hybrid solution
Features:
- Backend statistics API (cloud-native Prisma aggregation)
- Results page with hybrid solution (AI consensus + human final decision)
- Excel export (frontend generation, zero disk write, cloud-native)
- PRISMA-style exclusion reason analysis with bar chart
- Batch selection and export (3 export methods)
- Fixed logic contradiction (inclusion does not show exclusion reason)
- Optimized table width (870px, no horizontal scroll)

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

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

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

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

Ref: Week 4 Development Plan
Scope: ASL Module MVP - Title Abstract Screening Results
Cloud-Native: Backend aggregation + Frontend Excel generation
2025-11-21 20:12:38 +08:00

886 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI智能文献模块 - API设计规范
> **文档版本:** v2.1
> **创建日期:** 2025-10-29
> **维护者:** AI智能文献开发团队
> **最后更新:** 2025-11-21
> **更新说明:** 更新实际API格式、字段映射说明、测试数据示例
---
## 📋 文档说明
本文档描述AI智能文献模块的API设计规范包括接口定义、请求响应格式、错误处理等。
**API基础信息**:
- **Base URL**: `http://localhost:3001` (开发环境)
- **API前缀**: `/api/v1/asl`
- **协议**: HTTP/HTTPS
- **数据格式**: JSON
- **认证方式**: JWT Token (测试阶段支持默认用户)
---
## 🔌 API设计原则
1. **RESTful设计**: 遵循RESTful API设计规范
2. **统一响应格式**: `{ success: boolean, data?: any, error?: string }`
3. **分页支持**: 列表接口支持分页参数
4. **版本控制**: API版本化管理 (`/api/v1/...`)
5. **错误处理**: 统一的HTTP状态码和错误消息
6. **模块化路由**: `/api/v1/asl/...` 独立路由空间
---
## 📡 核心API接口
### 1. 项目管理 (Projects)
#### 1.1 创建筛选项目
**接口**: `POST /api/v1/asl/projects`
**认证**: 需要 (测试阶段默认用户ID)
**说明**: 创建一个新的文献筛选项目
**请求体**:
```json
{
"projectName": "SGLT2抑制剂系统综述",
"picoCriteria": {
"P": "2型糖尿病成人患者",
"I": "SGLT2抑制剂empagliflozin、dapagliflozin等",
"C": "安慰剂或常规降糖疗法",
"O": "心血管结局MACE、心衰住院、心血管死亡",
"S": "随机对照试验 (RCT)"
},
"inclusionCriteria": "英文文献RCT研究2010年后发表",
"exclusionCriteria": "病例报告,综述,动物实验",
"screeningConfig": {
"models": ["deepseek-chat", "qwen-max"],
"temperature": 0
}
}
```
**响应示例**:
```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": "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",
...
}
}
```
**测试命令**:
```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
{
"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
{
"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
{
"success": true,
"data": {
"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,
"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": 2
}
}
}
```
---
#### 3.4 审核冲突文献
**接口**: `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
}
}
```
---
## 📋 响应格式规范
### 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限流
- [ ] 完善错误处理
---
---
## 🆕 Week 4 新增API
### 4.1 获取项目统计数据(云原生:后端聚合)
**接口**: `GET /api/v1/asl/projects/:projectId/statistics`
**认证**: 需要
**说明**: 获取项目的筛选统计数据(总数、纳入率、排除率、排除原因分析等)
**路径参数**:
- `projectId`: 项目ID
**响应示例**:
```json
{
"success": true,
"data": {
"total": 199,
"included": 85,
"excluded": 90,
"pending": 24,
"conflict": 24,
"reviewed": 175,
"exclusionReasons": {
"P不匹配人群": 40,
"I不匹配干预": 25,
"S不匹配研究设计": 15,
"其他原因": 10
},
"includedRate": "42.7",
"excludedRate": "45.2",
"pendingRate": "12.1"
}
}
```
**特点**
- ✅ 云原生后端Prisma聚合查询6个并行查询
- ✅ 性能:<500ms199篇文献
- ✅ 减少网络传输从MB级降到KB级
**测试命令**:
```bash
curl http://localhost:3001/api/v1/asl/projects/55941145-bba0-4b15-bda4-f0a398d78208/statistics
```
---
**文档版本:** v2.2
**最后更新:** 2025-11-21Week 4完成
**维护者:** AI智能文献开发团队
**本次更新**
- ✅ 新增统计API接口
- ✅ 更新PICOS格式说明P/I/C/O/S
- ✅ 添加云原生架构标注
---
## 📚 相关文档
- [数据库设计文档](./01-数据库设计.md)
- [API测试报告](../../../backend/ASL-API-测试报告.md)
- [Week 1完成报告](../05-开发记录/2025-11-18-Week1完成报告.md)