## Why 后端接口服务 `02010067`(`src.DRG.HISData.HisDataService.GetInpatientData`)在开启费用明细同步(`BS_HISSyncConfig.FeeFlag='Y'`)后,单次调用返回 **504 Gateway Timeout**,同步链路不可用。 根因有两点,二者叠加才致命: 1. **落库是逐行的,耗时随费用行数线性放大。** `SaveInpatientFeeData`(`HisDataService.cls:658-894`)对每一条费用明细都执行:1 次存在性 SQL(`&sql(SELECT ID ... WHERE Adm_Dr=? AND FeedetlSn=?)`)+ 1 次通用 ORM 调用(`src.util.operatetable.Insert/Update`,内部含 `%Library.ClassDefinition.%ExistsId()` 类定义查找、`FromDynamicObj` 对约 57 个属性的反射映射、`%Save()` 维护 5 个索引)+ 1 次全字段 `feeItem.%ToJSON()`;且**每行都是一个独立隐式事务**,即每行一次 journal 提交。实测 10 条就诊 = 681 条费用明细,折算约 50–100ms/行;生产单批次为**数万行**,耗时达 20–50 分钟量级,必然超出任何网关超时阈值。 2. **整条链路挤在一个同步 HTTP 请求里。** 从公司转发器 `172.16.1.6:8082` 到 `172.16.2.15:8082` 再到 IRIS,任意一跳的超时配置都会先于后端返回 504。因此**单纯调大超时无法根治**,必须让受理请求毫秒级返回。 此外审计中发现两个既有缺陷会进一步放大耗时:`GetInpatientData:441-446` 无条件重复调用 `DeviceFeeWarning`(DRG 时分组算两遍、DIP 时结果被覆盖);`synFlag='Y'` 时 `GetMedicalRecord` 对**每个就诊**串行发起一次 HIS + DRG 平台 HTTP 调用。 ## What Changes 采用「**受理异步化(根治 504)+ 落库批量化(根治耗时)**」双轨方案,分 6 个模块: - **M1 异步任务受理与状态机**:新建 `User.BSHISSyncTask`(`BS_HISSyncTask`)任务表,承载 pending/running/success/partial/failed 状态流转与进度计数。`02010067` 新增**可选**入参 `asyncFlag`(缺省取 `BS_HISSyncConfig.AsyncFlag`,再缺省 `'N'`):`'N'` 时走现有同步路径、返回结构与现状**完全一致**;`'Y'` 时落任务记录后由 IRIS `JOB` 启动后台进程,请求在毫秒级返回受理回执 `{taskId, status}`。 - **M2 任务进度查询**:新增接口服务 `02010089` → `HisDataService.GetSyncTaskProgress`,按 `taskId` 返回状态、阶段、已处理/总数、成功/失败数与错误摘要,供前端轮询。 - **M3 费用明细批量落库引擎**:重写 `SaveInpatientFeeData`。① 按就诊一次性预加载已有 `(FeedetlSn → ID)` 到内存,行内 O(1) 判定插入/更新,消除逐行 SELECT;② 用 `%SQL.Statement` 一次 `%Prepare` 参数化 INSERT/UPDATE、循环 `%Execute`,替代逐行 ORM 调用;③ 分段事务(默认每 500 行 `TCOMMIT`+`TSTART`),journal 提交次数降至 1/500;④ `FeeDetailJson` 仅新插入时序列化,更新时沿用原值。目标:**单行耗时下降一个数量级**(约 50–100ms → <5ms)。 - **M4 主链路缺陷修复**:删除 `GetInpatientData:441-446` 的重复 `DeviceFeeWarning` 调用并修正 DIP/DRG 分支;`GetMedicalRecord` 的每人次 HTTP 调用纳入异步阶段并受开关控制。 - **M5 网关与链路加固**:补全 `frontend/nginx.conf` 8082 两个 location 缺失的 `proxy_connect_timeout`/`proxy_send_timeout`/`client_max_body_size`/`proxy_buffering`;并排查中间转发器 `172.16.1.6:8082` 的超时配置(504 大概率源于该跳)。 - **M6 前端进度化改造**:`DataSync.tsx` 同步请求携带 `asyncFlag:'Y'` 获取 `taskId`,轮询 `02010089` 并用现有 `Progress` 组件展示真实百分比,完成后再调 `02010075`;同时移除前端 7 天切批逻辑(改由后端一次吃下整个日期范围并上报进度)。 **模块间数据流转**: ``` 前端「立即同步」 -> 02010067(asyncFlag='Y') -- 建 BS_HISSyncTask(pending) -- JOB 起后台进程 -- 立即回 {taskId} | +---------------------------+ v HIS 05900014 取数 -> SaveInpatientData(就诊/DRG参数/诊断/手术) -> SaveInpatientFeeData(M3 批量落库) -> 持续回写 BS_HISSyncTask 进度/状态 <- 前端轮询 02010089(taskId) 读进度 -> 终态后调 02010075 拉取患者列表 ``` - **非 BREAKING**:默认 `asyncFlag='N'`,`02010067` 同步模式的返回结构逐字保持现状(`result` 仍为 HIS 原始数组,不做任何裁剪)——满足"保持返回结构原样"的约束;异步回执是**新增的可选返回形态**,仅当调用方显式传 `asyncFlag='Y'` 时生效。 ## Capabilities ### New Capabilities - `his-sync-async-task`:HIS 数据同步的异步受理与任务生命周期管理。覆盖 `BS_HISSyncTask` 任务表、`02010067` 的 `asyncFlag` 受理分支、IRIS `JOB` 后台执行、并发去重与进度上报,以及 `02010089` 进度查询接口。 - `his-fee-batch-persistence`:HIS 住院费用明细的批量化落库。覆盖去重映射预加载、预编译 SQL 落库、分段事务提交与惰性 JSON 序列化,在保持 `(AdmDr, FeedetlSn)` 增量 Upsert 语义与既有返回字段不变的前提下消除逐行开销。 ### Modified Capabilities - `his-data-sync-consolidation`:新增需求——`GetInpatientData` 需支持可选的异步受理模式;并修正其分组/预警调用链中 `DeviceFeeWarning` 被重复调用、`GetDIPGroupScoreFeeWarning` 结果被覆盖的既有缺陷。 ## Impact - **后端新增/改造** - `src/src/User/BSHISSyncTask.cls`(新建任务表类)。 - `src/src/DRG/HISData/HisDataService.cls`:`SaveInpatientFeeData`(重写落库内核)、`GetInpatientData`(新增 `asyncFlag` 受理分支、修复重复分组调用)、`GetSyncTaskProgress`(新建)、`RunSyncTaskAsync`(新建,JOB 入口)。 - `src/src/DRG/HISData/Interface.cls`:新增 `GetSyncTaskProgress`(02010089)委托方法。 - `src/src/DRG/HISData/SyncTaskService.cls` / `src/src/User/BSHISSyncConfig.cls`:`AsyncFlag` 配置列透传(02010079 / 02010080)。 - **数据库**:新增物理表 `BS_HISSyncTask` 及 `(HospCode, Status)`、`(TaskID)` 索引;`BS_HISSyncConfig` 增加 `AsyncFlag` 列并回填 `'Y'`。 - **脚本/注册**:新增 `scripts/insert_his_sync_task_interface.sql`(注册 02010089)、`scripts/alter_his_sync_config_asyncflag.sql`。 - **前端**:`frontend/src/api/hisData.ts` 增加 `asyncFlag` 入参与进度查询方法;`frontend/src/pages/HIS/DataSync.tsx` 增加受理-轮询流程(复用现有 `Progress` 组件)。 - **运维配置**:`frontend/nginx.conf` 超时与缓冲参数补全;需同步核对中间转发器 `172.16.1.6:8082` 的超时设置。 - **不在本次范围**:费用明细的前端查询页面;`02010068` 的独立调度改造(复用 M3 成果即可受益);任务历史归档与清理策略。 - **部署要求**:需重新编译 `User.BSHISSyncTask`、`User.BSHISSyncConfig`、`src.DRG.HISData.*` 后生效;生产 IRIS 需允许 `JOB` 后台进程。