feat: 完成CRM商机和线索管理模块开发

## 新增功能

### 商机中心 (/opportunity)
- Stats统计卡片(商机总数、金额、赢单、转化率)
- Pipeline商机管道(阶段Tab:全部/线索/谈判中/方案/赢单)
- 商机列表真实数据渲染(来自crm_opportunity表)
- 商机卡片详情(经销商、负责人、金额、概率)
- Pipeline计数实时更新

### 线索中心 (/lead)
- 线索列表完整功能(CRUD)
- 线索详情Drawer(基础信息 + 跟进记录Timeline)
- 新建线索(含ERP客户关联、手机号验证)
- 添加跟进记录(跟进方式、内容、下次时间)
- 分配负责人(用户选择器,显示真实姓名)
- 线索转经销商(自动创建商机)
- 删除线索(逻辑删除)

## 后端开发

### 数据库表
- crm_lead(线索表)
- crm_lead_follow(线索跟进记录表)
- crm_dealer(经销商表)
- crm_opportunity(商机表)
- crm_opportunity_follow(商机跟进记录表)
- 数据字典初始化

### API接口
- 线索管理:CRUD、详情、跟进、分配、转化
- 商机管理:列表查询
- 用户选择器:员工门户专用API

### 核心功能
- 线索转化自动创建经销商和商机
- 负责人翻译显示真实姓名(修复)
- 手机号前后端双重格式验证(修复)

## 前端开发

### 页面架构改进
- 商机中心:保留原CRM设计风格(Stats + Pipeline)
- 线索中心:独立页面(完整线索管理)
- 左侧菜单:独立菜单项(商机中心、线索中心)

### API模块
- src/api/crm/:线索和商机API类型定义和调用方法
- src/api/user/:用户选择器API

### 样式设计
- 商机中心:100%保持原CRM Pipeline设计风格
- 使用CSS变量系统(var(--radius-lg), var(--shadow-sm)等)
- Pipeline Tab白色圆角设计
- 商机卡片阴影和hover效果
- 头像堆叠显示

## 配置修改

- Gateway路由:添加CRM模块路由配置
- Gateway路由:添加system模块路由配置
- Aside菜单:拆分商机中心和线索中心

## Bug修复

- 修复负责人显示手机号问题(UserNameTranslationImpl返回昵称)
- 修复手机号格式验证缺失(前后端双重验证)
- 修复商机管道设计风格不一致(完整复制原CRM样式)

## 文档

- CRM销售模块详细设计说明书V3.md
- CRM线索转化API契约
- CRM线索转化开发计划
- CRM线索转化测试指引
- CRM线索管理测试指引
- CRM商机管理测试指引
- CRM架构改进报告
- CRM Bug修复报告

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
大壮
2026-05-20 09:46:59 +00:00
parent 6ad14b07dc
commit 3f643ef31f
59 changed files with 11876 additions and 18 deletions

View File

@@ -0,0 +1,262 @@
# CRM线索中心模块开发完成总结
## 开发日期
2026-05-19
## 项目信息
- **服务归属**: hzhub-system (端口 8083)
- **包路径**: org.hzhub.crm
- **技术栈**: Spring Boot 3.5.8 + MyBatis-Plus + Sa-Token
---
## 一、创建的文件列表
### 1. 数据库设计
- `/data/hzhub/hzhub-system/src/main/resources/db/crm_lead_init.sql`
- 数据字典定义5个字典类型
- crm_lead 表(线索表)
- crm_lead_follow 表(跟进记录表)
### 2. Entity 实体类
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/domain/CrmLead.java`
- 继承 TenantEntity
- 包含 customerCode 字段ERP客户编码
- 使用 @TableLogic 逻辑删除
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/domain/CrmLeadFollow.java`
- 继承 TenantEntity
### 3. Bo 业务对象
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/domain/bo/CrmLeadBo.java`
- 继承 BaseEntity
- 使用 @AutoMapper 注解
- 包含 customerCode 字段
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/domain/bo/CrmLeadFollowBo.java`
### 4. Vo 视图对象
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/domain/vo/CrmLeadVo.java`
- 使用 @Translation 字段翻译
- mobile 字段使用 @Sensitive 脱敏
- 包含 customerCode 字段
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/domain/vo/CrmLeadFollowVo.java`
### 5. Mapper 接口
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/mapper/CrmLeadMapper.java`
- 继承 BaseMapperPlus
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/mapper/CrmLeadFollowMapper.java`
### 6. Mapper XML 映射文件
- `/data/hzhub/hzhub-system/src/main/resources/mapper/crm/CrmLeadMapper.xml`
- `/data/hzhub/hzhub-system/src/main/resources/mapper/crm/CrmLeadFollowMapper.xml`
### 7. Service 接口与实现
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/service/ICrmLeadService.java`
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/service/ICrmLeadFollowService.java`
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/service/impl/CrmLeadServiceImpl.java`
- 实现列表查询、详情、新增、编辑、删除、分配、跟进记录查询、添加跟进
- **关键逻辑**: 如果提供 customerCode调用 ERP 服务拉取客户信息
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/service/impl/CrmLeadFollowServiceImpl.java`
### 8. ERP 集成类
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/service/ErpIntegrationService.java`
- 封装对 hzhub-erp 的调用
- 使用 RestTemplate 调用 http://localhost:8082/erp/dynamic/v1/customer/detail
### 9. Controller 控制器
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/controller/CrmLeadController.java`
- 遵循 API 契约接口定义
-@SaCheckPermission 注解(员工门户权限由 Gateway 控制)
- 使用 @Log@RepeatSubmit 注解
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/crm/controller/CrmLeadFollowController.java`
### 10. 配置类
- `/data/hzhub/hzhub-system/src/main/java/org/hzhub/system/config/RestTemplateConfig.java`
- 配置 RestTemplate Bean
- `/data/hzhub/hzhub-system/src/main/resources/application.yml`
- 添加 ERP 配置: erp.base-url
---
## 二、数据库表结构摘要
### crm_lead线索表
主要字段:
- **lead_id**: 主键ASSIGN_ID
- **customer_code**: ERP客户编码varchar(100),可选)
- **company_name**: 公司名称(必填)
- **contact_name**: 联系人(必填)
- **mobile**: 手机号(必填)
- **region_id**: 区域ID关联 sys_dept
- **source_type**: 来源类型字典crm_lead_source
- **intent_level**: AI意向等级字典crm_intent_level
- **ai_score**: AI评分decimal(5,2)
- **risk_level**: 风险等级字典crm_risk_level
- **owner_user_id**: 负责人(关联 sys_user
- **lead_status**: 状态字典crm_lead_status
- **del_flag**: 删除标志(逻辑删除)
继承 TenantEntity 字段:
- tenant_id, create_dept, create_by, create_time, update_by, update_time
索引:
- idx_tenant_id, idx_customer_code, idx_mobile, idx_owner_user_id, idx_lead_status, idx_create_time
### crm_lead_follow跟进记录表
主要字段:
- **follow_id**: 主键
- **lead_id**: 线索ID必填
- **follow_type**: 跟进方式字典crm_follow_type
- **content**: 跟进内容(必填)
- **ai_summary**: AI摘要
- **next_follow_time**: 下次跟进时间
- **follow_user_id**: 跟进人(关联 sys_user
- **del_flag**: 删除标志
---
## 三、主要实现的接口功能
### 1. 线索列表查询 (GET /crm/lead/list)
- 支持多条件筛选公司名称模糊、手机号、意向等级、负责人、customerCode等
- 使用 TableDataInfo 分页返回
- mobile 字段自动脱敏
- 字典字段自动翻译
### 2. 线索详情查询 (GET /crm/lead/{leadId})
- 返回线索详细信息
- 字段自动翻译(负责人姓名、区域名称、字典值等)
### 3. 新增线索 (POST /crm/lead)
- **关键逻辑**: 如果提供 customerCode自动从 ERP 拉取客户信息填充
- 校验手机号唯一性
- 使用 @RepeatSubmit 防重复提交
- 记录操作日志
### 4. 编辑线索 (PUT /crm/lead)
- 校验线索存在性
- 校验手机号唯一性
- 记录操作日志
### 5. 删除线索 (DELETE /crm/lead/{leadIds})
- 支持批量删除(逻辑删除)
- 记录操作日志
### 6. 分配线索 (PUT /crm/lead/assign)
- 更新 owner_user_id
- 自动更新状态为 "following"
### 7. 获取跟进记录列表 (GET /crm/lead/follow/{leadId})
- 根据线索ID查询跟进记录
- 按创建时间倒序
### 8. 添加跟进记录 (POST /crm/lead/follow)
- 自动设置跟进人为当前用户
- 如果提供下次跟进时间,更新线索的 nextFollowTime
- 记录操作日志
---
## 四、ERP集成的实现方式
### 实现方式
使用 `RestTemplate` 调用 hzhub-erp 服务
### 配置
- **配置项**: `erp.base-url` (默认: http://localhost:8082)
- **配置类**: `RestTemplateConfig` (提供 RestTemplate Bean)
### 调用逻辑
```java
// CrmLeadServiceImpl.insertLead() 方法
if (StringUtils.isNotBlank(lead.getCustomerCode())) {
// 调用 ERP 服务拉取客户详情
Map<String, Object> customerDetail = erpIntegrationService
.getCustomerDetail(lead.getCustomerCode());
// 自动填充线索基础信息
if (customerDetail != null) {
lead.setCompanyName((String) customerDetail.get("customerName"));
lead.setContactName((String) customerDetail.get("contactName"));
lead.setMobile((String) customerDetail.get("phone"));
// ... 其他字段
}
}
```
### ERP接口
- `GET /erp/dynamic/v1/customer/detail?customerCode={code}`
- 返回客户信息Map形式
---
## 五、需要注意的配置项
### 1. 数据字典类型(需在数据库初始化)
- **crm_lead_source**: 线索来源activity/referral/website/exhibition/wecom/erp/other
- **crm_lead_status**: 线索状态new/following/converted/invalid
- **crm_intent_level**: AI意向等级high/medium/low
- **crm_risk_level**: 风险等级high/medium/low
- **crm_follow_type**: 跟进方式phone/wecom/visit/email/other
### 2. ERP配置application.yml
```yaml
erp:
base-url: ${ERP_BASE_URL:http://localhost:8082}
```
可通过环境变量 `ERP_BASE_URL` 配置 ERP 服务地址。
### 3. SQL初始化顺序
执行 `/data/hzhub/hzhub-system/src/main/resources/db/crm_lead_init.sql`
1. 先创建数据字典sys_dict_type, sys_dict_data
2. 再创建业务表crm_lead, crm_lead_follow
### 4. Gateway路由配置
需在 `hzhub-gateway/src/main/resources/application.yml` 中添加:
```yaml
spring:
cloud:
gateway:
routes:
- id: hzhub-crm
uri: lb://hzhub-system
predicates:
- Path=/crm/**
filters:
- StripPrefix=1
```
---
## 六、后续待实现功能(第二阶段)
### 1. AI意向分析
- 调用 hzhub-ai 服务(`/ai/analyze/intent`
- 自动生成 aiScore、intentLevel
### 2. AI跟进摘要生成
- 调用 hzhub-ai 服务(`/ai/summarize`
- 自动生成 aiSummary
### 3. 线索转经销商 (POST /crm/lead/convert)
- 创建 crm_dealer 数据
- 迁移历史跟进记录
- 更新线索状态为 "converted"
---
## 七、关键特性总结
1. **多租户支持**: 所有实体类继承 TenantEntity自动租户隔离
2. **ERP关联**: customerCode 字段关联 ERP 客户,自动拉取信息
3. **字段翻译**: 使用 @Translation 注解自动翻译字典值、用户名、部门名
4. **敏感字段脱敏**: mobile 字段列表查询时自动脱敏
5. **逻辑删除**: 使用 @TableLogic,删除时不物理删除
6. **员工门户适配**: 无 Sa-Token 权限注解,权限由 Gateway 控制
7. **防重复提交**: 新增操作使用 @RepeatSubmit
8. **操作日志**: 新增、编辑、删除使用 @Log 记录
---
## 开发完成
所有代码已创建完毕,可进行编译测试。

View File

@@ -0,0 +1,939 @@
# CRM销售自动化渠道版执行级详细设计说明书
# 1. 文档说明
## 1.1 文档目标
本文档用于指导CRM销售自动化渠道版系统的
- 数据库设计
- 后端接口开发
- 前端页面开发
- AI能力集成
- 企业微信集成
- 自动化流程配置
- 权限与组织体系建设
本文档属于“开发执行版设计文档”。
---
# 2. 系统总体架构
## 2.1 技术架构建议
| 层级 | 技术建议 |
|---|---|
| 前端Web | Vue3 + Element Plus |
| 移动端 | 企业微信H5 + UniApp |
| 后端 | Java Spring Boot |
| 数据库 | MySQL 8 |
| 缓存 | Redis |
| 消息队列 | RabbitMQ |
| 搜索 | Elasticsearch |
| AI服务 | Python FastAPI |
| 文件存储 | MinIO |
| 工作流 | Flowable |
| BI | FineBI / Superset |
---
# 3. 数据库设计规范
## 3.1 通用字段规范
所有业务表统一包含:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| created_by | bigint | 创建人 |
| created_at | datetime | 创建时间 |
| updated_by | bigint | 更新人 |
| updated_at | datetime | 更新时间 |
| deleted | tinyint | 逻辑删除 |
| tenant_id | bigint | 租户ID |
---
# 4. 线索中心模块设计
# 4.1 模块目标
用于管理潜在经销商。
支持:
- 多渠道线索接入
- AI意向识别
- AI风险分析
- 自动分配销售
- 商机转化
---
# 4.2 数据表设计
## 4.2.1 leads线索表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| company_name | varchar(200) | 公司名称 |
| contact_name | varchar(100) | 联系人 |
| mobile | varchar(50) | 手机号 |
| wechat | varchar(100) | 微信号 |
| province | varchar(50) | 省 |
| city | varchar(50) | 市 |
| region_id | bigint | 区域ID |
| source_type | varchar(50) | 来源类型 |
| activity_name | varchar(100) | 活动名称 |
| referrer_name | varchar(100) | 推荐人 |
| industry | varchar(100) | 行业 |
| company_scale | varchar(100) | 公司规模 |
| store_count | int | 门店数 |
| intent_level | varchar(20) | AI意向等级 |
| ai_score | decimal(5,2) | AI评分 |
| risk_level | varchar(20) | 风险等级 |
| owner_user_id | bigint | 负责人 |
| lead_status | varchar(50) | 状态 |
| converted_dealer_id | bigint | 转化经销商ID |
---
## 4.2.2 lead_follow_records线索跟进记录
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| lead_id | bigint | 线索ID |
| follow_type | varchar(50) | 跟进方式 |
| content | text | 跟进内容 |
| ai_summary | text | AI摘要 |
| next_follow_time | datetime | 下次跟进时间 |
| follow_user_id | bigint | 跟进人 |
---
# 4.3 接口设计
## 4.3.1 创建线索
### API
POST /api/leads
### 请求参数
```json
{
"companyName":"XX贸易有限公司",
"contactName":"张三",
"mobile":"13800000000",
"wechat":"zhangsan",
"province":"广东省",
"city":"深圳市",
"industry":"食品",
"storeCount":20
}
```
### 业务逻辑
1. 校验手机号是否重复
2. 调用AI服务分析意向等级
3. 自动生成AI评分
4. 根据区域规则分配销售
5. 创建自动跟进任务
---
## 4.3.2 线索转经销商
POST /api/leads/convert
### 逻辑
1. 创建dealer数据
2. 迁移历史跟进记录
3. 创建初始商机
4. 更新线索状态
---
# 4.4 页面原型说明
## 4.4.1 线索列表页
### 页面布局
```text
-------------------------------------------------
顶部:搜索栏 + 高级筛选
-------------------------------------------------
左侧:区域树
右侧:线索列表
-------------------------------------------------
底部:分页
```
### 筛选项
- 区域
- 来源
- AI意向等级
- 风险等级
- 销售负责人
- 创建时间
### 表格字段
| 字段 |
|---|
| 公司名称 |
| 联系人 |
| 手机 |
| 区域 |
| AI评分 |
| 意向等级 |
| 风险等级 |
| 当前负责人 |
| 跟进状态 |
| 下次跟进时间 |
### 操作按钮
- 查看
- 分配
- 跟进
- 转经销商
- 作废
---
## 4.4.2 AI分析侧边栏
右侧固定展示:
- AI意向评分
- AI风险提示
- 推荐动作
- 推荐销售话术
- 推荐拜访时间
---
# 5. 经销商中心模块设计
# 5.1 数据表设计
## 5.1.1 dealers经销商表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| dealer_name | varchar(200) | 经销商名称 |
| dealer_code | varchar(100) | 编码 |
| contact_name | varchar(100) | 联系人 |
| mobile | varchar(50) | 手机 |
| province | varchar(50) | 省 |
| city | varchar(50) | 市 |
| level | varchar(50) | 等级 |
| lifecycle | varchar(50) | 生命周期 |
| signed_at | datetime | 签约时间 |
| store_count | int | 门店数 |
| team_size | int | 团队规模 |
| total_order_amount | decimal(18,2) | 累计订单金额 |
| total_payment_amount | decimal(18,2) | 累计回款金额 |
| activity_score | decimal(5,2) | 活跃评分 |
| risk_score | decimal(5,2) | 风险评分 |
| owner_user_id | bigint | 负责人 |
---
## 5.1.2 dealer_tags经销商标签表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| dealer_id | bigint | 经销商ID |
| tag_name | varchar(100) | 标签名称 |
| tag_type | varchar(50) | 标签类型 |
| score | decimal(5,2) | 标签评分 |
---
# 5.2 接口设计
## 5.2.1 获取经销商画像
GET /api/dealers/{id}/profile
### 返回内容
```json
{
"dealerName":"XX贸易",
"activityLevel":"高活跃",
"riskLevel":"低风险",
"growthTrend":"高增长",
"lastVisitTime":"2026-05-10",
"nextVisitTime":"2026-05-20"
}
```
---
# 5.3 页面设计
## 5.3.1 经销商详情页
### 页面布局
```text
顶部:基础信息卡片
-------------------------------------------------
Tab页
1. 基础档案
2. 商机
3. 拜访记录
4. 订单
5. 回款
6. AI画像
7. 会话记录
-------------------------------------------------
右侧AI经营分析面板
```
### AI经营分析面板
显示:
- 活跃度趋势
- 近90天订单趋势
- 流失风险
- 推荐动作
- 竞品风险
---
# 6. 拜访管理模块设计
# 6.1 数据表设计
## 6.1.1 visit_plans拜访计划表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| dealer_id | bigint | 经销商ID |
| visit_type | varchar(50) | 拜访类型 |
| planned_time | datetime | 计划时间 |
| visit_user_id | bigint | 销售人员 |
| status | varchar(50) | 状态 |
---
## 6.1.2 visit_records拜访记录表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| dealer_id | bigint | 经销商ID |
| visit_plan_id | bigint | 拜访计划ID |
| visit_time | datetime | 拜访时间 |
| participants | varchar(500) | 参与人员 |
| voice_file_url | varchar(500) | 录音文件 |
| ai_summary | text | AI摘要 |
| ai_requirements | text | AI提取需求 |
| ai_risk | text | AI风险 |
| next_action | text | 下一步动作 |
| latitude | decimal(10,6) | 纬度 |
| longitude | decimal(10,6) | 经度 |
| sign_photo_url | varchar(500) | 签到照片 |
---
# 6.2 AI语音处理流程
```text
语音上传
-> ASR语音识别
-> NLP结构化提取
-> AI摘要生成
-> 风险分析
-> 推荐下一步动作
-> 写入CRM
```
---
# 6.3 页面设计
## 6.3.1 移动端拜访页面
### 页面模块
- 地图签到
- 语音录入按钮
- 拍照上传
- AI实时摘要
- 下一步动作建议
### AI辅助区域
自动生成:
- 客户关注点
- 异议问题
- 竞品信息
- 推荐招商话术
---
# 7. 商机管理模块设计
# 7.1 数据表设计
## 7.1.1 opportunities商机表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| dealer_id | bigint | 经销商ID |
| opportunity_name | varchar(200) | 商机名称 |
| stage | varchar(50) | 商机阶段 |
| estimated_amount | decimal(18,2) | 预计金额 |
| success_rate | decimal(5,2) | 成交概率 |
| expected_sign_date | date | 预计签约时间 |
| owner_user_id | bigint | 销售负责人 |
| ai_next_stage | varchar(50) | AI建议阶段 |
| ai_probability | decimal(5,2) | AI成交预测 |
---
## 7.1.2 opportunity_stage_logs阶段日志表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| opportunity_id | bigint | 商机ID |
| old_stage | varchar(50) | 原阶段 |
| new_stage | varchar(50) | 新阶段 |
| change_reason | text | 变更原因 |
| changed_by | bigint | 变更人 |
---
# 7.2 商机阶段规则
| 阶段 | 条件 |
|---|---|
| 初步接触 | 创建商机 |
| 需求沟通 | 已记录需求 |
| 招商政策沟通 | 已发送政策 |
| 样品测试 | 已寄样 |
| 商务谈判 | 已讨论返点 |
| 签约中 | 已提交合同 |
| 已签约 | 合同生效 |
---
# 7.3 AI自动推进逻辑
## 规则示例
```text
如果AI识别
- 已询价
- 已谈返点
- 已谈库存
则自动建议推进至“商务谈判”阶段。
```
---
# 7.4 页面设计
## 7.4.1 商机看板页
### 视图模式
- Kanban阶段看板
- 列表模式
- 销售漏斗模式
### 看板列
```text
初步接触
需求沟通
招商政策沟通
样品测试
商务谈判
签约中
已签约
```
### 卡片展示
- 经销商名称
- 金额
- AI成交概率
- 最近跟进时间
- 风险提示
---
# 8. 合同管理模块设计
# 8.1 数据表设计
## 8.1.1 contracts合同表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| contract_no | varchar(100) | 合同编号 |
| dealer_id | bigint | 经销商ID |
| opportunity_id | bigint | 商机ID |
| contract_amount | decimal(18,2) | 合同金额 |
| sign_date | date | 签约日期 |
| expire_date | date | 到期日期 |
| contract_status | varchar(50) | 状态 |
| approval_status | varchar(50) | 审批状态 |
| sign_file_url | varchar(500) | 合同文件 |
| ai_risk_summary | text | AI风险摘要 |
---
# 8.2 AI合同分析
AI识别
- 高风险条款
- 超标准返点
- 区域冲突
- 超长账期
---
# 8.3 审批流设计
```text
销售提交
-> 区域经理审批
-> 财务审批
-> 法务审批
-> 总部审批
-> 电子签章
```
---
# 9. 订单管理模块设计
# 9.1 数据表设计
## 9.1.1 orders订单表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| order_no | varchar(100) | 订单编号 |
| dealer_id | bigint | 经销商ID |
| contract_id | bigint | 合同ID |
| order_amount | decimal(18,2) | 订单金额 |
| order_status | varchar(50) | 订单状态 |
| shipment_status | varchar(50) | 发货状态 |
| payment_status | varchar(50) | 回款状态 |
| logistics_status | varchar(50) | 物流状态 |
| erp_sync_status | varchar(50) | ERP同步状态 |
---
# 9.2 ERP同步逻辑
## 同步内容
- 订单
- 发货
- 库存
- 回款
- 物流
## 同步方式
- 定时拉取
- Webhook回调
- MQ异步同步
---
# 9.3 页面设计
## 9.3.1 订单中心
### 页面布局
```text
顶部:订单筛选
-------------------------------------------------
中部:订单表格
-------------------------------------------------
右侧:订单风险分析
```
### 风险分析
- 延迟发货风险
- 超账期风险
- 异常退货风险
---
# 10. 回款管理模块设计
# 10.1 数据表设计
## 10.1.1 payments回款表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| dealer_id | bigint | 经销商ID |
| order_id | bigint | 订单ID |
| payment_amount | decimal(18,2) | 回款金额 |
| payment_date | date | 回款日期 |
| receivable_due_date | date | 应收截止日 |
| overdue_days | int | 超期天数 |
| payment_status | varchar(50) | 状态 |
---
# 10.2 AI预警规则
| 条件 | 预警 |
|---|---|
| 超过30天未回款 | 高风险 |
| 连续2次延迟 | 中风险 |
| 回款金额下降 | 流失风险 |
---
# 11. 企业微信协同模块设计
# 11.1 集成能力
## 企业微信侧边栏
展示:
- 经销商画像
- 最近订单
- 最近拜访
- 商机阶段
- AI风险
---
## 会话存档同步
同步内容:
- 文本
- 图片
- 文件
- 语音
---
# 11.2 数据表设计
## 11.2.1 wecom_chat_records企业微信会话表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| external_user_id | varchar(100) | 外部联系人 |
| dealer_id | bigint | 经销商ID |
| sender_id | bigint | 发送人 |
| message_type | varchar(50) | 消息类型 |
| message_content | text | 内容 |
| send_time | datetime | 发送时间 |
| ai_analysis_result | text | AI分析结果 |
---
# 11.3 AI会话分析
识别:
- 采购意向
- 价格异议
- 投诉风险
- 竞品信息
---
# 12. AI分析中心设计
# 12.1 AI标签体系
| 标签类型 | 示例 |
|---|---|
| 活跃标签 | 高频沟通 |
| 风险标签 | 流失风险 |
| 经营标签 | 高增长 |
| 敏感标签 | 价格敏感 |
---
# 12.2 AI预测模型
| 模型 | 输入 |
|---|---|
| 成交预测 | 商机数据 |
| 回款预测 | 订单与历史回款 |
| 流失预测 | 活跃度与订单 |
| 补货预测 | 销量趋势 |
---
# 13. 自动化工作流设计
# 13.1 自动提醒规则
| 规则 | 动作 |
|---|---|
| 7天未跟进 | 创建跟进提醒 |
| 30天未下单 | 创建经营风险提醒 |
| 合同即将到期 | 通知销售与经理 |
| 回款超期 | 通知财务与销售 |
---
# 13.2 自动任务规则
| 条件 | 自动任务 |
|---|---|
| 高意向线索 | 自动创建拜访 |
| 商机推进 | 自动创建回访 |
| 合同签约 | 自动创建首单跟进 |
---
# 14. BI分析设计
# 14.1 BI指标体系
## 销售指标
- 销售额
- 回款率
- 转化率
- 客单价
- 区域增长率
---
## AI经营指标
- 高风险经销商数
- 高潜经销商数
- AI成交预测准确率
- AI流失预测准确率
---
# 14.2 仪表盘设计
## 总部仪表盘
展示:
- 全国销售地图
- 区域排名
- 经销商增长趋势
- AI风险预警
- 商机漏斗
---
## 销售个人仪表盘
展示:
- 今日待跟进
- 今日拜访
- 本月成交
- AI推荐客户
- AI销售建议
---
# 15. 权限与组织设计
# 15.1 RBAC模型
## 数据权限层级
```text
总部
-> 大区
-> 区域
-> 城市
-> 销售
```
---
# 15.2 权限控制点
| 模块 | 控制点 |
|---|---|
| 线索 | 查看/分配/转移 |
| 经销商 | 编辑/归属 |
| 合同 | 审批/金额修改 |
| 回款 | 查看/核销 |
| BI | 区域数据隔离 |
---
# 16. 移动端设计
# 16.1 企业微信H5页面
必须支持:
- 快速拜访
- AI语音录入
- 地图签到
- 拍照上传
- 快速订单查询
- AI风险提醒
---
# 16.2 移动端交互要求
| 要求 | 说明 |
|---|---|
| 单手操作 | 核心按钮底部固定 |
| 弱网容错 | 本地缓存 |
| 快速录入 | 支持语音 |
| 离线能力 | 支持草稿 |
---
# 17. 性能与安全设计
# 17.1 性能目标
| 指标 | 目标 |
|---|---|
| 页面响应 | <2秒 |
| AI分析响应 | <5秒 |
| ERP同步延迟 | <1分钟 |
| 并发支持 | 5000用户 |
---
# 17.2 安全设计
## 安全要求
- HTTPS加密
- JWT鉴权
- 数据权限隔离
- 敏感字段脱敏
- 操作日志审计
- 企业微信身份校验
---
# 18. AI能力优先级实施建议
# P0第一阶段必须上线
- 企业微信集成
- 客户画像
- AI语音拜访
- 会话分析
- 订单查询
---
# P1第二阶段
- AI标签
- AI摘要
- AI意向识别
- 自动提醒
---
# P2第三阶段
- AI Copilot
- AI销售建议
- AI预测
- AI自动推进商机
---
# 19. 项目实施建议
# 第一阶段
建设:
- 基础CRM
- 企业微信
- 拜访管理
- 商机管理
- 订单查询
---
# 第二阶段
建设:
- AI标签
- AI会话分析
- AI语音拜访
- 自动化工作流
---
# 第三阶段
建设:
- AI预测
- AI Copilot
- AI经营分析
- 智能决策
---
# 20. 最终产品定位
系统最终定位:
# “AI驱动的渠道销售经营平台”
区别于传统CRM
传统CRM记录客户
本系统:
- AI驱动增长
- AI驱动招商
- AI驱动销售动作
- AI驱动经营分析
- AI驱动渠道运营

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

512
docs/crm-api-contract-v3.md Normal file
View File

@@ -0,0 +1,512 @@
# CRM 线索中心模块 API 契约V3 - 员工门户)
## 基础信息
- **服务归属**: hzhub-system (端口 8083)
- **API前缀**: `/crm/lead` (通过 Gateway 路由 `/crm/**` → hzhub-system)
- **前端项目**: hzhub-portal-employee (员工门户)
- **响应格式**: `R<T>` (org.hzhub.common.core.domain.R)
- **分页格式**: `TableDataInfo<T>` (org.hzhub.common.mybatis.core.page.TableDataInfo)
---
## 接口列表
### 1. 线索列表查询
**接口**: `GET /crm/lead/list`
**请求参数** (Query):
```json
{
"companyName": "XX贸易", // 公司名称(模糊查询)
"mobile": "13800000000", // 手机号
"intentLevel": "high", // AI意向等级字典crm_intent_level
"riskLevel": "low", // 风险等级字典crm_risk_level
"ownerUserId": 12345, // 负责人ID
"leadStatus": "following", // 线索状态字典crm_lead_status
"sourceType": "activity", // 来源类型字典crm_lead_source
"customerCode": "C001", // ERP客户编码
"pageNum": 1, // 页码
"pageSize": 10 // 每页大小
}
```
**响应**: `TableDataInfo<CrmLeadVo>`
```json
{
"code": 200,
"msg": "查询成功",
"rows": [
{
"leadId": 1001,
"tenantId": "000000",
"customerCode": "C001", // ERP客户编码
"companyName": "XX贸易有限公司",
"contactName": "张三",
"mobile": "138****0000", // 脱敏
"wechat": "zhangsan",
"province": "广东省",
"city": "深圳市",
"regionId": 100,
"regionName": "华南区", // 翻译
"sourceType": "activity",
"sourceTypeName": "活动", // 翻译
"industry": "食品",
"industryName": "食品行业", // 翻译
"storeCount": 20,
"intentLevel": "high",
"intentLevelName": "高意向", // 翻译
"aiScore": 85.5,
"riskLevel": "low",
"riskLevelName": "低风险", // 翻译
"ownerUserId": 12345,
"ownerUserName": "李四", // 翻译
"leadStatus": "following",
"leadStatusName": "跟进中", // 翻译
"nextFollowTime": "2026-05-20 14:00:00",
"createBy": 1,
"createByName": "系统管理员", // 翻译
"createTime": "2026-05-15 10:00:00"
}
],
"total": 100
}
```
---
### 2. 线索详情查询
**接口**: `GET /crm/lead/{leadId}`
**路径参数**: `leadId` (Long)
**响应**: `R<CrmLeadVo>`
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"leadId": 1001,
"customerCode": "C001",
"companyName": "XX贸易有限公司",
"contactName": "张三",
"mobile": "13800000000", // 未脱敏
// ... 其他字段同列表
}
}
```
---
### 3. 新增线索
**接口**: `POST /crm/lead`
**请求体**: `CrmLeadBo`
```json
{
"customerCode": "C001", // ERP客户编码可选
"companyName": "XX贸易有限公司",
"contactName": "张三",
"mobile": "13800000000",
"wechat": "zhangsan",
"province": "广东省",
"city": "深圳市",
"regionId": 100, // 关联 sys_dept
"sourceType": "activity",
"activityName": "春季招商会",
"referrerName": "王五",
"industry": "食品",
"companyScale": "50-100人",
"storeCount": 20,
"remark": "意向强烈,希望尽快对接"
}
```
**业务逻辑**:
1. 如果提供 `customerCode`,调用 `hzhub-erp:8082/erp/dynamic/v1/customer/detail` 拉取ERP客户信息
2. 自动填充客户基础信息companyName, contactName, mobile等
3. 校验手机号是否重复(同租户内)
4. 调用 LangChain4j AI服务分析意向等级`hzhub-ai:6039/ai/analyze/intent` - **第二阶段实现**
5. 根据区域规则sys_dept分配销售owner_user_id - **可选**
6. 返回成功消息
**响应**: `R<Void>`
```json
{
"code": 200,
"msg": "新增成功"
}
```
---
### 4. 编辑线索
**接口**: `PUT /crm/lead`
**请求体**: `CrmLeadBo`
```json
{
"leadId": 1001,
"companyName": "XX贸易已改名",
"contactName": "张三",
"mobile": "13800000000",
// ... 其他可编辑字段
}
```
**响应**: `R<Void>`
```json
{
"code": 200,
"msg": "修改成功"
}
```
---
### 5. 删除线索
**接口**: `DELETE /crm/lead/{leadIds}`
**路径参数**: `leadIds` (String逗号分隔如 "1001,1002,1003")
**响应**: `R<Void>`
```json
{
"code": 200,
"msg": "删除成功"
}
```
---
### 6. 分配线索
**接口**: `PUT /crm/lead/assign`
**请求体**:
```json
{
"leadId": 1001,
"ownerUserId": 12345 // 新负责人ID关联 sys_user
}
```
**响应**: `R<Void>`
```json
{
"code": 200,
"msg": "分配成功"
}
```
---
### 7. 获取跟进记录列表
**接口**: `GET /crm/lead/follow/{leadId}`
**路径参数**: `leadId` (Long)
**响应**: `R<List<CrmLeadFollowVo>>`
```json
{
"code": 200,
"msg": "查询成功",
"data": [
{
"followId": 2001,
"leadId": 1001,
"followType": "phone",
"followTypeName": "电话", // 翻译
"content": "客户表达了合作意向,希望了解招商政策",
"aiSummary": "客户意向高,关注返点政策",
"nextFollowTime": "2026-05-20 14:00:00",
"followUserId": 12345,
"followUserName": "李四", // 翻译
"createTime": "2026-05-15 15:00:00"
}
]
}
```
---
### 8. 添加跟进记录
**接口**: `POST /crm/lead/follow`
**请求体**: `CrmLeadFollowBo`
```json
{
"leadId": 1001,
"followType": "phone",
"content": "与客户沟通了具体合作细节,客户对返点政策满意",
"nextFollowTime": "2026-05-20 14:00:00"
}
```
**业务逻辑**:
1. 保存跟进记录
2. 调用 LangChain4j AI生成摘要`hzhub-ai:6039/ai/summarize` - **第二阶段实现**
3. 更新线索的 `nextFollowTime`
**响应**: `R<Void>`
```json
{
"code": 200,
"msg": "跟进成功"
}
```
---
### 9. 线索转经销商(第二阶段实现)
**接口**: `POST /crm/lead/convert`
**请求体**:
```json
{
"leadId": 1001,
"dealerName": "XX贸易",
"dealerCode": "DL20260001",
"customerCode": "C001" // ERP客户编码可选
}
```
**响应**: `R<Void>`
```json
{
"code": 200,
"msg": "转化成功"
}
```
---
## 数据字典定义
### crm_lead_source线索来源
| 字典值 | 字典标签 | 备注 |
|---|---|---|
| activity | 活动 | 线下招商活动 |
| referral | 推荐 | 客户推荐 |
| website | 网站 | 官网咨询 |
| exhibition | 展会 | 行业展会 |
| wecom | 企业微信 | 企业微信咨询 |
| erp | ERP客户 | 从ERP客户转化 |
| other | 其他 | 其他来源 |
### crm_lead_status线索状态
| 字典值 | 字典标签 | 备注 |
|---|---|---|
| new | 新线索 | 刚录入,未分配 |
| following | 跟进中 | 已分配,正在跟进 |
| converted | 已转化 | 已转为经销商 |
| invalid | 已作废 | 线索无效 |
### crm_intent_levelAI意向等级
| 字典值 | 字典标签 | AI评分范围 |
|---|---|---|
| high | 高意向 | >= 80 |
| medium | 中意向 | 60-80 |
| low | 低意向 | < 60 |
### crm_risk_level风险等级
| 字典值 | 字典标签 | 备注 |
|---|---|---|
| high | 高风险 | 需重点关注 |
| medium | 中风险 | 需持续跟踪 |
| low | 低风险 | 正常跟进 |
### crm_follow_type跟进方式
| 字典值 | 字典标签 |
|---|---|
| phone | 电话 |
| wecom | 企业微信 |
| visit | 拜访 |
| email | 邮件 |
| other | 其他 |
---
## 前端类型定义TypeScript - 员工门户)
```typescript
// CrmLeadVo
export interface CrmLeadVo {
leadId: number;
tenantId: string;
customerCode?: string; // ERP客户编码
companyName: string;
contactName: string;
mobile: string;
wechat?: string;
province?: string;
city?: string;
regionId?: number;
regionName?: string;
sourceType?: string;
sourceTypeName?: string;
activityName?: string;
referrerName?: string;
industry?: string;
industryName?: string;
companyScale?: string;
storeCount?: number;
intentLevel?: string;
intentLevelName?: string;
aiScore?: number;
riskLevel?: string;
riskLevelName?: string;
ownerUserId?: number;
ownerUserName?: string;
leadStatus: string;
leadStatusName?: string;
convertedDealerId?: number;
nextFollowTime?: string;
remark?: string;
createBy: number;
createByName?: string;
createTime: string;
updateBy?: number;
updateByName?: string;
updateTime?: string;
}
// CrmLeadBo
export interface CrmLeadBo {
leadId?: number;
customerCode?: string; // ERP客户编码可选
companyName: string;
contactName: string;
mobile: string;
wechat?: string;
province?: string;
city?: string;
regionId?: number;
sourceType?: string;
activityName?: string;
referrerName?: string;
industry?: string;
companyScale?: string;
storeCount?: number;
ownerUserId?: number;
remark?: string;
}
// CrmLeadFollowVo
export interface CrmLeadFollowVo {
followId: number;
leadId: number;
followType: string;
followTypeName?: string;
content: string;
aiSummary?: string;
nextFollowTime?: string;
followUserId: number;
followUserName?: string;
createTime: string;
}
// CrmLeadFollowBo
export interface CrmLeadFollowBo {
followId?: number;
leadId: number;
followType: string;
content: string;
nextFollowTime?: string;
}
// TableDataInfo员工门户已定义
export interface TableDataInfo<T> {
code: number;
msg: string;
rows: T[];
total: number;
}
// R员工门户已定义
export interface R<T> {
code: number;
msg: string;
data?: T;
}
```
---
## 注意事项(员工门户适配)
1. **多租户支持**: 所有查询自动过滤租户IDTenantEntity
2. **数据权限**: 根据 sys_dept 层级进行数据隔离
3. **敏感字段脱敏**: mobile 字段在列表查询时脱敏
4. **字段翻译**: 字典字段、用户ID、部门ID 自动翻译为名称
5. **操作日志**: 新增、编辑、删除操作记录日志
6. **防重复提交**: 新增操作防重复
7. **逻辑删除**: 使用 @TableLogic,删除时不物理删除
8. **ERP关联**: 如果提供 customerCode自动拉取ERP客户信息
9. **无需Sa-Token注解**: 员工门户权限由Gateway统一控制
---
## ERP集成接口hzhub-erp
### 获取ERP客户详情
**接口**: `GET /erp/dynamic/v1/customer/detail`
**请求参数**: `customerCode`
**响应**: `R<CustomerVO>`
**CustomerVO**(员工门户已定义):
```typescript
interface CustomerVO {
customerCode: string;
customerName: string;
contactName: string;
salesAreaName: string;
brandName: string;
phone: string;
province: string;
city: string;
// ... 其他字段见 hzhub-portal-employee/src/api/erp/index.ts
}
```
---
## 开发优先级
- **P0必须实现**: 接口1-8基础CRUD + 跟进)
- **P1第二阶段**: 接口9线索转经销商+ AI意向识别 + AI摘要生成
- **P2第三阶段**: AI风险分析 + AI预测模型

View File

@@ -0,0 +1,308 @@
# CRM模块架构改进 - 页面拆分完成报告
## 📋 改进方案
### 改进前
- `/crm` 页面商机管道Tab + 线索管理Tab + 客户列表Tab
- 一个页面包含多个功能模块,复杂度高
### 改进后
- `/opportunity` 页面:**商机中心**(独立的商机管道页面)
- `/lead` 页面:**线索中心**(独立的线索管理页面)
- `/crm` 页面:保留作为客户列表页面(可选)
---
## ✅ 完成的工作
### 路由配置修改
**文件**`/data/hzhub/hzhub-portal-employee/src/routers/modules/staticRouter.ts`
**修改内容**
```typescript
{
path: '/opportunity',
name: 'opportunity',
component: () => import('@/pages/opportunity/index.vue'),
meta: {
title: '商机中心',
subtitle: '商机管道管理',
icon: 'TrendCharts',
},
},
{
path: '/lead',
name: 'lead',
component: () => import('@/pages/lead/index.vue'),
meta: {
title: '线索中心',
subtitle: '线索跟进转化',
icon: 'UserFilled',
},
},
```
**移除内容**
- 原有的 `/crm` 路由(已替换为两个新路由)
---
### 商机中心页面创建
**文件**`/data/hzhub/hzhub-portal-employee/src/pages/opportunity/index.vue`
**页面内容**
- **页面头部**:标题"商机中心",描述"管理经销商商机管道,跟进商机进展"
- **Pipeline阶段Tab**全部、线索、谈判中、方案、赢单5个阶段
- **Pipeline管道视图**:横向多列布局,每列显示对应阶段的商机卡片
- **商机卡片**:显示商机名称、经销商名称、负责人、预计成交日期、金额、成功概率
**数据来源**
- 调用 `getOpportunityList()` API获取真实商机数据
- 商机数据来自 `crm_opportunity` 表(关联经销商)
**功能特点**
- 简洁的管道视图,专注商机管理
- 实时计数统计各阶段商机数量
- 卡片悬停效果和交互动画
- 优雅的响应式设计
---
### 线索中心页面创建
**文件**`/data/hzhub/hzhub-portal-employee/src/pages/lead/index.vue`
**页面内容**
- **页面头部**:标题"线索中心",描述"管理销售线索,跟进转化"
- **筛选栏**关键词搜索、AI意向等级、线索状态筛选
- **线索列表表格**公司名称、联系人、手机脱敏、ERP编码、AI意向、负责人、状态、创建时间
- **操作按钮**:详情、跟进、分配、转经销商、删除
- **线索详情Drawer**完整信息和跟进记录Timeline
- **跟进记录Drawer**:添加跟进记录表单
- **新建线索Dialog**:创建线索表单(含手机号验证)
- **分配线索Dialog**:用户选择器(支持搜索)
- **转经销商Dialog**:转化表单
**完整功能**
- 线索列表查询(分页、筛选)
- 线索详情查看(含跟进记录)
- 新建线索含ERP客户关联
- 添加跟进记录
- 分配线索负责人(用户选择器)
- 线索转经销商(自动创建商机)
- 删除线索(逻辑删除)
- 手机号格式验证(前后端双重验证)
---
## 🎯 架构优势
### 功能模块化
- **商机中心**:专注商机管道和跟进推进
- **线索中心**:专注线索获取和转化
- **职责清晰**:每个页面职责单一,降低复杂度
### 用户体验优化
- **独立入口**:左侧菜单两个独立菜单项,访问更直接
- **页面聚焦**:每个页面专注单一业务场景,减少干扰
- **性能提升**:每个页面独立加载,减少初始加载负担
### 代码可维护性
- **文件独立**:每个页面独立文件,便于维护和扩展
- **代码解耦**移除Tab切换逻辑代码更简洁
- **扩展灵活**:每个页面可独立扩展功能,不影响其他页面
---
## 📊 数据关系图
```
线索中心 (/lead)
└─线索(crm_lead)
└─转化
└─经销商(crm_dealer)
└─关联
└─商机(crm_opportunity)
└─显示在
└─商机中心 (/opportunity)
```
**业务流程**
1. **线索中心**:获取和管理销售线索
2. **转化操作**:线索转化为经销商
3. **自动创建**:转化时自动创建初始商机(阶段=lead
4. **商机中心**:查看和跟进商机管道
---
## 🚀 测试指引
### 步骤1重启服务
服务正在重启,完成后访问员工门户。
---
### 步骤2验证左侧菜单
访问http://localhost:5137
**预期结果**
- 左侧菜单显示两个新菜单项:
- **商机中心**图标TrendCharts
- **线索中心**图标UserFilled
- 原"销售CRM"菜单项消失(已被替换)
---
### 步骤3测试线索中心
**操作流程**
1. 点击左侧菜单"线索中心"
2. 查看线索列表自动加载
3. 测试新建线索功能(含手机号验证)
4. 测试线索详情查看
5. 测试跟进记录添加
6. 测试分配负责人(用户选择器)
7. 测试线索转经销商(自动创建商机)
8. 测试删除线索
**验证点**
- 页面独立无Tab切换
- 线索列表完整显示
- 所有功能正常工作
- 手机号格式验证生效
- 负责人显示姓名(而非登录账号)
---
### 步骤4测试商机中心
**操作流程**
1. 点击左侧菜单"商机中心"
2. 查看商机管道显示
3. 点击Pipeline阶段Tab切换
4. 查看商机卡片信息(经销商名称、负责人、金额等)
**验证点**
- 页面独立,简洁管道视图
- 商机数据正确显示(来自转化的线索)
- Pipeline计数实时更新
- 卡片交互效果正常
- 负责人姓名正确显示
---
### 步骤5验证完整业务流程
**完整流程测试**
1. 在**线索中心**创建新线索
2. 在**线索中心**转化线索为经销商
3. 切换到**商机中心**查看商机
4. 验证商机自动创建(阶段=lead名称="初始商机")
5. 验证商机关联经销商正确
**后端验证**
```sql
-- 查询线索
SELECT lead_id, company_name, lead_status, converted_dealer_id
FROM crm_lead
WHERE company_name = '测试公司';
-- 查询经销商
SELECT dealer_id, dealer_name, dealer_code, source_lead_id
FROM crm_dealer
WHERE dealer_code = 'DL20260001';
-- 查询商机
SELECT opportunity_id, opportunity_name, dealer_id, stage, source_lead_id,
dealer_name, owner_user_name
FROM crm_opportunity_view -- 视图包含翻译字段
WHERE source_lead_id = {线ID};
```
**预期结果**
- 线索状态 = converted
- 经销商source_lead_id关联线索
- 商机stage = lead
- 商机dealer_id关联经销商
- 商机owner_user_name显示负责人姓名
---
## 📝 文件清单
### 创建的新文件
1. `/data/hzhub/hzhub-portal-employee/src/pages/opportunity/index.vue` (7.3KB)
2. `/data/hzhub/hzhub-portal-employee/src/pages/lead/index.vue` (25KB)
### 修改的文件
1. `/data/hzhub/hzhub-portal-employee/src/routers/modules/staticRouter.ts`
- 添加两个新路由(/opportunity, /lead
- 移除原/crm路由
---
## ✅ 功能对比
| 功能 | 改进前销售CRM | 改进后 |
|---|---|---|
| 商机管道 | Tab切换访问 | 独立页面"商机中心" |
| 线索管理 | Tab切换访问 | 独立页面"线索中心" |
| 客户列表 | Tab切换访问 | 可保留或移除 |
| 页面复杂度 | 高多Tab | 低(单功能) |
| 菜单结构 | 1个菜单项 | 2个菜单项 |
| 用户体验 | 需切换Tab | 直接访问 |
| 代码维护 | 复杂耦合 | 简单独立 |
---
## 🎯 后续建议
### 功能扩展方向
**商机中心扩展**
- 商机详情Drawer
- 商机编辑功能
- 商机跟进记录
- 商机阶段推进操作
- 商机统计分析
**线索中心扩展**
- 线索批量导入
- 线索来源分析
- 线索质量评分
- 线索跟进提醒
- 线索转化率统计
**共同功能**
- AI意向分析Week 2-3
- AI跟进摘要Week 2-3
- 企业微信集成Week 4+
---
## 📊 本次改进总结
### 技术实现
- ✅ 路由拆分2个独立路由
- ✅ 页面拆分2个独立页面
- ✅ 功能完整性保持(所有原有功能正常)
- ✅ 代码质量提升(解耦、简化)
### 架构优化
- ✅ 模块化设计(每个页面单一职责)
- ✅ 数据流清晰(线索→经销商→商机)
- ✅ 用户体验优化(直接访问、减少切换)
### 可维护性
- ✅ 文件独立(便于维护和扩展)
- ✅ 代码简洁移除Tab切换逻辑
- ✅ 扩展灵活(独立扩展不影响其他)
---
**架构改进完成,请测试验证功能!**

View File

@@ -0,0 +1,361 @@
# CRM线索分配和删除功能 - 测试指引
## ✅ 开发完成状态
### 后端开发hzhub-system- 已完成
**新增文件**
- 无新文件(修改现有文件)
**修改文件**
- SysUserController.java - 添加 `/system/user/portal/select` API员工门户用户选择器
**总计**1个文件修改
---
### 前端开发hzhub-portal-employee- 已完成
**新增文件**
- API文件2个`src/api/user/index.ts`, `src/api/user/types.ts`
**修改文件**
- 页面文件1个`src/pages/crm/index.vue`
- 添加分配和删除按钮操作列从220px扩展到280px
- 添加分配Dialog和用户选择器
- 添加删除确认逻辑
- 添加用户列表加载、分配提交、删除处理方法
**总计**2个新API文件 + 1个页面文件修改
---
## 🚀 测试步骤
### 前提条件
1. 确保数据库SQL已执行crm_dealer表和数据字典
2. 确保所有服务正常运行
3. 已完成线索转化功能测试
---
### 测试1用户选择器功能
**测试步骤**
1. 登录员工门户http://localhost:5137
2. 导航到"销售CRM" → "线索管理"Tab
3. 点击某个线索的"分配"按钮
4. 查看分配Dialog弹出
5. 查看用户选择下拉框
**预期结果**
- 分配Dialog正常弹出
- 用户选择下拉框显示用户列表
- 每个用户选项显示:昵称(用户名)- 部门名称
- 下拉框支持搜索过滤(输入关键词后实时搜索)
---
### 测试2线索分配功能
**测试步骤**
1. 在分配Dialog中选择一个用户作为负责人
2. 点击"确认分配"按钮
**预期结果**
- 显示"分配成功"提示
- Dialog自动关闭
- 线索列表刷新,负责人列显示新分配的用户头像
- 线索状态变为"跟进中"(如果之前是"新线索"
**后端验证**
```sql
SELECT lead_id, company_name, owner_user_id, lead_status
FROM crm_lead
WHERE lead_id = {线ID};
```
**预期结果**
- `owner_user_id` = 新分配的用户ID
- `lead_status` = 'following'(如果之前是'new'
---
### 测试3已转化线索的分配按钮隐藏
**测试步骤**
1. 查找已转化的线索(线索状态为"已转化"
2. 查看操作列按钮
**预期结果**
- "分配"按钮不显示(已转化线索不能分配)
- "转经销商"按钮不显示(已转化线索不能重复转化)
- 只显示"详情"、"跟进"、"删除"按钮
---
### 测试4线索删除功能
**测试步骤**
1. 创建一个测试线索(用于删除测试)
2. 点击该线索的"删除"按钮
3. 查看删除确认对话框
**预期结果**
- 弹出确认对话框,显示:"确定要删除线索"XXX"吗?删除后无法恢复。"
- 有"确定"和"取消"按钮
4. 点击"确定"按钮
**预期结果**
- 显示"删除成功"提示
- 线索从列表消失(逻辑删除)
**后端验证**
```sql
SELECT lead_id, company_name, del_flag
FROM crm_lead
WHERE lead_id = {线ID};
```
**预期结果**
- `del_flag` = 1逻辑删除标记
---
### 测试5删除取消操作
**测试步骤**
1. 点击某个线索的"删除"按钮
2. 在确认对话框中点击"取消"
**预期结果**
- 对话框关闭
- 线索列表不刷新
- 线索数据未删除
---
## 📊 完整功能测试清单
| 测试项 | 状态 | 备注 |
|---|---|---|
| 用户选择器加载 | ⏳ | |
| 用户搜索过滤 | ⏳ | |
| 分配Dialog显示 | ⏳ | |
| 正常分配流程 | ⏳ | |
| 已转化线索分配按钮隐藏 | ⏳ | |
| 删除确认对话框 | ⏳ | |
| 正常删除流程 | ⏳ | |
| 删除取消操作 | ⏳ | |
---
## 🔧 后端接口验证
### 用户选择器API
**接口**`GET /system/user/portal/select`
**请求参数**
- keyword可选搜索关键词
**请求示例**
```bash
GET http://localhost:8080/system/user/portal/select?keyword=admin
Headers:
Authorization: Bearer {token}
ClientID: employee-portal
```
**成功响应**
```json
{
"code": 200,
"msg": "操作成功",
"data": [
{
"userId": 1,
"userName": "admin",
"nickName": "管理员",
"deptName": "研发部门",
"phonenumber": "15888888888",
"status": "0"
}
]
}
```
---
### 线索分配API
**接口**`PUT /crm/lead/assign`
**请求参数**
```json
{
"leadId": 1,
"ownerUserId": 12345
}
```
**请求示例**
```bash
PUT http://localhost:8080/crm/lead/assign
Headers:
Authorization: Bearer {token}
ClientID: employee-portal
Body:
{
"leadId": 1,
"ownerUserId": 12345
}
```
**成功响应**
```json
{
"code": 200,
"msg": "操作成功"
}
```
---
### 线索删除API
**接口**`DELETE /crm/lead/{leadId}`
**请求示例**
```bash
DELETE http://localhost:8080/crm/lead/1
Headers:
Authorization: Bearer {token}
ClientID: employee-portal
```
**成功响应**
```json
{
"code": 200,
"msg": "操作成功"
}
```
---
## 🐛 常见问题排查
### 问题1用户选择器加载失败
**排查步骤**
1. 检查hzhub-system服务是否启动
2. 检查Gateway路由配置`/system/**`路由)
3. 查看浏览器Console错误日志
4. 查看后端日志:
```bash
tail -f /data/hzhub/hzhub-system/logs/hzhub-system.log
```
---
### 问题2分配成功但负责人未更新
**排查步骤**
1. 查询线索数据确认字段更新:
```sql
SELECT lead_id, owner_user_id, lead_status FROM crm_lead WHERE lead_id = {线索ID};
```
2. 检查前端是否调用了`loadLeads()`刷新列表
3. 检查列表数据中的`ownerUserName`字段是否正确翻译
---
### 问题3删除后线索仍显示在列表
**排查步骤**
1. 查询线索的`del_flag`字段:
```sql
SELECT lead_id, del_flag FROM crm_lead WHERE lead_id = {线索ID};
```
2. 检查前端列表查询是否正确过滤了`del_flag=1`的记录
3. 检查后端Mapper查询条件是否包含`del_flag`过滤
---
### 问题4已转化线索仍显示分配按钮
**排查步骤**
1. 检查前端条件渲染:
```vue
<el-button v-if="row.leadStatus !== 'converted'" ...>
```
2. 检查线索列表数据中`leadStatus`字段的值
3. 使用浏览器开发者工具检查元素是否被渲染
---
## ✅ 开发总结
### 实现的功能
1. **用户选择器**
- 员工门户专用用户选择API无需Sa-Token权限注解
- 支持关键词搜索过滤
- 返回简化用户信息ID、用户名、昵称、部门
- 只返回状态正常的用户
2. **线索分配**
- 分配按钮和Dialog UI
- 用户选择下拉框(支持搜索)
- 分配成功后更新负责人和状态
- 已转化线索不显示分配按钮
3. **线索删除**
- 删除按钮和确认对话框
- 逻辑删除设置del_flag=1
- 删除成功后列表刷新
- 用户可取消删除操作
### 技术要点
- **Gateway权限控制**员工门户API不需要Sa-Token权限注解权限由Gateway统一控制
- **用户选择器优化**使用分页查询pageSize=1000获取所有用户避免性能问题
- **前端交互优化**使用ElMessageBox.confirm提供删除确认防止误操作
- **状态联动**:分配线索时自动将状态更新为"跟进中"
---
## 🎯 下一步开发计划
根据"方案A实用优先",后续开发顺序:
**Week 2-3**AI功能
1. AI意向分析 - 调用hzhub-ai服务分析线索意向
2. AI跟进摘要 - 使用LangChain4j生成跟进摘要
3. AI风险分析 - 基于线索数据生成风险评估
**Week 4+**:企业微信集成
1. 移动端H5页面
2. 企业微信侧边栏
3. 企业微信消息推送
---
**当前任务完成,请开始测试!**

272
docs/crm-bug-fix-report.md Normal file
View File

@@ -0,0 +1,272 @@
# CRM线索管理功能问题修复报告
## 发现的问题
### 问题1新增线索时缺少手机号格式验证
**问题描述**
- 后端CrmLeadBo缺少手机号格式校验注解
- 前端:新建线索表单缺少手机号格式验证
**影响**
- 用户可以输入任意格式的手机号,导致数据质量下降
---
### 问题2负责人显示为手机号而非姓名
**问题描述**
- UserNameTranslationImpl翻译类调用userService.selectUserNameById返回userName登录账号
- 应该调用userService.selectNicknameById返回nickName用户昵称/真实姓名)
**影响**
- 线索列表负责人列显示登录账号如admin而不是用户真实姓名如管理员
- 用户期望看到负责人姓名,而非登录账号
---
## 修复方案
### 问题1修复手机号格式验证
#### 后端修复
**修改文件**`hzhub-system/src/main/java/org/hzhub/crm/domain/bo/CrmLeadBo.java`
**修改内容**
```java
// 导入Pattern注解
import jakarta.validation.constraints.Pattern;
// mobile字段添加正则验证
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
@Size(min = 0, max = 50, message = "手机号长度不能超过{max}个字符")
private String mobile;
```
**正则表达式说明**
- `^1` - 以1开头
- `[3-9]` - 第二位为3-9
- `\d{9}` - 后面9位为数字
- `$` - 结尾
验证中国手机号格式13x, 14x, 15x, 16x, 17x, 18x, 19x开头的11位数字
---
#### 前端修复
**修改文件**`hzhub-portal-employee/src/pages/crm/index.vue`
**修改内容**
1. **添加手机号验证函数**
```typescript
// 手机号验证规则
const mobileValidator = (value: string) => {
if (!value) {
return '请输入手机号';
}
const mobileRegex = /^1[3-9]\d{9}$/;
if (!mobileRegex.test(value)) {
return '手机号格式不正确';
}
return '';
};
```
2. **修改submitLead方法添加验证**
```typescript
async function submitLead() {
if (!leadForm.value.companyName || !leadForm.value.contactName || !leadForm.value.mobile) {
ElMessage.warning('请填写必填信息');
return;
}
// 验证手机号格式
const mobileError = mobileValidator(leadForm.value.mobile);
if (mobileError) {
ElMessage.warning(mobileError);
return;
}
try {
await createLead(leadForm.value);
ElMessage.success('线索创建成功');
showAddLeadDialog.value = false;
await loadLeads();
}
catch (error: any) {
ElMessage.error(error?.message || '创建线索失败');
}
}
```
---
### 问题2修复负责人显示姓名
#### 后端修复
**修改文件**`hzhub-ai/hzhub-common/hzhub-common-translation/src/main/java/org/hzhub/common/translation/core/impl/UserNameTranslationImpl.java`
**修改内容**
```java
@Override
public String translation(Object key, String other) {
if (key instanceof Long id) {
// 返回用户昵称而不是登录账号
return userService.selectNicknameById(id);
}
return null;
}
```
**修复说明**
- 从调用`selectUserNameById`改为调用`selectNicknameById`
- `selectNicknameById`返回用户昵称(真实姓名),而不是登录账号
- 使用缓存`@Cacheable(cacheNames = CacheNames.SYS_NICKNAME)`,性能更好
**影响范围**
- 所有使用`USER_ID_TO_NAME`翻译的地方都会显示用户昵称
- 包括createBy, updateBy, ownerUserId, followUserId等字段
---
## 编译和部署
### 编译步骤
```bash
# 1. 编译hzhub-ai包含translation模块修改
cd /data/hzhub/hzhub-ai
mvn clean install -DskipTests
# 2. 编译hzhub-system包含CrmLeadBo修改
cd /data/hzhub/hzhub-system
mvn clean compile -DskipTests
# 3. 重启所有服务
cd /data/hzhub
./restart-all.sh
```
**编译结果**
- ✅ hzhub-ai: BUILD SUCCESS (55.753s)
- ✅ hzhub-system: BUILD SUCCESS (19.007s)
---
## 测试验证
### 测试1手机号格式验证
#### 后端验证测试
使用Postman或curl测试
```bash
POST http://localhost:8080/crm/lead
Headers:
Authorization: Bearer {token}
ClientID: employee-portal
Body:
{
"companyName": "测试公司",
"contactName": "张三",
"mobile": "12345678901", // 错误格式
"sourceType": "activity"
}
```
**预期响应**
```json
{
"code": 500,
"msg": "手机号格式不正确"
}
```
#### 前端验证测试
**测试步骤**
1. 登录员工门户http://localhost:5137
2. 导航到"销售CRM" → "线索管理"
3. 点击"新建线索"
4. 输入错误手机号12345678901
5. 点击"创建线索"
**预期结果**
- 显示提示:"手机号格式不正确"
- 表单不提交
---
### 测试2负责人显示姓名
**测试步骤**
1. 创建线索并分配负责人
2. 查看线索列表负责人列
**预期结果**
- 负责人列显示用户真实姓名(如"管理员"
- 不显示登录账号(如"admin")
**后端验证**
```sql
-- 查询用户数据
SELECT user_id, user_name, nick_name, phonenumber FROM sys_user WHERE user_id = 1;
-- 预期结果:
-- user_name: admin (登录账号)
-- nick_name: 管理员 (真实姓名)
```
---
## 修复影响范围
### 手机号验证
**影响模块**
- CRM线索管理新建、编辑线索
- 未来可能影响:经销商管理、客户管理
**数据质量提升**
- 防止错误手机号数据进入系统
- 提升线索数据质量
---
### 负责人显示
**影响模块**
- CRM线索管理负责人显示
- CRM经销商管理负责人显示
- 系统通知管理(创建人、更新人显示)
- OSS对象存储创建人显示
- 跟进记录(跟进人显示)
**用户体验提升**
- 显示真实姓名,更符合用户认知
- 避免混淆登录账号和真实姓名
---
## 相关文档
- [CRM线索管理测试指引](docs/crm-testing-guide.md)
- [CRM线索转化测试指引](docs/crm-convert-testing-guide.md)
- [CRM线索分配删除测试指引](docs/crm-assign-delete-testing-guide.md)
---
## 总结
两个问题均已修复:
1. ✅ 手机号格式验证后端Pattern注解 + 前端验证函数)
2. ✅ 负责人显示姓名修改UserNameTranslationImpl返回昵称
请重新测试验证功能。

View File

@@ -0,0 +1,103 @@
# CRM 线索转经销商 API 契约
## 基础信息
- **服务**: hzhub-system (8083)
- **API**: `POST /lead/convert`
- **Gateway路由**: `/crm/**` → StripPrefix=1 → `/lead/convert`
---
## 接口定义
### 线索转经销商
**API**: `POST /lead/convert`
**请求参数** (CrmLeadConvertBo):
```json
{
"leadId": 1001, // 必填线索ID
"dealerName": "XX贸易有限公司", // 必填,经销商名称
"dealerCode": "DL20260001", // 必填,经销商编码
"customerCode": "C001", // 可选ERP客户编码
"signedAt": "2026-05-20", // 可选,签约时间
"level": "C" // 可选经销商等级默认C
}
```
**响应**: `R<Void>`
```json
{
"code": 200,
"msg": "转化成功"
}
```
---
## 业务逻辑
1. 查询线索信息(`crm_lead`
2. 校验线索状态(必须不是"已转化"
3. 创建经销商记录(`crm_dealer`
- 从线索复制基础信息companyName→dealerName, contactName, mobile, province, city
- 设置 sourceLeadId = leadId
- 设置 ownerUserId = lead.ownerUserId
4. 迁移跟进记录(可选):
-`crm_lead_follow` 数据复制到 `crm_dealer_follow`(如果有此表)
5. 创建初始商机(`crm_opportunity`
- opportunityName = "初始商机"
- dealerId = 新经销商ID
- stage = "初步接触"
6. 更新线索状态:
- leadStatus = "converted"
- convertedDealerId = 新经销商ID
7. 返回成功消息
---
## 数据字典
### crm_dealer_level经销商等级
| 字典值 | 字典标签 |
|---|---|
| A | A级经销商 |
| B | B级经销商 |
| C | C级经销商 |
### crm_lifecycle生命周期
| 字典值 | 字典标签 |
|---|---|
| active | 活跃期 |
| stable | 稳定期 |
| decline | 衰退期 |
| churn | 流失期 |
---
## 前端类型定义
```typescript
export interface CrmLeadConvertBo {
leadId: number; // 必填
dealerName: string; // 必填
dealerCode: string; // 必填
customerCode?: string; // 可选
signedAt?: string; // 可选,格式 YYYY-MM-DD
level?: string; // 可选,默认 C
}
```
---
## 注意事项
1. **数据校验**: 线索ID必须存在且状态未转化
2. **唯一性**: dealerCode在同一租户内唯一
3. **事务性**: 整个转化过程使用事务(@Transactional
4. **ERP关联**: 如果提供customerCode在经销商详情中可查看ERP数据

150
docs/crm-convert-plan.md Normal file
View File

@@ -0,0 +1,150 @@
# CRM线索转经销商功能开发计划
## 功能概述
将线索转化为正式经销商,创建经销商档案、迁移跟进记录、创建初始商机。
---
## 数据表设计
### crm_dealer经销商表
```sql
CREATE TABLE IF NOT EXISTS crm_dealer (
dealer_id BIGINT NOT NULL COMMENT '经销商ID主键',
tenant_id VARCHAR(20) DEFAULT '000000' COMMENT '租户ID',
customer_code VARCHAR(100) DEFAULT NULL COMMENT 'ERP客户编码关联',
dealer_name VARCHAR(200) NOT NULL COMMENT '经销商名称',
dealer_code VARCHAR(100) NOT NULL COMMENT '经销商编码',
contact_name VARCHAR(100) DEFAULT NULL COMMENT '联系人',
mobile VARCHAR(50) DEFAULT NULL COMMENT '手机',
province VARCHAR(50) DEFAULT NULL COMMENT '',
city VARCHAR(50) DEFAULT NULL COMMENT '',
level VARCHAR(50) DEFAULT 'C' COMMENT '经销商等级字典crm_dealer_level',
lifecycle VARCHAR(50) DEFAULT 'active' COMMENT '生命周期字典crm_lifecycle',
signed_at DATETIME DEFAULT NULL COMMENT '签约时间',
store_count INT DEFAULT 0 COMMENT '门店数',
team_size INT DEFAULT 0 COMMENT '团队规模',
total_order_amount DECIMAL(18,2) DEFAULT 0 COMMENT '累计订单金额',
total_payment_amount DECIMAL(18,2) DEFAULT 0 COMMENT '累计回款金额',
activity_score DECIMAL(5,2) DEFAULT 0 COMMENT '活跃评分',
risk_score DECIMAL(5,2) DEFAULT 0 COMMENT '风险评分',
owner_user_id BIGINT DEFAULT NULL COMMENT '负责人(关联 sys_user',
source_lead_id BIGINT DEFAULT NULL COMMENT '来源线索ID',
create_dept BIGINT DEFAULT NULL COMMENT '创建部门',
create_by BIGINT DEFAULT NULL COMMENT '创建人',
create_time DATETIME DEFAULT NULL COMMENT '创建时间',
update_by BIGINT DEFAULT NULL COMMENT '更新人',
update_time DATETIME DEFAULT NULL COMMENT '更新时间',
del_flag INT DEFAULT 0 COMMENT '删除标志',
PRIMARY KEY (dealer_id),
KEY idx_tenant_id (tenant_id),
KEY idx_customer_code (customer_code),
KEY idx_dealer_code (dealer_code),
KEY idx_owner_user_id (owner_user_id),
KEY idx_source_lead_id (source_lead_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='CRM经销商表';
```
---
## 后端接口设计
### 1. 线索转经销商
**API**: `POST /lead/convert`
**请求参数**:
```json
{
"leadId": 1001,
"dealerName": "XX贸易有限公司",
"dealerCode": "DL20260001",
"customerCode": "C001" // 可选ERP客户编码
}
```
**业务逻辑**:
1. 查询线索信息
2. 创建 `crm_dealer` 记录
3. 迁移跟进记录:`crm_lead_follow``crm_dealer_follow`
4. 创建初始商机:`crm_opportunity`
5. 更新线索状态为"已转化"
6. 返回经销商ID
---
## 前端UI设计
### 转经销商Dialog
```vue
<el-dialog v-model="showConvertDialog" title="线索转经销商" width="600px">
<el-form :model="convertForm" label-width="120px">
<el-form-item label="经销商名称" required>
<el-input v-model="convertForm.dealerName" placeholder="默认为线索公司名称" />
</el-form-item>
<el-form-item label="经销商编码" required>
<el-input v-model="convertForm.dealerCode" placeholder="请输入经销商编码" />
</el-form-item>
<el-form-item label="ERP客户编码">
<el-input v-model="convertForm.customerCode" placeholder="可选关联ERP客户" />
</el-form-item>
<el-form-item label="签约时间">
<el-date-picker v-model="convertForm.signedAt" type="date" value-format="YYYY-MM-DD" />
</el-form-item>
<el-form-item label="经销商等级">
<el-select v-model="convertForm.level">
<el-option label="A级经销商" value="A" />
<el-option label="B级经销商" value="B" />
<el-option label="C级经销商" value="C" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="showConvertDialog = false">取消</el-button>
<el-button type="success" @click="submitConvert">确认转化</el-button>
</template>
</el-dialog>
```
---
## 开发任务清单
### 后端任务
1. ✅ 创建数据表:`crm_dealer_init.sql`
2. ✅ Entity`CrmDealer.java`
3. ✅ Bo`CrmDealerBo.java`
4. ✅ Vo`CrmDealerVo.java`
5. ✅ Mapper`CrmDealerMapper.java`
6. ✅ Service`ICrmDealerService.java` + `Impl`
7. ✅ Controller转化接口 `POST /lead/convert`
### 前端任务
1. ✅ API定义`convertLeadToDealer()` 函数
2. ✅ 转经销商Dialog UI
3. ✅ 转化成功后列表刷新
---
## 开发顺序
建议按以下顺序开发:
**Day 1-2**: 后端开发
- 数据表、Entity、Service、Controller
**Day 3**: 前端开发
- Dialog UI、API调用、转化逻辑
**Day 4**: 测试验证
- 线索转化流程测试
- 经销商数据验证
---
请按照此计划开始开发。

View File

@@ -0,0 +1,397 @@
# CRM线索转经销商功能 - 测试指引
## ✅ 后端开发完成状态
**创建文件统计**
- 数据库SQL1个`crm_dealer_init.sql`
- Entity实体类1个`CrmDealer.java`
- Bo业务对象2个`CrmDealerBo.java`, `CrmLeadConvertBo.java`
- Vo视图对象1个`CrmDealerVo.java`
- Mapper接口1个`CrmDealerMapper.java`
- Service实现修改1个`CrmLeadServiceImpl.java`,添加`convertToDealer`方法)
- Controller修改1个`CrmLeadController.java`,添加`POST /lead/convert`接口)
**总计**6个新代码文件 + 1个SQL文件 + 2个现有文件修改
---
## ✅ 前端开发完成状态
**修改文件统计**
- 页面扩展1个`/crm/index.vue`添加转经销商Dialog和转化逻辑
- API类型定义1个修改`types.ts`,添加`LeadConvertRequest`类型)
- API调用方法1个修改`index.ts`,添加`convertLeadToDealer`函数)
**总计**3个文件修改
---
## 🚀 测试步骤
### 步骤1数据库初始化
**⚠️ 重要必须先执行数据库SQL**
执行SQL脚本创建`crm_dealer`表和数据字典:
```bash
# 方式1使用Docker MySQL容器推荐
cd /data/hzhub/hzhub-deploy
docker compose exec -T mysql mysql -u root -pHzhub@2024 hzhub < /data/hzhub/hzhub-system/src/main/resources/db/crm_dealer_init.sql
# 方式2手动在数据库客户端执行
# 打开数据库客户端如Navicat、DBeaver连接到hzhub数据库
# 执行SQL文件/data/hzhub/hzhub-system/src/main/resources/db/crm_dealer_init.sql
```
**验证SQL执行成功**
```sql
-- 检查表创建
SHOW TABLES LIKE 'crm_dealer';
DESC crm_dealer;
-- 检查数据字典
SELECT dict_type, dict_name FROM sys_dict_type WHERE dict_type IN ('crm_dealer_level', 'crm_lifecycle');
SELECT dict_value, dict_label FROM sys_dict_data WHERE dict_type = 'crm_dealer_level';
SELECT dict_value, dict_label FROM sys_dict_data WHERE dict_type = 'crm_lifecycle';
```
**预期结果**
- `crm_dealer`表存在,包含所有字段
- 数据字典类型:`crm_dealer_level`(经销商等级)、`crm_lifecycle`(生命周期)
- 经销商等级数据A、B、C
- 生命周期数据active、stable、decline、churn
---
### 步骤2重启后端服务
所有服务已通过`restart-all.sh`重启完成,无需额外操作。
**验证服务状态**
```bash
cd /data/hzhub
./status-all.sh
```
**预期结果**
- hzhub-system: Running (PID: 1771446)
- hzhub-gateway: Running (PID: 1771913)
- hzhub-portal-employee: Running (PID: 1772306)
---
### 步骤3测试线索转化功能
#### 测试准备:创建测试线索
1. 登录员工门户http://localhost:5137
2. 导航到"销售CRM" → "线索管理"Tab
3. 点击"新建线索",填写以下信息:
- 公司名称:测试贸易有限公司
- 联系人:张三
- 手机号13800138000
- 线索来源:活动
- 活动名称:春季招商会
4. 点击"创建线索",确认创建成功
---
#### 测试转化流程
**测试步骤**
1. 在线索列表中,找到刚创建的测试线索
2. 点击该线索行的"转化"按钮
3. 查看转经销商Dialog弹出
**Dialog字段检查**
- 经销商名称:默认填充线索公司名称(可修改)
- 经销商编码:输入框(必填)
- ERP客户编码输入框可选
- 签约时间:日期选择器(可选)
- 经销商等级下拉选择默认C可选A/B/C
4. 填写转化表单:
- 经销商名称:保持默认"测试贸易有限公司"
- 经销商编码DL20260001
- 签约时间:选择今天或任意日期
- 经销商等级选择C级经销商
5. 点击"确认转化"按钮
**预期结果**
- 显示"转化成功"提示
- Dialog自动关闭
- 线索列表刷新,该线索状态变为"已转化"
- 线索行的"转化"按钮消失或变为禁用状态
---
#### 后端数据验证
**验证线索状态更新**
```sql
-- 查询线索状态
SELECT lead_id, company_name, lead_status, converted_dealer_id
FROM crm_lead
WHERE company_name = '测试贸易有限公司';
```
**预期结果**
- `lead_status` = 'converted'
- `converted_dealer_id` 有值指向新创建的经销商ID
---
**验证经销商创建**
```sql
-- 查询经销商数据
SELECT dealer_id, dealer_name, dealer_code, contact_name, mobile, level, lifecycle, source_lead_id
FROM crm_dealer
WHERE dealer_code = 'DL20260001';
```
**预期结果**
- `dealer_name` = '测试贸易有限公司'
- `dealer_code` = 'DL20260001'
- `contact_name` = '张三'(从线索复制)
- `mobile` = '13800138000'(从线索复制)
- `level` = 'C'
- `lifecycle` = 'active'
- `source_lead_id` = 线索ID关联
---
#### 测试重复转化(负面测试)
**测试步骤**
1. 尝试再次转化已转化的线索
2. 点击已转化线索的"转化"按钮
**预期结果**
- 后端返回错误:"线索已转化,不能重复转化"
- Dialog显示错误提示
---
#### 测试经销商编码唯一性(负面测试)
**测试步骤**
1. 创建另一个新线索(不同手机号):
- 公司名称:另一个测试公司
- 联系人:李四
- 手机号13900139000
2. 点击"转化",填写表单:
- 经销商编码DL20260001重复编码
3. 点击"确认转化"
**预期结果**
- 后端返回错误:"经销商编码已存在"
- Dialog显示错误提示
---
## 🔧 后端接口验证
### API调用测试使用Postman或curl
**转化接口**
```bash
POST http://localhost:8080/crm/lead/convert
Headers:
Authorization: Bearer {token}
ClientID: employee-portal
Body:
{
"leadId": 1,
"dealerName": "测试贸易有限公司",
"dealerCode": "DL20260001",
"signedAt": "2026-05-20",
"level": "C"
}
```
**成功响应**
```json
{
"code": 200,
"msg": "操作成功"
}
```
**错误响应示例**
```json
{
"code": 500,
"msg": "线索已转化,不能重复转化"
}
```
---
## 📊 完整功能测试清单
| 测试项 | 预期结果 | 实际结果 | 备注 |
|---|---|---|---|
| 数据库SQL执行 | 表和数据字典创建成功 | ✅/❌ | |
| 服务重启 | 所有服务正常运行 | ✅/❌ | |
| 创建测试线索 | 线索创建成功 | ✅/❌ | |
| 转化Dialog显示 | Dialog正常弹出字段完整 | ✅/❌ | |
| 默认值填充 | 公司名称自动填充 | ✅/❌ | |
| 经销商等级下拉 | 显示A/B/C选项默认C | ✅/❌ | |
| 正常转化流程 | 转化成功,提示显示 | ✅/❌ | |
| 线索状态更新 | lead_status = converted | ✅/❌ | |
| 经销商数据创建 | 所有字段正确复制 | ✅/❌ | |
| 重复转化拦截 | 错误提示显示 | ✅/❌ | |
| 编码唯一性校验 | 错误提示显示 | ✅/❌ | |
---
## 🐛 常见问题排查
### 问题1转化按钮点击无响应
**排查步骤**
1. 检查浏览器Console是否有错误日志
2. 检查前端代码中`submitConvert`函数是否正确实现
3. 检查`convertLeadToDealer` API调用是否正常
---
### 问题2转化成功但经销商数据未创建
**排查步骤**
1. 检查数据库中`crm_dealer`表是否创建成功
2. 检查数据字典是否存在
3. 查看hzhub-system日志
```bash
tail -f /data/hzhub/hzhub-system/logs/hzhub-system.log
```
4. 确认`CrmDealerMapper`是否正确注入到`CrmLeadServiceImpl`
---
### 问题3转化成功但线索状态未更新
**排查步骤**
1. 查询线索数据:
```sql
SELECT lead_id, lead_status, converted_dealer_id FROM crm_lead WHERE lead_id = {线索ID};
```
2. 检查`CrmLeadServiceImpl.convertToDealer`方法中是否执行了线索更新
3. 检查事务是否正确提交(方法有`@Transactional`注解)
---
### 问题4Gateway路由失败
**排查步骤**
1. 检查Gateway服务是否启动
2. 检查Gateway路由配置
```bash
cat /data/hzhub/hzhub-gateway/src/main/resources/application.yml | grep -A 10 "hzhub-crm"
```
3. 测试Gateway健康http://localhost:8080/actuator/health
---
## ✅ 测试完成确认
**请按照以上步骤进行测试,完成后告知测试结果。**
**测试报告格式**
```
测试日期:{填写日期}
测试人员:{填写姓名}
测试结果:
- 数据库初始化:✅/❌
- 转化功能:✅/❌
- 数据验证:✅/❌
- 异常处理:✅/❌
问题记录:
1. {问题描述}
2. {问题描述}
下一步建议:
{填写内容}
```
---
## 📝 开发总结
### 实现的功能
1. **数据库层**
- 创建`crm_dealer`表,包含经销商完整字段
- 初始化经销商等级和生命周期数据字典
- 建立线索与经销商的关联(`converted_dealer_id`, `source_lead_id`
2. **业务逻辑层**
- 线索状态校验(防止重复转化)
- 经销商编码唯一性校验
- 从线索复制基础信息到经销商
- 线索状态更新为"已转化"
- 关联线索和经销商ID
- 事务保证数据一致性
3. **前端交互层**
- 转经销商Dialog UI
- 表单字段默认值填充(公司名称)
- 经销商等级下拉选择
- 转化成功提示和列表刷新
- 错误提示显示
### 待实现功能(后续阶段)
1. **跟进记录迁移**
- 将线索跟进记录迁移到经销商跟进记录表(需要创建`crm_dealer_follow`表)
2. **初始商机创建**
- 转化时自动创建初始商机(需要创建`crm_opportunity`表)
3. **ERP数据关联**
- 如果提供了ERP客户编码在经销商详情中可查看ERP数据
4. **用户选择器集成**
- 分配线索时使用真实的用户选择组件
5. **线索删除功能**
- 完整的线索删除功能实现
---
## 🎯 下一阶段功能预告
根据"方案A实用优先",后续开发顺序:
**第2项功能**:用户选择器组件
- 替换线索分配中的硬编码用户ID输入
- 实现真实的用户选择下拉组件
**第3项功能**:线索删除功能
- 完善删除按钮和确认逻辑
**Week 2-3**AI功能AI意向分析、AI跟进摘要、AI风险分析
**Week 4+**企业微信集成、移动H5页面
---
**当前任务完成,请开始测试!**

View File

@@ -0,0 +1,393 @@
# CRM商机管理功能 - 测试指引
## ✅ 开发完成状态
### 后端开发hzhub-system- 已完成
**创建文件**
- 数据库SQL1个`crm_opportunity_init.sql`
- Entity实体类1个`CrmOpportunity.java`
- Bo业务对象1个`CrmOpportunityBo.java`
- Vo视图对象1个`CrmOpportunityVo.java`
- Mapper接口1个`CrmOpportunityMapper.java`
- Mapper XML1个`CrmOpportunityMapper.xml`
- Service接口1个`ICrmOpportunityService.java`
- Service实现1个`CrmOpportunityServiceImpl.java`
- Controller控制器1个`CrmOpportunityController.java`
**修改文件**
- CrmLeadServiceImpl.java - 在线索转化时自动创建初始商机
**总计**9个新文件 + 1个SQL文件 + 1个现有文件修改
---
### 前端开发hzhub-portal-employee- 已完成
**修改文件**
- API类型定义1个修改`api/crm/types.ts`,添加商机类型)
- API调用方法1个修改`api/crm/index.ts`添加商机API
- CRM页面1个修改`pages/crm/index.vue`,商机管道使用真实数据)
**总计**3个文件修改
---
## 🚀 测试步骤
### 步骤1数据库初始化
**⚠️ 重要必须先执行数据库SQL**
创建商机表、跟进记录表和数据字典:
```bash
# 方式1使用Docker MySQL容器推荐
cd /data/hzhub/hzhub-deploy
sudo docker compose exec -T mysql mysql -u root -pHzhub@2024 hzhub < /data/hzhub/hzhub-system/src/main/resources/db/crm_opportunity_init.sql
# 方式2手动在数据库客户端执行
# 打开数据库客户端如Navicat、DBeaver连接到hzhub数据库
# 执行SQL文件/data/hzhub/hzhub-system/src/main/resources/db/crm_opportunity_init.sql
```
**验证SQL执行成功**
```bash
# 检查表创建
sudo docker compose exec mysql mysql -u root -pHzhub@2024 hzhub -e "SHOW TABLES LIKE 'crm_opportunity';"
sudo docker compose exec mysql mysql -u root -pHzhub@2024 hzhub -e "SHOW TABLES LIKE 'crm_opportunity_follow';"
# 检查数据字典
sudo docker compose exec mysql mysql -u root -pHzhub@2024 hzhub -e "SELECT dict_type, dict_name FROM sys_dict_type WHERE dict_type IN ('crm_opportunity_stage', 'crm_opportunity_status');"
```
**预期结果**
- `crm_opportunity`表存在(商机表)
- `crm_opportunity_follow`表存在(跟进记录表)
- 数据字典类型:`crm_opportunity_stage`(商机阶段)、`crm_opportunity_status`(商机状态)
- 商机阶段数据lead、negotiation、proposal、closing、lost
- 商机状态数据active、won、lost、paused
---
### 步骤2重启服务
由于修改了后端代码和前端代码,需要重启服务:
```bash
cd /data/hzhub
./restart-all.sh
```
**验证服务状态**
```bash
./status-all.sh
```
**预期结果**
- hzhub-system: Running
- hzhub-gateway: Running
- hzhub-portal-employee: Running
---
### 步骤3测试商机管道功能
#### 测试准备:转化线索创建经销商
1. 登录员工门户http://localhost:5137
2. 导航到"销售CRM" → "线索管理"Tab
3. 选择一个线索,点击"转化"按钮
4. 填写转化表单(经销商编码、签约时间等)
5. 点击"确认转化"
**预期结果**
- 线索转化成功
- 创建经销商记录
- **自动创建初始商机**(商机名称="初始商机",阶段="lead"
---
#### 测试1商机管道显示真实数据
**测试步骤**
1. 点击"商机管道"Tab
2. 查看Pipeline视图
**预期结果**
- 商机管道显示真实数据不再是mock数据
- Pipeline顶部显示各阶段计数全部、线索、谈判中、方案、赢单
- 商机卡片显示:
- 商机名称(如"初始商机"
- 经销商名称(如"测试贸易有限公司"
- 负责人姓名
- 预计成交日期
- 商机金额
- 阶段标签(线索/赢单等)
---
#### 测试2商机阶段筛选
**测试步骤**
1. 在商机管道顶部点击不同阶段Tab全部、线索、谈判中、方案、赢单
2. 观察商机卡片的变化
**预期结果**
- 点击"线索"Tab只显示阶段为"lead"的商机
- 点击"赢单"Tab只显示阶段为"closing"的商机
- 计数实时更新
---
#### 测试3自动创建商机验证
**后端验证**
```sql
-- 查询刚转化的线索对应的商机
SELECT o.opportunity_id, o.opportunity_name, o.dealer_id, o.stage, o.source_lead_id,
d.dealer_name, d.dealer_code
FROM crm_opportunity o
LEFT JOIN crm_dealer d ON o.dealer_id = d.dealer_id
WHERE o.source_lead_id = {线ID};
```
**预期结果**
- 商机记录存在
- `opportunity_name` = '初始商机'
- `stage` = 'lead'
- `dealer_id` 关联到新创建的经销商
- `source_lead_id` = 线索ID
- `dealer_name` 显示经销商名称
---
#### 测试4商机列表API测试
**API调用测试**使用Postman或curl
```bash
GET http://localhost:8080/crm/opportunity/list?pageNum=1&pageSize=10
Headers:
Authorization: Bearer {token}
ClientID: employee-portal
```
**成功响应**
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"rows": [
{
"opportunityId": 1,
"opportunityName": "初始商机",
"dealerId": 1,
"dealerName": "测试贸易有限公司",
"stage": "lead",
"stageName": "线索",
"amount": 0,
"probability": 10,
"ownerUserId": 1,
"ownerUserName": "管理员",
"status": "active",
"statusName": "进行中"
}
],
"total": 1
}
}
```
---
## 📊 完整功能测试清单
| 测试项 | 状态 | 备注 |
|---|---|---|
| 数据库SQL执行 | ⏳ 待执行 | |
| 表创建验证 | ⏳ 待测试 | |
| 数据字典验证 | ⏳ 待测试 | |
| 服务重启 | ⏳ 待执行 | |
| 线索转化创建商机 | ⏳ 待测试 | |
| 商机管道显示 | ⏳ 待测试 | |
| 商机阶段筛选 | ⏳ 待测试 | |
| 商机数据验证 | ⏳ 待测试 | |
| 商机列表API | ⏳ 待测试 | |
---
## 🐛 常见问题排查
### 问题1商机管道显示空列表
**排查步骤**
1. 检查crm_opportunity表是否创建
2. 检查是否有商机数据(先转化线索创建经销商)
3. 查看浏览器Console错误日志
4. 查看后端日志:
```bash
tail -f /data/hzhub/hzhub-system/logs/hzhub-system.log
```
---
### 问题2线索转化后商机未创建
**排查步骤**
1. 查询crm_opportunity表
```sql
SELECT * FROM crm_opportunity WHERE source_lead_id = {线索ID};
```
2. 检查CrmLeadServiceImpl.convertToDealer方法是否正确调用opportunityService
3. 查看后端日志中的商机创建记录
---
### 问题3商机管道仍显示mock数据
**排查步骤**
1. 检查前端代码是否正确导入getOpportunityList
2. 检查onMounted是否调用loadOpportunities
3. 检查opportunityList是否绑定到商机卡片渲染
4. 清空浏览器缓存重新加载页面
---
### 问题4负责人显示为空
**排查步骤**
1. 查询商机数据中的owner_user_id字段
2. 检查用户翻译是否生效UserNameTranslationImpl
3. 查询sys_user表确认用户数据存在
---
## 🎯 功能说明
### 商机管道设计
**数据流**
```
线索(crm_lead)
↓转化
经销商(crm_dealer)
↓自动创建
商机(crm_opportunity) [阶段:lead]
↓跟进推进
└阶段变化: lead → negotiation → proposal → closing
```
**阶段含义**
- **lead线索**:初始商机,刚转化
- **negotiation谈判中**:正在谈判价格和条件
- **proposal方案**:已提交方案报价
- **closing赢单**:即将成交
- **lost输单**:商机失败
**商机管道视图**
- 管道顶部阶段Tab切换全部/线索/谈判中/方案/赢单)
- 管道卡片:商机信息(名称、经销商、负责人、金额、日期)
- 实时计数:各阶段商机数量统计
---
## ✅ 开发总结
### 实现的功能
1. **数据库层**
- 创建crm_opportunity表商机表
- 创建crm_opportunity_follow表跟进记录表
- 初始化商机阶段和状态数据字典
2. **业务逻辑层**
- 商机CRUD完整功能新增、修改、删除、查询
- 线索转化自动创建初始商机
- 商机关联经销商方案A
- 商机数据翻译(经销商名称、负责人姓名)
3. **前端交互层**
- 商机管道使用真实数据渲染
- Pipeline阶段Tab切换和筛选
- 商机卡片动态显示
- 实时计数统计
### 架构关系
**确认的设计方案**
- ✅ 方案A商机关联经销商
- ✅ 商机管道"客户" = 经销商
- ✅ ERP客户是独立对象数据参考源
- ✅ 创建crm_opportunity表
**数据关系图**
```
ERP客户独立对象数据源
↓(可选关联)
线索crm_lead
↓转化
经销商crm_dealer
↓关联
商机crm_opportunity[可多个]
↓跟进
商机跟进记录crm_opportunity_follow
```
---
## 📝 后续开发建议
### 待实现功能
1. **商机跟进功能**
- 添加商机跟进按钮和Dialog
- 创建跟进记录
- AI跟进摘要
2. **商机编辑功能**
- 商机详情查看
- 商机信息修改
- 阶段推进
3. **商机新建功能**
- 直接为经销商创建新商机(不通过线索转化)
4. **商机筛选增强**
- 经销商搜索筛选
- 负责人筛选
- 商机金额范围筛选
5. **商机统计分析**
- 商机金额统计
- 成功率分析
- 阶段转化率分析
---
## 🎯 下一步开发计划
根据"方案A实用优先",后续开发顺序:
**本周剩余时间**:完善商机基础功能
- 商机跟进功能
- 商机详情查看
- 商机编辑功能
**Week 2-3**AI功能
- AI意向分析
- AI跟进摘要
- AI风险分析
**Week 4+**:企业微信集成
---
**当前任务完成请执行SQL并开始测试**

504
docs/crm-testing-guide.md Normal file
View File

@@ -0,0 +1,504 @@
# CRM线索中心模块 - 开发完成与测试指引
## ✅ 开发完成状态
### 后端开发hzhub-system- 已完成
**创建文件统计**
- 数据库SQL1个
- Entity实体类2个
- Bo业务对象2个
- Vo视图对象2个
- Mapper接口2个
- Mapper XML2个
- Service接口与实现4个
- Controller控制器2个
- ERP集成服务1个
- RestTemplate配置1个
- application.yml配置1个修改
**总计**19个代码文件 + 1个SQL文件 + 1个配置修改
---
### 前端开发hzhub-portal-employee- 已完成
**创建文件统计**
- API类型定义1个types.ts
- API调用方法1个index.ts
- 页面扩展1个/crm/index.vue从107行扩展到779行
**总计**2个API文件 + 1个页面扩展
---
### Gateway配置 - 已完成
**路由配置**
- 已添加 `/crm/**` 路由到 hzhub-system 服务
- 配置文件:`hzhub-gateway/src/main/resources/application.yml`
---
## 🚀 启动测试步骤
### 步骤1数据库初始化
**执行SQL脚本**
```bash
# 登录MySQL
mysql -h localhost -u root -p
# 执行初始化SQL
source /data/hzhub/hzhub-system/src/main/resources/db/crm_lead_init.sql;
# 检查表创建和数据字典
show tables like 'crm_%';
select * from sys_dict_type where dict_type like 'crm_%';
```
**SQL文件内容**
- 创建 `crm_lead` 表(线索表)
- 创建 `crm_lead_follow` 表(跟进记录表)
- 初始化5个数据字典
- crm_lead_source线索来源
- crm_lead_status线索状态
- crm_intent_levelAI意向等级
- crm_risk_level风险等级
- crm_follow_type跟进方式
---
### 步骤2启动后端服务
**启动顺序**(按依赖关系):
#### 1. 启动基础设施
```bash
cd hzhub-deploy
docker-compose up -d mysql redis weaviate
# 检查服务状态
docker-compose ps
```
#### 2. 启动 hzhub-ai可选第一阶段不需要AI功能
```bash
cd hzhub-ai/hzhub-admin
mvn spring-boot:run -Dspring-boot.run.profiles=dev
```
**注意**第一阶段测试不需要启动AI服务AI功能在第二阶段实现。
#### 3. 启动 hzhub-system必须
```bash
cd hzhub-system
mvn spring-boot:run -Dspring-boot.run.profiles=dev
```
**验证**
- 访问http://localhost:8083/actuator/health
- 确认服务健康状态为 UP
#### 4. 启动 hzhub-erp可选测试ERP关联功能
```bash
cd hzhub-erp
mvn spring-boot:run -Dspring-boot.run.profiles=dev
```
**注意**如果要测试ERP客户关联功能需要启动ERP服务。
#### 5. 启动 hzhub-gateway必须
```bash
cd hzhub-gateway
mvn spring-boot:run -Dspring-boot.run.profiles=dev
```
**验证**
- 访问http://localhost:8080/actuator/health
- 确认服务健康状态为 UP
---
### 步骤3启动前端服务
```bash
cd hzhub-portal-employee
pnpm install # 如果没有安装依赖
pnpm dev
```
**访问**http://localhost:5137
**验证**
- 登录员工门户
- 导航到"销售CRM"页面
- 确认页面正常加载
---
## 🧪 功能测试清单
### 测试1Tab切换功能
**测试步骤**
1. 登录员工门户http://localhost:5137
2. 点击左侧菜单"销售CRM"
3. 确认默认显示"商机管道"Tab
4. 点击"线索管理"Tab
5. 确认线索列表自动加载
**预期结果**
- Tab切换流畅无卡顿
- 切换到"线索管理"时显示空列表或现有线索数据
---
### 测试2新建线索功能
**测试步骤**
1. 在"线索管理"Tab点击"新建线索"按钮
2. 填写必填字段:
- 公司名称:测试贸易有限公司
- 联系人:张三
- 手机号13800138000
3. 选择来源类型:活动
4. 填写活动名称:春季招商会
5. 点击"创建线索"
**预期结果**
- 显示"创建成功"提示
- 线索列表自动刷新,显示新创建的线索
- 手机号脱敏显示为138****8000
**后端验证**
```sql
select * from crm_lead order by create_time desc limit 1;
```
---
### 测试3ERP客户关联功能需要启动ERP服务
**测试步骤**
1. 新建线索时,不填写基础信息
2. 填写ERP客户编码C001需要ERP中存在的客户编码
3. 点击"创建线索"
**预期结果**
- 后端自动从ERP拉取客户信息
- 线索列表显示的公司名称、联系人、手机号来自ERP
- ERP编码显示为蓝色链接
**后端验证**
- 查看后端日志确认调用ERP API`GET /erp/dynamic/v1/customer/detail?customerCode=C001`
---
### 测试4线索详情查看
**测试步骤**
1. 在线索列表中,点击某个线索的"详情"按钮
2. 查看详情Drawer展示
3. 确认字段完整显示
**预期结果**
- Drawer右侧打开宽度50%
- 公司名称、联系人、手机号完整显示(未脱敏)
- AI意向评分显示进度条初始可能为空第二阶段AI分析后填充
- 风险等级显示标签
- ERP编码显示链接如果有
---
### 测试5线索跟进功能
**测试步骤**
1. 在线索列表中,点击某个线索的"跟进"按钮
2. 选择跟进方式:电话
3. 输入跟进内容:与客户沟通了合作意向,客户对产品感兴趣
4. 选择下次跟进时间:明天
5. 点击"保存跟进"
**预期结果**
- 显示"跟进成功"提示
- Drawer关闭
- 线索列表刷新,"下次跟进时间"列更新
**详情验证**
1. 打开线索详情Drawer
2. 查看跟进记录Timeline
3. 确认最新跟进记录显示在最上方
4. AI摘要字段可能为空第二阶段实现
**后端验证**
```sql
select * from crm_lead_follow where lead_id = {线ID} order by create_time desc;
```
---
### 测试6线索筛选功能
**测试步骤**
1. 在"线索管理"Tab的筛选栏
2. 输入关键词:测试
3. 选择AI意向等级高意向
4. 选择线索状态:跟进中
5. 点击"搜索"
**预期结果**
- 线索列表只显示符合条件的记录
- 分页总数更新
- 清空筛选条件后,列表恢复完整显示
---
### 测试7线索分配功能
**测试步骤**
1. 在线索列表中,点击某个线索的"分配"按钮暂未在UI显示需要后端接口测试
2. 使用API工具如Postman测试
```
PUT http://localhost:8080/crm/lead/assign
Headers: Authorization: Bearer {token}
Body: {
"leadId": 1,
"ownerUserId": 12345
}
```
**预期结果**
- 后端返回:{"code":200,"msg":"分配成功"}
- 线索负责人更新为指定用户
---
### 测试8线索删除功能
**测试步骤**
1. 在线索列表中,点击某个线索的"删除"按钮暂未在UI显示需要后端接口测试
2. 使用API工具测试
```
DELETE http://localhost:8080/crm/lead/1
Headers: Authorization: Bearer {token}
```
**预期结果**
- 后端返回:{"code":200,"msg":"删除成功"}
- 线索从列表消失(逻辑删除)
**后端验证**
```sql
select * from crm_lead where lead_id = 1; -- del_flag = 1
```
---
## 🔧 配置检查清单
### 1. 数据库配置
**检查MySQL连接**
```bash
mysql -h localhost -u root -p -e "show databases like 'hzhub';"
```
**检查CRM表创建**
```sql
use hzhub;
show tables like 'crm_%';
desc crm_lead;
desc crm_lead_follow;
```
---
### 2. 数据字典配置
**检查字典类型**
```sql
select dict_type, dict_name from sys_dict_type where dict_type like 'crm_%';
```
**预期结果**
- crm_lead_source - 线索来源
- crm_lead_status - 线索状态
- crm_intent_level - AI意向等级
- crm_risk_level - 风险等级
- crm_follow_type - 跟进方式
---
### 3. Gateway路由配置
**检查路由配置**
```bash
cat hzhub-gateway/src/main/resources/application.yml | grep -A 10 "hzhub-crm"
```
**预期结果**
```yaml
- id: hzhub-crm
uri: http://${SYSTEM_HOST:localhost}:${SYSTEM_PORT:8083}
predicates:
- Path=/crm/**
filters:
- StripPrefix=1
```
---
### 4. ERP服务配置
**检查ERP配置**
```bash
cat hzhub-system/src/main/resources/application.yml | grep "erp.base-url"
```
**预期结果**
```yaml
erp:
base-url: ${ERP_BASE_URL:http://localhost:8082}
```
---
## 🐛 常见问题排查
### 问题1线索列表加载失败
**排查步骤**
1. 检查hzhub-system服务是否启动
2. 检查Gateway路由配置
3. 检查数据库表是否创建
4. 查看浏览器Console错误日志
5. 查看后端日志:`tail -f hzhub-system/logs/hzhub-system.log`
---
### 问题2新建线索失败
**排查步骤**
1. 检查数据库连接是否正常
2. 检查数据字典是否初始化
3. 检查必填字段是否填写
4. 查看后端日志中的错误信息
---
### 问题3ERP客户关联失败
**排查步骤**
1. 检查hzhub-erp服务是否启动
2. 检查ERP服务健康http://localhost:8082/erp/test/health
3. 检查customerCode是否在ERP中存在
4. 查看hzhub-system日志中的ERP调用记录
---
### 问题4Gateway路由失败
**排查步骤**
1. 检查Gateway服务是否启动
2. 检查Gateway日志`tail -f hzhub-gateway/logs/hzhub-gateway.log`
3. 确认路由配置顺序CRM路由在hzhub-ai-workflow之前
4. 测试Gateway健康http://localhost:8080/actuator/health
---
## 📊 性能测试建议
### API响应时间测试
**使用Postman或curl测试**
```bash
# 线索列表查询
curl -w "\nTime: %{time_total}s\n" \
-H "Authorization: Bearer {token}" \
"http://localhost:8080/crm/lead/list?pageNum=1&pageSize=10"
# 线索详情查询
curl -w "\nTime: %{time_total}s\n" \
-H "Authorization: Bearer {token}" \
"http://localhost:8080/crm/lead/1"
```
**预期响应时间**
- 列表查询:< 200ms
- 详情查询:< 100ms
- 新增线索:< 300ms含ERP调用
---
## 🎯 第二阶段功能预告
### 待实现功能
1. **AI意向分析**
- 调用hzhub-ai服务分析线索意向
- 自动生成AI评分
2. **AI跟进摘要**
- 使用LangChain4j生成跟进摘要
- 自动提取关键信息
3. **线索转经销商**
- 完整的转化流程UI
- 创建经销商数据
4. **用户选择器**
- 分配线索时使用真实的用户选择组件
5. **企业微信集成**
- 移动端H5页面
- 企业微信侧边栏
---
## 📝 测试报告模板
**测试日期**{填写日期}
**测试人员**{填写姓名}
**测试环境**
- MySQL版本8.0.x
- Redis版本7.x
- Node版本22.x
- JDK版本17
**测试结果**
| 测试项 | 结果 | 备注 |
|---|---|---|
| Tab切换 | ✅ | |
| 新建线索 | ✅ | |
| ERP关联 | ❌ | |
| 线索详情 | ✅ | |
| 线索跟进 | ✅ | |
| 线索筛选 | ✅ | |
| 线索分配 | ✅/❌ | |
| 线索删除 | ✅/❌ | |
**问题记录**
1. {问题描述}
2. {问题描述}
---
## ✅ 完成确认
**请按照以上步骤进行测试,完成后告知测试结果,以便继续第二阶段开发!**