5.7 KiB
5.7 KiB
线索管理模块迁移方案 — 05 业务逻辑与特殊场景
原则(第六步):本节为开发门禁文档。未在本节逐条对照 Java 实现前,不得修改
backend/app/crud/crm/clue*.py或新增路由。
1. 定时任务 / 触发器 / 监听器
| 类型 | 线索模块 | 说明 |
|---|---|---|
| MySQL 触发器 | 无 | sx.sql 无 crm_clue 触发器 |
| Quartz / SnailJob | 无 | 无 *Clue*Job |
| Spring 事件监听 | 无 | 转化/跟进均在 Service 同步事务内完成 |
结论:线索无独立后台任务;与 公海池规则定时回收 无关。
2. 线索状态机
new(新线索)
→ follow(跟进中) # 首次新增跟进记录时自动切换
→ invalid(无效) # 手动标记无效
→ converted(已转化) # 转化客户成功
| 规则 | Java 行为(须对齐) |
|---|---|
| 已转化 | is_converted=1,不可再编辑/删除/分配/再转化 |
| 无效 | status=invalid,不可转化 |
| 转化条件 | checkConvertible:至少 1 次跟进、非 invalid、未转化 |
| 删除 | 已转化线索校验不通过则拒绝(deleteWithValidByIds) |
3. 新增线索 insertByBo
- 校验手机号租户内唯一
- 默认
status=new,level=unrated(若未传) - 填充
owner_user_id:未传时取当前登录用户 - 冗余
owner_user_name(UserService 翻译) - 数据权限:列表查询带
@DataPermission(门户用角色数据范围 union)
4. 修改线索 updateByBo
- 已转化不可改
- 改手机号时排除自身查重
- 更新
update_by/update_time
5. 批量分配 assignClues
- 参数:
ids[]、ownerUserId、remark(可选) - 已转化线索跳过或整批失败(以 Java 异常信息为准,实施时读
assignClues源码定稿) - 写
assign_time、assign_by,更新负责人姓名冗余
6. 转化客户 convertToCustomer(事务)
必须在同一事务内:
- 校验
checkConvertible - 创建
crm_customer(字段映射见CrmClueConvertBo+ 客户模块既有逻辑) - 创建主联系人
crm_contact(姓名、手机等从线索带出) - 更新线索:
status=converted、is_converted=1、converted_time、customer_id、converted_by - 客户表回写
clue_id关联来源线索
禁止:只更新线索不建客户,或先 commit 客户后更新线索。
7. 标记无效 markAsInvalid
- 支持批量
ids[]+reason - 已转化不可标记无效
8. 新增跟进 CrmClueFollowServiceImpl.insertByBo(关键)
新增跟进后 级联更新线索(门户 CRUD 必须保持一致):
| 线索字段 | 更新规则 |
|---|---|
last_time |
当前时间 |
follow_count |
+1 |
next_time |
跟进记录的 next_time(若有) |
status |
若当前为 new → 改为 follow |
修改跟进时:若 next_time 变更,同步回写线索 next_time。
删除跟进:是否回减 follow_count —— 以 Java deleteWithValidByIds 为准(实施前读源码)。
9. 列表视图(多 Tab)
| 视图 | Java 方法 | 过滤要点 |
|---|---|---|
| 全部 | queryPageList |
租户 + 数据权限 |
| 我的 | queryMyClues |
owner_user_id = 当前用户 |
| 待跟进 | queryToFollowClues |
next_time <= now 且状态 in (new,follow) |
| 今日新增 | 原 GET /todayNew 或列表加日期条件 |
create_time 当天 |
| 已转化 | 前端筛 status=converted 或 is_converted=1 |
与 Java 筛选项一致 |
门户 API 建议:POST /web/crm/clue/list + viewType 枚举,与现 Python list_clues 对齐。
10. 导入导出
| 能力 | Java | 门户现状 |
|---|---|---|
| 导出 Excel | POST /export,*Vo + @ExcelDictFormat |
✅ POST /web/crm/clue/export,经 CLUE_EXPORT_COLUMNS + export_rows_to_xlsx_response 字典翻译 |
| 导入模板 | POST /importTemplate |
✅ |
| 批量导入 | POST /import + MultipartFile |
✅ |
线索导出字典列(须与列表展示一致):
| 列 | dict_type |
|---|---|
| 客户类型 | crm_customer_type |
| 线索来源 | crm_clue_source |
| 线索等级 | crm_clue_level |
| 线索状态 | crm_clue_status |
| 所属行业 | crm_industry |
| 所在园区 | crm_customer_park |
Java 对照:shanxia/crm/.../vo/CrmClueVo.java。门户列定义:backend/app/utils/crm_export_columns.py → CLUE_EXPORT_COLUMNS。
11. 统计分析(5 接口)
后端五路由已实现;前端统计菜单隐藏(sqxp.ts isHide: true),页面保留供后续启用。
12. 查重 checkDuplicate
- 入参:
mobile、company、excludeId - 返回可能重复的线索列表
- 门户 未实现;表单失焦/保存前可选对接
13. 跨模块依赖
| 依赖 | 说明 |
|---|---|
| 客户模块 | 转化时复用 create customer / create contact |
| 用户下拉 | GET /web/admin/users/options 或 fetchUserList |
| 字典 | useDictStore / dictStore.getOptions('crm_clue_*') |
| 附件 | MinIO;跟进 attachments 逗号分隔 URL |
| 园区 | Java 已废弃 parkAreaList API,改用字典 crm_customer_park |
14. 权限标识(sys_menu)
与公海池/客户一致:crm:clue:list|query|add|edit|remove|export|import|assign|follow|convert|invalid。
v-auth 使用动作短码:add、edit、remove 等(门户 auth.ts)。
15. 开发顺序建议
- 读本节 +
04-api-spec.md - 对照
CrmClueServiceImpl.java逐方法打勾 - 先写/改 CRUD 单测或 Postman 集合
- 再挂
api/crm.py路由 - 最后适配前端(step-03)