Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 76c68cd544 | |||
| fedf789511 |
88
ibs-group/pom.xml
Normal file
88
ibs-group/pom.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>3.8.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ibs-group</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Mockito依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.3.3</version> <!-- 请根据需要选择合适的版本 -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- JUnit依赖 -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version> <!-- 请根据需要选择合适的版本 -->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.locationtech.jts</groupId>
|
||||
<artifactId>jts-core</artifactId>
|
||||
<version>1.18.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>5.3.31</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.postgresql</groupId>-->
|
||||
<!-- <artifactId>postgresql</artifactId>-->
|
||||
<!-- <version>42.3.3</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel-core</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
<version>5.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ibs</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,164 @@
|
||||
package com.ruoyi.group.controller;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberTemplate;
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.dto.GridImportDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import com.ruoyi.group.service.ICustGroupService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "客群管理接口")
|
||||
@RestController
|
||||
@RequestMapping("/group/cust")
|
||||
public class CustGroupController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private ICustGroupService custGroupService;
|
||||
|
||||
/**
|
||||
* 查询客群列表
|
||||
*/
|
||||
@ApiOperation("查询客群列表")
|
||||
@Log(title = "客群管理-查询客群列表")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo listCustGroup(CustGroupQueryDTO dto) {
|
||||
startPage();
|
||||
List<CustGroupVO> list = custGroupService.listCustGroup(dto);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客群详情
|
||||
*/
|
||||
@ApiOperation("获取客群详情")
|
||||
@Log(title = "客群管理-获取客群详情")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getCustGroup(@PathVariable Long id) {
|
||||
CustGroupVO vo = custGroupService.getCustGroup(id);
|
||||
return AjaxResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步创建客群(网格导入)
|
||||
*/
|
||||
@ApiOperation("异步创建客群(网格导入)")
|
||||
@Log(title = "客群管理-网格导入创建客群", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/createByGrid")
|
||||
public AjaxResult createCustGroupByGrid(@RequestBody @Valid GridImportDTO gridImportDTO) {
|
||||
String id = custGroupService.createCustGroupByGrid(gridImportDTO);
|
||||
return AjaxResult.success(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步创建客群(模板导入)
|
||||
*/
|
||||
@ApiOperation("异步创建客群(模板导入)")
|
||||
@Log(title = "客群管理-异步创建客群", businessType = BusinessType.INSERT)
|
||||
@PostMapping(value = "/createByTemplate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public AjaxResult createCustGroupByTemplate(@RequestPart("dto") @Valid String dtoJson,
|
||||
@RequestPart("file") MultipartFile file) {
|
||||
CustGroup custGroup = JSON.parseObject(dtoJson, CustGroup.class);
|
||||
return AjaxResult.success(custGroupService.createCustGroupByTemplate(custGroup, file));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新客群
|
||||
*/
|
||||
@ApiOperation("更新客群")
|
||||
@Log(title = "客群管理-更新客群", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/update")
|
||||
public AjaxResult updateCustGroup(@RequestBody @Valid CustGroup custGroup) {
|
||||
String result = custGroupService.updateCustGroup(custGroup);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新客群(网格导入)
|
||||
*/
|
||||
@ApiOperation("更新客群(网格导入)")
|
||||
@Log(title = "客群管理-更新客群(网格导入)", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/updateByGrid")
|
||||
public AjaxResult updateCustGroupByGrid(@RequestBody @Valid GridImportDTO gridImportDTO) {
|
||||
String result = custGroupService.updateCustGroupByGrid(gridImportDTO);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新客群(模板导入)
|
||||
*/
|
||||
@ApiOperation("更新客群(模板导入)")
|
||||
@Log(title = "客群管理-更新客群(模板导入)", businessType = BusinessType.UPDATE)
|
||||
@PostMapping(value = "/updateByTemplate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public AjaxResult updateCustGroupByTemplate(@RequestPart("dto") @Valid String dtoJson,
|
||||
@RequestPart("file") MultipartFile file) {
|
||||
CustGroup custGroup = JSON.parseObject(dtoJson, CustGroup.class);
|
||||
return AjaxResult.success(custGroupService.updateCustGroupByTemplate(custGroup, file));
|
||||
}
|
||||
|
||||
/**
|
||||
* 轮询客群创建状态
|
||||
*/
|
||||
@ApiOperation("轮询客群创建状态")
|
||||
@Log(title = "客群管理-轮询客群创建状态")
|
||||
@GetMapping("/createStatus/{id}")
|
||||
public AjaxResult getCreateStatus(@PathVariable Long id) {
|
||||
String status = custGroupService.getCreateStatus(id);
|
||||
return AjaxResult.success(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户信息模板下载
|
||||
*/
|
||||
@ApiOperation("客户信息模板")
|
||||
@Log(title = "客群管理-客户信息模板", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/download")
|
||||
public void download(HttpServletResponse response) {
|
||||
ExcelUtil<CustGroupMemberTemplate> util = new ExcelUtil<>(CustGroupMemberTemplate.class);
|
||||
util.exportExcel(response, null, "客户信息模板");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除客群
|
||||
*/
|
||||
@ApiOperation("删除客群")
|
||||
@Log(title = "客群管理-删除客群", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/delete")
|
||||
public AjaxResult deleteCustGroup(@RequestBody List<Long> idList) {
|
||||
String result = custGroupService.deleteCustGroup(idList);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动移除客群客户
|
||||
*/
|
||||
@ApiOperation("手动移除客群客户")
|
||||
@Log(title = "客群管理-手动移除客户", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/removeMembers")
|
||||
public AjaxResult removeMembers(@RequestParam Long groupId, @RequestBody List<Long> memberIds) {
|
||||
String result = custGroupService.removeMembers(groupId, memberIds);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.ruoyi.group.domain.dto;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 客群客户Excel模板
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupMemberTemplate {
|
||||
|
||||
/**
|
||||
* 客户类型
|
||||
*/
|
||||
@ApiModelProperty(value = "客户类型:个人/企业/商户", name = "custType")
|
||||
@Excel(name = "客户类型(个人/企业/商户)", prompt = "必填", combo = "个人,企业,商户")
|
||||
private String custType;
|
||||
|
||||
/**
|
||||
* 客户号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户号", name = "custId")
|
||||
@Excel(name = "客户号", prompt = "必填")
|
||||
private String custId;
|
||||
|
||||
/**
|
||||
* 客户姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户姓名", name = "custName")
|
||||
@Excel(name = "客户姓名")
|
||||
private String custName;
|
||||
|
||||
/**
|
||||
* 客户身份证号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户身份证号(个人客户必填)", name = "custIdc")
|
||||
@Excel(name = "客户身份证号(个人客户必填)")
|
||||
private String custIdc;
|
||||
|
||||
/**
|
||||
* 统信码
|
||||
*/
|
||||
@ApiModelProperty(value = "统信码(企业/商户客户必填)", name = "socialCreditCode")
|
||||
@Excel(name = "统信码(企业/商户客户必填)")
|
||||
private String socialCreditCode;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.group.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客群查询DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupQueryDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 客群名称(模糊查询)
|
||||
*/
|
||||
@ApiModelProperty(value = "客群名称", name = "groupName")
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 客群模式:0=静态, 1=动态
|
||||
*/
|
||||
@ApiModelProperty(value = "客群模式", name = "groupMode")
|
||||
private String groupMode;
|
||||
|
||||
/**
|
||||
* 创建方式:1=模板导入, 2=绩效网格, 3=地理网格, 4=自定义网格
|
||||
*/
|
||||
@ApiModelProperty(value = "创建方式", name = "createMode")
|
||||
private String createMode;
|
||||
|
||||
/**
|
||||
* 客群状态:0=正常, 1=已禁用
|
||||
*/
|
||||
@ApiModelProperty(value = "客群状态", name = "groupStatus")
|
||||
private String groupStatus;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
@ApiModelProperty(value = "页码", name = "pageNum")
|
||||
private Integer pageNum = 1;
|
||||
|
||||
/**
|
||||
* 每页大小
|
||||
*/
|
||||
@ApiModelProperty(value = "每页大小", name = "pageSize")
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.ruoyi.group.domain.dto;
|
||||
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网格导入客群DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class GridImportDTO {
|
||||
|
||||
/**
|
||||
* 客群信息
|
||||
*/
|
||||
@ApiModelProperty(value = "客群信息", name = "custGroup")
|
||||
@Valid
|
||||
@NotNull(message = "客群信息不能为空")
|
||||
private CustGroup custGroup;
|
||||
|
||||
/**
|
||||
* 网格类型:0=绩效网格, 1=地理网格, 2=绘制网格
|
||||
*/
|
||||
@ApiModelProperty(value = "网格类型:0=绩效网格, 1=地理网格, 2=绘制网格", name = "gridType")
|
||||
@NotBlank(message = "网格类型不能为空")
|
||||
private String gridType;
|
||||
|
||||
/**
|
||||
* 绩效网格业务类型:retail=零售, corporate=公司(gridType=0时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "绩效网格业务类型:retail=零售, corporate=公司", name = "cmpmBizType")
|
||||
private String cmpmBizType;
|
||||
|
||||
/**
|
||||
* 绩效网格客户经理柜员号列表(gridType=0时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理柜员号列表", name = "userNames")
|
||||
private List<String> userNames;
|
||||
|
||||
/**
|
||||
* 地理网格ID列表(gridType=1时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "地理网格ID列表", name = "regionGridIds")
|
||||
private List<Long> regionGridIds;
|
||||
|
||||
/**
|
||||
* 绘制网格ID列表(gridType=2时必填)
|
||||
*/
|
||||
@ApiModelProperty(value = "绘制网格ID列表", name = "drawGridIds")
|
||||
private List<Long> drawGridIds;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群实体
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@TableName("ibs_cust_group")
|
||||
public class CustGroup {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群名称
|
||||
*/
|
||||
@ApiModelProperty(value = "客群名称", name = "groupName")
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 客群模式:0=静态, 1=动态
|
||||
*/
|
||||
@ApiModelProperty(value = "客群模式:0=静态, 1=动态", name = "groupMode")
|
||||
private String groupMode;
|
||||
|
||||
/**
|
||||
* 创建方式:1=模板导入, 2=绩效网格, 3=地理网格, 4=自定义网格
|
||||
*/
|
||||
@ApiModelProperty(value = "创建方式:1=模板导入, 2=绩效网格, 3=地理网格, 4=自定义网格", name = "createMode")
|
||||
private String createMode;
|
||||
|
||||
/**
|
||||
* 柜员号
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员号", name = "userName")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 柜员名称
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员名称", name = "nickName")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 所属机构ID
|
||||
*/
|
||||
@ApiModelProperty(value = "所属机构ID", name = "deptId")
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 是否开启共享:0=否, 1=是
|
||||
*/
|
||||
@ApiModelProperty(value = "是否开启共享:0=否, 1=是", name = "shareEnabled")
|
||||
private Integer shareEnabled;
|
||||
|
||||
/**
|
||||
* 可见部门ID列表(逗号分隔)
|
||||
*/
|
||||
@ApiModelProperty(value = "可见部门ID列表(逗号分隔)", name = "shareDeptIds")
|
||||
private String shareDeptIds;
|
||||
|
||||
/**
|
||||
* 共享部门ID列表(非表字段,用于接收前端传参)
|
||||
*/
|
||||
@ApiModelProperty(value = "共享部门ID列表", name = "shareDeptIdList")
|
||||
@TableField(exist = false)
|
||||
private List<Long> shareDeptIdList;
|
||||
|
||||
/**
|
||||
* 客群状态:0=正常, 1=已禁用
|
||||
*/
|
||||
@ApiModelProperty(value = "客群状态:0=正常, 1=已禁用", name = "groupStatus")
|
||||
private String groupStatus;
|
||||
|
||||
/**
|
||||
* 创建状态:0=创建中, 1=创建成功, 2=创建失败
|
||||
*/
|
||||
@ApiModelProperty(value = "创建状态:0=创建中, 1=创建成功, 2=创建失败", name = "createStatus")
|
||||
private String createStatus;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 删除标识:0=正常, 1=删除
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
@TableField("del_flag")
|
||||
private Integer delFlag;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ApiModelProperty(value = "备注", name = "remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 网格类型:0=绩效网格, 1=地理网格, 2=绘制网格(动态客群使用)
|
||||
*/
|
||||
@ApiModelProperty(value = "网格类型", name = "gridType")
|
||||
private String gridType;
|
||||
|
||||
/**
|
||||
* 绩效业务类型:retail=零售, corporate=公司(动态客群使用)
|
||||
*/
|
||||
@ApiModelProperty(value = "绩效业务类型", name = "cmpmBizType")
|
||||
private String cmpmBizType;
|
||||
|
||||
/**
|
||||
* 客户经理列表(逗号分隔,动态客群使用)
|
||||
*/
|
||||
@ApiModelProperty(value = "客户经理列表", name = "gridUserNames")
|
||||
private String gridUserNames;
|
||||
|
||||
/**
|
||||
* 地理网格ID列表(逗号分隔,动态客群使用)
|
||||
*/
|
||||
@ApiModelProperty(value = "地理网格ID列表", name = "regionGridIds")
|
||||
private String regionGridIds;
|
||||
|
||||
/**
|
||||
* 绘制网格ID列表(逗号分隔,动态客群使用)
|
||||
*/
|
||||
@ApiModelProperty(value = "绘制网格ID列表", name = "drawGridIds")
|
||||
private String drawGridIds;
|
||||
|
||||
/**
|
||||
* 有效期截止时间
|
||||
*/
|
||||
@ApiModelProperty(value = "有效期截止时间", name = "validTime")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date validTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.ruoyi.group.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 客群客户关联实体
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@TableName("ibs_cust_group_member")
|
||||
public class CustGroupMember {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群ID
|
||||
*/
|
||||
@ApiModelProperty(value = "客群ID", name = "groupId")
|
||||
private Long groupId;
|
||||
|
||||
/**
|
||||
* 客户类型:0=个人, 1=商户, 2=企业
|
||||
*/
|
||||
@ApiModelProperty(value = "客户类型:0=个人, 1=商户, 2=企业", name = "custType")
|
||||
private String custType;
|
||||
|
||||
/**
|
||||
* 客户号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户号", name = "custId")
|
||||
private String custId;
|
||||
|
||||
/**
|
||||
* 客户姓名(冗余)
|
||||
*/
|
||||
@ApiModelProperty(value = "客户姓名(冗余)", name = "custName")
|
||||
private String custName;
|
||||
|
||||
/**
|
||||
* 客户身份证号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户身份证号", name = "custIdc")
|
||||
private String custIdc;
|
||||
|
||||
/**
|
||||
* 统信码(商户/企业有)
|
||||
*/
|
||||
@ApiModelProperty(value = "统信码(商户/企业有)", name = "socialCreditCode")
|
||||
private String socialCreditCode;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 删除标识:0=正常, 1=删除
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
@TableField("del_flag")
|
||||
private Integer delFlag;
|
||||
|
||||
/**
|
||||
* 手动移除标识:0=否, 1=是(被手动移除的客户不会被定时任务重新导入)
|
||||
*/
|
||||
@ApiModelProperty(value = "手动移除标识:0=否, 1=是", name = "manualRemove")
|
||||
@TableField("manual_remove")
|
||||
private Integer manualRemove;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.ruoyi.group.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 客群客户VO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupMemberVO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群ID
|
||||
*/
|
||||
@ApiModelProperty(value = "客群ID", name = "groupId")
|
||||
private Long groupId;
|
||||
|
||||
/**
|
||||
* 客户类型:0=个人, 1=商户, 2=企业
|
||||
*/
|
||||
@ApiModelProperty(value = "客户类型:0=个人, 1=商户, 2=企业", name = "custType")
|
||||
private String custType;
|
||||
|
||||
/**
|
||||
* 客户号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户号", name = "custId")
|
||||
private String custId;
|
||||
|
||||
/**
|
||||
* 客户姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "客户姓名", name = "custName")
|
||||
private String custName;
|
||||
|
||||
/**
|
||||
* 客户身份证号
|
||||
*/
|
||||
@ApiModelProperty(value = "客户身份证号", name = "custIdc")
|
||||
private String custIdc;
|
||||
|
||||
/**
|
||||
* 统信码(商户/企业有)
|
||||
*/
|
||||
@ApiModelProperty(value = "统信码(商户/企业有)", name = "socialCreditCode")
|
||||
private String socialCreditCode;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "创建时间", name = "createTime")
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.ruoyi.group.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群VO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CustGroupVO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID", name = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客群名称
|
||||
*/
|
||||
@ApiModelProperty(value = "客群名称", name = "groupName")
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 客群模式:0=静态, 1=动态
|
||||
*/
|
||||
@ApiModelProperty(value = "客群模式:0=静态, 1=动态", name = "groupMode")
|
||||
private String groupMode;
|
||||
|
||||
/**
|
||||
* 创建方式:1=模板导入, 2=绩效网格, 3=地理网格, 4=自定义网格
|
||||
*/
|
||||
@ApiModelProperty(value = "创建方式:1=模板导入, 2=绩效网格, 3=地理网格, 4=自定义网格", name = "createMode")
|
||||
private String createMode;
|
||||
|
||||
/**
|
||||
* 柜员号
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员号", name = "userName")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 柜员名称
|
||||
*/
|
||||
@ApiModelProperty(value = "柜员名称", name = "nickName")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 所属机构ID
|
||||
*/
|
||||
@ApiModelProperty(value = "所属机构ID", name = "deptId")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 是否开启共享:0=否, 1=是
|
||||
*/
|
||||
@ApiModelProperty(value = "是否开启共享:0=否, 1=是", name = "shareEnabled")
|
||||
private Integer shareEnabled;
|
||||
|
||||
/**
|
||||
* 可见部门ID列表
|
||||
*/
|
||||
@ApiModelProperty(value = "可见部门ID列表", name = "shareDeptIds")
|
||||
private List<Long> shareDeptIds;
|
||||
|
||||
/**
|
||||
* 客群状态:0=正常, 1=已禁用
|
||||
*/
|
||||
@ApiModelProperty(value = "客群状态:0=正常, 1=已禁用", name = "groupStatus")
|
||||
private String groupStatus;
|
||||
|
||||
/**
|
||||
* 客户数量
|
||||
*/
|
||||
@ApiModelProperty(value = "客户数量", name = "custCount")
|
||||
private Integer custCount;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@ApiModelProperty(value = "创建者", name = "createBy")
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "创建时间", name = "createTime")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@ApiModelProperty(value = "更新者", name = "updateBy")
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "更新时间", name = "updateTime")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ApiModelProperty(value = "备注", name = "remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 客户列表
|
||||
*/
|
||||
@ApiModelProperty(value = "客户列表", name = "custList")
|
||||
private List<CustGroupMemberVO> custList;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.ruoyi.group.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface CustGroupMapper extends BaseMapper<CustGroup> {
|
||||
|
||||
/**
|
||||
* 查询客群数量(根据部门ID和共享设置)
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @param userName 用户名
|
||||
* @return 数量
|
||||
*/
|
||||
// Long countByDeptOrUser(@Param("deptId") Long deptId, @Param("userName") Long userName);
|
||||
|
||||
/**
|
||||
* 查询客群列表
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 客群VO列表
|
||||
*/
|
||||
List<CustGroupVO> selectCustGroupList(@Param("dto") CustGroupQueryDTO dto);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ruoyi.group.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.group.domain.entity.CustGroupMember;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 客群客户关联Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface CustGroupMemberMapper extends BaseMapper<CustGroupMember> {
|
||||
|
||||
/**
|
||||
* 查询客群客户数量
|
||||
*
|
||||
* @param groupId 客群ID
|
||||
* @return 数量
|
||||
*/
|
||||
Long countByGroupId(@Param("groupId") Long groupId);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.ruoyi.group.service;
|
||||
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.dto.GridImportDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客群Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ICustGroupService {
|
||||
|
||||
/**
|
||||
* 查询客群列表
|
||||
*
|
||||
* @param dto 查询条件
|
||||
* @return 客群VO列表
|
||||
*/
|
||||
List<CustGroupVO> listCustGroup(CustGroupQueryDTO dto);
|
||||
|
||||
/**
|
||||
* 异步创建客群(模板导入)
|
||||
*
|
||||
* @param custGroup 客群实体
|
||||
* @param file Excel文件
|
||||
* @return 客群ID
|
||||
*/
|
||||
String createCustGroupByTemplate(CustGroup custGroup, MultipartFile file);
|
||||
|
||||
/**
|
||||
* 异步创建客群(网格导入)
|
||||
*
|
||||
* @param gridImportDTO 网格导入条件
|
||||
* @return 客群ID
|
||||
*/
|
||||
String createCustGroupByGrid(GridImportDTO gridImportDTO);
|
||||
|
||||
/**
|
||||
* 更新客群(网格导入)
|
||||
*
|
||||
* @param gridImportDTO 网格导入条件
|
||||
* @return 结果消息
|
||||
*/
|
||||
String updateCustGroupByGrid(GridImportDTO gridImportDTO);
|
||||
|
||||
/**
|
||||
* 更新客群(模板导入)
|
||||
*
|
||||
* @param custGroup 客群实体
|
||||
* @param file Excel文件
|
||||
* @return 结果消息
|
||||
*/
|
||||
String updateCustGroupByTemplate(CustGroup custGroup, MultipartFile file);
|
||||
|
||||
/**
|
||||
* 更新客群
|
||||
*
|
||||
* @param custGroup 客群实体
|
||||
* @return 结果消息
|
||||
*/
|
||||
String updateCustGroup(CustGroup custGroup);
|
||||
|
||||
/**
|
||||
* 删除客群
|
||||
*
|
||||
* @param idList 客群ID列表
|
||||
* @return 结果消息
|
||||
*/
|
||||
String deleteCustGroup(List<Long> idList);
|
||||
|
||||
/**
|
||||
* 获取客群详情
|
||||
*
|
||||
* @param id 客群ID
|
||||
* @return 客群VO
|
||||
*/
|
||||
CustGroupVO getCustGroup(Long id);
|
||||
|
||||
/**
|
||||
* 检查客群名称是否存在
|
||||
*
|
||||
* @param groupName 客群名称
|
||||
* @return true=存在, false=不存在
|
||||
*/
|
||||
boolean checkGroupNameExist(String groupName);
|
||||
|
||||
/**
|
||||
* 查询客群创建状态
|
||||
*
|
||||
* @param id 客群ID
|
||||
* @return 创建状态:0=创建中, 1=创建成功, 2=创建失败
|
||||
*/
|
||||
String getCreateStatus(Long id);
|
||||
|
||||
/**
|
||||
* 手动移除客群客户
|
||||
*
|
||||
* @param groupId 客群ID
|
||||
* @param memberIds 客群成员ID列表
|
||||
* @return 结果消息
|
||||
*/
|
||||
String removeMembers(Long groupId, List<Long> memberIds);
|
||||
|
||||
/**
|
||||
* 更新动态客群(定时任务调用)
|
||||
* 根据原始导入条件重新查询并更新客户列表
|
||||
*/
|
||||
void updateDynamicCustGroups();
|
||||
|
||||
/**
|
||||
* 检查并禁用过期客群(定时任务调用)
|
||||
*/
|
||||
void checkAndDisableExpiredGroups();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,817 @@
|
||||
package com.ruoyi.group.service.impl;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||
import com.ruoyi.ibs.cmpm.domain.entity.GridCmpm;
|
||||
import com.ruoyi.ibs.cmpm.mapper.GridCmpmMapper;
|
||||
import com.ruoyi.ibs.draw.domain.entity.DrawGridShapeRelate;
|
||||
import com.ruoyi.ibs.draw.domain.entity.DrawShapeCust;
|
||||
import com.ruoyi.ibs.draw.mapper.DrawGridShapeRelateMapper;
|
||||
import com.ruoyi.ibs.draw.mapper.DrawShapeCustMapper;
|
||||
import com.ruoyi.ibs.grid.domain.vo.CustVO;
|
||||
import com.ruoyi.ibs.grid.service.RegionGridListService;
|
||||
import com.ruoyi.group.domain.dto.CustGroupMemberTemplate;
|
||||
import com.ruoyi.group.domain.dto.CustGroupQueryDTO;
|
||||
import com.ruoyi.group.domain.dto.GridImportDTO;
|
||||
import com.ruoyi.group.domain.entity.CustGroup;
|
||||
import com.ruoyi.group.domain.entity.CustGroupMember;
|
||||
import com.ruoyi.group.domain.vo.CustGroupMemberVO;
|
||||
import com.ruoyi.group.domain.vo.CustGroupVO;
|
||||
import com.ruoyi.group.mapper.CustGroupMapper;
|
||||
import com.ruoyi.group.mapper.CustGroupMemberMapper;
|
||||
import com.ruoyi.group.service.ICustGroupService;
|
||||
import com.ruoyi.ibs.grid.domain.entity.RegionCustUser;
|
||||
import com.ruoyi.ibs.grid.domain.entity.RegionGrid;
|
||||
import com.ruoyi.ibs.grid.mapper.RegionCustUserMapper;
|
||||
import com.ruoyi.ibs.grid.mapper.RegionGridMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.val;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 客群Service实现
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CustGroupServiceImpl implements ICustGroupService {
|
||||
|
||||
@Resource
|
||||
private CustGroupMapper custGroupMapper;
|
||||
|
||||
@Resource
|
||||
private CustGroupMemberMapper custGroupMemberMapper;
|
||||
|
||||
@Resource(name = "excelImportExecutor")
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Resource
|
||||
private GridCmpmMapper gridCmpmMapper;
|
||||
|
||||
@Resource
|
||||
private RegionCustUserMapper regionCustUserMapper;
|
||||
|
||||
@Resource
|
||||
private RegionGridMapper regionGridMapper;
|
||||
|
||||
@Resource
|
||||
private RegionGridListService regionGridListService;
|
||||
|
||||
@Resource
|
||||
private DrawShapeCustMapper drawShapeCustMapper;
|
||||
|
||||
@Resource
|
||||
private DrawGridShapeRelateMapper drawGridShapeRelateMapper;
|
||||
|
||||
@Resource
|
||||
private SysDeptMapper sysDeptMapper;
|
||||
|
||||
@Override
|
||||
public List<CustGroupVO> listCustGroup(CustGroupQueryDTO dto) {
|
||||
return custGroupMapper.selectCustGroupList(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String createCustGroupByTemplate(CustGroup custGroup, MultipartFile file) {
|
||||
// 检查客群名称是否存在
|
||||
if (checkGroupNameExist(custGroup.getGroupName())) {
|
||||
throw new ServiceException("客群名称已存在");
|
||||
}
|
||||
// 获取当前用户信息
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
custGroup.setUserName(user.getUserName());
|
||||
custGroup.setNickName(user.getNickName());
|
||||
// 设置默认值
|
||||
custGroup.setGroupMode("0"); // 静态
|
||||
custGroup.setCreateMode("1"); // 模板导入
|
||||
if (StringUtils.isEmpty(custGroup.getGroupStatus())) {
|
||||
custGroup.setGroupStatus("0");
|
||||
}
|
||||
// 设置创建状态为创建中
|
||||
custGroup.setCreateStatus("0");
|
||||
// 插入客群
|
||||
custGroupMapper.insert(custGroup);
|
||||
// 获取当前用户部门编码(异步线程中无法获取)
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
// 异步导入客户
|
||||
executorService.submit(() -> doImportCustGroupByTemplate(custGroup, file, headId));
|
||||
return String.valueOf(custGroup.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String createCustGroupByGrid(GridImportDTO gridImportDTO) {
|
||||
CustGroup custGroup = gridImportDTO.getCustGroup();
|
||||
// 检查客群名称是否存在
|
||||
if (checkGroupNameExist(custGroup.getGroupName())) {
|
||||
throw new ServiceException("客群名称已存在");
|
||||
}
|
||||
// 获取当前用户信息
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
custGroup.setUserName(user.getUserName());
|
||||
custGroup.setNickName(user.getNickName());
|
||||
// 默认状态为正常
|
||||
if (StringUtils.isEmpty(custGroup.getGroupStatus())) {
|
||||
custGroup.setGroupStatus("0");
|
||||
}
|
||||
// 设置创建模式和状态
|
||||
custGroup.setGroupMode(custGroup.getGroupMode());
|
||||
// 根据网格类型设置创建方式:0=模板导入, 2=绩效网格, 3=地理网格, 4=绘制网格
|
||||
String gridType = gridImportDTO.getGridType();
|
||||
if ("0".equals(gridType)) {
|
||||
custGroup.setCreateMode("2"); // 绩效网格
|
||||
} else if ("1".equals(gridType)) {
|
||||
custGroup.setCreateMode("3"); // 地理网格
|
||||
} else if ("2".equals(gridType)) {
|
||||
custGroup.setCreateMode("4"); // 绘制网格
|
||||
} else {
|
||||
throw new ServiceException("无效的网格类型");
|
||||
}
|
||||
|
||||
// 保存网格导入条件(用于动态客群后续更新)
|
||||
custGroup.setGridType(gridImportDTO.getGridType());
|
||||
if ("0".equals(gridType)) {
|
||||
custGroup.setCmpmBizType(gridImportDTO.getCmpmBizType());
|
||||
if (gridImportDTO.getUserNames() != null && !gridImportDTO.getUserNames().isEmpty()) {
|
||||
custGroup.setGridUserNames(String.join(",", gridImportDTO.getUserNames()));
|
||||
}
|
||||
} else if ("1".equals(gridType)) {
|
||||
if (gridImportDTO.getRegionGridIds() != null && !gridImportDTO.getRegionGridIds().isEmpty()) {
|
||||
custGroup.setRegionGridIds(gridImportDTO.getRegionGridIds().stream()
|
||||
.map(String::valueOf).collect(Collectors.joining(",")));
|
||||
}
|
||||
} else if ("2".equals(gridType)) {
|
||||
if (gridImportDTO.getDrawGridIds() != null && !gridImportDTO.getDrawGridIds().isEmpty()) {
|
||||
custGroup.setDrawGridIds(gridImportDTO.getDrawGridIds().stream()
|
||||
.map(String::valueOf).collect(Collectors.joining(",")));
|
||||
}
|
||||
}
|
||||
|
||||
// 设置创建状态为创建中
|
||||
custGroup.setCreateStatus("0");
|
||||
// 插入客群
|
||||
custGroupMapper.insert(custGroup);
|
||||
// 重新设置回DTO(确保异步线程能获取到正确的ID和状态)
|
||||
gridImportDTO.setCustGroup(custGroup);
|
||||
// 获取当前用户部门编码(异步线程中无法获取)
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
// 异步导入客户
|
||||
executorService.submit(() -> doImportCustGroupByGrid(gridImportDTO, headId));
|
||||
return String.valueOf(custGroup.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String updateCustGroup(CustGroup custGroup) {
|
||||
CustGroup existGroup = custGroupMapper.selectById(custGroup.getId());
|
||||
if (existGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
// 检查客群名称是否存在(排除自己)
|
||||
if (!existGroup.getGroupName().equals(custGroup.getGroupName()) && checkGroupNameExist(custGroup.getGroupName())) {
|
||||
throw new ServiceException("客群名称已存在");
|
||||
}
|
||||
custGroupMapper.updateById(custGroup);
|
||||
return "客群更新成功";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String updateCustGroupByGrid(GridImportDTO gridImportDTO) {
|
||||
CustGroup custGroup = gridImportDTO.getCustGroup();
|
||||
// 检查客群是否存在
|
||||
CustGroup existGroup = custGroupMapper.selectById(custGroup.getId());
|
||||
if (existGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
// 更新客群基本信息
|
||||
if (!existGroup.getGroupName().equals(custGroup.getGroupName()) && checkGroupNameExist(custGroup.getGroupName())) {
|
||||
throw new ServiceException("客群名称已存在");
|
||||
}
|
||||
// 重新查询数据库,获取最新状态
|
||||
CustGroup latestGroup = custGroupMapper.selectById(custGroup.getId());
|
||||
latestGroup.setGroupName(custGroup.getGroupName());
|
||||
latestGroup.setGroupMode(custGroup.getGroupMode());
|
||||
latestGroup.setRemark(custGroup.getRemark());
|
||||
latestGroup.setValidTime(custGroup.getValidTime());
|
||||
latestGroup.setShareEnabled(custGroup.getShareEnabled());
|
||||
latestGroup.setShareDeptIds(custGroup.getShareDeptIds());
|
||||
// 更新数据库
|
||||
custGroupMapper.updateById(latestGroup);
|
||||
// 重新设置回DTO(确保异步线程能获取到正确的ID和状态)
|
||||
gridImportDTO.setCustGroup(latestGroup);
|
||||
// 获取当前用户部门编码(异步线程中无法获取)
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
// 异步导入客户
|
||||
executorService.submit(() -> doImportCustGroupByGrid(gridImportDTO, headId));
|
||||
return "客群更新中";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String updateCustGroupByTemplate(CustGroup custGroup, MultipartFile file) {
|
||||
// 检查客群是否存在
|
||||
CustGroup existGroup = custGroupMapper.selectById(custGroup.getId());
|
||||
if (existGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
// 更新客群基本信息
|
||||
if (!existGroup.getGroupName().equals(custGroup.getGroupName()) && checkGroupNameExist(custGroup.getGroupName())) {
|
||||
throw new ServiceException("客群名称已存在");
|
||||
}
|
||||
// 重新查询数据库,获取最新状态
|
||||
CustGroup latestGroup = custGroupMapper.selectById(custGroup.getId());
|
||||
latestGroup.setGroupName(custGroup.getGroupName());
|
||||
latestGroup.setGroupMode(custGroup.getGroupMode());
|
||||
latestGroup.setRemark(custGroup.getRemark());
|
||||
latestGroup.setValidTime(custGroup.getValidTime());
|
||||
latestGroup.setShareEnabled(custGroup.getShareEnabled());
|
||||
latestGroup.setShareDeptIds(custGroup.getShareDeptIds());
|
||||
// 更新数据库
|
||||
custGroupMapper.updateById(latestGroup);
|
||||
// 获取当前用户部门编码(异步线程中无法获取)
|
||||
String headId = SecurityUtils.getHeadId();
|
||||
// 异步导入客户(使用最新状态的对象)
|
||||
executorService.submit(() -> doImportCustGroupByTemplate(latestGroup, file, headId));
|
||||
return "客群更新中";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String deleteCustGroup(List<Long> idList) {
|
||||
if (idList == null || idList.isEmpty()) {
|
||||
throw new ServiceException("请选择要删除的客群");
|
||||
}
|
||||
for (Long id : idList) {
|
||||
// 删除客群客户关联
|
||||
LambdaQueryWrapper<CustGroupMember> memberWrapper = new LambdaQueryWrapper<>();
|
||||
memberWrapper.eq(CustGroupMember::getGroupId, id);
|
||||
custGroupMemberMapper.delete(memberWrapper);
|
||||
// 删除客群
|
||||
custGroupMapper.deleteById(id);
|
||||
}
|
||||
return "客群删除成功";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String removeMembers(Long groupId, List<Long> memberIds) {
|
||||
if (memberIds == null || memberIds.isEmpty()) {
|
||||
throw new ServiceException("请选择要移除的客户");
|
||||
}
|
||||
// 检查客群是否存在
|
||||
CustGroup custGroup = custGroupMapper.selectById(groupId);
|
||||
if (custGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
// 标记为手动移除(软删除)
|
||||
for (Long memberId : memberIds) {
|
||||
CustGroupMember member = custGroupMemberMapper.selectById(memberId);
|
||||
if (member != null && member.getGroupId().equals(groupId)) {
|
||||
member.setManualRemove(1);
|
||||
member.setDelFlag(1);
|
||||
custGroupMemberMapper.updateById(member);
|
||||
}
|
||||
}
|
||||
return "成功移除 " + memberIds.size() + " 个客户";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustGroupVO getCustGroup(Long id) {
|
||||
CustGroup custGroup = custGroupMapper.selectById(id);
|
||||
if (custGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
CustGroupVO vo = new CustGroupVO();
|
||||
vo.setId(custGroup.getId());
|
||||
vo.setGroupName(custGroup.getGroupName());
|
||||
vo.setGroupMode(custGroup.getGroupMode());
|
||||
vo.setCreateMode(custGroup.getCreateMode());
|
||||
vo.setUserName(custGroup.getUserName());
|
||||
vo.setNickName(custGroup.getNickName());
|
||||
vo.setDeptId(custGroup.getDeptId());
|
||||
vo.setShareEnabled(custGroup.getShareEnabled());
|
||||
vo.setGroupStatus(custGroup.getGroupStatus());
|
||||
vo.setRemark(custGroup.getRemark());
|
||||
vo.setCreateBy(custGroup.getCreateBy());
|
||||
vo.setCreateTime(custGroup.getCreateTime());
|
||||
vo.setUpdateBy(custGroup.getUpdateBy());
|
||||
vo.setUpdateTime(custGroup.getUpdateTime());
|
||||
// 处理共享部门ID列表
|
||||
if (StringUtils.isNotEmpty(custGroup.getShareDeptIds())) {
|
||||
List<Long> deptIds = new ArrayList<>();
|
||||
for (String idStr : custGroup.getShareDeptIds().split(",")) {
|
||||
if (StringUtils.isNotEmpty(idStr)) {
|
||||
deptIds.add(Long.valueOf(idStr));
|
||||
}
|
||||
}
|
||||
vo.setShareDeptIds(deptIds);
|
||||
}
|
||||
// 查询客户列表
|
||||
LambdaQueryWrapper<CustGroupMember> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustGroupMember::getGroupId, id);
|
||||
List<CustGroupMember> memberList = custGroupMemberMapper.selectList(wrapper);
|
||||
List<CustGroupMemberVO> memberVOList = new ArrayList<>();
|
||||
for (CustGroupMember member : memberList) {
|
||||
CustGroupMemberVO memberVO = new CustGroupMemberVO();
|
||||
memberVO.setId(member.getId());
|
||||
memberVO.setGroupId(member.getGroupId());
|
||||
memberVO.setCustType(member.getCustType());
|
||||
memberVO.setCustId(member.getCustId());
|
||||
memberVO.setCustName(member.getCustName());
|
||||
memberVO.setCustIdc(member.getCustIdc());
|
||||
memberVO.setSocialCreditCode(member.getSocialCreditCode());
|
||||
memberVO.setCreateTime(member.getCreateTime());
|
||||
memberVOList.add(memberVO);
|
||||
}
|
||||
vo.setCustList(memberVOList);
|
||||
vo.setCustCount(memberVOList.size());
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkGroupNameExist(String groupName) {
|
||||
LambdaQueryWrapper<CustGroup> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustGroup::getGroupName, groupName);
|
||||
return custGroupMapper.selectCount(wrapper) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateStatus(Long id) {
|
||||
CustGroup custGroup = custGroupMapper.selectById(id);
|
||||
if (custGroup == null) {
|
||||
throw new ServiceException("客群不存在");
|
||||
}
|
||||
return custGroup.getCreateStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDynamicCustGroups() {
|
||||
log.info("开始更新动态客群...");
|
||||
|
||||
// 查询所有动态客群
|
||||
LambdaQueryWrapper<CustGroup> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustGroup::getGroupMode, "1"); // 1=动态
|
||||
wrapper.eq(CustGroup::getGroupStatus, "0"); // 0=正常
|
||||
wrapper.eq(CustGroup::getCreateStatus, "1"); // 1=创建成功
|
||||
List<CustGroup> dynamicGroups = custGroupMapper.selectList(wrapper);
|
||||
|
||||
if (dynamicGroups.isEmpty()) {
|
||||
log.info("没有需要更新的动态客群");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("找到 {} 个动态客群需要更新", dynamicGroups.size());
|
||||
Date now = new Date();
|
||||
|
||||
for (CustGroup custGroup : dynamicGroups) {
|
||||
// 检查有效期,过期的客群跳过更新
|
||||
if (custGroup.getValidTime() != null && custGroup.getValidTime().before(now)) {
|
||||
log.info("动态客群已过期,跳过更新,客群ID:{},客群名称:{},有效期:{}",
|
||||
custGroup.getId(), custGroup.getGroupName(), custGroup.getValidTime());
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
updateDynamicCustGroup(custGroup);
|
||||
log.info("动态客群更新成功,客群ID:{},客群名称:{}", custGroup.getId(), custGroup.getGroupName());
|
||||
} catch (Exception e) {
|
||||
log.error("动态客群更新失败,客群ID:{},客群名称:{}", custGroup.getId(), custGroup.getGroupName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("动态客群更新完成,总计:{},成功:{},失败:{}",
|
||||
dynamicGroups.size(),
|
||||
dynamicGroups.stream().filter(g -> {
|
||||
// 假设更新成功的状态设置
|
||||
LambdaQueryWrapper<CustGroup> w = new LambdaQueryWrapper<>();
|
||||
w.eq(CustGroup::getId, g.getId());
|
||||
// 这里简单统计,实际可以通过更精确的方式
|
||||
return true;
|
||||
}).count(),
|
||||
0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAndDisableExpiredGroups() {
|
||||
log.info("开始检查并禁用过期客群...");
|
||||
|
||||
Date now = new Date();
|
||||
|
||||
// 查询所有正常状态且有过期时间的客群
|
||||
LambdaQueryWrapper<CustGroup> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustGroup::getGroupStatus, "0"); // 0=正常
|
||||
wrapper.isNotNull(CustGroup::getValidTime);
|
||||
wrapper.le(CustGroup::getValidTime, now); // validTime <= now
|
||||
List<CustGroup> expiredGroups = custGroupMapper.selectList(wrapper);
|
||||
|
||||
if (expiredGroups.isEmpty()) {
|
||||
log.info("没有需要禁用的过期客群");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("找到 {} 个过期客群需要禁用", expiredGroups.size());
|
||||
|
||||
for (CustGroup custGroup : expiredGroups) {
|
||||
try {
|
||||
custGroup.setGroupStatus("1"); // 1=已禁用
|
||||
custGroupMapper.updateById(custGroup);
|
||||
log.info("客群已禁用,客群ID:{},客群名称:{},有效期:{}",
|
||||
custGroup.getId(), custGroup.getGroupName(), custGroup.getValidTime());
|
||||
} catch (Exception e) {
|
||||
log.error("禁用过期客群失败,客群ID:{},客群名称:{}", custGroup.getId(), custGroup.getGroupName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("过期客群禁用完成,总计:{}", expiredGroups.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个动态客群(增量更新方式)
|
||||
*/
|
||||
private void updateDynamicCustGroup(CustGroup custGroup) {
|
||||
// 从客群部门获取 headId(定时任务中无登录用户上下文)
|
||||
// headId 是 deptId 的前三位
|
||||
String headId = "";
|
||||
if (custGroup.getDeptId() != null) {
|
||||
String deptIdStr = String.valueOf(custGroup.getDeptId());
|
||||
headId = deptIdStr.substring(0, 3);
|
||||
}
|
||||
|
||||
// 查询现有客户(排除手动移除的客户,只查询正常状态的客户)
|
||||
LambdaQueryWrapper<CustGroupMember> existWrapper = new LambdaQueryWrapper<>();
|
||||
existWrapper.eq(CustGroupMember::getGroupId, custGroup.getId())
|
||||
.eq(CustGroupMember::getDelFlag, 0)
|
||||
.eq(CustGroupMember::getManualRemove, 0)
|
||||
.select(CustGroupMember::getCustId, CustGroupMember::getCustType);
|
||||
List<CustGroupMember> existMembers = custGroupMemberMapper.selectList(existWrapper);
|
||||
Set<String> existKeySet = existMembers.stream()
|
||||
.map(m -> m.getCustId() + "_" + m.getCustType())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 构造 GridImportDTO 复用现有导入方法
|
||||
GridImportDTO gridImportDTO = new GridImportDTO();
|
||||
gridImportDTO.setCustGroup(custGroup);
|
||||
gridImportDTO.setGridType(custGroup.getGridType());
|
||||
gridImportDTO.setCmpmBizType(custGroup.getCmpmBizType());
|
||||
|
||||
// 根据网格类型设置参数并查询
|
||||
List<CustGroupMember> newMemberList = new ArrayList<>();
|
||||
String gridType = custGroup.getGridType();
|
||||
if ("0".equals(gridType)) {
|
||||
// 绩效网格
|
||||
if (StringUtils.isNotEmpty(custGroup.getGridUserNames())) {
|
||||
gridImportDTO.setUserNames(Arrays.asList(custGroup.getGridUserNames().split(",")));
|
||||
}
|
||||
newMemberList.addAll(importFromCmpmGrid(custGroup, gridImportDTO, headId));
|
||||
} else if ("1".equals(gridType)) {
|
||||
// 地理网格
|
||||
if (StringUtils.isNotEmpty(custGroup.getRegionGridIds())) {
|
||||
gridImportDTO.setRegionGridIds(Arrays.stream(custGroup.getRegionGridIds().split(","))
|
||||
.map(Long::valueOf).collect(Collectors.toList()));
|
||||
}
|
||||
newMemberList.addAll(importFromRegionGrid(custGroup, gridImportDTO));
|
||||
} else if ("2".equals(gridType)) {
|
||||
// 绘制网格
|
||||
if (StringUtils.isNotEmpty(custGroup.getDrawGridIds())) {
|
||||
gridImportDTO.setDrawGridIds(Arrays.stream(custGroup.getDrawGridIds().split(","))
|
||||
.map(Long::valueOf).collect(Collectors.toList()));
|
||||
}
|
||||
newMemberList.addAll(importFromDrawGrid(custGroup, gridImportDTO));
|
||||
}
|
||||
|
||||
// 计算差异
|
||||
Set<String> newKeySet = newMemberList.stream()
|
||||
.map(m -> m.getCustId() + "_" + m.getCustType())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 需要删除的客户:存在于旧列表但不存在于新列表
|
||||
List<String> toDeleteKeys = new ArrayList<>(existKeySet);
|
||||
toDeleteKeys.removeAll(newKeySet);
|
||||
// 需要新增的客户:存在于新列表但不存在于旧列表
|
||||
List<CustGroupMember> toAddMembers = newMemberList.stream()
|
||||
.filter(m -> !existKeySet.contains(m.getCustId() + "_" + m.getCustType()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 删除不再存在的客户
|
||||
if (!toDeleteKeys.isEmpty()) {
|
||||
for (String key : toDeleteKeys) {
|
||||
String[] parts = key.split("_");
|
||||
LambdaQueryWrapper<CustGroupMember> deleteWrapper = new LambdaQueryWrapper<>();
|
||||
deleteWrapper.eq(CustGroupMember::getGroupId, custGroup.getId())
|
||||
.eq(CustGroupMember::getCustId, parts[0])
|
||||
.eq(CustGroupMember::getCustType, parts[1]);
|
||||
custGroupMemberMapper.delete(deleteWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
// 插入新增客户
|
||||
int addCount = 0;
|
||||
for (CustGroupMember member : toAddMembers) {
|
||||
try {
|
||||
custGroupMemberMapper.insert(member);
|
||||
addCount++;
|
||||
} catch (org.springframework.dao.DuplicateKeyException e) {
|
||||
log.debug("客户已存在,跳过:groupId={}, custId={}", member.getGroupId(), member.getCustId());
|
||||
}
|
||||
}
|
||||
|
||||
log.info("客群客户更新完成,客群ID:{},原数量:{},新数量:{},新增:{},删除:{}",
|
||||
custGroup.getId(), existMembers.size(), newMemberList.size(), addCount, toDeleteKeys.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步导入客户
|
||||
*/
|
||||
private void doImportCustGroupByTemplate(CustGroup custGroup, MultipartFile file, String headId) {
|
||||
try {
|
||||
// 解析Excel
|
||||
List<CustGroupMemberTemplate> templateList = EasyExcel.read(file.getInputStream())
|
||||
.head(CustGroupMemberTemplate.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
if (templateList.isEmpty()) {
|
||||
throw new ServiceException("导入列表为空");
|
||||
}
|
||||
// 校验和去重
|
||||
Set<String> uniqueCustIds = new HashSet<>();
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
for (CustGroupMemberTemplate template : templateList) {
|
||||
// 校验客户类型
|
||||
String custType = template.getCustType();
|
||||
if (StringUtils.isEmpty(custType)) {
|
||||
throw new ServiceException("客户类型不能为空");
|
||||
}
|
||||
// 转换客户类型值
|
||||
String custTypeValue;
|
||||
switch (custType) {
|
||||
case "个人":
|
||||
custTypeValue = "0";
|
||||
break;
|
||||
case "企业":
|
||||
custTypeValue = "2";
|
||||
break;
|
||||
case "商户":
|
||||
custTypeValue = "1";
|
||||
break;
|
||||
default:
|
||||
throw new ServiceException("客户类型填写错误,只能填写:个人、企业、商户");
|
||||
}
|
||||
// 客户号不能为空
|
||||
if (StringUtils.isEmpty(template.getCustId())) {
|
||||
throw new ServiceException("客户号不能为空");
|
||||
}
|
||||
// 检查重复
|
||||
if (!uniqueCustIds.add(template.getCustId())) {
|
||||
continue; // 跳过重复客户
|
||||
}
|
||||
// 创建客户成员
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustType(custTypeValue);
|
||||
member.setCustId(template.getCustId());
|
||||
member.setCustName(template.getCustName());
|
||||
member.setCustIdc(template.getCustIdc());
|
||||
member.setSocialCreditCode(template.getSocialCreditCode());
|
||||
member.setCreateTime(new Date());
|
||||
// 个人客户必须有身份证号
|
||||
if ("0".equals(custTypeValue) && StringUtils.isEmpty(member.getCustIdc())) {
|
||||
throw new ServiceException("个人客户[" + template.getCustId() + "]身份证号不能为空");
|
||||
}
|
||||
// 企业/商户客户必须有统信码
|
||||
if (("1".equals(custTypeValue) || "2".equals(custTypeValue))
|
||||
&& StringUtils.isEmpty(member.getSocialCreditCode())) {
|
||||
throw new ServiceException("企业/商户客户[" + template.getCustId() + "]统信码不能为空");
|
||||
}
|
||||
memberList.add(member);
|
||||
}
|
||||
// 批量插入
|
||||
int batchSize = 1000;
|
||||
int successCount = 0;
|
||||
int skippedCount = 0;
|
||||
int restoredCount = 0;
|
||||
for (int i = 0; i < memberList.size(); i += batchSize) {
|
||||
int endIndex = Math.min(i + batchSize, memberList.size());
|
||||
List<CustGroupMember> batchList = memberList.subList(i, endIndex);
|
||||
for (CustGroupMember member : batchList) {
|
||||
try {
|
||||
custGroupMemberMapper.insert(member);
|
||||
successCount++;
|
||||
} catch (DuplicateKeyException e) {
|
||||
// 客户已存在,检查是否是被手动移除的
|
||||
LambdaQueryWrapper<CustGroupMember> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(CustGroupMember::getGroupId, member.getGroupId())
|
||||
.eq(CustGroupMember::getCustId, member.getCustId())
|
||||
.eq(CustGroupMember::getCustType, member.getCustType());
|
||||
CustGroupMember existMember = custGroupMemberMapper.selectOne(queryWrapper);
|
||||
if (existMember != null && existMember.getManualRemove() != null && existMember.getManualRemove() == 1) {
|
||||
// 是被手动移除的客户,清除标记并恢复
|
||||
existMember.setManualRemove(0);
|
||||
existMember.setDelFlag(0);
|
||||
existMember.setCustName(member.getCustName());
|
||||
custGroupMemberMapper.updateById(existMember);
|
||||
restoredCount++;
|
||||
log.debug("恢复手动移除的客户:groupId={}, custId={}", member.getGroupId(), member.getCustId());
|
||||
} else {
|
||||
// 正常存在的客户,跳过
|
||||
skippedCount++;
|
||||
log.debug("客户已存在,跳过:groupId={}, custId={}", member.getGroupId(), member.getCustId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("客群客户导入完成(模板),客群ID:{},成功:{},跳过重复:{},恢复:{}",
|
||||
custGroup.getId(), successCount, skippedCount, restoredCount);
|
||||
// 更新创建状态为成功
|
||||
custGroup.setCreateStatus("1");
|
||||
custGroupMapper.updateById(custGroup);
|
||||
} catch (Exception e) {
|
||||
// 更新创建状态为失败
|
||||
custGroup.setCreateStatus("2");
|
||||
custGroupMapper.updateById(custGroup);
|
||||
log.error("客群客户导入失败,客群ID:{}", custGroup.getId(), e);
|
||||
throw new ServiceException("客群客户导入失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步导入客户(网格方式)
|
||||
*/
|
||||
private void doImportCustGroupByGrid(GridImportDTO gridImportDTO, String headId) {
|
||||
CustGroup custGroup = gridImportDTO.getCustGroup();
|
||||
try {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
String gridType = gridImportDTO.getGridType();
|
||||
// 根据网格类型查询客户
|
||||
if ("0".equals(gridType)) {
|
||||
// 绩效网格
|
||||
memberList.addAll(importFromCmpmGrid(custGroup, gridImportDTO, headId));
|
||||
} else if ("1".equals(gridType)) {
|
||||
// 地理网格
|
||||
memberList.addAll(importFromRegionGrid(custGroup, gridImportDTO));
|
||||
} else if ("2".equals(gridType)) {
|
||||
// 绘制网格
|
||||
memberList.addAll(importFromDrawGrid(custGroup, gridImportDTO));
|
||||
}
|
||||
if (memberList.isEmpty()) {
|
||||
throw new ServiceException("未查询到任何客户");
|
||||
}
|
||||
// 批量插入
|
||||
int batchSize = 1000;
|
||||
int successCount = 0;
|
||||
int skippedCount = 0;
|
||||
int restoredCount = 0;
|
||||
for (int i = 0; i < memberList.size(); i += batchSize) {
|
||||
int endIndex = Math.min(i + batchSize, memberList.size());
|
||||
List<CustGroupMember> batchList = memberList.subList(i, endIndex);
|
||||
for (CustGroupMember member : batchList) {
|
||||
try {
|
||||
custGroupMemberMapper.insert(member);
|
||||
successCount++;
|
||||
} catch (DuplicateKeyException e) {
|
||||
// 客户已存在,检查是否是被手动移除的
|
||||
LambdaQueryWrapper<CustGroupMember> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(CustGroupMember::getGroupId, member.getGroupId())
|
||||
.eq(CustGroupMember::getCustId, member.getCustId())
|
||||
.eq(CustGroupMember::getCustType, member.getCustType());
|
||||
CustGroupMember existMember = custGroupMemberMapper.selectOne(queryWrapper);
|
||||
if (existMember != null && existMember.getManualRemove() != null && existMember.getManualRemove() == 1) {
|
||||
// 是被手动移除的客户,清除标记并恢复
|
||||
existMember.setManualRemove(0);
|
||||
existMember.setDelFlag(0);
|
||||
existMember.setCustName(member.getCustName());
|
||||
custGroupMemberMapper.updateById(existMember);
|
||||
restoredCount++;
|
||||
log.debug("恢复手动移除的客户:groupId={}, custId={}", member.getGroupId(), member.getCustId());
|
||||
} else {
|
||||
// 正常存在的客户,跳过
|
||||
skippedCount++;
|
||||
log.debug("客户已存在,跳过:groupId={}, custId={}", member.getGroupId(), member.getCustId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("客群客户导入完成(网格),客群ID:{},成功:{},跳过重复:{},恢复:{}",
|
||||
custGroup.getId(), successCount, skippedCount, restoredCount);
|
||||
// 更新创建状态为成功
|
||||
custGroup.setCreateStatus("1");
|
||||
custGroupMapper.updateById(custGroup);
|
||||
} catch (Exception e) {
|
||||
// 更新创建状态为失败
|
||||
custGroup.setCreateStatus("2");
|
||||
custGroupMapper.updateById(custGroup);
|
||||
log.error("客群客户导入失败,客群ID:{}", custGroup.getId(), e);
|
||||
throw new ServiceException("客群客户导入失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从绩效网格导入客户
|
||||
*/
|
||||
private List<CustGroupMember> importFromCmpmGrid(CustGroup custGroup, GridImportDTO gridImportDTO, String headId) {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
// 确定要查询的网格类型
|
||||
List<String> gridTypes = new ArrayList<>();
|
||||
String cmpmBizType = gridImportDTO.getCmpmBizType();
|
||||
if ("retail".equals(cmpmBizType)) {
|
||||
gridTypes.add("retail");
|
||||
} else if ("corporate".equals(cmpmBizType)) {
|
||||
gridTypes.add("corporate");
|
||||
gridTypes.add("corporate_account");
|
||||
} else {
|
||||
throw new ServiceException("请选择绩效网格业务类型(零售/公司)");
|
||||
}
|
||||
// 查询客户
|
||||
for (String userName : gridImportDTO.getUserNames()) {
|
||||
for (String gridType : gridTypes) {
|
||||
List<GridCmpm> cmpmList = gridCmpmMapper.getGridCmpmByUserName(userName, headId, gridType);
|
||||
for (GridCmpm cmpm : cmpmList) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustId(cmpm.getCustId());
|
||||
member.setCustName(cmpm.getCustName());
|
||||
member.setCustType(cmpm.getCustType());
|
||||
member.setCustIdc(cmpm.getCustIdc());
|
||||
member.setSocialCreditCode(cmpm.getUsci());
|
||||
member.setCreateTime(new Date());
|
||||
memberList.add(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
return memberList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从地理网格导入客户
|
||||
*/
|
||||
private List<CustGroupMember> importFromRegionGrid(CustGroup custGroup, GridImportDTO gridImportDTO) {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
// 查询地理网格获取编码
|
||||
if (gridImportDTO.getRegionGridIds() == null || gridImportDTO.getRegionGridIds().isEmpty()) {
|
||||
throw new ServiceException("请选择地理网格");
|
||||
}
|
||||
List<RegionGrid> regionGrids = regionGridMapper.selectBatchIds(gridImportDTO.getRegionGridIds());
|
||||
// 使用 selectAllCustFromGrid 方法查询所有客户(不限制客户类型)
|
||||
for (RegionGrid regionGrid : regionGrids) {
|
||||
List<RegionCustUser> custUsers = regionGridListService.selectAllCustFromGrid(regionGrid);
|
||||
for (RegionCustUser custUser : custUsers) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustId(custUser.getCustId());
|
||||
member.setCustName(custUser.getCustName());
|
||||
member.setCustType(custUser.getCustType());
|
||||
member.setCreateTime(new Date());
|
||||
memberList.add(member);
|
||||
}
|
||||
}
|
||||
return memberList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从绘制网格导入客户
|
||||
*/
|
||||
private List<CustGroupMember> importFromDrawGrid(CustGroup custGroup, GridImportDTO gridImportDTO) {
|
||||
List<CustGroupMember> memberList = new ArrayList<>();
|
||||
if (gridImportDTO.getDrawGridIds() == null || gridImportDTO.getDrawGridIds().isEmpty()) {
|
||||
throw new ServiceException("请选择绘制网格");
|
||||
}
|
||||
// 查询绘制网格关联的图形ID
|
||||
for (Long gridId : gridImportDTO.getDrawGridIds()) {
|
||||
LambdaQueryWrapper<DrawGridShapeRelate> relateWrapper = new LambdaQueryWrapper<>();
|
||||
relateWrapper.eq(DrawGridShapeRelate::getGridId, gridId);
|
||||
List<DrawGridShapeRelate> relates = drawGridShapeRelateMapper.selectList(relateWrapper);
|
||||
for (DrawGridShapeRelate relate : relates) {
|
||||
// 根据图形ID查询客户
|
||||
LambdaQueryWrapper<DrawShapeCust> custWrapper = new LambdaQueryWrapper<>();
|
||||
custWrapper.eq(DrawShapeCust::getShapeId, relate.getShapeId());
|
||||
List<DrawShapeCust> shapeCusts = drawShapeCustMapper.selectList(custWrapper);
|
||||
for (DrawShapeCust shapeCust : shapeCusts) {
|
||||
CustGroupMember member = new CustGroupMember();
|
||||
member.setGroupId(custGroup.getId());
|
||||
member.setCustId(shapeCust.getCustId());
|
||||
member.setCustName(shapeCust.getCustName());
|
||||
member.setCustType(shapeCust.getCustType());
|
||||
member.setCreateTime(new Date());
|
||||
memberList.add(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
return memberList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.group.mapper.CustGroupMapper">
|
||||
|
||||
<select id="selectCustGroupList" resultType="CustGroupVO">
|
||||
SELECT
|
||||
cg.id,
|
||||
cg.group_name,
|
||||
cg.group_mode,
|
||||
cg.create_mode,
|
||||
cg.user_name,
|
||||
cg.nick_name,
|
||||
cg.dept_id,
|
||||
cg.share_enabled,
|
||||
cg.share_dept_ids,
|
||||
cg.group_status,
|
||||
cg.create_by,
|
||||
cg.create_time,
|
||||
cg.update_by,
|
||||
cg.update_time,
|
||||
cg.remark,
|
||||
cg.del_flag,
|
||||
(SELECT COUNT(*) FROM ibs_cust_group_member cgm WHERE cgm.group_id = cg.id AND cgm.del_flag = '0') AS cust_count
|
||||
FROM ibs_cust_group cg
|
||||
<where>
|
||||
cg.del_flag = '0'
|
||||
and create_status = '1'
|
||||
<if test="dto.groupName != null and dto.groupName != ''">
|
||||
AND cg.group_name LIKE CONCAT('%', #{dto.groupName}, '%')
|
||||
</if>
|
||||
<if test="dto.groupMode != null and dto.groupMode != ''">
|
||||
AND cg.group_mode = #{dto.groupMode}
|
||||
</if>
|
||||
<if test="dto.createMode != null and dto.createMode != ''">
|
||||
AND cg.create_mode = #{dto.createMode}
|
||||
</if>
|
||||
<if test="dto.groupStatus != null and dto.groupStatus != ''">
|
||||
AND cg.group_status = #{dto.groupStatus}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY cg.create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -97,6 +97,13 @@ public class GridCmpmController extends BaseController {
|
||||
return gridCmpmService.selectCustManagerResult();
|
||||
}
|
||||
|
||||
@GetMapping("/custManager/custLevel/list")
|
||||
@Log(title = "绩效网格-管户报表星级列表")
|
||||
@ApiOperation("管户报表星级列表")
|
||||
public AjaxResult getCustLevelListForManager() {
|
||||
return success(gridCmpmService.getCustLevelListForManager());
|
||||
}
|
||||
|
||||
@GetMapping("/custLevel/count")
|
||||
@Log(title = "绩效网格-查询客户分层等级")
|
||||
@ApiOperation("查询客户分层等级")
|
||||
|
||||
@@ -18,4 +18,8 @@ public class CustManagerDTO {
|
||||
@ApiModelProperty(value = "网点名",notes = "")
|
||||
private String branchId;
|
||||
|
||||
/** 状态类型:current(本月)、last(上月)、rise(上升)、fall(下降) */
|
||||
@ApiModelProperty(value = "状态类型", notes = "current(本月)、last(上月)、rise(上升)、fall(下降)")
|
||||
private String statusType;
|
||||
|
||||
}
|
||||
|
||||
@@ -152,6 +152,13 @@ public class GridCmpmService {
|
||||
return new DwbRetailResultVO();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管户报表星级列表
|
||||
*/
|
||||
public List<String> getCustLevelListForManager() {
|
||||
return gridCmpmMapper.getCustLevelList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 每月定时设置统计数据
|
||||
*/
|
||||
@@ -226,7 +233,6 @@ public class GridCmpmService {
|
||||
// 获取上月各星级客户数
|
||||
Map<String, Integer> historyLevelCountMap = getCustLevelCountMap(custManagerDTO, "last");
|
||||
Map<String, Integer> custLevelCompLm = calculateLevelChanges(historyLevelCountMap, currentLevelCountMap);
|
||||
vo.setCustLevelCompLm(custLevelCompLm);
|
||||
|
||||
// 在 vo.setCustLevelCompLm 之前,按顺序重新组织数据
|
||||
String[] order = {"5星", "4星", "3星", "2星", "1星", "基础", "长尾"};
|
||||
|
||||
@@ -35,4 +35,12 @@ public interface RegionGridListService {
|
||||
|
||||
List<RegionGridListVO> getSecGridListByManager(RegionGridListDTO regionGridListDTO);
|
||||
|
||||
/**
|
||||
* 查询网格内所有客户(不限制客户类型,用于导入客群)
|
||||
* @param regionGrid 地理网格对象
|
||||
* @return 网格内所有客户列表
|
||||
*/
|
||||
List<RegionCustUser> selectAllCustFromGrid(RegionGrid regionGrid);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.ibs.grid.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.bean.BeanUtils;
|
||||
import com.ruoyi.ibs.draw.domain.dto.grid.CustCountDTO;
|
||||
@@ -429,4 +430,25 @@ public class RegionGridListServiceImpl implements RegionGridListService {
|
||||
|
||||
return secGridListByManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询网格内所有客户(不限制客户类型,用于导入客群)
|
||||
* @param regionGrid 地理网格对象
|
||||
* @return 网格内所有客户列表
|
||||
*/
|
||||
@Override
|
||||
public List<RegionCustUser> selectAllCustFromGrid(RegionGrid regionGrid) {
|
||||
LambdaQueryWrapper<RegionCustUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
// 根据网格等级判断使用一级还是二级网格ID查询
|
||||
if (regionGrid.getGridLevel().equals("1")) {
|
||||
queryWrapper.eq(RegionCustUser::getTopGridId, regionGrid.getGridId());
|
||||
} else if (regionGrid.getGridLevel().equals("2")) {
|
||||
queryWrapper.eq(RegionCustUser::getSecGridId, regionGrid.getGridId());
|
||||
} else {
|
||||
throw new ServiceException("无效的网格等级: " + regionGrid.getGridLevel());
|
||||
}
|
||||
// 不限制客户类型,查询所有类型的客户
|
||||
return regionCustUserMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -142,6 +142,28 @@
|
||||
<if test="managerId != null and managerId !='' ">and manager_id = #{managerId}</if>
|
||||
<if test="outletId != null and outletId !='' ">and outlet_id = #{outletId}</if>
|
||||
<if test="branchId != null and branchId !='' ">and branch_id = #{branchId}</if>
|
||||
<if test="statusType != null and statusType !=''">
|
||||
<choose>
|
||||
<when test="statusType == 'current'">
|
||||
<!-- 本月:本月是指定星级的客户 -->
|
||||
and cust_level = #{custLevel}
|
||||
</when>
|
||||
<when test="statusType == 'last'">
|
||||
<!-- 上月:上月是指定星级的客户 -->
|
||||
and cust_level_lm = #{custLevel}
|
||||
</when>
|
||||
<when test="statusType == 'rise'">
|
||||
<!-- 上升:上升到指定星级的客户(本月是指定星级,上月星级更低) -->
|
||||
and cust_level = #{custLevel}
|
||||
and cust_level_comp_lm like '上升%'
|
||||
</when>
|
||||
<when test="statusType == 'fall'">
|
||||
<!-- 下降:从指定星级下降的客户(上月是指定星级,本月星级更低) -->
|
||||
and cust_level_lm = #{custLevel}
|
||||
and cust_level_comp_lm like '下降%'
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
@@ -438,6 +460,7 @@
|
||||
select distinct
|
||||
cust_level
|
||||
from dwb_retail_cust_level_manager_detail_875
|
||||
order by cust_level
|
||||
</select>
|
||||
|
||||
<select id="getCustCountByLevel" resultType="int">
|
||||
|
||||
1
pom.xml
1
pom.xml
@@ -226,6 +226,7 @@
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-common</module>
|
||||
<module>ibs</module>
|
||||
<module>ibs-group</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
||||
@@ -74,6 +74,13 @@
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 客群管理-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ibs-group</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
2
ruoyi-ui/.gitignore
vendored
2
ruoyi-ui/.gitignore
vendored
@@ -22,5 +22,3 @@ selenium-debug.log
|
||||
dist.zip
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
vue.config.js
|
||||
@@ -15,3 +15,11 @@ export function gridCmpmCustManagerResult(data) {
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取管户报表星级列表
|
||||
export function getCustLevelList() {
|
||||
return request({
|
||||
url: '/grid/cmpm/custManager/custLevel/list',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 统计卡片 -->
|
||||
<div :gutter="24" class="sum-box">
|
||||
<el-card class="box-card">
|
||||
<div class="my-span-checklist-title">
|
||||
总资产余额
|
||||
</div>
|
||||
<div class="my-span-checklist-main">
|
||||
<span>{{ cardInfo.custAumBal }}</span>
|
||||
<span>{{ formatYi(cardInfo.custAumBal) }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card class="box-card">
|
||||
@@ -14,7 +15,7 @@
|
||||
总资产余额较上月变动
|
||||
</div>
|
||||
<div class="my-span-checklist-main">
|
||||
<span>{{ cardInfo.aumBalCompLm }}</span>
|
||||
<span>{{ formatYi(cardInfo.aumBalCompLm) }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card class="box-card">
|
||||
@@ -22,7 +23,7 @@
|
||||
总资产余额月日均
|
||||
</div>
|
||||
<div class="my-span-checklist-main">
|
||||
<span>{{ cardInfo.custAumMonthAvg }}</span>
|
||||
<span>{{ formatYi(cardInfo.custAumMonthAvg) }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card class="box-card">
|
||||
@@ -66,6 +67,33 @@
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 搜索区域 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="90px">
|
||||
<el-form-item label="客户星级" prop="custLevel">
|
||||
<el-select v-model="queryParams.custLevel" placeholder="请选择" clearable style="width: 150px">
|
||||
<el-option
|
||||
v-for="level in custLevelOptions"
|
||||
:key="level"
|
||||
:label="level"
|
||||
:value="level"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="星级状态" prop="statusType">
|
||||
<el-select v-model="queryParams.statusType" placeholder="请选择" clearable style="width: 150px">
|
||||
<el-option label="本月" value="current" />
|
||||
<el-option label="上月" value="last" />
|
||||
<el-option label="上升" value="rise" />
|
||||
<el-option label="下降" value="fall" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-card class="header-statics" style="display: none">
|
||||
<ul class="statics-cnt">
|
||||
<li>
|
||||
@@ -122,7 +150,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { gridCmpmCustManagerList, gridCmpmCustManagerResult } from '@/api/gridSearch/accountManageReport/index'
|
||||
import { gridCmpmCustManagerList, gridCmpmCustManagerResult, getCustLevelList } from '@/api/gridSearch/accountManageReport/index'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -137,19 +165,50 @@ import { gridCmpmCustManagerList, gridCmpmCustManagerResult } from '@/api/gridSe
|
||||
},
|
||||
tableData: [],
|
||||
loading: false,
|
||||
custLevelOptions: [],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
pageSize: 10,
|
||||
custLevel: null,
|
||||
statusType: null
|
||||
},
|
||||
total: 0,
|
||||
topData: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 从 URL 参数获取筛选条件
|
||||
const { custLevel, statusType } = this.$route.query
|
||||
if (custLevel) {
|
||||
this.queryParams.custLevel = custLevel
|
||||
}
|
||||
if (statusType) {
|
||||
this.queryParams.statusType = statusType
|
||||
}
|
||||
this.loadCustLevelOptions()
|
||||
this.getData()
|
||||
this.getSum()
|
||||
},
|
||||
methods: {
|
||||
/** 加载客户星级选项 */
|
||||
loadCustLevelOptions() {
|
||||
getCustLevelList().then(res => {
|
||||
this.custLevelOptions = res.data || []
|
||||
}).catch(() => {
|
||||
this.custLevelOptions = []
|
||||
})
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getData()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.queryParams.custLevel = null
|
||||
this.queryParams.statusType = null
|
||||
this.handleQuery()
|
||||
},
|
||||
getData() {
|
||||
this.loading = true;
|
||||
gridCmpmCustManagerList(this.queryParams).then(res => {
|
||||
@@ -183,10 +242,21 @@ import { gridCmpmCustManagerList, gridCmpmCustManagerResult } from '@/api/gridSe
|
||||
},
|
||||
toSum(obj) {
|
||||
let sum = 0
|
||||
Object.keys(obj).map(key => {
|
||||
sum = sum + obj[key] * 1
|
||||
Object.keys(obj).forEach(key => {
|
||||
// 只计算2星级及以上的:key中包含"2星"、"3星"、"4星"、"5星"
|
||||
if (key.includes('2星') || key.includes('3星') || key.includes('4星') || key.includes('5星')) {
|
||||
sum += obj[key]
|
||||
}
|
||||
})
|
||||
return sum
|
||||
},
|
||||
/** 格式化为亿元 */
|
||||
formatYi(value) {
|
||||
if (value === null || value === '' || value === undefined) return '-'
|
||||
const num = parseFloat(value)
|
||||
if (isNaN(num)) return '-'
|
||||
// 换算为亿元,保留2位小数
|
||||
return (num / 100000000).toFixed(2) + '亿元'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
</div>
|
||||
<div class="top_num">
|
||||
<span style="font-size: 14px;">较上月变动</span>
|
||||
<span v-if="String(item.inc).includes('-')" style=" font-size: 14px;color: #EF3F35">{{ changeData(item.inc)
|
||||
<span v-if="String(item.inc).includes('-')" style=" font-size: 14px;color: #00B453">{{ changeData(item.inc)
|
||||
}}<i class="el-icon-caret-bottom"></i></span>
|
||||
<span v-else style=" font-size: 14px;color: #00B453">{{ changeData(item.inc) }}<i
|
||||
<span v-else style=" font-size: 14px;color: #EF3F35">{{ changeData(item.inc) }}<i
|
||||
class="el-icon-caret-top"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,18 +30,24 @@
|
||||
<div class="vt-main top-vt-main">
|
||||
<div class="top_num">
|
||||
<span>上月值</span>
|
||||
<span style="font-size: 14px;">{{ item.yiAmt }}</span>
|
||||
<span style="font-size: 14px; cursor: pointer; color: #409EFF;" @click="goToCustManager(item.itemNm, 'last')">{{ item.yiAmt }}</span>
|
||||
</div>
|
||||
<div class="top_num">
|
||||
<span>当月值</span>
|
||||
<span style="font-size: 14px;">{{ item.inc }}</span>
|
||||
<span style="font-size: 14px; cursor: pointer; color: #409EFF;" @click="goToCustManager(item.itemNm, 'current')">{{ item.inc }}</span>
|
||||
</div>
|
||||
<div class="top_num">
|
||||
<span style="font-size: 14px;">较上月变动</span>
|
||||
<span v-if="String(item.curAmt).includes('-')" style=" font-size: 14px;color: #EF3F35">{{ item.curAmt
|
||||
}}<i class="el-icon-caret-bottom"></i></span>
|
||||
<span v-else style=" font-size: 14px;color: #00B453">{{ item.curAmt }}<i
|
||||
class="el-icon-caret-top"></i></span>
|
||||
<span v-if="String(item.curAmt).includes('-')"
|
||||
style="font-size: 14px; color: #00B453; cursor: pointer;"
|
||||
@click="goToCustManager(item.itemNm, 'fall')">
|
||||
{{ item.curAmt }}<i class="el-icon-caret-bottom"></i>
|
||||
</span>
|
||||
<span v-else
|
||||
style="font-size: 14px; color: #EF3F35; cursor: pointer;"
|
||||
@click="goToCustManager(item.itemNm, 'rise')">
|
||||
{{ item.curAmt }}<i class="el-icon-caret-top"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -875,6 +881,23 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 跳转到管户报表页面 */
|
||||
goToCustManager(itemNm, statusType) {
|
||||
// 从 itemNm 中提取星级,如 "3星客户" → "3星","基础客户" → "基础"
|
||||
// 使用正则匹配以"星"或"基础"或"长尾"开头的内容
|
||||
let custLevel = itemNm.replace('客户', '').trim()
|
||||
// 如果没有"客户"后缀,直接使用整个名称
|
||||
if (custLevel === itemNm) {
|
||||
custLevel = itemNm
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/gridSearch/accountManageReport',
|
||||
query: {
|
||||
custLevel: custLevel,
|
||||
statusType: statusType
|
||||
}
|
||||
})
|
||||
},
|
||||
getData() {
|
||||
this.loading = true
|
||||
if (this.selectedTab === '3') {
|
||||
|
||||
Reference in New Issue
Block a user