Files
mp-java/docs/ai/后端实现指南.md
赵忠林 9c929301b9 feat(credit): 添加客户跟进七步骤功能
- 在CreditMpCustomer实体类中添加七个跟进步骤相关字段
- 实现跟进步骤审核功能,包括单个和批量审核接口
- 添加待审核步骤查询接口和客户跟进统计功能
- 实现流程结束功能和详细的步骤状态管理
- 创建相应的DTO和VO数据传输对象
- 在Mapper层添加待审核步骤查询SQL实现
2026-03-22 22:32:02 +08:00

459 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 客户跟进7步骤后端实现指南
## 📋 概述
本指南详细说明如何实现客户跟进7个步骤功能的后端代码包括数据库设计、Java后端实现和API接口。
## 🗄️ 数据库设计
### 1. 修改 credit_mp_customer 表结构
```sql
-- 为第5-7步添加字段第1-4步字段已存在
-- 第5步合同签订
ALTER TABLE credit_mp_customer ADD COLUMN follow_step5_submitted TINYINT DEFAULT 0 COMMENT '是否已提交';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step5_submitted_at VARCHAR(255) COMMENT '提交时间';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step5_contracts TEXT COMMENT '合同信息JSON数组';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step5_need_approval TINYINT DEFAULT 1 COMMENT '是否需要审核';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step5_approved TINYINT DEFAULT 0 COMMENT '是否审核通过';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step5_approved_at VARCHAR(255) COMMENT '审核时间';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step5_approved_by BIGINT COMMENT '审核人ID';
-- 第6步订单回款
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_submitted TINYINT DEFAULT 0 COMMENT '是否已提交';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_submitted_at VARCHAR(255) COMMENT '提交时间';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_payment_records TEXT COMMENT '财务录入的回款记录JSON数组';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_expected_payments TEXT COMMENT '预计回款JSON数组';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_need_approval TINYINT DEFAULT 1 COMMENT '是否需要审核';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_approved TINYINT DEFAULT 0 COMMENT '是否审核通过';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_approved_at VARCHAR(255) COMMENT '审核时间';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step6_approved_by BIGINT COMMENT '审核人ID';
-- 第7步电话回访
ALTER TABLE credit_mp_customer ADD COLUMN follow_step7_submitted TINYINT DEFAULT 0 COMMENT '是否已提交';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step7_submitted_at VARCHAR(255) COMMENT '提交时间';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step7_visit_records TEXT COMMENT '回访记录JSON数组';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step7_need_approval TINYINT DEFAULT 1 COMMENT '是否需要审核';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step7_approved TINYINT DEFAULT 0 COMMENT '是否审核通过';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step7_approved_at VARCHAR(255) COMMENT '审核时间';
ALTER TABLE credit_mp_customer ADD COLUMN follow_step7_approved_by BIGINT COMMENT '审核人ID';
-- 添加流程结束相关字段
ALTER TABLE credit_mp_customer ADD COLUMN follow_process_ended TINYINT DEFAULT 0 COMMENT '流程是否已结束';
ALTER TABLE credit_mp_customer ADD COLUMN follow_process_end_time VARCHAR(255) COMMENT '流程结束时间';
ALTER TABLE credit_mp_customer ADD COLUMN follow_process_end_reason TEXT COMMENT '流程结束原因';
```
### 2. 创建审核记录表(可选)
```sql
CREATE TABLE credit_follow_approval (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
customer_id BIGINT NOT NULL COMMENT '客户ID',
step TINYINT NOT NULL COMMENT '步骤号',
approved TINYINT NOT NULL COMMENT '是否通过',
remark TEXT COMMENT '审核备注',
approved_by BIGINT COMMENT '审核人ID',
approved_at VARCHAR(255) COMMENT '审核时间',
created_at VARCHAR(255) COMMENT '创建时间',
INDEX idx_customer_step (customer_id, step),
INDEX idx_approved_by (approved_by)
) COMMENT='跟进步骤审核记录';
```
## ☕ Java后端实现
### 1. 实体类修改
```java
// CreditMpCustomer.java 添加字段
public class CreditMpCustomer {
// ... 现有字段
// 第5步字段
private Integer followStep5Submitted;
private String followStep5SubmittedAt;
private String followStep5Contracts;
private Integer followStep5NeedApproval;
private Integer followStep5Approved;
private String followStep5ApprovedAt;
private Long followStep5ApprovedBy;
// 第6步字段
private Integer followStep6Submitted;
private String followStep6SubmittedAt;
private String followStep6PaymentRecords;
private String followStep6ExpectedPayments;
private Integer followStep6NeedApproval;
private Integer followStep6Approved;
private String followStep6ApprovedAt;
private Long followStep6ApprovedBy;
// 第7步字段
private Integer followStep7Submitted;
private String followStep7SubmittedAt;
private String followStep7VisitRecords;
private Integer followStep7NeedApproval;
private Integer followStep7Approved;
private String followStep7ApprovedAt;
private Long followStep7ApprovedBy;
// 流程结束字段
private Integer followProcessEnded;
private String followProcessEndTime;
private String followProcessEndReason;
// getter/setter 方法...
}
```
### 2. DTO类创建
```java
// FollowStepApprovalDTO.java
@Data
public class FollowStepApprovalDTO {
private Long customerId;
private Integer step;
private Boolean approved;
private String remark;
}
// BatchFollowStepApprovalDTO.java
@Data
public class BatchFollowStepApprovalDTO {
private List<FollowStepApprovalDTO> approvals;
}
// FollowStatisticsDTO.java
@Data
public class FollowStatisticsDTO {
private Integer totalSteps;
private Integer completedSteps;
private Integer currentStep;
private Double progress;
private List<FollowStepDetailDTO> stepDetails;
}
// FollowStepDetailDTO.java
@Data
public class FollowStepDetailDTO {
private Integer step;
private String title;
private String status; // pending, submitted, approved, rejected
private String submittedAt;
private String approvedAt;
}
```
### 3. Service层实现
```java
// CreditMpCustomerServiceImpl.java 添加方法
@Service
public class CreditMpCustomerServiceImpl implements CreditMpCustomerService {
/**
* 审核跟进步骤
*/
@Override
@Transactional
public void approveFollowStep(FollowStepApprovalDTO dto) {
CreditMpCustomer customer = getById(dto.getCustomerId());
if (customer == null) {
throw new ServiceException("客户不存在");
}
// 验证步骤是否已提交
if (!isStepSubmitted(customer, dto.getStep())) {
throw new ServiceException("该步骤尚未提交,无法审核");
}
// 更新审核状态
updateStepApproval(customer, dto);
// 记录审核日志
saveApprovalLog(dto);
// 如果审核通过,更新客户步骤状态
if (dto.getApproved()) {
updateCustomerStep(customer, dto.getStep());
}
}
/**
* 批量审核跟进步骤
*/
@Override
@Transactional
public void batchApproveFollowSteps(BatchFollowStepApprovalDTO dto) {
for (FollowStepApprovalDTO approval : dto.getApprovals()) {
approveFollowStep(approval);
}
}
/**
* 获取待审核的跟进步骤列表
*/
@Override
public List<PendingApprovalStepVO> getPendingApprovalSteps(FollowStepQueryDTO query) {
return baseMapper.selectPendingApprovalSteps(query);
}
/**
* 获取客户跟进统计
*/
@Override
public FollowStatisticsDTO getFollowStatistics(Long customerId) {
CreditMpCustomer customer = getById(customerId);
if (customer == null) {
throw new ServiceException("客户不存在");
}
FollowStatisticsDTO statistics = new FollowStatisticsDTO();
statistics.setTotalSteps(7);
List<FollowStepDetailDTO> stepDetails = new ArrayList<>();
int completedSteps = 0;
int currentStep = 1;
for (int i = 1; i <= 7; i++) {
FollowStepDetailDTO detail = getStepDetail(customer, i);
stepDetails.add(detail);
if ("approved".equals(detail.getStatus())) {
completedSteps++;
currentStep = i + 1;
} else if ("submitted".equals(detail.getStatus()) && currentStep == 1) {
currentStep = i;
}
}
statistics.setCompletedSteps(completedSteps);
statistics.setCurrentStep(Math.min(currentStep, 7));
statistics.setProgress((double) completedSteps / 7 * 100);
statistics.setStepDetails(stepDetails);
return statistics;
}
/**
* 结束客户跟进流程
*/
@Override
@Transactional
public void endFollowProcess(Long customerId, String reason) {
CreditMpCustomer customer = getById(customerId);
if (customer == null) {
throw new ServiceException("客户不存在");
}
customer.setFollowProcessEnded(1);
customer.setFollowProcessEndTime(DateUtil.formatDateTime(new Date()));
customer.setFollowProcessEndReason(reason);
updateById(customer);
}
// 私有辅助方法...
private boolean isStepSubmitted(CreditMpCustomer customer, Integer step) {
switch (step) {
case 1: return customer.getFollowStep1Submitted() == 1;
case 2: return customer.getFollowStep2Submitted() == 1;
// ... 其他步骤
case 7: return customer.getFollowStep7Submitted() == 1;
default: return false;
}
}
private void updateStepApproval(CreditMpCustomer customer, FollowStepApprovalDTO dto) {
String currentTime = DateUtil.formatDateTime(new Date());
Long currentUserId = SecurityFrameworkUtils.getLoginUserId();
switch (dto.getStep()) {
case 5:
customer.setFollowStep5Approved(dto.getApproved() ? 1 : 0);
customer.setFollowStep5ApprovedAt(currentTime);
customer.setFollowStep5ApprovedBy(currentUserId);
break;
case 6:
customer.setFollowStep6Approved(dto.getApproved() ? 1 : 0);
customer.setFollowStep6ApprovedAt(currentTime);
customer.setFollowStep6ApprovedBy(currentUserId);
break;
case 7:
customer.setFollowStep7Approved(dto.getApproved() ? 1 : 0);
customer.setFollowStep7ApprovedAt(currentTime);
customer.setFollowStep7ApprovedBy(currentUserId);
break;
}
updateById(customer);
}
}
```
### 4. Controller层实现
```java
// CreditMpCustomerController.java 添加接口
@RestController
@RequestMapping("/credit/credit-mp-customer")
public class CreditMpCustomerController {
@PostMapping("/approve-follow-step")
@OperLog(title = "审核跟进步骤", businessType = BusinessType.UPDATE)
public R<Void> approveFollowStep(@RequestBody FollowStepApprovalDTO dto) {
creditMpCustomerService.approveFollowStep(dto);
return R.ok();
}
@PostMapping("/batch-approve-follow-steps")
@OperLog(title = "批量审核跟进步骤", businessType = BusinessType.UPDATE)
public R<Void> batchApproveFollowSteps(@RequestBody BatchFollowStepApprovalDTO dto) {
creditMpCustomerService.batchApproveFollowSteps(dto);
return R.ok();
}
@GetMapping("/pending-approval-steps")
@OperLog(title = "获取待审核跟进步骤", businessType = BusinessType.SELECT)
public R<List<PendingApprovalStepVO>> getPendingApprovalSteps(FollowStepQueryDTO query) {
List<PendingApprovalStepVO> list = creditMpCustomerService.getPendingApprovalSteps(query);
return R.ok(list);
}
@GetMapping("/follow-statistics/{customerId}")
@OperLog(title = "获取客户跟进统计", businessType = BusinessType.SELECT)
public R<FollowStatisticsDTO> getFollowStatistics(@PathVariable Long customerId) {
FollowStatisticsDTO statistics = creditMpCustomerService.getFollowStatistics(customerId);
return R.ok(statistics);
}
@PostMapping("/end-follow-process")
@OperLog(title = "结束客户跟进流程", businessType = BusinessType.UPDATE)
public R<Void> endFollowProcess(@RequestBody EndFollowProcessDTO dto) {
creditMpCustomerService.endFollowProcess(dto.getCustomerId(), dto.getReason());
return R.ok();
}
}
```
### 5. Mapper层SQL
```xml
<!-- CreditMpCustomerMapper.xml 添加查询方法 -->
<select id="selectPendingApprovalSteps" resultType="com.your.package.PendingApprovalStepVO">
SELECT
c.id as customerId,
c.to_user as customerName,
5 as step,
'合同签订' as stepTitle,
c.follow_step5_submitted_at as submittedAt,
u.real_name as submittedBy,
c.follow_step5_contracts as content
FROM credit_mp_customer c
LEFT JOIN sys_user u ON c.user_id = u.user_id
WHERE c.follow_step5_submitted = 1
AND c.follow_step5_approved = 0
AND c.deleted = 0
UNION ALL
SELECT
c.id as customerId,
c.to_user as customerName,
6 as step,
'订单回款' as stepTitle,
c.follow_step6_submitted_at as submittedAt,
u.real_name as submittedBy,
c.follow_step6_expected_payments as content
FROM credit_mp_customer c
LEFT JOIN sys_user u ON c.user_id = u.user_id
WHERE c.follow_step6_submitted = 1
AND c.follow_step6_approved = 0
AND c.deleted = 0
UNION ALL
SELECT
c.id as customerId,
c.to_user as customerName,
7 as step,
'电话回访' as stepTitle,
c.follow_step7_submitted_at as submittedAt,
u.real_name as submittedBy,
c.follow_step7_visit_records as content
FROM credit_mp_customer c
LEFT JOIN sys_user u ON c.user_id = u.user_id
WHERE c.follow_step7_submitted = 1
AND c.follow_step7_approved = 0
AND c.deleted = 0
<if test="step != null">
HAVING step = #{step}
</if>
<if test="customerId != null">
HAVING customerId = #{customerId}
</if>
ORDER BY submittedAt DESC
</select>
```
## 🔧 业务逻辑说明
### 1. 步骤解锁机制
- 第一步始终可用
- 后续步骤需要前一步审核通过才能进行
- 前端通过 `canEnterStep` 逻辑控制
### 2. 审核流程
- 步骤提交后设置 `needApproval = 1`
- 管理员在后台审核
- 审核通过后设置 `approved = 1` 并更新时间
### 3. 数据格式
- 所有复杂数据使用JSON格式存储
- 文件上传返回URL存储在JSON数组中
- 时间统一使用 `YYYY-MM-DD HH:mm:ss` 格式
### 4. 权限控制
- 销售只能提交和查看自己的客户
- 管理员可以审核所有步骤
- 财务人员可以录入第6步回款数据
## 📱 前端集成
前端代码已经完成,包括:
- 7个步骤的完整页面
- 步骤状态显示和跳转逻辑
- 数据提交和验证
- 客户详情页面的汇总显示
## 🚀 部署步骤
1. 执行数据库迁移脚本
2. 部署Java后端代码
3. 更新前端API调用
4. 测试完整流程
5. 配置权限和审核流程
## 📝 注意事项
1. **数据备份**:执行数据库变更前请备份
2. **权限配置**:确保各角色权限正确配置
3. **文件上传**:确认文件上传服务正常
4. **审核流程**:测试审核流程的完整性
5. **性能优化**:大量数据时考虑分页和索引优化
## 🔄 后续扩展
可以考虑的功能:
- 跟进模板和标准化流程
- 自动提醒和通知
- 数据统计和报表
- 跟进效率分析
- 客户满意度评估