Files
zkxw/docs/superpowers/specs/2026-07-02-protocol-standard-import-design.md
T
2026-07-02 12:25:00 +08:00

288 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 采集协议单 · 一键导入标准信息
> 日期:2026-07-02
> 状态:已实现
> 关联:`ProtocolFormDialog.vue`、捐赠单 `DonationFormDialog.vue` + `donation-standard-import-parse.ts`
> 参考样例:客户提供的标准信息1(单样本趸交)、标准信息2(双存部分缴费)
---
## 1. 背景与目标
采集协议单**新增**弹窗需支持「一键导入」:粘贴客户标准文本,解析后填充各 Tab 字段。交互与捐赠协议单一致(左侧粘贴区 + 右侧基本信息,仅新增模式展示)。
### 1.1 已确认业务规则
| 规则 | 决策 |
|------|------|
| **金额** | **以标准信息中的金额为准**(合同金额、转账金额等),不以样本优惠价自动合计覆盖导入结果 |
| **缴费方式** | 文本为「微信 / 支付宝 / 银行卡 / 现金」等时,**默认趸交 `dj`**;仅当明确出现「分期」时设为 `fq` |
| **转账方式** | 「转账方式:微信」或「缴费方式:微信」(非分期语义)→ 映射字典 `zzfs`(如微信→`wxzz`) |
| **导入策略** | 点击一键导入时**先清空**可覆盖字段,再按当前粘贴内容填充(与捐赠单一致) |
| **协议级采集时间** | 多样本时取各样本采集时间中的**最早值** |
### 1.2 非目标
- 后端新 API(纯前端解析 + 既有 lookup 接口)
- 编辑模式下一键导入
- 附件、协议号自动生成规则变更
---
## 2. 标准文本格式
### 2.1 标准信息1(单样本 · 趸交 · 两笔转账)
```
围产期干细胞储存
造血干细胞:ZKZX34000870
产妇姓名:刘晓艳
…
缴费方式:趸交
转账方式:微信
合同金额:22880元
转账金额:22880元
转账时间:2026年6月17日13时09分05秒2000元,6月18日15:50:12付20880元
孕妇电话:13966850002
运输方式:顺丰快递
预计送达时间:
```
### 2.2 标准信息2(双存 · 部分缴费 · 人员携带)
```
围产期干细胞储存(双存)
造血干细胞:ZKZX34000922
脐带间充质干细胞:ZKQD34000839
…
缴费方式:微信
合同金额:37000元
转账金额:2000元
转账时间:2026年3月10日11:34:40
运输方式:露露帮助到医院取样本送到实验室
备注:剩余尾款两天内交清
```
---
## 3. 字段映射
### 3.1 公共字段(与捐赠类似)
| 客户 key / 模式 | 目标字段 | 备注 |
|-----------------|----------|------|
| 产妇姓名 | 母亲姓名 / 关联客户 | 远程匹配 |
| 孕妇电话 | `motherPhone` | 去空格 |
| 新生儿性别 | `newbornSex` | 男孩/女孩 |
| 新生儿体重 | `newbornWeightGram` | |
| 新生儿评分 | `apgar1min` | |
| 分娩时间 | `newbornDeliveryTime` | |
| 母血采集时间 | `maternalBloodCollectTime` | 未采集→清空 |
| 分娩方式 | `deliveryMode` | 含「刨宫产」→ `pgc` |
| 胎次 | `birthOrder` | 中文数字 |
| 采集医护 | `medicalStaff` | |
| 采集医院 | `regionId` + `hospitalId` | |
| 销售人员 | `salesUserId` | **仅销售,不改采集专员** |
| 备注 | `remark` | |
| 运输方式 | 样本 `transport` | 见 §3.4 |
| 预计送达时间 | `transport.etaTime` | 空则跳过 |
### 3.2 样本:编码行 + 采集时间行
**编码行**(优先识别样本行):
```
造血干细胞:ZKZX34000870
脐带间充质干细胞:ZKQD34000839
```
| 类型关键词 | 系统类型名 | typeKey |
|------------|------------|---------|
| 造血干细胞(非间充质) | 围产期造血干细胞 | `hsc` |
| 脐带间充质干细胞 | 脐带间充质干细胞 | `uc_msc` |
**采集时间行**(与编码行按 typeKey 合并):
| 字段名(含别名) | typeKey |
|------------------|---------|
| 造血干细胞采集时间、造血干细胞样本采集时间 | `hsc` |
| 脐带间充质干细胞采集时间、脐带采集时间 | `uc_msc` |
- 首行标题(围产期干细胞储存…)仅作**无编码/无时间行**时的兜底类型匹配。
- 协议级 `sampleCollectTime` = 各 hint 已解析 `collectTime` 的**最早值**。
**样本编码**:按文本中的 `ZK…` 编码远程查 `fetchSampleCodeList`,写入 `sampleCodeId` + `sampleCode`;找不到则 warning。
**样本价格**:匹配样本类型后带出 `storagePrice` 作为原价/优惠价初始值;**合同金额仍以文本「合同金额」为准**(§3.3)。
### 3.3 缴费(金额以标准信息为准)
| 客户字段 | 解析 | 写入 |
|----------|------|------|
| 缴费方式:趸交 | `payMode = dj` | 缴费主表 |
| 缴费方式:分期 | `payMode = fq` | 缴费主表 + 分期默认参数 |
| 缴费方式:微信/支付宝/… | **`payMode = dj`**(非分期) | 同时作为转账方式 hint |
| 转账方式:微信 | `transferType` | 字典匹配 `zzfs` |
| 合同金额:22880元 | `22880` | **`formData.contractAmount`**(权威,覆盖自动合计) |
| 转账金额 | 单值或明细金额 | 缴费明细 `transferAmount` |
| 转账时间 | 见 §3.3.1 | 缴费明细 `transferTime` |
**趸交 + 部分已转**(标准2):`payMode=dj`,合同 37000,明细 1 条 transfer 2000;`syncPaymentDueAmounts()` 计算待缴应缴额。
**趸交 + 多笔转账**(标准1):解析 2 条明细(2000 + 20880),转账方式均为微信;合计应等于合同金额,不等则 warning。
#### 3.3.1 转账时间复杂格式
支持拆段,例如:
`2026年6月17日13时09分05秒2000元,6月18日15:50:12付20880元`
→ 两条 `{ transferTime, transferAmount }`。
单段格式:`2026年3月10日11:34:40` + 全局「转账金额」字段。
### 3.4 运输
复用 `resolveTransportType`(含顺丰快递→`kdys`、顺丰车→`ryxd`、顺风车/露露帮助…→`ryxd`)。
- `kdys`:匹配快递公司,填 `expressCompanyId`
- `ryxd`:不填快递;可选从文本提取人名(如「露露」)→ `carrierName`
---
## 4. 技术设计
### 4.1 新建解析器
**文件**:`web-admin/src/utils/protocol-standard-import-parse.ts`
```typescript
export type ProtocolSampleImportHint = {
typeKey: 'hsc' | 'uc_msc'
typeName: string
sampleCode?: string
collectTime?: string
}
export type ProtocolPaymentTransferHint = {
transferAmount: number
transferTime: string // YYYY-MM-DD HH:mm:ss
}
export type ProtocolStandardImportParsed = {
sampleTypeHeader: string
sampleHints: ProtocolSampleImportHint[]
motherName?: string
motherPhone?: string
newbornSex?: '1' | '0'
newbornWeightGram?: number | null
apgarScore?: number | null
newbornDeliveryTime?: string
sampleCollectTime?: string
maternalBloodCollectTime?: string
maternalBloodExplicitEmpty?: boolean
deliveryMode?: string
birthOrder?: number | null
medicalStaff?: string
hospitalName?: string
salesUserName?: string
payMode?: 'dj' | 'fq'
contractAmount?: number | null
transferTypeLabel?: string // 原始「微信」等,填充时查字典
paymentTransfers: ProtocolPaymentTransferHint[]
transportModeText?: string
transportType?: 'kdys' | 'ryxd'
etaTime?: string
remark?: string
}
```
**复用**(import from 已有模块):
- `parseChineseDatetimeText` / `formatDatetimeToMinute`
- `parseBirthOrder`
- `resolveTransportType`
- `matchSampleTypeByExactName` / `matchCellSampleType`
- `isBlankString` / `extractNumericPart`
**新增**:
- `parsePayMode(text)`:`分期`→`fq`,否则 `dj`(趸交、微信、空均默认 dj)
- `parseSampleCodeLine(key, value)`:类型名 + ZK 编码
- `parsePaymentTransferSegments(text)`:多笔转账时间行
- `resolveTransferTypeCode(label, dictOptions)`:label→`wxzz` 等
### 4.2 UI
**文件**:`ProtocolFormDialog.vue`
- 新增模式 Tab「基本信息」:左侧 `section-card--import`(与捐赠同布局类名,见 `DonationFormDialog` SCSS)
- `standardImportText` + `handleStandardImport`
- `clearFormBeforeStandardImport()`:清空导入覆盖范围(含 samples、paymentDetails、缴费主表金额字段、客户/采集字段;**保留**协议状态、登记日期、采集专员、附件)
- `handleStandardImport` 流程见 §4.3
### 4.3 填充流程
```
1. parseProtocolStandardImportText(text)
2. clearFormBeforeStandardImport()
3. 预加载:样本类型、站点、快递、转账字典 zzfs
4. 并行:母亲(by name/phone)、医院、销售用户
5. 写入采集/客户/新生儿字段
6. 按 sampleHints 创建样本行(类型+编码 lookup+运输)
7. formData.contractAmount = parsed.contractAmount(来自标准信息)
8. formData.payMode = parsed.payMode ?? 'dj'
9. 重建 paymentDetails from paymentTransfers + transferType
10. syncFormSamplesAfterImport()
11. syncPaymentDueAmounts()(不调用 syncContractAmount 覆盖合同额)
12. 若样本价合计与合同金额差异 > 0.01 → warning(提示人工核对样本优惠价)
13. ElMessage success/warning
```
### 4.4 与捐赠差异摘要
| 项 | 捐赠 | 采集协议 |
|----|------|----------|
| 样本编码 | 自动生成 | 文本指定 + API 匹配 |
| 合同金额 | 无 | **标准信息为准** |
| 缴费 | 无 | 主表 + 明细 |
| 销售导入 | 同时写采集专员 | **仅 salesUserId** |
| 孕妇电话 | 无 | 有 |
---
## 5. 测试用例
| 用例 | 断言 |
|------|------|
| 标准信息1 全文 | 1 样本 ZKZX…;contract=22880;payMode=dj;2 条明细 2000+20880;运输 kdys |
| 标准信息2 全文 | 2 样本;contract=37000;payMode=dj;1 明细 2000;运输 ryxd;remark 有值 |
| 缴费方式:微信 | payMode=dj,transferType 匹配微信 |
| 缴费方式:分期 | payMode=fq |
| 刨宫产 / 头胎 | deliveryMode=pgc,birthOrder=1 |
| 重复点击导入 | 旧数据清空,仅保留新粘贴结果 |
---
## 6. 改动文件清单
| 文件 | 改动 |
|------|------|
| `utils/protocol-standard-import-parse.ts` | 新建 |
| `views/cell-storage/protocol/ProtocolFormDialog.vue` | UI + 导入逻辑 + SCSS |
| `utils/donation-standard-import-parse.ts` | 可选:导出共享函数,避免重复 |
| `utils/chinese-datetime-parse.ts` | 如需支持「付20880元」段内金额,扩展解析 |
**不改**:后端、DB。
---
## 7. 决策记录
| 日期 | 决策 |
|------|------|
| 2026-07-02 | 金额以标准信息为准,不用样本价自动合计覆盖合同金额 |
| 2026-07-02 | 缴费方式「微信」等默认趸交,仅明确「分期」时分期 |
| 2026-07-02 | 协议级 sampleCollectTime 取最早采集时间 |
| 2026-07-02 | 导入前清空可覆盖字段 |