Files
ctms/docs/setup-config-api.md
T

209 lines
5.7 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.
# 立项配置接口说明(Excel 导入导出版)
## 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 \
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.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`