# 医疗问诊 Agent API 文档 > 当前文档只描述前端联调需要的后端能力。 ## 1. 联调地址 | 项目 | 地址 | |---|---| | 公网网关 | `http://8.160.178.88/fastapi` | | API Base URL | `http://8.160.178.88/fastapi/api/v1` | | Swagger | `http://8.160.178.88/fastapi/docs` | | OpenAPI JSON | `http://8.160.178.88/fastapi/openapi.json` | | 存活检查 | `http://8.160.178.88/fastapi/health/live` | | 就绪检查 | `http://8.160.178.88/fastapi/health/ready` | ## 2. 通用规则 除健康检查外,所有业务接口都需要携带: ```http Authorization: Bearer X-Entry-Scene: vue_frontend X-Request-Id: <可选> ``` 普通 JSON 接口统一返回: ```json { "code": "OK", "message": "success", "data": {} } ``` 前端判断规则: - HTTP 状态码为 `2xx` - `code` 等于 `OK` - 业务数据从 `data` 读取 SSE 流式接口不返回上述 JSON 包装,而是返回 `event + data` 事件流。 ## 3. 前置接口 ### 3.1 当前用户 | 接口名称 | url | api | methods | params(入参) | response(返回参数) | |---|---|---|---|---|---| | 当前用户 | `http://8.160.178.88/fastapi/api/v1/auth/me` | `/api/v1/auth/me` | `GET` | Header:`Authorization` 必填,格式 `Bearer `;`X-Entry-Scene` 建议传。 | `data.user_id`、`data.username`、`data.display_name`、`data.role`、`data.phone`、`data.institution_id`、`data.department_id`、`data.status` 等 Django 用户中心字段。 | 请求示例: ```http GET /api/v1/auth/me Authorization: Bearer X-Entry-Scene: vue_frontend ``` 成功返回示例: ```json { "code": "OK", "message": "success", "data": { "user_id": "37", "source": "django_user_center", "username": "13700000099", "display_name": "测试用户", "tenant_id": "1", "role": "student", "phone": "13700000099", "avatar": "", "gender": 0, "institution_id": 1, "institution_name": "测试机构", "department_id": 2, "department_name": "儿科", "status": 1 } } ``` ### 3.2 病例读取 | 接口名称 | url | api | methods | params(入参) | response(返回参数) | |---|---|---|---|---|---| | 病例列表 | `http://8.160.178.88/fastapi/api/v1/cases` | `/api/v1/cases` | `GET` | Query:`department_id` 选填,科室 ID;`training_type` 选填;`mode` 选填,允许 `practice`、`teaching`。 | `data.items[]`,包含 `id`、`title`、`department_id`、`difficulty`、`chief_complaint`、`has_teaching_video`、`has_quiz`。 | | 病例详情 | `http://8.160.178.88/fastapi/api/v1/cases/{case_id}` | `/api/v1/cases/{case_id}` | `GET` | Path:`case_id` 必填,病例 ID。 | 病例入口展示信息,不返回标准答案、隐藏病史、检查结果和评分规则。 | ## 4. 训练页面接口 | 接口名称 | url | api | methods | params(入参) | response(返回参数) | |---|---|---|---|---|---| | 推荐配置信息 | `http://8.160.178.88/fastapi/api/v1/training-config/recommended?case_id={case_id}` | `/api/v1/training-config/recommended` | `GET` | Query:`case_id` 必填,病例 ID。 | `data.recommended` 默认配置;`data.recommended_labels` 中文标签。 | | 训练配置信息 | `http://8.160.178.88/fastapi/api/v1/training-config/options?case_id={case_id}` | `/api/v1/training-config/options` | `GET` | Query:`case_id` 必填,病例 ID。 | `data.options` 全部可选项;`data.recommended` 推荐默认值。 | | 新建会话 | `http://8.160.178.88/fastapi/api/v1/sessions` | `/api/v1/sessions` | `POST` | Body:`case_id` 必填;`training_type` 必填;`mode` 必填,当前训练填 `practice`;`score_type` 选填,允许 `percentage`、`five_point`;`patient_config` 选填。 | `data.session_id`、`data.session_code`、`data.status`、`data.patient_opening`、`data.patient_config`。 | | 流式会话 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/chat/stream` | `/api/v1/sessions/{session_id}/chat/stream` | `POST` | Path:`session_id` 必填;Body:`message` 必填,医学生问句。 | SSE:`message_delta` 返回患者回复增量;`message_done` 返回耗时;`error` 返回错误。 | | 王主任练习提示 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/hints/stream` | `/api/v1/sessions/{session_id}/hints/stream` | `POST` | Path:`session_id` 必填;Body:`last_user_message` 选填;`scope` 选填,默认 `current_conversation`。 | SSE:`hint_delta` 返回一句话提示增量;`hint_done` 返回结束事件。 | | 体格检查列表获取 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/physical-exams` | `/api/v1/sessions/{session_id}/physical-exams` | `GET` | Path:`session_id` 必填。 | `data.items[]`,包含体格检查项 `item_code`、`item_name`、`item_type`。不返回结果。 | | 辅助检查列表获取 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/auxiliary-exams` | `/api/v1/sessions/{session_id}/auxiliary-exams` | `GET` | Path:`session_id` 必填。 | `data.items[]`,包含辅助检查项 `item_code`、`item_name`、`item_type`。不返回结果。 | | 体格检查某项结果 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/physical-exams/{item_code}` | `/api/v1/sessions/{session_id}/physical-exams/{item_code}` | `POST` | Path:`session_id` 必填;`item_code` 必填,必须属于体格检查。 | `data.result_text`、`data.result_structured`、`data.context_written`、`data.already_ordered`。 | | 辅助检查某项结果 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/auxiliary-exams/{item_code}` | `/api/v1/sessions/{session_id}/auxiliary-exams/{item_code}` | `POST` | Path:`session_id` 必填;`item_code` 必填,必须属于辅助检查。 | `data.result_text`、`data.result_structured`、`data.context_written`、`data.already_ordered`。 | | 完成问诊 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/complete-inquiry` | `/api/v1/sessions/{session_id}/complete-inquiry` | `POST` | Path:`session_id` 必填。至少完成一轮医生问诊。 | `data.session_id`、`data.status=diagnosis`。 | | 提交诊断 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/diagnosis` | `/api/v1/sessions/{session_id}/diagnosis` | `POST` | Path:`session_id` 必填;Body:`primary_diagnosis` 必填;`diagnosis_basis` 必填;`differential_diagnoses` 选填数组。 | `data.status=treatment`。 | | 提交治疗 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/treatment` | `/api/v1/sessions/{session_id}/treatment` | `POST` | Path:`session_id` 必填;Body:`treatment_principle`、`treatment_measures` 必填;`risk_plan`、`communication`、`follow_up` 选填。 | `data.status=evaluating`。 | | 生成评价 | `http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/evaluation` | `/api/v1/sessions/{session_id}/evaluation` | `POST` | Path:`session_id` 必填;Body:`score_type` 选填,允许 `percentage`、`five_point`。必须已提交治疗。 | `data.evaluation_id`、`data.total_score`、`data.dimension_scores[]`、`data.score_details[]`、`data.overall_comment`。 | | 获取评价(详情) | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}` | `/api/v1/evaluations/{evaluation_id}` | `GET` | Path:`evaluation_id` 必填。只允许当前用户访问自己的评价。 | 评价详情,包含病例、总分、维度评分、评分明细、改进建议、PDF 路径。 | | 下载 PDF | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}/download-pdf` | `/api/v1/evaluations/{evaluation_id}/download-pdf` | `GET` | Path:`evaluation_id` 必填。Header:`Authorization` 必填。 | 成功时返回 `application/pdf` 文件流,浏览器可下载;失败时返回统一错误 JSON。 | ### 4.1 训练配置入参和返回示例 请求: ```http GET /api/v1/training-config/options?case_id=2 Authorization: Bearer X-Entry-Scene: vue_frontend ``` 返回: ```json { "code": "OK", "message": "success", "data": { "case_id": 2, "recommended": { "visit_environment": "outpatient", "age_group": "child", "education_level": "higher", "personality": "calm" }, "recommended_labels": { "visit_environment": "门诊", "age_group": "儿童", "education_level": "高等教育", "personality": "平和" }, "options": { "visit_environment": [ {"value": "outpatient", "label": "门诊"}, {"value": "emergency", "label": "急诊"}, {"value": "ward", "label": "病房"} ], "age_group": [ {"value": "child", "label": "儿童"}, {"value": "youth", "label": "青年"}, {"value": "middle_aged", "label": "中年"}, {"value": "elderly", "label": "老年"} ], "education_level": [ {"value": "primary_or_below", "label": "小学及以下"}, {"value": "secondary", "label": "中等教育"}, {"value": "higher", "label": "高等教育"} ], "personality": [ {"value": "calm", "label": "平和"}, {"value": "anxious", "label": "焦虑"}, {"value": "impatient", "label": "急躁"}, {"value": "cooperative", "label": "配合"}, {"value": "suspicious", "label": "多疑"} ] } } } ``` ### 4.2 新建会话入参和返回示例 请求: ```json { "case_id": 2, "training_type": "diagnosis_treatment", "mode": "practice", "score_type": "percentage", "patient_config": { "visit_environment": "outpatient", "age_group": "child", "education_level": "higher", "personality": "calm" } } ``` 返回: ```json { "code": "OK", "message": "success", "data": { "session_id": 12, "session_code": "sess_20260608120000_xxxx", "status": "inquiry", "patient_opening": "家长:医生,孩子发热咳嗽好几天了,昨天开始喘得厉害,精神也不太好。", "patient_config": { "values": { "visit_environment": "outpatient", "age_group": "child", "education_level": "higher", "personality": "calm" }, "labels": { "visit_environment": "门诊", "age_group": "儿童", "education_level": "高等教育", "personality": "平和" } } } } ``` ### 4.3 SSE 流式会话返回格式 请求: ```json { "message": "孩子发热几天了?最高体温多少?" } ``` 返回: ```text event: message_delta data: {"delta":"发热有4天了,"} event: message_delta data: {"delta":"最高烧到39度多。"} event: message_done data: {"latency_ms":1800,"first_token_ms":500,"model":"deepseek-chat","fallback_used":false} ``` ### 4.4 检查结果返回示例 ```json { "code": "OK", "message": "success", "data": { "item_code": "blood_routine", "item_name": "血常规", "item_type": "lab", "result_text": "WBC 12.5×10^9/L,中性粒细胞比例72%,提示感染及炎症反应。", "result_structured": { "wbc": "12.5×10^9/L", "neutrophil": "72%" }, "is_key": true, "is_abnormal": true, "context_written": true, "already_ordered": false } } ``` 检查规则: - 检查结果只来自数据库,不由 LLM 生成。 - 检查结果会写入本次会话短期 memory 和评分依据。 - 同一会话重复申请相同 `item_code` 时返回已有结果,`already_ordered=true`。 ### 4.5 诊断和治疗提交示例 提交诊断: ```json { "primary_diagnosis": "支气管肺炎", "differential_diagnoses": ["支气管哮喘急性发作", "上呼吸道感染"], "diagnosis_basis": "结合发热、咳嗽、喘息、肺部湿啰音、胸片异常、炎症指标升高和血氧情况,符合儿童支气管肺炎表现。" } ``` 提交治疗: ```json { "treatment_principle": "抗感染、止咳平喘、改善氧合并严密观察病情变化。", "treatment_measures": "根据病情进行抗感染治疗,必要时雾化吸入缓解喘息,监测体温、呼吸和血氧。", "risk_plan": "关注低氧、呼吸困难加重、持续高热、精神反应差和脱水。", "communication": "向家属说明病情、用药注意事项、危险信号和复诊指征。", "follow_up": "治疗后复查体温、呼吸、血氧和必要炎症指标。" } ``` ## 5. 教学互动接口 | 接口名称 | url | api | methods | params(入参) | response(返回参数) | |---|---|---|---|---|---| | 获取教学列表(题目 选项 答案 解析文本 视频) | `http://8.160.178.88/fastapi/api/v1/teaching/cases/{case_id}/items` | `/api/v1/teaching/cases/{case_id}/items` | `GET` | Path:`case_id` 必填,必须存在 `teaching_case` 数据。 | `data.case` 病例摘要;`data.questions[]` 题目列表,包含 `stem`、`options[]`、`answer`、`analysis`、`video`。 | | 生成评价 | `http://8.160.178.88/fastapi/api/v1/teaching/evaluation` | `/api/v1/teaching/evaluation` | `POST` | Body:`case_id` 必填;`answers[]` 必填;`answers[].question_id` 必填;`answers[].selected_answer` 必填;`score_type` 选填。 | `data.session_id`、`data.evaluation_id`、`data.total_score`、`data.dimension_scores[]`、`data.score_details[]`、`data.overall_comment`。 | | 获取评价(详情) | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}` | `/api/v1/evaluations/{evaluation_id}` | `GET` | Path:`evaluation_id` 必填。 | 教学互动评价详情,结构与训练评价一致。 | | 下载 PDF | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}/download-pdf` | `/api/v1/evaluations/{evaluation_id}/download-pdf` | `GET` | Path:`evaluation_id` 必填。 | 返回 `application/pdf` 文件流。 | 获取教学列表返回示例: ```json { "code": "OK", "message": "success", "data": { "case": { "case_id": 2, "title": "支气管肺炎 - 6岁男性患儿", "chief_complaint": "发热、咳嗽4天,喘息1天" }, "teaching_goal": "围绕儿科肺炎问诊、检查选择、诊断依据、治疗决策和医患沟通完成互动训练。", "questions": [ { "question_id": "q1", "question_type": "single_choice", "stem": "该患儿最需要优先关注的病情严重程度指标是?", "options": [ {"key": "A", "text": "体温峰值"}, {"key": "B", "text": "血氧饱和度"} ], "answer": "B", "analysis": "血氧饱和度能帮助判断低氧和肺炎严重程度。", "video": {"title": "儿童肺炎教学示例视频", "url": ""}, "knowledge_points": ["严重程度评估", "血氧判断"] } ] } } ``` 生成教学评价请求示例: ```json { "case_id": 2, "score_type": "percentage", "answers": [ {"question_id": "q1", "selected_answer": "B"}, {"question_id": "q2", "selected_answer": "A"} ] } ``` ## 6. 个人中心接口 | 接口名称 | url | api | methods | params(入参) | response(返回参数) | |---|---|---|---|---|---| | 训练记录列表 | `http://8.160.178.88/fastapi/api/v1/evaluations` | `/api/v1/evaluations` | `GET` | Header:`Authorization` 必填。 | `data.items[]` 当前用户完整训练后的评价记录,包含 `evaluation_id`、`case_title`、`score_type`、`total_score`、`created_at`、`pdf_exported`。 | | 训练记录详情(评价详情) | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}` | `/api/v1/evaluations/{evaluation_id}` | `GET` | Path:`evaluation_id` 必填。 | 完整评价详情,训练和教学互动评价共用。 | 训练记录列表返回示例: ```json { "code": "OK", "message": "success", "data": { "items": [ { "evaluation_id": 101, "case_title": "支气管肺炎 - 6岁男性患儿", "score_type": "percentage", "total_score": 82, "created_at": "2026-06-08T12:00:00", "pdf_exported": true } ] } } ``` ## 7. PDF 下载前端写法 因为下载接口需要 Bearer token,前端不能直接使用普通 ``。使用 `fetch` 获取 blob 后触发下载: ```ts async function downloadEvaluationPdf(baseUrl: string, token: string, evaluationId: number) { const response = await fetch(`${baseUrl}/evaluations/${evaluationId}/download-pdf`, { method: "GET", headers: { Authorization: `Bearer ${token}`, "X-Entry-Scene": "vue_frontend", }, }); if (!response.ok) { const error = await response.json().catch(() => null); throw new Error(error?.message || `PDF 下载失败:${response.status}`); } const blob = await response.blob(); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `evaluation_${evaluationId}.pdf`; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); } ``` ## 8. 常见错误码 | HTTP | code | 说明 | |---:|---|---| | 401 | `AUTH_CREDENTIAL_REQUIRED` | 缺少 Authorization。 | | 401 | `AUTH_USER_INVALID` | token 无效、过期或 Django 返回非 200。 | | 403 | `AUTH_USER_DISABLED` | Django 用户状态被禁用。 | | 503 | `AUTH_USER_CENTER_UNAVAILABLE` | Django 用户中心超时或不可达。 | | 404 | `CASE_NOT_FOUND` | 病例不存在、未发布或已停用。 | | 404 | `SESSION_NOT_FOUND` | 会话不存在或不属于当前用户。 | | 400 | `SESSION_STATUS_INVALID` | 当前状态不允许执行该操作。 | | 400 | `INQUIRY_REQUIRED` | 完成问诊前没有医生提问。 | | 400 | `DIAGNOSIS_REQUIRED` | 提交治疗前没有提交诊断。 | | 400 | `TREATMENT_REQUIRED` | 生成评价前没有提交治疗。 | | 404 | `ORDER_ITEM_NOT_FOUND` | 当前病例不存在该检查项。 | | 400 | `ORDER_ITEM_TYPE_MISMATCH` | 检查接口类型和检查项类型不匹配。 | | 404 | `EVALUATION_NOT_FOUND` | 评价不存在或不属于当前用户。 | | SSE error | `LLM_STREAM_TIMEOUT` | 流式问诊首段或总耗时超时。 | | SSE error | `LLM_STREAM_FAILED` | 流式模型调用失败。 | | 500 | `PDF_EXPORT_FAILED` | PDF 生成失败。 | ## 9. 当前保留接口清单 当前后端业务模块: - 训练页面:推荐配置、训练配置、新建会话、流式会话、王主任练习提示、检查列表、检查结果、完成问诊、诊断、治疗、评价、评价详情、PDF 下载。 - 教学互动:教学列表、教学评价、评价详情、PDF 下载。 - 个人中心:训练记录列表、训练记录详情。