Files
chis_osi/docs/04-字段与接口映射.md
T

13 KiB
Raw Blame History

04 · 字段与接口映射

本文是 mapping/ 与 contract/ 两层的落地指引:接口能力映射、PHIS→OSI 字段映射策略、码表清单、checkId 幂等键设计。


1. 接口能力 → 内部方法映射

OSI serviceId 路径 内部方法(osi 包) dataType(pipeline 分流)
JKDA00001 /jkda/create CreateHealthRecord health_record
JKDA00003 /jkda/update UpdateHealthRecord health_record
JKDA00002 /auto/jkda/find FindHealthRecord (查询)
JKDA00005 /jkda/findrqbj FindPersonSign (查询)
JKTJ00001 /jktj/create CreateHealthCheck health_check
JKTJ00003 /jktj/update UpdateHealthCheck health_check
JKTJ00002 /auto/jktj/query QueryHealthCheck (查询)
JKTJLIST00002 /auto/jktjlist/query ListHealthCheckPeople (查询)
JKTJLSJL00002 /auto/jktjlscx/query LastHealthCheck (查询)
LNRZLPG00001 /lnrzlpg/create CreateElderlySelfCare elderly_self_care
LNRZLPG00003 /lnrzlpg/update UpdateElderlySelfCare elderly_self_care
LNRZYTZ00001 /lnrzyygl/create CreateTCMConstitution tcm
LNRZYTZ00003 /lnrzyygl/update UpdateTCMConstitution tcm
(待确认) /auto/zyjkzd/create SaveTCMGuidance tcm_guidance
(待确认) /auto/zyjkzd/update UpdateTCMGuidance tcm_guidance
WGDZ00001 /auto/wgdzcx/query QueryGridAddress (字典)
ZRYS00001 /auto/zryscx/query QueryDoctors (字典)
YPML00001 /auto/ypmlcx/query QueryDrugs (字典)
CXJG00002 /auto/cxjg/query QueryOrgs (字典)

⚠ "(待确认)"项以 01 文档第 7 节为准,联调回填后更新 osi/codes.go 的 serviceId 常量与 pathOf 路由表。


2. 字段映射策略

2.1 三类字段,三种处理

  1. 直传字段:PHIS 与 OSI 同义且同形(如姓名、出生日期 yyyy-MM-dd)。直接拷贝,做必填/长度校验。
  2. 码表字段:枚举值需经字典转换(性别、民族、血型、职业…)。统一走 dict.go 双向查表,未命中报 ValidationError,绝不静默置空。
  3. 结构/多选字段:嵌套节点(既往史/家族史/手术/外伤/输血/生活环境)、逗号拼接多选。集中在各业务域映射函数里组装。

2.2 映射函数约定

// 返回结构化校验错误,pipeline 在投递前据此拦截,避免把脏数据打到平台。
func MapHealthRecord(src phis.HealthRecord, ctx MapContext) (contract.HealthRecordCreate, []ValidationError)
  • MapContext 携带机构级常量:orgCode/userName/operateUser/regionCode 默认值与字典快照。
  • 校验项:必填(idCard/personName/sexCode/birthday/mobileNumber/regionCode/manaDoctorId/manaUnitId…)、长度上限、码表合法性、日期格式。
  • 映射是纯函数,便于用 01 文档样例 + 联调真实样本做单测(对齐旧项目"可测试改动补最小必要测试")。

3. 码表清单(dict.go 初始内容)

取值来自 docx 字段说明,建模时全部落为常量表,并加注释标"来源:OSI 文档 §字段名"。

维度 取值(节选)
性别 sexCode 0 未知 / 1 男 / 2 女 / 9 未说明
户籍 registeredPermanent 1 户籍 / 2 非户籍
血型 bloodTypeCode 1 A / 2 B / 3 O / 4 AB / 5 不详
RH rhBloodCode 1 阳性 / 2 阴性 / 3 不详
文化程度 educationCode 10 研究生 / 20 本科 / 31 大专 / 41 中专 / 47 技校 / 60 高中 / 70 初中 / 80 小学 / 90 文盲 / 91 不详
职业 workCode 0 负责人 / 1·2 专技 / 3 办事 / 4 商业服务 / 5 农林牧渔 / 9-9 生产运输 / X 军人 / Y 其他 / 8 无职业
婚姻 maritalStatusCode 10 未婚 / 20 已婚 / 30 丧偶 / 40 离婚 / 90 未说明
医保 insuranceCode(多选) 01 城镇职工 / 02 城乡居民 / 04 贫困救助 / 05 商业 / 06 全公费 / 07 全自费 / 99 其他
民族 nationCode 01 汉 … 56 基诺 / 99 其他(56 项全表)
人群标记 personSign PU 普通 / GRQY 已签约 / LAO 老年 / GAO 高血压 / TANG 糖尿病 / FU 孕产妇 / ER 儿童 / FEI 肺结核 / JING 精神 / CAN 残疾
药物过敏 ywgms(多选) 0101 无 / 0102 青霉素 / 0103 磺胺 / 0104 链霉素 / 0109 其他
既往疾病 jwsjbcode 0201 无 / 0202 高血压 / 0203 糖尿病 / … / 0299 其他
残疾 cjqk(多选) 1101 无 / 1102 视力 / 1103 听力 / 1104 言语 / 1105 肢体 / 1106 智力 / 1107 精神 / 1108 孤独症 / 1109 脑瘫 / 1199 其他
厨房排风 cookAirTool 1 无 / 2 油烟机 / 3 换气扇 / 4 烟囱 / 9 其他
燃料 fuelType 1 液化气 / 2 煤 / 3 天然气 / 4 沼气 / 5 柴火 / 9 其他
饮水 waterSourceCode 1 自来水 / 2 净化水 / 3 井水 / 4 河湖水 / 5 塘水 / 9 其他
厕所 washroom 1 卫生厕所 / 2 粪池式 / 3 马桶 / 4 露天粪坑 / 5 简易棚厕 / 6 其他
机构类型 organizType A 医院 / B 社区中心(站) / C 卫生院 / D 门诊诊所村室 / D6 村卫生室 / R 市卫生局

多选字段统一用英文逗号拼接(文档示例如 "0102,0103")。注意 docx 个别返回样例用了中文逗号,解析时两者都要兼容。


4. 主数据依赖:字典服务先行

创建类接口的若干必填字段依赖公共服务查询结果,建议在投递前用字典缓存解析:

regionCode  ← QueryGridAddress(parentCode)    // 网格地址
manaDoctorId/operateUser ← QueryDoctors(manaUnitId)  // 责任医生
manaUnitId/organizCode   ← QueryOrgs(...)            // 机构

策略:启动或定时拉取这些字典,缓存到本地(redis 可选 + 内存),映射时按 PHIS 的地址/医生/机构名称反查 OSI 码。命中失败计入校验错误,不投递。


5. checkId 与幂等键设计

checkId(第三方业务唯一识别码,长度 20)是新项目幂等的核心。

5.1 生成规则(mapping/checkid.go)

要求确定性:同一源记录无论重试多少次,都得到同一 checkId。

checkId = 截断20位( 编码( 源系统标识 | dataType | 源记录主键 [ | 版本/更新时间] ) )
  • 同一条源记录的"创建"应使用稳定 checkId → 平台据此识别为同一档案,避免重复建档。
  • "更新"沿用原 checkId(走 update 接口)。
  • 若源记录内容变更需视为新版本上送,可把"更新时间/版本号"纳入 checkId 计算——取决于平台是否以 checkId 去重(见 03 文档开放问题 5)。

5.2 幂等存储

  • 键:checkId(替代旧项目 account|idCard|dataType|sha1(saveBody))。
  • 值:{status: success|failed, phrId, lastTs, attempts}。
  • 命中 success:跳过,不重复投递。
  • failed:允许后续重试。
  • 存储:redis 优先、本地 JSON 降级(沿用旧项目 idempotency_store 思路)。

用 checkId 做幂等键的好处:与平台对账口径一致(平台也认 checkId),且不受报文字段微调影响。


6. 校验与错误分类(与 pipeline 配合)

成功码以 docs/01 §1 为准:实测为字符串 "01"(非 "1"),判定按去前导零后 == "1"。

错误来源 分类 处理
映射缺必填/码表未命中/格式非法 不可重试(数据错) 直接 failed,回写 PHIS,附 ValidationError 明细
网络错误 / SOCKS / EOF / 超时 可重试 退避重试,计熔断
OSI code == "405"(服务超时) 可重试 退避重试
OSI code 非成功码非 405(业务/权限拒绝) 不可重试 failed,记 message 供排查
HTTP 5xx / 429 可重试 退避重试

7. 待补字段表

以下接口的完整字段表 docx 未充分给出或存在坑点,建模时以联调样本为准并在此登记:

  • 体检 jktj/create 全量字段(hcData/lsData/exaData/aeData,体量最大)
  • 老年人自理评估 lnrzlpg 字段
  • 中医体质辨识 lnrzyygl 字段
  • 中医健康指导 zyjkzd 字段 + serviceId
  • 个人档案查询 JKDA00002 的请求信封与返回结构 —— 已联调实测,见 §8
  • 其余列表/查询接口的分页与返回数组结构(体检/老年人/中医指导)

8. JKDA00002 个人档案查询 · 联调实测契约

来源:2026-07 沙箱一次成功查询(code="01" 操作成功)。下方均为脱敏结构,真实身份证/姓名/联系方式等 PII 只在本地样本,不入库。 这是 contract/ 里 FindHealthRecord 请求/响应结构体与 osi.FindHealthRecord 的事实基线。

8.1 请求(POST /osi/api/auto/jkda/find)

{
  "serviceId": "JKDA00002",
  "uploadinfo": {
    "baseInfo":   { "idCard": "<idCard>" },
    "manageInfo": { "DSFMC": "<userName>", "operateUser": "<operateUser>", "operateUnit": "<orgCode-18位>" }
  }
}
  • baseInfo 三选一:idCard / phrid / personName。
  • manageInfo 三字段来自机构级常量(见 docs/01 §3 三种机构码区分)。
  • 请求头另带 orgCode(=operateUnit) / deviceSN(查询可空) / ts / userName(=DSFMC) / password,签名规则见 docs/01 §2。

8.2 响应(code="01",data 为数组,每元素 = 一份档案聚合)

节点 类型 说明
healthRecord object 档案主体(人口学 + 管理字段),见 8.3
pastHistory object 既往史标志位:ywgms(药物过敏)/jwsjb标志/bls/ycbs(遗传病)/cjqk(残疾)/jzsfqn/jzsmq/jzszn/jzsxdjm(家族史·父/母/子女/兄弟姐妹) 等 code
jwsjb array 既往疾病:{ jwsjbcode, jwsjbmc, jwsjbqzsj(确诊时间) }
jwsss array 既往手术:{ jwssscode, jwsssmc, jwsssqzsj }
jwsws array 既往外伤:{ jwswscode, jwswsmc }
jwssx array 既往输血:{ jwssxcode, jwssxyy(原因) }
familyMiddle object 生活环境:waterSourceCode/fuelType/cookAirTool/washroom/livestockColumn/isFillShhj

pastHistory/familyMiddle 实测是 object(非 docx 查询侧标的 list);多选标志仍以码值出现。

8.3 healthRecord 关键字段(实测字段名,注意坑点拼写)

字段 语义 备注
idCard personName sexCode birthday 人口学主键四要素 直传+校验
phrId 健康档案号 注意驼峰 phrId(查询入参用小写 phrid)
empiId EMPI 主索引 32 位十六进制串
checkId 第三方业务唯一码 本样本为 null(存量档案无 checkId)→ 佐证幂等键需我方生成,见 §5
manaUnitId createUnit 管辖/建档机构 9 位机构码,≠ 请求头 orgCode(18位)
manaDoctorId createUser 责任医生/建档人 机构内人员 ID
regionCode addressCode homePlaceCode 行政区划/网格码 12 位
address adressNumber 现住址/门牌号 ⚠门牌号字段名少一个 d:adressNumber
homePlace homePlaceNumber 户籍地/门牌
nationCode educationCode workCode maritalStatusCode bloodTypeCode rhBloodCode insuranceCode 码表字段 走 dict.go 双向查表(§3)
personGroup otherPersonGroup 人群标记 与 JKDA00005 personSign 联动
isFillShhj 是否填生活环境 y/n
contact contactPhone mobileNumber phoneNumber 联系人/电话 PII
status createDate 档案状态/建档日期

建模提示:data 用数组承接(可能多档案/多版本);insuranceType、otherPersonGroup、checkId 等实测可为 null,结构体用指针或 omitempty,映射层不得因 null 报错。


9. 公共字典查询 · 联调实测契约

来源:2026-07-07 沙箱验证。使用本地未入库凭据和一条已存在档案反查主数据后验证;下方只记录脱敏事实,不记录真实身份证、机构码、医生姓名或密钥。

9.1 请求信封

四个公共查询接口与 JKDA 查询一致,仍走统一信封:

{
  "serviceId": "<公共查询serviceId>",
  "uploadinfo": {
    "baseInfo": { "...": "..." },
    "manageInfo": { "DSFMC": "<userName>", "operateUser": "<operateUser>", "operateUnit": "<orgCode-18位>" }
  }
}

9.2 已验证结果

接口 serviceId 真实验证结论 备注
网格地址查询 WGDZ00001 code="01" 且返回数组非空 用已存在档案的区划/网格码派生 parentCode 候选值验证
责任医生查询 ZRYS00001 code="01" 且返回数组非空 入参 manaUnitId 使用档案返回的 9 位机构码
机构查询 CXJG00002 code="01" 且返回数组非空 入参 organizCode 使用档案返回的 9 位机构码
药品目录查询 YPML00001 未做真实联调 T-101 已完成客户端封装与单测;后续有药品关键字/拼音码时补样本

T-103 字典缓存可以先依赖网格、责任医生、机构三类真实验证结果。药品目录与健康档案创建闭环无直接依赖,不阻塞 T-103/T-206。