SpringBoot+XXL-Job 客户公海自动回收设计:双计时规则、锁定豁免、领取上限如何闭环
🌐演示地址:http://ruoyioffice.com | 📦源码1·GitHub:ruoyi-office | 📦源码2·GitCode:ruoyi-office | 📦源码3·Gitee:ruoyi-office | 💬微信:17156169080(备注「RuoYi Office」)
CRM 有公海菜单不等于能盘活客户。真正难的是:按什么规则掉进公海、谁豁免、入池后权限怎么清、领回来计时怎么重新起算、会不会一人囤光池子。本文按 RuoYi Office 源码,把自动回收闭环从配置讲到 XXL-Job,再到领取上限。
▲ 新风格全景(深色双钟):成交超时 / 跟进超时 OR 触发 → Job 入池清权 → 领取重建 OWNER → 上限门禁
引言:公海不是垃圾桶,是「计时 + 清权 + 再分配」
相对《CRM 客户管理》讲建档与跟进全景,本文只钉四个问题:
| 问题 | 系统答法 |
|---|---|
| 何时该掉公海? | 双计时 OR:成交超时或跟进超时 |
| 谁不能掉? | 已锁定、已成交 |
| 掉进去发生什么? | owner=null、联系人联动、删 OWNER 权限 |
| 领出来要注意什么? | 重置ownerTime、重建 OWNER、校验领取上限 |
一、配置:公海开关与双计时
公海配置表核心字段:
| 字段 | 含义 |
|---|---|
enabled | 是否启用自动入池 |
dealExpireDays | 未成交放入公海天数(自ownerTime) |
contactExpireDays | 未跟进放入公海天数 |
notifyEnabled/notifyDays | 是否提前提醒及天数 |
▲ 系统配置里维护双超时与提醒;未启用则 Job 直接返回 0
计时基准是ownerTime(成为负责人的时间),不是客户创建时间——领取/分配后重新起算,避免「刚领就被规则误伤」。
二、候选查询:双钟 OR + 豁免
CrmCustomerMapper.selectListByAutoPool:
query.gt(CrmCustomerDO::getOwnerUserId,0);// 仍有负责人query.eq(lockStatus,false).eq(dealStatus,false);// 未锁定 + 未成交query.and(q->{// 成交超时:ownerTime < now - dealExpireDaysq.lt(ownerTime,dealExpireTime)// 或 跟进超时:ownerTime 超时 且 (末次跟进超时 或 为空).or(w->w.lt(ownerTime,contactExpireTime).and(p->p.lt(contactLastTime,contactExpireTime).or().isNull(contactLastTime)));});读法:
- 成交钟:挂名很久仍未成交 → 回收
- 跟进钟:归属超时且很久没跟(或从未跟)→ 回收
- 两钟OR:满足任一即可入候选
- 锁定 / 成交 → 整单豁免,保护重点客户与已赢单
三、Job:定时入池,失败不拖死整批
@XxlJob("customerAutoPutPoolJob")@TenantJobpublicStringexecute(){intcount=customerService.autoPutCustomerPool();returnString.format("掉入公海客户 %s 个",count);}autoPutCustomerPool:配置未启用则 0;否则逐个putCustomerPool,单条异常只打日志,继续处理其余——避免一个脏数据卡死全租户回收。
putCustomerPool三件事:
1. updateOwnerUserId(id, null) // 客户无负责人 2. contact.ownerUserId = null // 联系人联动(与领取对称) 3. deletePermission(CUSTOMER, OWNER) // 清数据权限,别人才能从公海看见/领取注意:删权限放在联系人更新之后,否则可能因客户权限已空导致联系人操作失败。
▲ 入池后的公海列表:无负责人客户在此待领取/分配
▲ 对照:仍有负责人的客户在「我的客户」;ownerTime 是公海计时起点
四、领取 / 分配:重建 OWNER 与上限
receiveCustomer(ids, ownerUserId, isReceive):
- 校验客户存在、目标用户存在
- 校验当前无负责人、未锁定、成交状态允许
validateCustomerExceedOwnerLimit——防止一人把公海囤光- 批量写
ownerUserId+ownerTime = now - 批量创建
CrmPermissionLevelEnum.OWNER - 操作日志区分「自行领取」与「管理员分配」
updateCustomers.add(newCrmCustomerDO().setId(id).setOwnerUserId(ownerUserId).setOwnerTime(LocalDateTime.now()));createPermissions.add(...OWNER...);▲ 领取/拥有上限与公海回收配套:回收释放资源,上限防止再被垄断
五、和客户总览文的边界
| 文 | 重心 |
|---|---|
| 客户管理一体化 | 建档、跟进、权限、公海「是什么」 |
| 本文 | 自动怎么掉、权限怎么清、领取怎么起算、上限怎么卡 |
线索转客户、商机回款链不在此展开。
六、推荐体验路径
在线演示:http://ruoyioffice.com/web/(账号admin/admin123)
- 打开客户公海配置,确认双超时与启用开关。
- 看公海客户列表与我的客户对照。
- 打开客户限制配置,理解领取上限。
- (运维)在任务平台查看
customerAutoPutPoolJob执行记录。
源码仓库:GitHub | GitCode | Gitee
常见问题(FAQ)
刚领取会不会马上又掉进公海?
领取会重置ownerTime。只要跟进/成交在超时天数内发生,就不会立刻再满足候选条件。
为什么要清 OWNER 权限而不只是改 ownerUserId?
CRM 列表常靠数据权限过滤;只改字段不清权限,会出现「名上没人、权限仍在」或「别人领不到」的脏状态。
锁定客户谁来决定?
业务上对重点客户点锁定;自动 Job 直接lockStatus=false才入选,保护战略客户。
没有 XXL-Job 能跑吗?
Job 注解挂在 XXL-Job;也可用等价定时调度调同一autoPutCustomerPool()方法,业务逻辑在 Service。
结语
公海自动回收的本质是双计时规则 + 豁免 + 清权入池 + 领取重建计时 + 上限防囤。配好看天数只是第一步;权限与ownerTime对称处理,池子才真能转起来。
你们公海是手工扔,还是已经按跟进天数自动掉?有没有遇过「掉了公海但别人仍看不到」?欢迎评论区交流。
💡想要体验 RuoYi Office 的强大功能?
🌐在线演示:http://ruoyioffice.com/web/(账号 admin / admin123)
📦源码仓库:GitHub | GitCode | Gitee
💬技术咨询:添加微信17156169080,备注「RuoYi Office」
⭐如果觉得不错,请给个 Star 支持一下!