# 线索管理模块 - API接口文档 > **模块**: 01-线索管理 > **版本**: v1.0 > **日期**: 2025-10-03 > **关联文档**: > - 需求文档: `docs/01-线索管理模块需求.md` > - 原型图: `yuanxing/01-线索管理原型图.md` > - 数据库: `sql/crm/01-crm_clue.sql` --- ## 📋 目录 - [1. 线索管理接口](#1-线索管理接口) - [2. 线索跟进记录接口](#2-线索跟进记录接口) - [3. 线索转化接口](#3-线索转化接口) - [4. 统计分析接口](#4-统计分析接口) - [5. 数据模型](#5-数据模型) --- ## 1. 线索管理接口 ### 1.1 查询线索列表(分页) **接口地址**: `GET /crm/clue/list` **接口描述**: 分页查询线索列表,支持多条件筛选和视图切换 **权限标识**: `crm:clue:list` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | | clueName | String | 否 | 线索姓名(模糊查询) | | mobile | String | 否 | 手机号(模糊查询) | | company | String | 否 | 公司名称(模糊查询) | | source | String | 否 | 线索来源:website/phone/exhibition/activity/referral/ads/social_media/other | | level | String | 否 | 线索等级:A/B/C/unrated | | status | String | 否 | 线索状态:new/follow/invalid/converted | | industry | String | 否 | 所属行业 | | province | String | 否 | 省份 | | city | String | 否 | 城市 | | ownerUserId | Long | 否 | 负责人ID | | budget | String | 否 | 预算范围 | | isConverted | Boolean | 否 | 是否已转化:0-否 1-是 | | beginTime | String | 否 | 开始时间 yyyy-MM-dd HH:mm:ss | | endTime | String | 否 | 结束时间 yyyy-MM-dd HH:mm:ss | | lastTimeBegin | String | 否 | 最后跟进开始时间 | | lastTimeEnd | String | 否 | 最后跟进结束时间 | | nextTimeBegin | String | 否 | 下次联系开始时间 | | nextTimeEnd | String | 否 | 下次联系结束时间 | **返回示例**: ```json { "code": 200, "msg": "查询成功", "rows": [ { "id": 1, "clueName": "张伟", "mobile": "13900001234", "company": "华为技术有限公司", "telephone": "0571-12345678", "email": "zhangwei@huawei.com", "title": "先生", "position": "技术总监", "source": "website", "level": "A", "industry": "互联网/IT", "province": "浙江省", "city": "杭州市", "district": "西湖区", "address": "文三路XXX号", "website": "https://www.huawei.com", "intentProducts": "CRM系统,ERP系统", "expectTime": "2025-03-01", "budget": "100k_500k", "requirement": "需要一套完整的企业管理系统", "status": "follow", "ownerUserId": 1, "ownerUserName": "张三", "lastTime": "2025-01-02 10:30:00", "nextTime": "2025-01-05 14:00:00", "followCount": 3, "isConverted": 0, "createTime": "2025-01-01 09:00:00", "createBy": 1, "remark": "" } ], "total": 156 } ``` --- ### 1.2 查询线索详情 **接口地址**: `GET /crm/clue/{id}` **接口描述**: 根据ID查询线索详细信息 **权限标识**: `crm:clue:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 线索ID | **返回示例**: ```json { "code": 200, "msg": "操作成功", "data": { "id": 1, "clueName": "张伟", "mobile": "13900001234", "company": "华为技术有限公司", "telephone": "0571-12345678", "email": "zhangwei@huawei.com", "title": "先生", "position": "技术总监", "source": "website", "level": "A", "industry": "互联网/IT", "province": "浙江省", "city": "杭州市", "district": "西湖区", "address": "文三路XXX号", "website": "https://www.huawei.com", "intentProducts": "CRM系统,ERP系统", "expectTime": "2025-03-01", "budget": "100k_500k", "requirement": "需要一套完整的企业管理系统", "status": "follow", "ownerUserId": 1, "ownerUserName": "张三", "lastTime": "2025-01-02 10:30:00", "nextTime": "2025-01-05 14:00:00", "followCount": 3, "isConverted": 0, "convertedTime": null, "customerId": null, "convertedBy": null, "assignTime": "2025-01-01 09:30:00", "assignBy": 1, "createTime": "2025-01-01 09:00:00", "createBy": 1, "updateTime": "2025-01-02 10:30:00", "updateBy": 1, "remark": "" } } ``` --- ### 1.3 新增线索 **接口地址**: `POST /crm/clue` **接口描述**: 新增线索信息 **权限标识**: `crm:clue:add` **请求体**: ```json { "clueName": "张伟", "mobile": "13900001234", "company": "华为技术有限公司", "telephone": "0571-12345678", "email": "zhangwei@huawei.com", "title": "先生", "position": "技术总监", "source": "website", "level": "A", "industry": "互联网/IT", "province": "浙江省", "city": "杭州市", "district": "西湖区", "address": "文三路XXX号", "website": "https://www.huawei.com", "intentProducts": "CRM系统,ERP系统", "expectTime": "2025-03-01", "budget": "100k_500k", "requirement": "需要一套完整的企业管理系统", "ownerUserId": 1, "nextTime": "2025-01-05 14:00:00", "remark": "" } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clueName | String | 是 | 线索姓名,最大100字符 | | mobile | String | 是 | 手机号,11位,需唯一校验 | | source | String | 是 | 线索来源 | | company | String | 否 | 公司名称,最大200字符 | | telephone | String | 否 | 固定电话,最大30字符 | | email | String | 否 | 邮箱,最大100字符 | | title | String | 否 | 称呼:先生/女士/其他 | | position | String | 否 | 职位,最大50字符 | | level | String | 否 | 线索等级:A/B/C/unrated,默认unrated | | industry | String | 否 | 所属行业,最大50字符 | | province | String | 否 | 省份,最大50字符 | | city | String | 否 | 城市,最大50字符 | | district | String | 否 | 区县,最大50字符 | | address | String | 否 | 详细地址,最大255字符 | | website | String | 否 | 客户网站,最大500字符 | | intentProducts | String | 否 | 意向产品,多个用逗号分隔 | | expectTime | String | 否 | 预计购买时间,格式yyyy-MM-dd | | budget | String | 否 | 预算范围 | | requirement | String | 否 | 需求描述,文本类型 | | ownerUserId | Long | 否 | 负责人ID,默认为当前用户 | | nextTime | String | 否 | 下次联系时间 yyyy-MM-dd HH:mm:ss | | remark | String | 否 | 备注,最大500字符 | **校验规则**: - 手机号必须为11位数字 - 手机号在同一租户下必须唯一 - 邮箱需符合邮箱格式 - 负责人ID必须存在 **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 1.4 修改线索 **接口地址**: `PUT /crm/clue` **接口描述**: 修改线索信息 **权限标识**: `crm:clue:edit` **请求体**: 同新增接口,但需要传入id **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 1.5 删除线索 **接口地址**: `DELETE /crm/clue/{ids}` **接口描述**: 删除线索(支持批量) **权限标识**: `crm:clue:remove` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 线索ID数组,多个用逗号分隔 | **业务规则**: - 已转化的线索不允许删除 - 删除线索时同时删除关联的跟进记录 **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 1.6 批量分配线索 **接口地址**: `PUT /crm/clue/assign` **接口描述**: 批量分配线索给指定负责人 **权限标识**: `crm:clue:assign` **请求体**: ```json { "ids": [1, 2, 3], "ownerUserId": 5, "remark": "分配原因" } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 线索ID数组 | | ownerUserId | Long | 是 | 新负责人ID | | remark | String | 否 | 分配说明 | **业务规则**: - 只能分配未转化的线索 - 记录分配时间和分配人 **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 1.7 修改线索状态 **接口地址**: `PUT /crm/clue/status` **接口描述**: 修改线索状态(批量标记为无效等) **权限标识**: `crm:clue:edit` **请求体**: ```json { "ids": [1, 2, 3], "status": "invalid", "remark": "客户无购买意向" } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 线索ID数组 | | status | String | 是 | 新状态:new/follow/invalid | | remark | String | 否 | 状态变更说明 | **业务规则**: - 已转化的线索不允许修改状态 **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 1.8 修改线索等级 **接口地址**: `PUT /crm/clue/level` **接口描述**: 修改线索等级 **权限标识**: `crm:clue:edit` **请求体**: ```json { "id": 1, "level": "A", "remark": "客户预算充足,意向强烈" } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 线索ID | | level | String | 是 | 线索等级:A/B/C/unrated | | remark | String | 否 | 等级评定说明 | **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 1.9 导出线索 **接口地址**: `POST /crm/clue/export` **接口描述**: 导出线索数据到Excel **权限标识**: `crm:clue:export` **请求体**: 查询参数同1.1列表查询接口 **返回**: Excel文件流 --- ### 1.10 导入线索 **接口地址**: `POST /crm/clue/import` **接口描述**: 批量导入线索数据 **权限标识**: `crm:clue:import` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | file | MultipartFile | 是 | Excel文件 | | updateSupport | Boolean | 否 | 是否更新已存在的线索,默认false | **返回示例**: ```json { "code": 200, "msg": "操作成功", "data": { "total": 100, "success": 95, "fail": 5, "errors": [ { "row": 3, "error": "手机号已存在" }, { "row": 7, "error": "手机号格式错误" } ] } } ``` --- ### 1.11 下载导入模板 **接口地址**: `POST /crm/clue/importTemplate` **接口描述**: 下载线索导入Excel模板 **权限标识**: `crm:clue:import` **请求参数**: 无 **返回**: Excel文件流 --- ### 1.12 查询待跟进线索 **接口地址**: `GET /crm/clue/toFollow` **接口描述**: 查询需要跟进的线索列表(下次联系时间已到) **权限标识**: `crm:clue:list` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | | ownerUserId | Long | 否 | 负责人ID,默认查询当前用户 | **返回示例**: ```json { "code": 200, "msg": "查询成功", "rows": [ { "id": 1, "clueName": "张伟", "mobile": "13900001234", "company": "华为技术有限公司", "level": "A", "status": "follow", "nextTime": "2025-01-03 10:00:00", "lastTime": "2025-01-01 14:00:00", "followCount": 2 } ], "total": 15 } ``` --- ### 1.13 查询我的线索 **接口地址**: `GET /crm/clue/mine` **接口描述**: 查询当前用户负责的线索列表 **权限标识**: `crm:clue:list` **请求参数**: 同1.1列表查询接口 **返回示例**: 同1.1列表查询接口 --- ## 2. 线索跟进记录接口 ### 2.1 查询跟进记录列表 **接口地址**: `GET /crm/clue/follow/list` **接口描述**: 查询指定线索的跟进记录列表 **权限标识**: `crm:clue:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clueId | Long | 是 | 线索ID | | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | **返回示例**: ```json { "code": 200, "msg": "查询成功", "rows": [ { "id": 1, "clueId": 1, "clueName": "张伟", "followType": "phone", "followContent": "电话沟通了客户需求,客户对CRM系统很感兴趣,希望能够演示一下产品功能", "nextTime": "2025-01-05 14:00:00", "attachments": "/upload/2025/01/file1.pdf,/upload/2025/01/file2.jpg", "createBy": 1, "createByName": "张三", "createTime": "2025-01-03 10:30:00", "remark": "" } ], "total": 5 } ``` --- ### 2.2 新增跟进记录 **接口地址**: `POST /crm/clue/follow` **接口描述**: 新增线索跟进记录 **权限标识**: `crm:clue:follow` **请求体**: ```json { "clueId": 1, "followType": "phone", "followContent": "电话沟通了客户需求,客户对CRM系统很感兴趣", "nextTime": "2025-01-05 14:00:00", "attachments": "/upload/2025/01/file1.pdf", "remark": "" } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clueId | Long | 是 | 线索ID | | followType | String | 是 | 跟进方式:phone/wechat/email/visit/other | | followContent | String | 是 | 跟进内容,文本类型 | | nextTime | String | 否 | 下次联系时间 yyyy-MM-dd HH:mm:ss | | attachments | String | 否 | 附件路径,多个用逗号分隔 | | remark | String | 否 | 备注,最大500字符 | **业务规则**: - 新增跟进记录后,自动更新线索的lastTime和followCount - 如果设置了nextTime,同步更新线索的nextTime - 如果线索状态为new,自动更新为follow **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 2.3 修改跟进记录 **接口地址**: `PUT /crm/clue/follow` **接口描述**: 修改跟进记录信息 **权限标识**: `crm:clue:follow` **请求体**: ```json { "id": 1, "followType": "phone", "followContent": "电话沟通了客户需求,客户对CRM系统很感兴趣", "nextTime": "2025-01-05 14:00:00", "attachments": "/upload/2025/01/file1.pdf", "remark": "" } ``` **业务规则**: - 只能修改自己创建的跟进记录 - 修改nextTime时同步更新线索的nextTime **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 2.4 删除跟进记录 **接口地址**: `DELETE /crm/clue/follow/{ids}` **接口描述**: 删除跟进记录(支持批量) **权限标识**: `crm:clue:follow` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 跟进记录ID数组 | **业务规则**: - 只能删除自己创建的跟进记录 - 删除后需要重新计算线索的followCount **返回示例**: ```json { "code": 200, "msg": "操作成功" } ``` --- ### 2.5 查询跟进记录详情 **接口地址**: `GET /crm/clue/follow/{id}` **接口描述**: 根据ID查询跟进记录详情 **权限标识**: `crm:clue:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 跟进记录ID | **返回示例**: ```json { "code": 200, "msg": "操作成功", "data": { "id": 1, "clueId": 1, "clueName": "张伟", "followType": "phone", "followContent": "电话沟通了客户需求,客户对CRM系统很感兴趣", "nextTime": "2025-01-05 14:00:00", "attachments": "/upload/2025/01/file1.pdf", "createBy": 1, "createByName": "张三", "createTime": "2025-01-03 10:30:00", "remark": "" } } ``` --- ## 3. 线索转化接口 ### 3.1 转化为客户 **接口地址**: `POST /crm/clue/convert` **接口描述**: 将线索转化为客户 **权限标识**: `crm:clue:convert` **请求体**: ```json { "clueId": 1, "createCustomer": true, "createContact": true, "customerName": "华为技术有限公司", "contactName": "张伟", "remark": "线索转化备注" } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clueId | Long | 是 | 线索ID | | createCustomer | Boolean | 是 | 是否创建客户 | | createContact | Boolean | 是 | 是否创建联系人 | | customerName | String | 否 | 客户名称(如果创建客户) | | contactName | String | 否 | 联系人姓名(如果创建联系人) | | remark | String | 否 | 转化说明 | **业务规则**: - 只能转化未转化的线索 - 转化后线索状态变为converted,isConverted=1 - 记录转化时间、转化人、客户ID - 根据线索信息自动创建客户和/或联系人 - 线索的跟进记录可关联到客户 **返回示例**: ```json { "code": 200, "msg": "操作成功", "data": { "customerId": 10, "contactId": 20 } } ``` --- ### 3.2 校验是否可转化 **接口地址**: `GET /crm/clue/checkConvert/{id}` **接口描述**: 校验线索是否可以转化 **权限标识**: `crm:clue:query` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 线索ID | **返回示例**: ```json { "code": 200, "msg": "操作成功", "data": { "canConvert": true, "reason": "", "existCustomer": false, "existContact": false } } ``` --- ## 4. 统计分析接口 ### 4.1 线索统计概览 **接口地址**: `GET /crm/clue/statistics/overview` **接口描述**: 获取线索统计概览数据 **权限标识**: `crm:clue:list` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ownerUserId | Long | 否 | 负责人ID,不传则查询当前用户 | | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 | **返回示例**: ```json { "code": 200, "msg": "查询成功", "data": { "totalCount": 156, "newCount": 23, "followCount": 98, "invalidCount": 15, "convertedCount": 20, "weekAddCount": 23, "toFollowCount": 15, "weekConvertCount": 8, "convertRate": 12.82, "avgFollowCount": 3.5 } } ``` --- ### 4.2 线索来源统计 **接口地址**: `GET /crm/clue/statistics/source` **接口描述**: 按线索来源统计数量和转化率 **权限标识**: `crm:clue:list` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 | **返回示例**: ```json { "code": 200, "msg": "查询成功", "data": [ { "source": "website", "sourceName": "网站留言", "count": 45, "convertedCount": 12, "convertRate": 26.67 }, { "source": "phone", "sourceName": "电话咨询", "count": 32, "convertedCount": 8, "convertRate": 25.00 } ] } ``` --- ### 4.3 线索等级分布 **接口地址**: `GET /crm/clue/statistics/level` **接口描述**: 按线索等级统计分布情况 **权限标识**: `crm:clue:list` **请求参数**: 无 **返回示例**: ```json { "code": 200, "msg": "查询成功", "data": [ { "level": "A", "levelName": "A级(高)", "count": 35, "percent": 22.44 }, { "level": "B", "levelName": "B级(中)", "count": 58, "percent": 37.18 }, { "level": "C", "levelName": "C级(低)", "count": 43, "percent": 27.56 }, { "level": "unrated", "levelName": "未评级", "count": 20, "percent": 12.82 } ] } ``` --- ### 4.4 线索转化趋势 **接口地址**: `GET /crm/clue/statistics/trend` **接口描述**: 查询线索新增和转化趋势(按天/周/月) **权限标识**: `crm:clue:list` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | type | String | 否 | 统计类型:day/week/month,默认day | | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 | **返回示例**: ```json { "code": 200, "msg": "查询成功", "data": [ { "date": "2025-01-01", "addCount": 12, "convertCount": 3 }, { "date": "2025-01-02", "addCount": 8, "convertCount": 2 } ] } ``` --- ### 4.5 负责人线索统计 **接口地址**: `GET /crm/clue/statistics/owner` **接口描述**: 按负责人统计线索数量和转化情况 **权限标识**: `crm:clue:list` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 | **返回示例**: ```json { "code": 200, "msg": "查询成功", "data": [ { "ownerUserId": 1, "ownerUserName": "张三", "totalCount": 45, "newCount": 12, "followCount": 25, "convertedCount": 8, "convertRate": 17.78, "avgFollowCount": 3.2 } ] } ``` --- ## 5. 数据模型 ### 5.1 ClueBo(线索业务对象) ```java public class CrmClueBo extends BaseEntity { /** 主键ID */ @NotNull(message = "主键不能为空", groups = { EditGroup.class }) private Long id; /** 线索姓名 */ @NotBlank(message = "线索姓名不能为空", groups = { AddGroup.class, EditGroup.class }) private String clueName; /** 手机号 */ @NotBlank(message = "手机号不能为空", groups = { AddGroup.class, EditGroup.class }) @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误") private String mobile; /** 公司名称 */ private String company; /** 固定电话 */ private String telephone; /** 邮箱 */ @Email(message = "邮箱格式错误") private String email; /** 称呼 */ private String title; /** 职位 */ private String position; /** 线索来源 */ @NotBlank(message = "线索来源不能为空", groups = { AddGroup.class, EditGroup.class }) private String source; /** 线索等级 */ private String level; /** 所属行业 */ private String industry; /** 省 */ private String province; /** 市 */ private String city; /** 区 */ private String district; /** 详细地址 */ private String address; /** 客户网站 */ private String website; /** 意向产品 */ private String intentProducts; /** 预计购买时间 */ private String expectTime; /** 预算范围 */ private String budget; /** 需求描述 */ private String requirement; /** 线索状态 */ private String status; /** 负责人ID */ private Long ownerUserId; /** 下次联系时间 */ private LocalDateTime nextTime; /** 备注 */ private String remark; } ``` --- ### 5.2 ClueVo(线索视图对象) ```java public class CrmClueVo implements Serializable { /** 主键ID */ @ExcelProperty(value = "ID") private Long id; /** 线索姓名 */ @ExcelProperty(value = "线索姓名") private String clueName; /** 手机号 */ @ExcelProperty(value = "手机号") private String mobile; /** 公司名称 */ @ExcelProperty(value = "公司名称") private String company; /** 固定电话 */ @ExcelProperty(value = "固定电话") private String telephone; /** 邮箱 */ @ExcelProperty(value = "邮箱") private String email; /** 称呼 */ @ExcelProperty(value = "称呼", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "crm_title") private String title; /** 职位 */ @ExcelProperty(value = "职位") private String position; /** 线索来源 */ @ExcelProperty(value = "线索来源", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "crm_clue_source") private String source; /** 线索等级 */ @ExcelProperty(value = "线索等级", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "crm_clue_level") private String level; /** 所属行业 */ @ExcelProperty(value = "所属行业") private String industry; /** 省 */ @ExcelProperty(value = "省") private String province; /** 市 */ @ExcelProperty(value = "市") private String city; /** 区 */ @ExcelProperty(value = "区") private String district; /** 详细地址 */ @ExcelProperty(value = "详细地址") private String address; /** 客户网站 */ @ExcelProperty(value = "客户网站") private String website; /** 意向产品 */ @ExcelProperty(value = "意向产品") private String intentProducts; /** 预计购买时间 */ @ExcelProperty(value = "预计购买时间") private String expectTime; /** 预算范围 */ @ExcelProperty(value = "预算范围", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "crm_budget") private String budget; /** 需求描述 */ private String requirement; /** 线索状态 */ @ExcelProperty(value = "线索状态", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "crm_clue_status") private String status; /** 负责人ID */ private Long ownerUserId; /** 负责人姓名 */ @ExcelProperty(value = "负责人") private String ownerUserName; /** 最后跟进时间 */ @ExcelProperty(value = "最后跟进时间") private LocalDateTime lastTime; /** 下次联系时间 */ @ExcelProperty(value = "下次联系时间") private LocalDateTime nextTime; /** 跟进次数 */ @ExcelProperty(value = "跟进次数") private Integer followCount; /** 是否已转化 */ private Integer isConverted; /** 转化时间 */ @ExcelProperty(value = "转化时间") private LocalDateTime convertedTime; /** 客户ID */ private Long customerId; /** 转化操作人 */ private Long convertedBy; /** 分配时间 */ private LocalDateTime assignTime; /** 分配人 */ private Long assignBy; /** 创建时间 */ @ExcelProperty(value = "创建时间") private LocalDateTime createTime; /** 更新时间 */ @ExcelProperty(value = "更新时间") private LocalDateTime updateTime; /** 备注 */ @ExcelProperty(value = "备注") private String remark; } ``` --- ### 5.3 ClueFollowBo(跟进记录业务对象) ```java public class CrmClueFollowBo extends BaseEntity { /** 主键ID */ @NotNull(message = "主键不能为空", groups = { EditGroup.class }) private Long id; /** 线索ID */ @NotNull(message = "线索ID不能为空", groups = { AddGroup.class }) private Long clueId; /** 跟进方式 */ @NotBlank(message = "跟进方式不能为空", groups = { AddGroup.class, EditGroup.class }) private String followType; /** 跟进内容 */ @NotBlank(message = "跟进内容不能为空", groups = { AddGroup.class, EditGroup.class }) private String followContent; /** 下次联系时间 */ private LocalDateTime nextTime; /** 附件 */ private String attachments; /** 备注 */ private String remark; } ``` --- ### 5.4 ClueFollowVo(跟进记录视图对象) ```java public class CrmClueFollowVo implements Serializable { /** 主键ID */ private Long id; /** 线索ID */ private Long clueId; /** 线索姓名 */ private String clueName; /** 跟进方式 */ @ExcelProperty(value = "跟进方式", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "crm_follow_type") private String followType; /** 跟进内容 */ @ExcelProperty(value = "跟进内容") private String followContent; /** 下次联系时间 */ @ExcelProperty(value = "下次联系时间") private LocalDateTime nextTime; /** 附件 */ private String attachments; /** 跟进人ID */ private Long createBy; /** 跟进人姓名 */ @ExcelProperty(value = "跟进人") private String createByName; /** 跟进时间 */ @ExcelProperty(value = "跟进时间") private LocalDateTime createTime; /** 备注 */ @ExcelProperty(value = "备注") private String remark; } ``` --- ## 6. 数据字典 ### 6.1 线索来源 (crm_clue_source) | 字典值 | 字典标签 | 说明 | |--------|---------|------| | website | 网站留言 | 官网表单提交 | | phone | 电话咨询 | 主动来电咨询 | | exhibition | 展会 | 展会获取 | | activity | 市场活动 | 线下活动 | | referral | 老客户推荐 | 客户推荐 | | ads | 广告投放 | 广告渠道 | | social_media | 社交媒体 | 微信、微博等 | | other | 其他 | 其他渠道 | --- ### 6.2 线索等级 (crm_clue_level) | 字典值 | 字典标签 | 说明 | |--------|---------|------| | A | A级(高) | 高意向线索 | | B | B级(中) | 中意向线索 | | C | C级(低) | 低意向线索 | | unrated | 未评级 | 尚未评级 | --- ### 6.3 线索状态 (crm_clue_status) | 字典值 | 字典标签 | 说明 | |--------|---------|------| | new | 新线索 | 刚创建的线索 | | follow | 跟进中 | 正在跟进 | | invalid | 无效 | 无效线索 | | converted | 已转化 | 已转化为客户 | --- ### 6.4 预算范围 (crm_budget) | 字典值 | 字典标签 | 说明 | |--------|---------|------| | below_10k | 1万以下 | 预算1万以下 | | 10k_50k | 1-5万 | 预算1-5万 | | 50k_100k | 5-10万 | 预算5-10万 | | 100k_500k | 10-50万 | 预算10-50万 | | above_500k | 50万以上 | 预算50万以上 | | unknown | 未知 | 预算未知 | --- ### 6.5 跟进方式 (crm_follow_type) | 字典值 | 字典标签 | 说明 | |--------|---------|------| | phone | 电话 | 电话沟通 | | wechat | 微信 | 微信沟通 | | email | 邮件 | 邮件沟通 | | visit | 拜访 | 上门拜访 | | other | 其他 | 其他方式 | --- ## 7. 权限标识汇总 | 权限标识 | 说明 | |---------|------| | crm:clue:list | 线索列表查询 | | crm:clue:query | 线索详情查询 | | crm:clue:add | 线索新增 | | crm:clue:edit | 线索修改 | | crm:clue:remove | 线索删除 | | crm:clue:export | 线索导出 | | crm:clue:import | 线索导入 | | crm:clue:assign | 线索分配 | | crm:clue:follow | 添加跟进记录 | | crm:clue:convert | 线索转化 | --- ## 8. 注意事项 1. **手机号唯一性**: 同一租户下手机号必须唯一 2. **数据权限**: 需要根据负责人字段实现数据权限控制 3. **跟进记录关联**: 新增跟进记录时自动更新线索的跟进统计信息 4. **状态自动变更**: 首次跟进时自动将状态从new变更为follow 5. **转化限制**: 已转化的线索不允许删除和修改关键信息 6. **附件存储**: 附件路径存储相对路径,多个用逗号分隔 7. **时间提醒**: nextTime字段用于生成待办任务和提醒 8. **数据脱敏**: 手机号和邮箱需要根据权限进行脱敏显示 9. **批量操作**: 批量操作需要注意事务一致性 10. **删除关联**: 删除线索时需要同时删除关联的跟进记录 --- **文档结束**