|
|
|
|
# 线索实体与字段模型
|
|
|
|
|
|
|
|
|
|
Type: grilling
|
|
|
|
|
Status: resolved
|
|
|
|
|
Blocked by: 04
|
|
|
|
|
<!-- 03 状态机主体已定稿,仅“线索作废”悬置,不影响线索字段模型(作废仅为状态枚举一值),故不再阻塞 -->
|
|
|
|
|
|
|
|
|
|
## Question
|
|
|
|
|
|
|
|
|
|
定义 `crm-lead` 的线索实体字段全集,作为 crm-lead 的地基。字段来源:新增线索表单 + 四视图列表字段 + 线索详情。
|
|
|
|
|
|
|
|
|
|
需在本 ticket 定清:
|
|
|
|
|
|
|
|
|
|
1. **基础字段**:线索名称、联系电话(含校验:手机/座机)、微信(校验)、电子邮箱(校验)、省份、城市、详细地址、渠道(字典)、品牌(字典)、需求产品(字典)、需求场景(字典)、咨询内容、是否加急。
|
|
|
|
|
2. **流转/归属字段**:线索状态(见 ticket 03)、所属公海池(引用 crm-rule 公海池 id)、领取人(`AuthUser.id`)、销售团队/销售部门(冗余还是从领取人推导?)、新增人员、新增时间、超时回收剩余有效期(计算字段还是存储?)。
|
|
|
|
|
3. **反馈相关字段**:反馈情况(有效/无效/未反馈)、反馈内容、最后反馈时间——存最新一条在主表,还是全部在反馈子表由主表冗余最新值?
|
|
|
|
|
4. **关注**:关注是"用户×线索"关联(我的关注列表 + 关注总人数),独立关联表。
|
|
|
|
|
5. **客户相关文件**:线索详情可下载附件——走 crm-file?关联形态。
|
|
|
|
|
6. **必填/校验/字典绑定**:哪些字段绑定哪个字典分组(对齐 crm-dict 的字段-分组绑定约定)。
|
|
|
|
|
7. **哪些字段冗余**:为列表筛选/展示性能,哪些跨模块字段(部门/团队/池名)冗余存储 vs 实时 join。
|
|
|
|
|
|
|
|
|
|
产出:线索实体字段表(名称/类型/必填/字典绑定/来源/冗余策略),写入 ## Answer;术语进 `crm-lead/CONTEXT.md`。依赖 03(状态)、04(公海池 id)。
|
|
|
|
|
|
|
|
|
|
## Decisions(grill 定稿)
|
|
|
|
|
|
|
|
|
|
- **[Q1=a]** 联系电话单字段 `phone` varchar(32),正则同时兼容手机/座机/带区号。
|
|
|
|
|
- **[Q2=c]** 反馈:统一操作日志子表 `lead_history` + 主表冗余最新反馈 5 列(feedback_status/content/time/by/product)。写反馈时事务内插子表 + 更新主表最新值。历史记录 Tab 复用同一张 `lead_history`(含领取/释放/反馈/新增/编辑等所有操作类型)。**⚠ 见 Amendment 2:拆出 `lead_feedback` 独立表(草稿/提交双态)。**
|
|
|
|
|
- **[Q3=a]** 团队/部门/领取人名 快照冗余;`dept_id` 冗余(= 池的 dept_id,因一部门一池永不变);`team_dept_id` 同理。领取/释放时刷新快照。
|
|
|
|
|
- **[Q4=b]** `recycle_deadline` / `expire_deadline` 存字段。
|
|
|
|
|
- 领取时:`recycle_deadline = claim_time + pool.recycle_days`
|
|
|
|
|
- 新增反馈时:重置 `recycle_deadline = now + pool.recycle_days`(反馈重置回收倒计时)
|
|
|
|
|
- `expire_deadline = create_time + pool.expire_days`(永不清零;仅激活时按 03 重置)
|
|
|
|
|
- **pool 配置变更时**:批量 UPDATE 该池所有已领取/跟进中线索的对应截止时刻;本身不当日回收,等次日定时任务扫。
|
|
|
|
|
- **[Q5=a]** 附件走 crm-file;关联表 `lead_attachment(id, lead_id, file_id)`。
|
|
|
|
|
- **[Q6=a]** 关注纯关联表 `lead_follow(id, user_id, lead_id, follow_time)`;`关注总人数` 由 `COUNT(*)` 现算,不主表冗余。
|
|
|
|
|
- **[Q7=ii]** 字典字段(channel/brand/product/scene)存 code varchar(64),跨环境稳定;展示时 JOIN crm-dict 取 label。
|
|
|
|
|
|
|
|
|
|
## Answer
|
|
|
|
|
|
|
|
|
|
### 一、`lead` 主表字段全集
|
|
|
|
|
|
|
|
|
|
| 分组 | 字段 | 类型 | 必填 | 来源/说明 |
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
| 主键 | `id` | bigint | Y | PK |
|
|
|
|
|
| **基础** | `lead_name` | varchar(200) | N | 线索名称 |
|
|
|
|
|
| | `phone` | varchar(32) | N | 单字段兼容手机/座机 |
|
|
|
|
|
| | `wechat` | varchar(64) | N | 微信号(校验) |
|
|
|
|
|
| | `email` | varchar(128) | N | 邮箱(校验) |
|
|
|
|
|
| | `province_region_id` | bigint | Y | sys_region level=1 |
|
|
|
|
|
| | `city_region_id` | bigint | Y | sys_region level=2/3,联动省 |
|
|
|
|
|
| | `address` | varchar(255) | N | 详细地址 |
|
|
|
|
|
| **业务来源** | `channel_code` | varchar(64) | Y | 字典 code(渠道分组) |
|
|
|
|
|
| | `brand_code` | varchar(64) | Y | 字典 code(品牌分组) |
|
|
|
|
|
| | `product_code` | varchar(64) | Y | 字典 code(需求产品分组) |
|
|
|
|
|
| | `scene_code` | varchar(64) | N | 字典 code(需求场景分组) |
|
|
|
|
|
| **核心** | `consult_content` | text | Y | 咨询内容 |
|
|
|
|
|
| | `status` | tinyint | Y | 线索状态(见 03,7 态) |
|
|
|
|
|
| | `is_urgent` | tinyint | Y | 是否加急 0/1,默认 0 |
|
|
|
|
|
| **归属** | `pool_id` | bigint | Y | 公海池外键(crm-rule) |
|
|
|
|
|
| | `pool_name_snapshot` | varchar(100) | Y | 冗余快照,池改名要级联刷 |
|
|
|
|
|
| | `dept_id` | bigint | Y | 冗余 = 池的 dept_id,一部门一池永不变 |
|
|
|
|
|
| | `team_dept_id` | bigint | Y | 冗余 = 池的 team_dept_id |
|
|
|
|
|
| | `owner_user_id` | bigint | N | 领取人;未领取时 NULL |
|
|
|
|
|
| | `owner_name_snapshot` | varchar(64) | N | 领取人姓名冗余 |
|
|
|
|
|
| | `owner_dept_id_snapshot` | bigint | N | 领取时销售所属部门快照(≠ 归属 dept_id,用于审计) |
|
|
|
|
|
| | `create_by` / `create_time` | | Y | BaseEntity, 新增人=销售 |
|
|
|
|
|
| **时效** | `claim_time` | datetime | N | 领取时刻 |
|
|
|
|
|
| | `recycle_deadline` | datetime | N | 回收截止时刻(存字段,索引) |
|
|
|
|
|
| | `expire_deadline` | datetime | Y | 失效截止时刻 = create_time + pool.M |
|
|
|
|
|
| **反馈快照** | `feedback_status` | tinyint | N | 有效/无效/未反馈 |
|
|
|
|
|
| | `feedback_content` | text | N | 最新反馈内容 |
|
|
|
|
|
| | `feedback_time` | datetime | N | 最新反馈时刻 |
|
|
|
|
|
| | `feedback_by_user_id` | bigint | N | 最新反馈人 |
|
|
|
|
|
| | `feedback_product_code` | varchar(64) | N | 最新反馈对应需求产品字典 code |
|
|
|
|
|
| BaseEntity | `update_by/update_time/deleted` | | | 逻辑删除;一律不可物理删(见 03) |
|
|
|
|
|
|
|
|
|
|
**必填项** = 城市、渠道、品牌、需求产品、咨询内容 5 项(含省份是必填但由城市联动导出)。原型明标 `*`。
|
|
|
|
|
|
|
|
|
|
**索引**:
|
|
|
|
|
- `idx_pool_status` (pool_id, status) — 公海视图筛选
|
|
|
|
|
- `idx_owner_status` (owner_user_id, status) — 我的线索
|
|
|
|
|
- `idx_recycle_deadline` (recycle_deadline) — 定时回收 job
|
|
|
|
|
- `idx_expire_deadline` (expire_deadline) — 定时失效 job
|
|
|
|
|
- `idx_dept_status` (dept_id, status) — 部门负责人/管理员视图筛选
|
|
|
|
|
|
|
|
|
|
### 二、关联/子表
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
lead_history -- 统一操作日志(含反馈)
|
|
|
|
|
├─ id, lead_id, op_type, op_time, op_user_id, op_user_dept_name, detail
|
|
|
|
|
├─ op_type: CREATE/CLAIM/RELEASE/FEEDBACK/EDIT/ASSIGN/CONVERT/EXPIRE/RECYCLE/ACTIVATE/...
|
|
|
|
|
└─ FEEDBACK 类的 detail 含: feedback_status/feedback_content/feedback_product_code
|
|
|
|
|
|
|
|
|
|
lead_follow(id, user_id, lead_id, follow_time) -- 关注 M:N
|
|
|
|
|
UNIQUE(user_id, lead_id)
|
|
|
|
|
|
|
|
|
|
lead_attachment(id, lead_id, file_id) -- 客户相关文件, file_id 引用 crm-file
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**关注总人数** 用 `SELECT COUNT(*) FROM lead_follow WHERE lead_id=?` 现算,不入主表冗余。
|
|
|
|
|
|
|
|
|
|
### 三、快照刷新时机
|
|
|
|
|
|
|
|
|
|
| 触发 | 刷新 |
|
|
|
|
|
|---|---|
|
|
|
|
|
| 领取 | `claim_time` `owner_user_id` `owner_name_snapshot` `owner_dept_id_snapshot` `recycle_deadline` |
|
|
|
|
|
| 反馈 | `feedback_*` 5 列 + `recycle_deadline = now + pool.N` |
|
|
|
|
|
| 释放/超时回收 | `owner_*` 清空、`claim_time`/`recycle_deadline` 清空;**反馈 5 列不清空**(grill #5) |
|
|
|
|
|
| 激活(F2) | `expire_deadline = now + pool.M` + **`recycle_deadline = now + pool.N`**(grill #6,N 也重置) |
|
|
|
|
|
| 池改名 | 批量刷 `pool_name_snapshot` |
|
|
|
|
|
| 池 recycle_days 变 | 批量刷该池已领取/跟进中的 `recycle_deadline = claim_time + new_N` |
|
|
|
|
|
| 池 expire_days 变 | 批量刷该池全部非终态的 `expire_deadline = create_time + new_M` |
|
|
|
|
|
|
|
|
|
|
### 四、字段-字典绑定(对齐 crm-dict)
|
|
|
|
|
|
|
|
|
|
| 字段 | 字典分组 code |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `channel_code` | `lead.channel` |
|
|
|
|
|
| `brand_code` | `lead.brand` |
|
|
|
|
|
| `product_code` | `lead.product`(反馈中的 `feedback_product_code` 同 group) |
|
|
|
|
|
| `scene_code` | `lead.scene` |
|
|
|
|
|
|
|
|
|
|
存 code,展示 JOIN crm-dict 取 label。
|
|
|
|
|
|
|
|
|
|
### 五、依赖声明
|
|
|
|
|
|
|
|
|
|
- **crm-auth**:`AuthUser`/`SysDept`(领取人、部门归属、快照)。
|
|
|
|
|
- **crm-rule**:`LeadPool`(外键 + 池名快照)。
|
|
|
|
|
- **crm-dict**:4 个字典分组(channel/brand/product/scene)。
|
|
|
|
|
- **crm-region**(ticket 02=1a 新建):`sys_region` 省市区。
|
|
|
|
|
- **crm-file**:附件文件 id。
|
|
|
|
|
|
|
|
|
|
### 六、CONTEXT 登记
|
|
|
|
|
|
|
|
|
|
- `crm-lead/CONTEXT.md`:线索术语(领取/反馈/释放/关注/加急/回收截止/失效截止)、快照策略、字典绑定、7 状态引用。
|
|
|
|
|
- `CONTEXT-MAP.md` 已有 crm-lead 行,无需新增。
|
|
|
|
|
|
|
|
|
|
### 七、下游影响
|
|
|
|
|
|
|
|
|
|
- **08 转商机 port**:转商机时传的字段集从本表选取(Q 待 08 定)。
|
|
|
|
|
- **05 权限方向**:`dept_id` 作 `@DataScope` 的 dept 列已在 05 定,本表落地。
|
|
|
|
|
- **04 池配置变更**:pool save service 需触发本表批量刷 `recycle_deadline`/`expire_deadline`/`pool_name_snapshot`。
|
|
|
|
|
|
|
|
|
|
## Status
|
|
|
|
|
本 ticket 字段模型已定稿可交付 → resolved。
|
|
|
|
|
|
|
|
|
|
## Amendment(08 追加)—— 省市字段改存 code
|
|
|
|
|
|
|
|
|
|
原 Answer 中 `province_region_id` / `city_region_id`(bigint FK)**修正为存国标 code**:
|
|
|
|
|
|
|
|
|
|
| 原字段 | 修正为 | 说明 |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `province_region_id bigint` | `province_code varchar(12)` | 国标 GB/T 2260 省代码(6位,如 `440000`) |
|
|
|
|
|
| `city_region_id bigint` | `city_code varchar(12)` | 国标 GB/T 2260 市/区代码(如 `440100`广州市 或 `440106`天河区) |
|
|
|
|
|
|
|
|
|
|
**理由**:
|
|
|
|
|
1. 存 code 与 crm-dict 存 code 的既有约定一致(Q7=ii)
|
|
|
|
|
2. 支持前缀 LIKE 祖先查询(`WHERE city_code LIKE '4401%'` 命中广州市本级 + 所有区),无需 JOIN sys_region
|
|
|
|
|
3. code 是国标稳定标识,跨环境/跨系统对齐
|
|
|
|
|
|
|
|
|
|
**依赖**:sys_region 表 `code UNIQUE` 字段(见 02 Amendment)。
|
|
|
|
|
|
|
|
|
|
**其余 06 定稿不变**:字段名、必填标记、其他字段、索引/子表全部保留(相关索引 `idx_dept_status` 等不涉及省市字段无需改)。
|
|
|
|
|
|
|
|
|
|
## Amendment 2(2026-08-12 grill)—— 拆出 `lead_feedback` 独立表 + 快照保留 + 激活重置 N
|
|
|
|
|
|
|
|
|
|
### A2.1 [Q2=c] 改写:拆出 `lead_feedback` 独立表(grill #3)
|
|
|
|
|
|
|
|
|
|
**改前**:反馈直接写 `lead_history` FEEDBACK 记录(detail 含 content),主表冗余最新值。
|
|
|
|
|
|
|
|
|
|
**改后**:拆出独立的 `lead_feedback` 表,支持草稿/提交双态:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
lead_feedback
|
|
|
|
|
├─ id, lead_id, user_id
|
|
|
|
|
├─ feedback_status, content, product_code
|
|
|
|
|
├─ attachment_ids json -- crm-file 文件 id 列表
|
|
|
|
|
├─ record_status tinyint -- 1=DRAFT, 2=SUBMITTED
|
|
|
|
|
├─ created_at, submitted_at
|
|
|
|
|
└─ INDEX(lead_id, user_id, record_status)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- **【保存草稿】**:写/更新 `lead_feedback` 行 `record_status='DRAFT'`,不校验必填,不改状态机,不写 `lead_history`,不刷主表快照。
|
|
|
|
|
- **【保存】(正式提交)**:`lead_feedback` 行 `record_status='SUBMITTED'`,主表更新 5 列快照,状态迁移(已领取→跟进中),N 重置,写 `lead_history` FEEDBACK 记录(detail 引用 `lead_feedback.id`,**不冗余内容**)。
|
|
|
|
|
|
|
|
|
|
**理由**:原型有“保存草稿”按钮,spec 未覆盖;拆表后草稿不污染操作日志,历史 Tab 从 `lead_history` 取,反馈内容从 `lead_feedback` 取。
|
|
|
|
|
|
|
|
|
|
**⚠(C) 已解决**:反馈可上传附件,存 `lead_feedback.attachment_ids`。
|
|
|
|
|
|
|
|
|
|
### A2.2 快照刷新表修正(grill #5 + #6)
|
|
|
|
|
|
|
|
|
|
| 触发 | 原规则 | 修正后 |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| 释放/超时回收 | `owner_*` 清空、`claim_time`/`recycle_deadline` 清空、**反馈 5 列也清空** | `owner_*`、`claim_time`、`recycle_deadline` 清空;**反馈 5 列不清空**(保留供下一位参考) |
|
|
|
|
|
| 激活 | `expire_deadline = now + pool.M` | `expire_deadline = now + pool.M` + `recycle_deadline = now + pool.N`(N 也重置) |
|
|
|
|
|
|
|
|
|
|
### A2.3 池 N 改动刷新修正
|
|
|
|
|
|
|
|
|
|
原快照表“池 recycle_days 变”行写的是 `recycle_deadline = claim_time + new_N`,对已领取和跟进中未区分。
|
|
|
|
|
|
|
|
|
|
**修正**:
|
|
|
|
|
- 已领取:`recycle_deadline = claim_time + new_N`
|
|
|
|
|
- 跟进中:`recycle_deadline = last_feedback_time + new_N`
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Amendment 3(2026-08-13 续 grill)
|
|
|
|
|
|
|
|
|
|
### A3.1 `lead_history` 全量 11 种类型,页面只展示 5 种(G3)
|
|
|
|
|
|
|
|
|
|
`lead_history.type` 为枚举,**全量落库 11 种**:CREATE / CLAIM / ASSIGN / FEEDBACK / CONVERT / RELEASE / RECYCLE / EXPIRE / ACTIVATE / VOID / EDIT。
|
|
|
|
|
|
|
|
|
|
- **写入口径**:11 种动作全部落库,作为管理员审计与纠纷排查的唯一来源。
|
|
|
|
|
- **展示口径**:详情页「历史记录」Tab 只 `WHERE type IN (CLAIM, RELEASE, FEEDBACK, CONVERT, EDIT)` 展示 5 种(领取/释放/反馈/转商机/编辑)。
|
|
|
|
|
- **作废审计**:VOID 记录 detail 保留原持有人 `owner_user_id`(作废清 owner 前留痕);`lead_feedback.user_id`(谁反馈无效)与 `lead_history` 均不受清 owner 影响,无主只是当前归属,历史全程可追溯。
|
|
|
|
|
|
|
|
|
|
详见 PRD §6.10。
|