design.md 12 KB

Context

现状

  • DRG分组工作台 页面(frontend/src/pages/DRG/Workbench.tsx)当前调用前端 mock API /api/medicalRecord/list 展示病案列表,数据为前端写死,未对接真实业务表。
  • 后端已有三张相关表,但工作台未整合使用:
    • BS_HISPatAdm(类 User.BSHISPatAdm)— HIS 就诊主表,主键 AdmID(HIS 就诊 ID),含患者、科室、入院时间、总费用、病案号 PatMedicalNo、医疗机构 FixmedinsCode 等,不含病案首页信息。
    • BS_DRGGroupRecord(类 User.BSDRGGroupRecord)— DRG 分组记录表,通过 AdmID 关联主表;同一患者可有多条记录,GroupStage 标识分组阶段(1=事前、2=事中、3=事后),含 DRG、DRGDesc、Weight、BenchmarkCost、CCFlag、MCCFlag、RiskLevel、GroupTime、ActiveFlag 等。
    • BS_DRGMedInsuMedicalRecord(类 User.BSDRGMedInsuMedicalRecord)— 病案首页信息表,含 MdtrtId(就诊ID)、MedcasNo(病案号)、患者基本信息、诊断/手术、费用等大量字段。
  • 后端接口服务集中在 src.DRG.Interface(包 src.DRG.Interface),通过 ClassMethod 派发到实现类(如 src.DRG.GroupDevice);前端统一经 invoke(code, params) 调用。
  • 现有 02010036(src.DRG.Interface.QueryDRGGroupRecord → src.DRG.GroupDevice.QueryDRGGroupRecord)已提供按 admID/medcasNo/groupStage 等条件查询 BS_DRGGroupRecord(ActiveFlag='1')的能力,前端 DRG/Results.tsx 已按 invoke('02010036', [params], undefined, { pageSize, currentPage }) 调用。
  • 现有 02010027(src.DRG.HISData.Interface,类 User.BSDRGMedInsuMedicalRecord)已提供病案首页详情查询,前端 hisData.ts 已封装 queryMedicalRecords(02010027),frontend/src/pages/HIS/MedicalRecords.tsx 已用 Tabs(基本信息/诊断手术/费用/分组/病案首页图片)展示其内容;其返回结构即为 BS_DRGMedInsuMedicalRecord 关键字段集合。

约束

  • 不得改动三张表结构。
  • 分组动作复用现有 02010001(DRG 分组器)与 02010035(保存分组记录),本次不新增分组写入接口。
  • 分组记录历史复用现有 02010036(用户确认不新建分组历史接口)。
  • 病案首页详情复用现有 02010027(用户确认不新建 02010005 病案首页详情接口,前端参考 MedicalRecords.tsx 布局展示)。
  • 医院筛选的 fixmedinsCode 取自前端登录 session 的 hospYBCode(用户确认)。
  • 编码 02010004–02010009 为可用池,按需取用且保持连续:本方案新增 2 个,连续占用 02010004、02010005(原拟 02010005 分组历史接口已取消;原拟 02010005 病案首页详情改复用 02010027;原拟 02010006 全量整合视图顺延占用 02010005,避免编码池断号)。

Goals / Non-Goals

Goals:

  • 以 BS_HISPatAdm 为主表,整合 BS_DRGGroupRecord、BS_DRGMedInsuMedicalRecord,提供工作台所需的查询/下钻接口。
  • 改造前端工作台,移除 mock,接入真实数据,列表一行一患者、三阶段(事前/事中/事后)分组成列,支持"分组详情"下钻。
  • 支持按登录用户所属医院(fixmedinsCode = 前端 session.hospYBCode)筛选。

Non-Goals:

  • 不新增 DRG 分组算法或分组写入逻辑(沿用 02010001 / 02010035;分组历史查询沿用 02010036;病案首页查询沿用 02010027)。
  • 不改造 DIP 工作台或其他菜单。
  • 不对三张表做结构变更、不做历史数据迁移脚本(假设数据已就绪)。

Decisions

D1. 接口编码取自 02010004–02010009 可用池,连续新增 2 个,病案首页与分组历史复用现有接口

  • 新增(连续编号):02010004 列表、02010005 患者全量整合视图。
  • 病案首页详情不新建 02010005,直接复用现有 02010027(src.DRG.HISData.Interface);前端参考 MedicalRecords.tsx 的 Tabs 布局展示其返回。
  • 分组记录历史不新建接口,直接复用现有 02010036(GroupDevice.QueryDRGGroupRecord),前端以 admID 过滤即可获取该患者全部阶段分组记录(已支持 groupStage 单阶段过滤)。
  • 编号顺延说明:原草案拟用 02010004/02010005(分组历史)/02010006(病案首页)/02010007(整合);现删除 02010005(分组历史)后,将病案首页详情改复用 02010027、全量整合视图顺延占用 02010005,使新增编码保持 02010004→02010005 连续不断号,后续扩展可从 02010006 起接。
  • 理由:用户确认"按需生成"且 02010027/02010036 已满足病案首页与分组历史查询;列表 + 整合视图已覆盖工作台其余查询/下钻诉求;保留连续编号便于后续 02010006+ 扩展。

D2. 后端实现类放置

  • 选择:在 src.DRG.Interface 新增 2 个 ClassMethod 派发;实现逻辑落到新建类 src.DRG.Workbench(而非继续膨胀 src.DRG.GroupDevice)。
  • 理由:GroupDevice 已 3000+ 行,按职责拆分更清晰;与现有 Interface → 实现类 派发风格一致。
  • 备选:扩展 GroupDevice —— 否决,避免过度膨胀。

D3. 列表数据组织(一行一患者 + 三阶段成列)

  • 选择:02010004 以 BS_HISPatAdm 为一行;对同一 AdmID 的 BS_DRGGroupRecord 按 GroupStage 聚合,输出 stage1/stage2/stage3 三个对象(含 drg、drgDesc、weight、status、groupTime),无记录则为 null;并输出 hasMedicalRecord(按 PatMedicalNo = MedcasNo 是否存在病案首页)。
  • 理由:用户明确要求三阶段成列 + "分组详情"下钻;一行一患者避免列表膨胀。

D4. 三表关联键

  • 选择:BS_HISPatAdm.PatMedicalNo = BS_DRGMedInsuMedicalRecord.MedcasNo(病案号)。
  • BS_HISPatAdm ↔ BS_DRGGroupRecord 通过 AdmID 关联(表结构已明确)。
  • 理由:用户确认按病案号关联;病案号是 HIS 就诊与病案首页之间最稳定的业务键。

D5. 医院筛选 fixmedinsCode 取自前端登录 session 的 hospYBCode

  • 选择:前端调用接口时从 getSession().hospYBCode(类型 LogonResult.hospYBCode,见 frontend/src/api/logon.ts)取当前登录医院医保机构代码作为 fixmedinsCode 入参;后端 02010004 按该值过滤 BS_HISPatAdm.FixmedinsCode。
  • 理由:用户确认以 session.hospYBCode 作为医院筛选入参;该字段为医保机构编码,与 BS_HISPatAdm.FixmedinsCode 口径一致(区别于 getCurrentHospId() 返回的 hospID)。

D6. 统计汇总随列表返回

  • 选择:02010004 在 result.statistics 中返回 { total, grouped, ungrouped, failed }(基于全量过滤后的聚合,非仅当前页),避免单独统计接口。

D7. 前端 API 封装

  • 选择:新建 frontend/src/api/drgWorkbench.ts,导出 queryWorkbenchList(02010004)、queryPatientFullView(02010005),并新增轻封装 queryMedicalRecord(02010027,复用 hisData.ts 既有 queryMedicalRecords 或参考 MedicalRecords.tsx)、queryGroupRecord(02010036,入参 { admID } 复用 Results.tsx 调用约定);统一经 invoke(code, [params]) 调用。
  • 理由:与 drgGrouping.ts/hisData.ts 等按域划分的 API 文件风格一致;病案首页与分组历史复用既有接口调用方式。

D8. "分组详情"下钻数据来源

  • 选择:点击列表"分组详情"按钮,调用 02010005 获取该患者全量整合视图 { hisAdm, medicalRecord, groupRecords[] } 一次性渲染;其中 medicalRecord 的数据形态与现有 02010027 的病案首页返回一致(前端可沿用 MedicalRecords.tsx 的 Tabs 布局展示),groupRecords[] 即该患者的全部分组历史(事前/事中/事后),等价于 02010036 按 admID 的返回,无需额外请求。
  • 备选:下钻时再单独调 02010027 + 02010036 —— 否决,避免冗余往返;02010027/02010036 仅在"病案首页查询"独立页面(MedicalRecords.tsx)与"分组结果查询"独立页面(Results.tsx)及后续可能的阶段筛选场景复用。

接口契约(概要)

02010004 工作台列表查询

  • 入参:{ fixmedinsCode(session.hospYBCode), page, limit, patientName?, patMedicalNo?, inLocDesc?, groupStatus?(已/未分组), startDate?, endDate? }
  • 出参:{ errorCode, errorMessage, result: { rows: WorkbenchRow[], total, statistics } }
  • WorkbenchRow:admID, patMedicalNo, patName, patSexDesc, age, inLocDesc, admDateTime, sumAmt, fixmedinsCode, hasMedicalRecord, stage1, stage2, stage3(各 stage:drg, drgDesc, weight, status, groupTime)

02010005 患者全量整合视图

  • 入参:{ admID }
  • 出参:{ errorCode, errorMessage, result: { hisAdm, medicalRecord, groupRecords[] } }
    • medicalRecord:数据形态同 02010027(BS_DRGMedInsuMedicalRecord 关键字段)
    • groupRecords[]:该患者全部 DRG 分组记录(事前/事中/事后),等价于 02010036 按 admID 的返回

02010027(现有,复用)病案首页详情

  • 入参:invoke('02010027', [params]),params 支持 admID/medcasNo/patientName 等(前端 hisData.ts.queryMedicalRecords 已封装)
  • 出参:{ errorCode, errorMessage, result: MedicalRecordDetail }(BS_DRGMedInsuMedicalRecord 关键字段,前端 MedicalRecords.tsx 已按 Tabs 展示)
  • 用途:病案首页查询独立页面(MedicalRecords.tsx);亦作为 02010005 medicalRecord 字段的数据形态参照。

02010036(现有,复用)DRG 分组记录查询

  • 入参:invoke('02010036', [params], undefined, { pageSize, currentPage }),其中 params 支持 admID/medcasNo/patientName/drg/groupStage/startDate/endDate 等
  • 出参:{ errorCode, errorMessage, result: { rows: GroupRecord[], total } }(仅 ActiveFlag='1')
  • 用途:分组结果查询页(Results.tsx)及作为 02010005 groupRecords[] 的数据源等价替代。

Risks / Trade-offs

  • [性能] 三表关联 + 分页聚合可能慢 → 在 BS_HISPatAdm.FixmedinsCode、BS_DRGGroupRecord.AdmID、病案首页 MedcasNo 上确保已有索引(表中已有 AdmID、FixmedinsCode 等索引;必要时为 MedcasNo 补索引);列表仅做轻量聚合,详情类接口按需下钻。
  • [数据一致性] 同一患者 AdmID 与 MedcasNo 可能不匹配 → 关联采用病案号;若某 AdmID 无对应病案首页,hasMedicalRecord=false、02010005 的 medicalRecord 返回空,不影响列表。
  • [多阶段口径] 同一阶段存在多条记录 → 取 ActiveFlag='1' 且 GroupTime 最新的一条作为该阶段展示值(与 02010036 口径一致)。
  • [字段口径] session.hospYBCode 与 BS_HISPatAdm.FixmedinsCode 必须同口径 → 联调阶段需抽样核对:若两者编码不一致(如带/不带前缀),需在后端做映射或改用其它可比对字段,并在 tasks 中补充核对点。
  • [前端改造回归] 现有"分组"按钮逻辑需保留 → 仅替换数据源,保留调用 02010001/02010035 的分组保存流程。

Migration Plan

  1. 后端:新增 src.DRG.Workbench 类与方法,并在 src.DRG.Interface 注册 02010004、02010005;在 IRIS 中编译。02010027、02010036 保持不变。
  2. 前端:新增 drgWorkbench.ts API(含 02010027、02010036 轻封装);重写 DRG/Workbench.tsx 数据源与表格结构。
  3. 验证:以 session.hospYBCode 对应医院登录,确认列表按该医院过滤、三阶段成列、点击"分组详情"下钻显示分组历史与病案首页(布局参考 MedicalRecords.tsx)。
  4. 回滚:前端恢复旧 Workbench.tsx,后端接口为新增只读方法,移除不影响既有功能;无数据结构迁移,回滚安全。

Open Questions

  • 病案首页字段极多(20+ 区块),02010005 的 medicalRecord 字段是否需按前端展示裁剪(与 02010027 保持一致)?→ 默认返回关键诊断/手术/费用字段,细节可在实现阶段与用户确认。
  • "分组状态"口径(已/未分组/失败)是否以是否存在 ActiveFlag=1 的分组记录判定?→ 默认采用此口径。
  • session.hospYBCode 与 BS_HISPatAdm.FixmedinsCode 是否完全一致口径?→ 实现联调时抽样核对,若不一致需补充映射(见 Risks)。