## 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)。