288 lines
10 KiB
Markdown
288 lines
10 KiB
Markdown
# 采集协议单 · 一键导入标准信息
|
||
|
||
> 日期: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 | 导入前清空可覆盖字段 |
|