213 lines
5.8 KiB
Markdown
213 lines
5.8 KiB
Markdown
# 立项配置接口指南
|
||
|
||
状态: `active`
|
||
适用范围: `setup-config`
|
||
最后更新: `2026-03-30`
|
||
|
||
## 1. 概览
|
||
- 基础路径: `/api/v1/studies/{study_id}/setup-config`
|
||
- 数据作用域: 单项目唯一配置(`study_setup_configs.study_id` 唯一约束)
|
||
- 存储格式: JSONB(字段结构与前端 `SetupConfigDraft` 对齐)
|
||
- 并发控制: 乐观锁(`expected_version`)
|
||
- 发布机制: 草稿/已发布(`publish_status`)
|
||
- 前端视图语义:
|
||
- `草稿视图`: 当前草稿可编辑
|
||
- `发布预览`: 当前草稿只读预览(不直接读取 `published_data`)
|
||
- `published_data`: 用于发布快照、差异比较与版本能力
|
||
- `published_project_snapshot`: 发布时的项目基础信息快照(用于“项目信息差异”判定)
|
||
|
||
## 2. 权限矩阵
|
||
- `GET /setup-config`
|
||
- 允许: 项目成员、管理员
|
||
- `PUT /setup-config`
|
||
- 允许: PM、ADMIN
|
||
- 限制: 项目锁定时返回 `403`
|
||
- `POST /setup-config/publish`
|
||
- 允许: PM、ADMIN
|
||
- 限制: 项目锁定时返回 `403`
|
||
- `GET /setup-config/export-excel`
|
||
- 允许: 项目成员、管理员
|
||
- `POST /setup-config/import-excel`
|
||
- 允许: PM、ADMIN
|
||
- 限制: 项目锁定时返回 `403`
|
||
|
||
## 3. 数据结构
|
||
|
||
### 3.1 请求体(保存)
|
||
```json
|
||
{
|
||
"expected_version": 3,
|
||
"data": {
|
||
"projectMilestones": [
|
||
{
|
||
"id": "m1",
|
||
"name": "首例入组",
|
||
"planDate": "2026-03-01",
|
||
"owner": "项目经理",
|
||
"remark": "",
|
||
"status": "未开始"
|
||
}
|
||
],
|
||
"enrollmentPlan": {
|
||
"totalTarget": 100,
|
||
"startDate": "2026-02-01",
|
||
"endDate": "2026-12-31",
|
||
"monthlyGoalNote": "按月拆解",
|
||
"stageBreakdown": "阶段1/2/3"
|
||
},
|
||
"siteMilestones": [],
|
||
"siteEnrollmentPlans": [],
|
||
"monitoringStrategies": [],
|
||
"centerConfirm": []
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 响应体(GET/PUT/PUBLISH/IMPORT-EXCEL)
|
||
```json
|
||
{
|
||
"id": "f0ac2fca-5fd3-470e-8e7e-2ded2b8f0f77",
|
||
"study_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
|
||
"version": 6,
|
||
"publish_status": "PUBLISHED",
|
||
"data": {
|
||
"projectMilestones": [],
|
||
"enrollmentPlan": {
|
||
"totalTarget": 120,
|
||
"startDate": "2026-02-01",
|
||
"endDate": "2026-12-31",
|
||
"monthlyGoalNote": "",
|
||
"stageBreakdown": ""
|
||
},
|
||
"siteMilestones": [],
|
||
"siteEnrollmentPlans": [],
|
||
"monitoringStrategies": [],
|
||
"centerConfirm": []
|
||
},
|
||
"published_data": null,
|
||
"published_project_snapshot": {
|
||
"code": "DEMO-CTMS",
|
||
"name": "演示项目",
|
||
"project_full_name": "演示项目全称",
|
||
"sponsor": "",
|
||
"protocol_no": "",
|
||
"lead_unit": "",
|
||
"principal_investigator": "",
|
||
"main_pm": "",
|
||
"research_analysis": "",
|
||
"research_product": "",
|
||
"control_product": "",
|
||
"indication": "",
|
||
"research_population": "",
|
||
"research_design": "",
|
||
"plan_start_date": "2026-02-01",
|
||
"plan_end_date": "2026-12-31",
|
||
"planned_site_count": 12,
|
||
"planned_enrollment_count": 120,
|
||
"summary_note": "",
|
||
"objective_note": "",
|
||
"status": "DRAFT",
|
||
"visit_interval_days": null,
|
||
"visit_total": null,
|
||
"visit_window_start_offset": null,
|
||
"visit_window_end_offset": null
|
||
},
|
||
"saved_by": "11111111-1111-1111-1111-111111111111",
|
||
"saved_by_name": "System Admin",
|
||
"published_by": null,
|
||
"published_by_name": null,
|
||
"published_at": null,
|
||
"created_at": "2026-02-09T01:30:00.000000Z",
|
||
"updated_at": "2026-02-09T02:11:13.000000Z"
|
||
}
|
||
```
|
||
|
||
## 4. 接口定义
|
||
|
||
### 4.1 GET 获取配置
|
||
```http
|
||
GET /api/v1/studies/{study_id}/setup-config
|
||
Authorization: Bearer <token>
|
||
```
|
||
|
||
### 4.2 PUT 保存配置(草稿)
|
||
```http
|
||
PUT /api/v1/studies/{study_id}/setup-config
|
||
Authorization: Bearer <token>
|
||
Content-Type: application/json
|
||
```
|
||
|
||
### 4.3 POST 发布配置
|
||
```http
|
||
POST /api/v1/studies/{study_id}/setup-config/publish
|
||
Authorization: Bearer <token>
|
||
Content-Type: application/json
|
||
```
|
||
|
||
### 4.4 GET 导出 Excel
|
||
```http
|
||
GET /api/v1/studies/{study_id}/setup-config/export-excel
|
||
Authorization: Bearer <token>
|
||
```
|
||
说明:
|
||
- 返回 `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
|
||
- 文件可直接作为导入模板继续回灌
|
||
|
||
### 4.5 POST 导入 Excel
|
||
```http
|
||
POST /api/v1/studies/{study_id}/setup-config/import-excel
|
||
Authorization: Bearer <token>
|
||
Content-Type: multipart/form-data
|
||
```
|
||
表单字段:
|
||
- `file`: `.xlsx` 文件(必填)
|
||
- `expected_version`: 当前配置版本(可选,建议携带)
|
||
|
||
说明:
|
||
- 导入会覆盖当前草稿并自增版本。
|
||
- 写入审计事件: `IMPORT_SETUP_CONFIG_EXCEL`。
|
||
|
||
## 5. 错误码与典型场景
|
||
- `400 BAD REQUEST`
|
||
- 上传文件非 `.xlsx`
|
||
- Excel 解析失败
|
||
- `403 FORBIDDEN`
|
||
- 非 PM/ADMIN 导入/保存/发布
|
||
- 项目已锁定
|
||
- `404 NOT FOUND`
|
||
- study 不存在
|
||
- `409 CONFLICT`
|
||
- `expected_version` 与服务端不一致
|
||
- `422 UNPROCESSABLE ENTITY`
|
||
- Excel 数据通过解析后,业务字段校验失败
|
||
|
||
## 6. 联调脚本(curl)
|
||
- 脚本路径: `docs/setup-config-curl-smoke.sh`
|
||
- 使用方式:
|
||
```bash
|
||
chmod +x docs/setup-config-curl-smoke.sh
|
||
BASE_URL=http://localhost:8888 \
|
||
EMAIL=admin@example.com \
|
||
PASSWORD=admin123 \
|
||
STUDY_ID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa \
|
||
bash docs/setup-config-curl-smoke.sh
|
||
```
|
||
|
||
## 7. Postman 联调集合
|
||
- Collection: `docs/postman/setup-config.postman_collection.json`
|
||
- Environment: `docs/postman/local.postman_environment.example.json`(导入后建议另存为你自己的本地环境)
|
||
|
||
## 8. 后端烟雾测试(非 pytest)
|
||
```bash
|
||
docker compose up -d db backend
|
||
docker compose exec -T backend python scripts/smoke_setup_config.py
|
||
```
|
||
|
||
## 9. 监控埋点(4xx/5xx)
|
||
- 中间件统计以下接口:
|
||
- `GET /api/v1/studies/{study_id}/setup-config`
|
||
- `PUT /api/v1/studies/{study_id}/setup-config`
|
||
- `POST /api/v1/studies/{study_id}/setup-config/publish`
|
||
- `GET /api/v1/studies/{study_id}/setup-config/export-excel`
|
||
- `POST /api/v1/studies/{study_id}/setup-config/import-excel`
|