# 立项配置接口指南 状态: `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": "CTMS-001", "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, "status": "DRAFT", "visit_schedule": [ { "visit_code": "基线访视", "baseline_offset_days": 0, "window_before_days": 0, "window_after_days": 0 }, { "visit_code": "V1", "baseline_offset_days": 7, "window_before_days": 2, "window_after_days": 2 } ] }, "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 ``` ### 4.2 PUT 保存配置(草稿) ```http PUT /api/v1/studies/{study_id}/setup-config Authorization: Bearer Content-Type: application/json ``` ### 4.3 POST 发布配置 ```http POST /api/v1/studies/{study_id}/setup-config/publish Authorization: Bearer Content-Type: application/json ``` ### 4.4 GET 导出 Excel ```http GET /api/v1/studies/{study_id}/setup-config/export-excel Authorization: Bearer ``` 说明: - 返回 `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` - 文件可直接作为导入模板继续回灌 ### 4.5 POST 导入 Excel ```http POST /api/v1/studies/{study_id}/setup-config/import-excel Authorization: Bearer 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@huapont.cn \ 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`