|
|
# 产品规则:邮件指令识别与拆分(锁定口径)
|
|
|
|
|
|
> **地位**:本页为指令「怎么认、怎么拆、谁可确认」的**产品真源**之一。
|
|
|
> **实现真源**:`src/services/parse/instruction-lexicon.ts`、`split-instructions.ts`、`classify.ts`。
|
|
|
> **约束**:解析链路**禁止**依赖 LLM / Cursor 临场理解;改规则先改本页 + 词表 + 单测。
|
|
|
> **日期**:2026-08-03
|
|
|
|
|
|
---
|
|
|
|
|
|
## 0. 一句话
|
|
|
|
|
|
主题与正文**都重要、要分开用**;一封多轮邮件里**只有最新一轮指令可确认**;标准四类走业务表单,非标准/软词走「客户指令」;同线程后续回复按**新 UID**再拉,不重做旧信。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 1. 信号源(三者并列,来源可区分)
|
|
|
|
|
|
| 信号源 | 用途 | UI 来源标签 |
|
|
|
|--------|------|-------------|
|
|
|
| **主题** | 柜号/提单/ETA/「新增预报」「DO请查收」等;可单独成指令单元 | 来自主题 |
|
|
|
| **正文** | 按时间轮/转发标签拆段;决定「当前可确认」 | 来自当前正文 / 来自历史引用 |
|
|
|
| **附件名** | 补 DO / 贴标清单等;**不能**仅凭正文「DO也同步上传」造空上传 DO | 来自附件名 |
|
|
|
|
|
|
冲突原则:
|
|
|
|
|
|
1. 正文**最新段**已是硬工单(换标/覆盖贴/贴标/拍照/拦截等)→ **压过**主题链路上历史「新增预报」。
|
|
|
2. **同线程主题未变**(仅 Re:/Fw: 前缀变化)时:后续轮次**只认该时段正文**,不得再用首封主题「新增预报」造当前/补缺预报卡;QQ 转发壳剥壳后的主题残片也不算指令。
|
|
|
3. 主题有、正文完全无指令时 → 才可用主题补缺(只读或非当前)。
|
|
|
4. 正文已覆盖同类型 → 主题**不再重复**出一张一样的卡。
|
|
|
5. 正文写「DO 也同步上传」但本封**无真实 DO 附件** → **不出**空的上传 DO 指令。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 2. 标准四类业务 ↔ UI
|
|
|
|
|
|
| UI kind | 典型关键词(见词表) | 确认动作 |
|
|
|
|---------|----------------------|----------|
|
|
|
| `forecast` | 新增预报、请查收新增预报 | 预报表单(人工确认) |
|
|
|
| `forecast` | 柜号+派送单,请查收(首票卡派清单) | 预报表单(只读历史) |
|
|
|
| `transfer` | 新增转仓、转仓(「不转仓」除外) | 详情先展示转仓表单;**确认时**再查 CC 到仓闸门,不可转则自动降级工单 |
|
|
|
| `transfer` 截图 | 正文仅「新增转仓请留意」+ 内嵌 JPG 表格 | 对每张截图 OCR → 解析「地址仓→仓库重定向」;按时间轮与附件顺序一一对应展示 |
|
|
|
| `work_order` | 贴标/换标/覆盖贴/操作指令、拍照、**指令性**拦截、快递单号;mail1 仅柜号+预约码 | 客户留言 SaveForm(人工确认) |
|
|
|
| `do_upload` | DO请查收;或真实 `*DO*.pdf` 等 | 上传 DO(人工确认) |
|
|
|
|
|
|
主流程四类均需人工确认,**不**因主题残留「新增预报」自动再写 CC。
|
|
|
|
|
|
> **渠道件数 ≠ 整票指令**:主题里的 `拦截-209件` / `FedEx-29件` 只是渠道汇总;整票真实指令以「拆柜清单更新 / 派送要求」为准。禁止把渠道名写成备注「邮件动作:拦截」。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 3. 客户指令(非标准 / 软词)
|
|
|
|
|
|
下列**不**硬套工单表单,归 `customer_instruction`(只读展示轮次/正文):
|
|
|
|
|
|
- 更新派送单
|
|
|
- 改自提 / 改为仓库自提 / 仓库自提
|
|
|
- 拆柜清单 / 卡转海 / 派送要求
|
|
|
- 按照正常预报接受、帮忙安排派单、安排派单
|
|
|
- 继续暂存 / 暂存等后续
|
|
|
- 有实质内容但无法归入标准四类的段落
|
|
|
|
|
|
---
|
|
|
|
|
|
## 4. 多轮线程拆分与「仅最新可确认」
|
|
|
|
|
|
### 4.1 如何切开
|
|
|
|
|
|
正文按下列边界切段(保留分隔标签到后一段,便于取时间/发件人):
|
|
|
|
|
|
- `在 yyyy-mm-dd … 写道` / `On … wrote:`
|
|
|
- `原始邮件` / `转发的邮件` / `Original Message` / `Original:`
|
|
|
- 发件人+发送时间 等邮件头块
|
|
|
|
|
|
**不用**单独的 `Dear` 作为切段点(避免同轮内误切)。
|
|
|
|
|
|
### 4.2 可确认范围
|
|
|
|
|
|
| 段 | `isCurrent` | 操作 |
|
|
|
|----|-------------|------|
|
|
|
| 最新一条有实质指令的段 | `true` | 可确认提交 |
|
|
|
| 更早的引用轮次(标准四类) | `false` | 只读(如历史预报) |
|
|
|
| 更早的软词「客户指令」 | `false` | **独立时间轮要出卡**:按正常预报接受 / 仓库「好的」 / 无法接收;仅丢掉无时间轮的「更新派送单」噪声 |
|
|
|
| 纯主题补缺单元 | 一般为 `false` | 只读展示线索 |
|
|
|
|
|
|
同轮内允许多种 UI 并存(例如当前换标 + 历史预报只读)。
|
|
|
`work_order_actions` 仅含「转仓」、或正文已拆出转仓/预报等标准单元时,**不得**再补一张工单卡。
|
|
|
|
|
|
历史引用若正文指令相同(同线程连转同一份「拦截 + 改自提」等,仅抄送折行不同)→ **只保留最新一条**,禁止出 2/3/4 张一样的工单卡。
|
|
|
工单备注须列出本段全部动作:硬词(拦截/贴标)与软词(改自提)并存时都写入「邮件动作」,不得只留拦截。
|
|
|
|
|
|
### 4.3 跳过 vs 仍展示的轮次
|
|
|
|
|
|
- **跳过(不出卡)**:QQ 转发壳、`发自我的iPhone`、空的 `Original:`、主题残片
|
|
|
- **仍按时间轮出卡(只读、不可确认)**:仓库 ACK「好的 / 收到」;「无法接收 / 产能有限」;「按照正常预报接受 / 安排派单」
|
|
|
- **同轮内 `====` 分组**(如换标 334 件两段 FBA)**不切开**,仍是这一轮一条工单
|
|
|
|
|
|
---
|
|
|
|
|
|
## 5. 同线程后续指令(拉取幂等)
|
|
|
|
|
|
| 情况 | 行为 |
|
|
|
|------|------|
|
|
|
| 客户在同主题下**新回复**(新 IMAP UID) | **会拉**:新邮件入库、重新拆段;仅最新段可确认 |
|
|
|
| 已入库的旧 UID | **不再拉**(`knownUids` / messageId / rawHash 幂等) |
|
|
|
| 超出 `IMAP_LOOKBACK_DAYS`(默认 3 天)的过旧回复 | 可能拉不到 |
|
|
|
| 新回复未过过滤规则 | 记拉取日志为跳过,不进业务列表 |
|
|
|
|
|
|
旧邮件保持原状态;**不会**因新回复自动把旧预报/旧工单再执行一遍。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 6. 柜头 / 预报相关(与指令并存)
|
|
|
|
|
|
- **提拆派**:预报时 `F_OperationType=0` 表示提拆派服务包,**不是**三个独立管理端「提柜/拆柜/派送」界面。
|
|
|
- **mail1 类**(仅柜号+预约码、无标准关键词):`classify` → `WORK_ORDER`;详情用 `work_order_actions` 补当前工单单元(见 `extractMailInstructions({ workOrderActions })`)。
|
|
|
- 模板表尾「注意:…」是填写说明,**不是**货件行。
|
|
|
- **预报未映射标签进备注**:主题/正文 `+` 分段里,已有 `名称:值` 前缀但对不上预报 UI 的字段(如 `封号:EMCEJJ0635`)写入 `F_MemoRemark`,**不得**当作客户名与 `YWZD` 一类短码竞争。
|
|
|
- 卡派清单列:附件有则填;UI **隐藏整列皆空**的 FormOrder 列,避免满屏「-」。
|
|
|
- 工单留言内容:取当前指令段,并从 `Dear` / `原箱号` 起,去掉转发头;**禁止**用整封线程正文盖住分段留言。
|
|
|
- **附件 ↔ 指令段(全邮件通用,禁止按单封特判)**:业务附件挂到**本段**表单(工单 `F_AttachFile` / 出库 `F_LabelFile`),按优先级:
|
|
|
1. **主键交叉**:附件名与本段正文/主题抽出同一业务主键则挂本段。主键:`FBA…`、原箱号 `YT…`、FNSKU `X0…`、唛头 `WL…`。**不用 ISO 柜号**分发工单附件(避免历史换标/拦截卡误挂当前文件)。
|
|
|
2. **文件名原文**:正文/主题出现该附件主文件名(去扩展名、去 `(1)` 副本后缀)→ 挂本段。
|
|
|
3. **角色兜底(仅当前可确认段)**:附件名无主键,但含 `卡转海` / `换标|覆盖贴|操作指令|贴标交付`,且本段也有对应角色词 → 挂当前段。历史只读段不用角色兜底。
|
|
|
4. **DO 文件**只进上传 DO 卡,不进工单附件。
|
|
|
5. **卡派资料/装箱清单 xlsx**是预报/转仓解析源,不进工单附件,除非规则 2 正文点名该文件。
|
|
|
6. 跳过 `*邮箱.pdf` / QQ 截图。一封多轮时每段独立匹配,**不得**把整封附件列表复制到每一张卡。
|
|
|
- **贴标指令单 ≠ 卡派预报行**:`lineage.template=label-instruction` 时,货件行只服务工单/出库核对;**新增预报**货件列表必须为空,不得把换标行(仓码当 Address、无体积毛重)当成 SaveContainer 预报展示。预报柜号优先主题/正文,不以贴标单内其它柜号覆盖。
|
|
|
- **同封多表格**:同时有卡派/提拆派 xlsx 与换标指令 xlsx 时,解析**优先卡派预报表**生成 `shipments`;换标文件仍作附件挂工单。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 7. 实现与测试对照表
|
|
|
|
|
|
| 规则 | 代码 | 单测(示例) |
|
|
|
|------|------|----------------|
|
|
|
| 词表 / 软硬分流 | `instruction-lexicon.ts` | `mail4-time-rounds.test.ts` |
|
|
|
| 拆段 / 最新可确认 / 主题补缺 | `split-instructions.ts` | `split-instructions.test.ts`、`mail4-time-rounds` |
|
|
|
| 正文硬工单压过主题预报 | `classify.ts` | `classify.test.ts`、`instruction-product-rules` |
|
|
|
| 线程拆单(Message 级) | `thread.ts` + poller | `thread.test.ts` |
|
|
|
| UID 幂等拉取 | `poller.ts` `knownUids` | 集成/烟雾 |
|
|
|
| 空 DO 不出指令 | `split-instructions` + `do-upload-extract` | `mail4-time-rounds`、`do-upload-extract` |
|
|
|
| 工单留言清洗 | `CcWorkOrderForm` `extractWorkOrderMessageBody` | `four-business.test.ts` |
|
|
|
| 附件↔指令段 | `match-segment-attachments.ts` | `match-segment-attachments.test.ts`、`four-business.test.ts` |
|
|
|
|
|
|
改口径流程:**改本页 → 改词表/拆分 → 改/补单测 → `pnpm test` 相关文件通过**。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 8. 与旧文档关系
|
|
|
|
|
|
- `docx/需求规格-邮件自动预报-v0.2.md` §4 类型打分仍有效;**本页补充**「拆分 / 客户指令 / 主题正文分工 / 仅最新确认」。
|
|
|
- 若与旧表述冲突,**以本页 + 上述实现文件为准**,并回写需求规格对应章节。
|
|
|
- Cursor 对话纪要**不是**运行时真源。
|