diff --git a/患者首页处理/数据可视化网页端/app/main.py b/患者首页处理/数据可视化网页端/app/main.py index 07c6698..b318d39 100644 --- a/患者首页处理/数据可视化网页端/app/main.py +++ b/患者首页处理/数据可视化网页端/app/main.py @@ -146,9 +146,6 @@ FIELD_GROUPS: list[dict[str, Any]] = [ "fields": [ ("outpatient_diagnosis", "门急诊诊断", "text", None), ("outpatient_diagnosis_code", "门急诊诊断编码", "text", None), - ("primary_diagnosis", "主要诊断", "text", None), - ("primary_diagnosis_code", "主要诊断编码", "text", None), - ("primary_admission_condition", "主要诊断入院病情", "text", None), ("discharge_diagnoses", "出院诊断", "json", None), ("injury_poisoning_external_cause", "损伤中毒外部原因", "text", None), ("injury_poisoning_code", "损伤中毒疾病编码", "text", None), @@ -385,9 +382,6 @@ AI_REDACT_PATTERNS = ( AI_UPLOAD_FIELDS = [ "outpatient_diagnosis", "outpatient_diagnosis_code", - "primary_diagnosis", - "primary_diagnosis_code", - "primary_admission_condition", "discharge_diagnoses", "operations", "pathology_diagnosis", @@ -1808,6 +1802,35 @@ def json_changed_fields(field: str, old_value: Any, new_value: Any) -> list[dict ] +def main_diagnosis_row_index(rows: list[Any]) -> int: + for index, row in enumerate(rows): + if isinstance(row, dict) and str(row.get("诊断类别") or "").strip() == "主要诊断": + return index + return 0 + + +def main_diagnosis_from_discharge_diagnoses(value: Any) -> dict[str, str]: + rows = value if isinstance(value, list) else [] + if not rows: + return {"primary_diagnosis": "", "primary_diagnosis_code": "", "primary_admission_condition": ""} + index = main_diagnosis_row_index(rows) + row = rows[index] if index < len(rows) and isinstance(rows[index], dict) else {} + return { + "primary_diagnosis": str(row.get("出院诊断") or row.get("诊断名称") or "").strip(), + "primary_diagnosis_code": str(row.get("疾病编码") or row.get("诊断编码") or "").strip(), + "primary_admission_condition": str(row.get("入院病情") or "").strip(), + } + + +def sync_primary_diagnosis_updates(updates: dict[str, Any], before: dict[str, Any]) -> None: + if "discharge_diagnoses" not in updates: + return + derived = main_diagnosis_from_discharge_diagnoses(updates.get("discharge_diagnoses")) + for field, value in derived.items(): + if comparable(before.get(field)) != comparable(value): + updates[field] = value + + def build_record_updates( record_id: int, fields: dict[str, Any], @@ -1838,6 +1861,8 @@ def build_record_updates( if "inpatient_no" in updates and not str(updates["inpatient_no"] or "").strip(): raise HTTPException(status_code=400, detail="患者号不能为空") + sync_primary_diagnosis_updates(updates, before) + manual_note = manual_note.strip() if manual_note: current = before.get("review_notes") or [] @@ -2343,7 +2368,7 @@ def build_ai_prompt(record: dict[str, Any], pdf_context: dict[str, Any], privacy 5. 只有仍需要复核或纠正的问题,classification 返回 "problem",并写入 remaining_issues。 6. 如果手术表格中能看到“手术及操作编码”列但对应单元格为空,写“编码栏可见但为空白”,不要写“编码区域未在首页显示”;单元格本来为空且无需补录时不要因此判为 problem。 7. 手术操作名称可能因为换行被结构化解析截断;如果 PDF定位文本或局部截图中显示完整多行名称,请把完整名称放入 suggested_updates。 -8. 门急诊诊断编码只能用于 outpatient_diagnosis_code;不要把门急诊诊断编码复制到 primary_diagnosis_code 或 discharge_diagnoses[].疾病编码,除非出院诊断表格对应“疾病编码”单元格本身清楚显示该编码。 +8. 门急诊诊断编码只能用于 outpatient_diagnosis_code;主要诊断请修正 discharge_diagnoses 中“诊断类别=主要诊断”的行,不要把门急诊诊断编码复制到 discharge_diagnoses[].疾病编码,除非出院诊断表格对应“疾病编码”单元格本身清楚显示该编码。 9. remaining_issues 只写当前文档复核人应该特别注意的内容;不要写如何修改,不要重复 suggested_updates,不要写“无需补录/无需处理/首页原貌”这类已判定无问题的说明。 10. 不要编造 PDF 中看不见的内容,不要输出置信度。 @@ -2353,7 +2378,7 @@ def build_ai_prompt(record: dict[str, Any], pdf_context: dict[str, Any], privacy "summary": "一句话结论,60字以内", "method": "AI视觉核验:PDF文本定位+局部截图,对照复核定位和结构化字段", "suggested_updates": [ - {{"field": "字段名或路径,例如 primary_diagnosis_code 或 operations[0].麻醉方式", "value": "PDF中应写入的值", "reason": "20字以内"}} + {{"field": "字段名或路径,例如 discharge_diagnoses[0].疾病编码 或 operations[0].麻醉方式", "value": "PDF中应写入的值", "reason": "20字以内"}} ], "remaining_issues": ["AI觉得有必要复核的内容,最多3条;无则返回空数组"], "evidence": [ @@ -2660,8 +2685,22 @@ def ai_outpatient_code_leak(path: tuple[str, int | None, str | None], value: Any return bool(target_is_diagnosis_code) +PRIMARY_DIAGNOSIS_AI_TARGETS = { + "primary_diagnosis": "出院诊断", + "主要诊断": "出院诊断", + "主要诊断名称": "出院诊断", + "primary_diagnosis_code": "疾病编码", + "主要诊断编码": "疾病编码", + "primary_admission_condition": "入院病情", + "主要诊断入院病情": "入院病情", +} + + def ai_update_path(field_text: str, item: dict[str, Any]) -> tuple[str, int | None, str | None] | None: text = str(field_text or "").strip() + for keyword, column in sorted(PRIMARY_DIAGNOSIS_AI_TARGETS.items(), key=lambda entry: len(entry[0]), reverse=True): + if keyword in text: + return ("discharge_diagnoses", -1, column) if text in EDITABLE_FIELDS: return (text, None, None) for name, meta in FIELD_META.items(): @@ -2726,6 +2765,10 @@ def ai_suggested_updates(result: dict[str, Any], before: dict[str, Any]) -> tupl continue rows = old_value if isinstance(old_value, list) else [] rows = [dict(row) if isinstance(row, dict) else {} for row in rows] + if index == -1 and field == "discharge_diagnoses": + if not rows: + rows = [{"诊断类别": "主要诊断", "出院诊断": "", "疾病编码": "", "入院病情": ""}] + index = main_diagnosis_row_index(rows) if index < 0 or index >= len(rows): continue compare_old = rows[index].get(key) @@ -2750,6 +2793,7 @@ def ai_suggested_updates(result: dict[str, Any], before: dict[str, Any]) -> tupl } ) + sync_primary_diagnosis_updates(updates, before) return updates, changed_fields diff --git a/患者首页处理/数据可视化网页端/app/static/app.js b/患者首页处理/数据可视化网页端/app/static/app.js index 7ee5ba4..c7c4269 100644 --- a/患者首页处理/数据可视化网页端/app/static/app.js +++ b/患者首页处理/数据可视化网页端/app/static/app.js @@ -68,9 +68,7 @@ const FIELD_KEYWORDS = { discharge_dept: ["出院科别", "科室"], hospital_days: ["住院天数"], major_department: ["大科室"], - primary_diagnosis: ["主要诊断"], - primary_diagnosis_code: ["主要诊断编码", "疾病编码"], - discharge_diagnoses: ["出院诊断", "其他诊断", "诊断编码", "入院病情"], + discharge_diagnoses: ["出院诊断", "主要诊断", "主要诊断编码", "主要诊断入院病情", "其他诊断", "诊断编码", "入院病情"], operations: ["手术", "操作", "麻醉", "切口"], total_cost: ["总费用"], self_pay_amount: ["自付"],