Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pac
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tools
pac
Commits
0a79ffa2
Commit
0a79ffa2
authored
Aug 26, 2026
by
luoqi
Browse files
Options
Browse Files
Download
Plain Diff
merge: 残根/残冠归 K03 → test
parents
c13974d1
4d9c6f13
Pipeline
#3598
failed in 0 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
95 additions
and
0 deletions
+95
-0
apps/pac-service/tests/reconcile-diagnosis-code.spec.ts
+80
-0
packages/types/src/canonical-codes.ts
+15
-0
No files found.
apps/pac-service/tests/reconcile-diagnosis-code.spec.ts
0 → 100644
View file @
0a79ffa2
/**
* reconcileDiagnosisCode — 宿主 std_code 错标 / 截码失真的纠偏规则。
*
* 两条规则各有一个**反向闸**,测试重点全在闸上 —— 闸失效不会报错,
* 只会让一批患者悄悄换场景(K08 缺牙 base 60 ↔ K03 牙体损伤 base 35),
* 表现为矩阵某一列莫名多/少几百格。
*
* 跑:
* pnpm test -- reconcile-diagnosis-code
*/
import
{
reconcileDiagnosisCode
}
from
'@pac/types'
;
describe
(
'reconcileDiagnosisCode'
,
()
=>
{
describe
(
'K00 → K08(后天缺失被错标成发育障碍)'
,
()
=>
{
it
.
each
([
'牙齿缺少'
,
'牙缺失'
,
'缺牙'
,
'后天性牙齿缺失'
])(
'%s → K08'
,
(
name
)
=>
{
expect
(
reconcileDiagnosisCode
(
'K00'
,
name
)).
toBe
(
'K08'
);
});
it
(
'带「先天」→ 保持 K00(真发育障碍)'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
'K00'
,
'先天性牙齿缺失'
)).
toBe
(
'K00'
);
expect
(
reconcileDiagnosisCode
(
'K00'
,
'先天缺牙'
)).
toBe
(
'K00'
);
});
it
(
'其它 K00 不动'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
'K00'
,
'乳牙滞留'
)).
toBe
(
'K00'
);
expect
(
reconcileDiagnosisCode
(
'K00'
,
'多生牙'
)).
toBe
(
'K00'
);
});
});
describe
(
'K08 → K03(K08.3 牙根残留被截成 K08 缺牙)'
,
()
=>
{
// 生产实测:名字恰为这几个的 932 条应翻 K03
it
.
each
([
'残根'
,
'残冠'
,
'残根残冠'
,
'残根/残冠'
])(
'%s → K03'
,
(
name
)
=>
{
expect
(
reconcileDiagnosisCode
(
'K08'
,
name
)).
toBe
(
'K03'
);
});
it
(
'无法保留 / 不能保留 → K03'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
'K08'
,
'无法保留'
)).
toBe
(
'K03'
);
expect
(
reconcileDiagnosisCode
(
'K08'
,
'患牙不能保留'
)).
toBe
(
'K03'
);
});
// ⛔ 反向闸:复合诊断(生产 325 条)两个病挤在一个 name,翻 K03 会丢掉缺牙那一半
it
.
each
([
'牙列缺损,残根'
,
'缺失,残根'
,
'残根,牙列缺损'
,
'牙缺失;#44残根'
,
'牙缺失, 残根残冠'
,
'16,12,26缺失,17,11,21,22,23,25,27残根'
,
])(
'复合诊断「%s」→ 保持 K08'
,
(
name
)
=>
{
expect
(
reconcileDiagnosisCode
(
'K08'
,
name
)).
toBe
(
'K08'
);
});
it
(
'纯缺牙类 K08 不动'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
'K08'
,
'后天性牙齿缺失'
)).
toBe
(
'K08'
);
expect
(
reconcileDiagnosisCode
(
'K08'
,
'牙列缺损'
)).
toBe
(
'K08'
);
expect
(
reconcileDiagnosisCode
(
'K08'
,
'牙齿缺少'
)).
toBe
(
'K08'
);
});
it
(
'残根本来就是 K03 的不受影响(医生没填 std_code 的多数派)'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
'K03'
,
'残根'
)).
toBe
(
'K03'
);
expect
(
reconcileDiagnosisCode
(
'K03'
,
'残冠'
)).
toBe
(
'K03'
);
});
});
describe
(
'边界'
,
()
=>
{
it
(
'code 为 null → null'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
null
,
'残根'
)).
toBeNull
();
});
it
(
'name 为 null → 原样返回,不误翻'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
'K08'
,
null
)).
toBe
(
'K08'
);
expect
(
reconcileDiagnosisCode
(
'K00'
,
null
)).
toBe
(
'K00'
);
});
it
(
'无关码不动'
,
()
=>
{
expect
(
reconcileDiagnosisCode
(
'K05'
,
'慢性牙周炎'
)).
toBe
(
'K05'
);
expect
(
reconcileDiagnosisCode
(
'K02'
,
'龋病'
)).
toBe
(
'K02'
);
});
});
});
packages/types/src/canonical-codes.ts
View file @
0a79ffa2
...
@@ -303,10 +303,25 @@ export const EXTERNAL_TREATMENT_VISIT_NEG_RE =
...
@@ -303,10 +303,25 @@ export const EXTERNAL_TREATMENT_VISIT_NEG_RE =
/// "牙齿缺少/缺失/缺牙"也错标成 K00(全库 1044 例)→ 冒出"萌出异常"误召(关平 BJ0U007377 牙25:
/// "牙齿缺少/缺失/缺牙"也错标成 K00(全库 1044 例)→ 冒出"萌出异常"误召(关平 BJ0U007377 牙25:
/// 残根拔除后缺失,宿主标 K00 → 误召萌出处置)。区分符=「先天」:有先天 → 真 K00(发育障碍),
/// 残根拔除后缺失,宿主标 K00 → 误召萌出处置)。区分符=「先天」:有先天 → 真 K00(发育障碍),
/// 无先天的缺牙义 → 后天缺失 = K08。萌出/多生牙等其它 K00 不动。
/// 无先天的缺牙义 → 后天缺失 = K08。萌出/多生牙等其它 K00 不动。
///
/// 残根/残冠纠偏(2026-08 王丽芳 TS0M013040 牙42):源 ICD 用 **K08.3 牙根残留**(医学上没标错),
/// 但 std_code 截前 3 位后跟 K08.1 后天缺失挤进同一个 K08 → 目标文案变成"邀约启动缺失牙修复
/// (种植/桥/义齿)",而临床路径是**拔除**或根管+桩核冠。K03 的 categories 含 surgical、
/// 目标文案本就写着"残根/残冠 → 充填/嵌体/拔除修复",且 POTENTIAL_LABEL_RULES 的
/// `K03 + EXTRACTION_NAME_KEYWORDS → extraction(拔牙治疗)` 正等着这批名字 —— 归 K03 才对得上。
/// 口径一致性:医生**没填** std_code 时按中文名映射本来就落 K03(全库 97,970 条);
/// 填了 K08.3xx 的这 932 条反而归错,本规则把少数派拉回多数派。
/// ⛔ 区分符=「缺失/缺牙/缺损」:复合诊断("牙列缺损,残根"/"牙缺失;#44残根",全库 325 条)
/// 两个病挤在一个 name 里,翻 K03 会丢掉缺牙那一半 → 保持 K08(基线分更高,且 K08 的已解决
/// 判定是结构家族宽集、含拔除,患者去拔了照样解除)。那是源头把多诊断挤成一行的问题,不在此修。
/// 源码不丢:transaction.rawPayload 原样留着 stdCode(K08.300x002 / K08.302 / K08.300),随时可倒查。
export
function
reconcileDiagnosisCode
(
code
:
string
|
null
,
nameZh
:
string
|
null
):
string
|
null
{
export
function
reconcileDiagnosisCode
(
code
:
string
|
null
,
nameZh
:
string
|
null
):
string
|
null
{
if
(
code
===
'K00'
&&
nameZh
&&
/缺
(
牙|失|少
)
/
.
test
(
nameZh
)
&&
!
/先天/
.
test
(
nameZh
))
{
if
(
code
===
'K00'
&&
nameZh
&&
/缺
(
牙|失|少
)
/
.
test
(
nameZh
)
&&
!
/先天/
.
test
(
nameZh
))
{
return
'K08'
;
return
'K08'
;
}
}
if
(
code
===
'K08'
&&
nameZh
&&
/残根|残冠|无法保留|不能保留/
.
test
(
nameZh
)
&&
!
/缺失|缺牙|缺损/
.
test
(
nameZh
))
{
return
'K03'
;
}
return
code
;
return
code
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment