外观
用户 API
用户接口维护建档资料、健康指标、疾病史、手术史和头像。所有 endpoint 都要求 Bearer JWT,后端用当前 token 解析出的 user_id 作为归属边界。
Endpoint 索引
| Method | Path | 用途 |
|---|---|---|
| PUT | /api/user/basic-info | 更新基本资料。 |
| PUT | /api/user/health-metrics | 更新健康指标与肿瘤相关字段。 |
| POST | /api/user/diseases | 新增疾病史。 |
| PUT | /api/user/diseases/{disease_id} | 更新本人疾病史。 |
| DELETE | /api/user/diseases/{disease_id} | 删除本人疾病史。 |
| POST | /api/user/operations | 新增手术史。 |
| PUT | /api/user/operations/{operation_id} | 更新本人手术史。 |
| DELETE | /api/user/operations/{operation_id} | 删除本人手术史。 |
| GET | /api/user/profile-completion | 读取建档完成度。 |
| POST | /api/user/avatar | 通过后端上传头像。 |
| POST | /api/user/avatar/upload-policy | 获取头像直传策略或本地上传指示。 |
| POST | /api/user/avatar/confirm | 确认 OSS 直传头像。 |
| DELETE | /api/user/avatar | 删除头像。 |
| GET | /api/user/avatar | 读取头像地址。 |
| GET | /api/user/profile | 读取完整用户档案。 |
| GET | /api/user/profile/basic | 读取运动计算所需基础资料。 |
Endpoint 契约
资料与健康指标
PUT /api/user/basic-info
| 项 | 内容 |
|---|---|
| Request | user_nickname、user_name、id_no、gender、birth、email、address |
| Response | success、updated_fields |
| Errors | 400 字段校验;401;500 |
| Consumer | UserApiClient.updateBasicInfo |
| Handler | user.update_basic_info |
| DB Touchpoints | 更新 users;写 update_logs |
| Tests | tests/api/test_user.py、tests/services/test_user_service.py |
PUT /api/user/health-metrics
| 项 | 内容 |
|---|---|
| Request | height、weight、bloodtype、血压、肿瘤相关字段 |
| Response | success、profile_id |
| Errors | 400 范围/格式;401;500 |
| Consumer | UserApiClient.updateHealthMetrics |
| Handler | user.update_health_metrics |
| DB Touchpoints | 更新 user_profiles;写 update_logs |
| Tests | tests/api/test_user.py、tests/services/test_user_service.py |
GET /api/user/profile-completion
| 项 | 内容 |
|---|---|
| Request | 无 |
| Response | 完成百分比、缺失字段、疾病/手术记录状态 |
| Errors | 401;500 |
| Consumer | UserApiClient.getProfileCompletion |
| Handler | user.get_profile_completion |
| DB Touchpoints | 读 users、user_profiles、user_diseases、user_operations |
| Tests | tests/api/test_user.py |
GET /api/user/profile
| 项 | 内容 |
|---|---|
| Request | 无 |
| Response | basic_info、health_metrics、diseases、operations |
| Errors | 401;500 |
| Consumer | UserApiClient.getUserProfile |
| Handler | user.get_user_profile |
| DB Touchpoints | 读 users、user_profiles、user_diseases、user_operations |
| Tests | tests/api/test_auth_dependency.py 覆盖 storage 注入 |
GET /api/user/profile/basic
| 项 | 内容 |
|---|---|
| Request | 无 |
| Response | gender、weight、height |
| Errors | 401;500 |
| Consumer | UserApiClient.getBasicProfile、运动热量计算 |
| Handler | user.get_user_basic_profile |
| DB Touchpoints | 读 users、user_profiles |
| Tests | Flutter exercise feedback tests |
疾病史
POST /api/user/diseases
| 项 | 内容 |
|---|---|
| Request | disease_name、disease_stage |
| Response | success、disease_id |
| Errors | 401;500 |
| Consumer | UserApiClient.addDisease |
| Handler | user.add_disease |
| DB Touchpoints | 写 user_diseases;写 update_logs |
| Tests | tests/api/test_user.py |
PUT /api/user/diseases/{disease_id}
| 项 | 内容 |
|---|---|
| Request | path disease_id;body disease_name、disease_stage |
| Response | success |
| Errors | 404 不存在或非本人;401;500 |
| Consumer | UserApiClient.updateDisease |
| Handler | user.update_disease |
| DB Touchpoints | 更新本人 user_diseases;写 update_logs |
| Tests | tests/services/test_user_service_owner_guard.py |
DELETE /api/user/diseases/{disease_id}
| 项 | 内容 |
|---|---|
| Request | path disease_id |
| Response | success |
| Errors | 404 不存在或非本人;401;500 |
| Consumer | UserApiClient.deleteDisease |
| Handler | user.delete_disease |
| DB Touchpoints | 软删除本人 user_diseases;写 update_logs |
| Tests | tests/services/test_user_service_owner_guard.py |
手术史
POST /api/user/operations
| 项 | 内容 |
|---|---|
| Request | oprt_disease、oprt_stage、oprt_time |
| Response | success、operation_id |
| Errors | 401;500 |
| Consumer | UserApiClient.addOperation |
| Handler | user.add_operation |
| DB Touchpoints | 写 user_operations;写 update_logs |
| Tests | tests/api/test_user.py |
PUT /api/user/operations/{operation_id}
| 项 | 内容 |
|---|---|
| Request | path operation_id;body oprt_disease、oprt_stage、oprt_time |
| Response | success |
| Errors | 404 不存在或非本人;401;500 |
| Consumer | UserApiClient.updateOperation |
| Handler | user.update_operation |
| DB Touchpoints | 更新本人 user_operations;写 update_logs |
| Tests | tests/services/test_user_service_owner_guard.py |
DELETE /api/user/operations/{operation_id}
| 项 | 内容 |
|---|---|
| Request | path operation_id |
| Response | success |
| Errors | 404 不存在或非本人;401;500 |
| Consumer | UserApiClient.deleteOperation |
| Handler | user.delete_operation |
| DB Touchpoints | 软删除本人 user_operations;写 update_logs |
| Tests | tests/services/test_user_service_owner_guard.py |
头像
POST /api/user/avatar
| 项 | 内容 |
|---|---|
| Request | multipart file |
| Response | success、avatar_url、avatar_path |
| Errors | 400 类型/大小/内容不合法;401;404 用户不存在;500 |
| Consumer | UserApiClient.uploadAvatar |
| Handler | user.upload_avatar |
| DB Touchpoints | 更新 users.avatar;写 update_logs;本地或 OSS 存储 |
| Tests | avatar storage tests、replacement point tests |
POST /api/user/avatar/upload-policy
| 项 | 内容 |
|---|---|
| Request | file_name、file_size |
| Response | 本地上传指示或 OSS policy |
| Errors | 400 文件名/类型/大小;401;500 |
| Consumer | UserApiClient.getAvatarUploadPolicy |
| Handler | user.get_avatar_upload_policy |
| DB Touchpoints | 不写业务表;读取 storage settings |
| Tests | tests/services/test_avatar_storage_service_unittest.py |
POST /api/user/avatar/confirm
| 项 | 内容 |
|---|---|
| Request | object_key |
| Response | success、avatar_key、avatar_url |
| Errors | 400 object key 不合法/直传未启用;401;404;500 |
| Consumer | UserApiClient.confirmAvatarUpload |
| Handler | user.confirm_avatar_upload |
| DB Touchpoints | 更新 users.avatar;写 update_logs |
| Tests | avatar storage tests |
DELETE /api/user/avatar
| 项 | 内容 |
|---|---|
| Request | 无 |
| Response | success、removed、avatar_url=null |
| Errors | 401;404;500 |
| Consumer | UserApiClient.deleteAvatar |
| Handler | user.delete_avatar |
| DB Touchpoints | 清空 users.avatar;写 update_logs;本地文件 best-effort cleanup |
| Tests | avatar storage tests |
GET /api/user/avatar
| 项 | 内容 |
|---|---|
| Request | 无 |
| Response | success、avatar_url、avatar |
| Errors | 401;404;500 |
| Consumer | UserApiClient.getAvatarUrl |
| Handler | user.get_avatar |
| DB Touchpoints | 读 users.avatar |
| Tests | replacement point tests |
字段边界
| 字段组 | 主要约束 |
|---|---|
| 基本资料 | birth 使用 YYYY-MM-DD;身份证格式由共享规则校验;字段更新写入 users。 |
| 健康指标 | 身高、体重、血压、脉搏有范围校验;diagnosis_date 归一为业务日期。 |
| 手术日期 | oprt_time 归一为业务日期,落 user_operations.oprt_time。 |
| 头像 | 支持 jpg/png/webp;后端校验扩展名、MIME、文件头和大小;OSS policy 只返回临时上传参数,不持久暴露密钥。 |
来源锚点
- Router:
apps/backend_service/app/api/user.py - Service:
apps/backend_service/app/services/user_service.py - Storage:
apps/backend_service/app/services/avatar_storage_service.py - Flutter:
apps/flutter_app/lib/api/user_api_client.dart - Tests:
apps/backend_service/tests/api/test_user.py、apps/backend_service/tests/services/test_user_service_owner_guard.py、apps/flutter_app/test/api/replacement_point_contract_test.dart