0410-海宁预警转发+北仑客群优化+海宁aum报表导出下载
This commit is contained in:
@@ -48,4 +48,22 @@ public class CustGroupMemberQueryDTO {
|
|||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "客户经理姓名")
|
@ApiModelProperty(value = "客户经理姓名")
|
||||||
private String nickName;
|
private String nickName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前用户角色
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "当前用户角色", hidden = true)
|
||||||
|
private String userRole;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前用户名
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "当前用户名", hidden = true)
|
||||||
|
private String currentUserName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前机构ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "当前机构ID", hidden = true)
|
||||||
|
private Long currentDeptId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ public class CustGroupQueryDTO implements Serializable {
|
|||||||
@ApiModelProperty(value = "视图类型", name = "viewType")
|
@ApiModelProperty(value = "视图类型", name = "viewType")
|
||||||
private String viewType;
|
private String viewType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前用户是否属于总行管理员口径
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "当前用户是否总行管理员", hidden = true)
|
||||||
|
private Boolean headRole;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页码
|
* 页码
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ public interface CustGroupMapper extends BaseMapper<CustGroup> {
|
|||||||
*/
|
*/
|
||||||
List<CustGroupVO> selectCustGroupList(@Param("dto") CustGroupQueryDTO dto,
|
List<CustGroupVO> selectCustGroupList(@Param("dto") CustGroupQueryDTO dto,
|
||||||
@Param("userName") String userName,
|
@Param("userName") String userName,
|
||||||
@Param("deptId") String deptId);
|
@Param("deptId") String deptId,
|
||||||
|
@Param("headId") String headId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID查询客群详情
|
* 根据ID查询客群详情
|
||||||
@@ -44,7 +45,9 @@ public interface CustGroupMapper extends BaseMapper<CustGroup> {
|
|||||||
*/
|
*/
|
||||||
CustGroupVO selectCustGroupById(@Param("id") Long id,
|
CustGroupVO selectCustGroupById(@Param("id") Long id,
|
||||||
@Param("userName") String userName,
|
@Param("userName") String userName,
|
||||||
@Param("deptId") String deptId);
|
@Param("deptId") String deptId,
|
||||||
|
@Param("headRole") Boolean headRole,
|
||||||
|
@Param("headId") String headId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验当前用户是否有客群查看权限
|
* 校验当前用户是否有客群查看权限
|
||||||
@@ -56,7 +59,18 @@ public interface CustGroupMapper extends BaseMapper<CustGroup> {
|
|||||||
*/
|
*/
|
||||||
Long countVisibleCustGroup(@Param("id") Long id,
|
Long countVisibleCustGroup(@Param("id") Long id,
|
||||||
@Param("userName") String userName,
|
@Param("userName") String userName,
|
||||||
@Param("deptId") String deptId);
|
@Param("deptId") String deptId,
|
||||||
|
@Param("headRole") Boolean headRole,
|
||||||
|
@Param("headId") String headId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验客群是否属于总行管理员共享操作范围
|
||||||
|
*
|
||||||
|
* @param id 客群ID
|
||||||
|
* @return 数量
|
||||||
|
*/
|
||||||
|
Long countHeadOperableCustGroup(@Param("id") Long id,
|
||||||
|
@Param("headId") String headId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询所有已有的客群标签
|
* 查询所有已有的客群标签
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ public class CustGroupMemberServiceImpl implements ICustGroupMemberService {
|
|||||||
@Override
|
@Override
|
||||||
public List<CustGroupMemberVO> listCustGroupMembers(Long groupId, CustGroupMemberQueryDTO dto) {
|
public List<CustGroupMemberVO> listCustGroupMembers(Long groupId, CustGroupMemberQueryDTO dto) {
|
||||||
custGroupService.checkCustGroupViewPermission(groupId);
|
custGroupService.checkCustGroupViewPermission(groupId);
|
||||||
|
dto.setUserRole(SecurityUtils.userRole());
|
||||||
|
dto.setCurrentUserName(SecurityUtils.getUsername());
|
||||||
|
dto.setCurrentDeptId(SecurityUtils.getDeptId());
|
||||||
// 在权限检查之后启动分页,避免权限检查SQL消耗分页设置
|
// 在权限检查之后启动分页,避免权限检查SQL消耗分页设置
|
||||||
int pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
|
int pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
|
||||||
int pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
|
int pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
|
||||||
@@ -109,7 +112,14 @@ public class CustGroupMemberServiceImpl implements ICustGroupMemberService {
|
|||||||
if (custGroup == null) {
|
if (custGroup == null) {
|
||||||
throw new ServiceException("客群不存在");
|
throw new ServiceException("客群不存在");
|
||||||
}
|
}
|
||||||
if (!SecurityUtils.getUsername().equals(custGroup.getUserName())) {
|
if (!SecurityUtils.hasRole("headAdmin")
|
||||||
|
&& !SecurityUtils.hasRole("headPublic")
|
||||||
|
&& !SecurityUtils.hasRole("headPrivate")
|
||||||
|
&& !SecurityUtils.hasRole("headOps")) {
|
||||||
|
throw new ServiceException("无权限操作该客群");
|
||||||
|
}
|
||||||
|
Long count = custGroupMapper.countHeadOperableCustGroup(groupId, SecurityUtils.getHeadId());
|
||||||
|
if (count == null || count <= 0) {
|
||||||
throw new ServiceException("无权限操作该客群");
|
throw new ServiceException("无权限操作该客群");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,12 +67,24 @@ public class CustGroupServiceImpl implements ICustGroupService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CustGroupVO> listCustGroup(CustGroupQueryDTO dto) {
|
public List<CustGroupVO> listCustGroup(CustGroupQueryDTO dto) {
|
||||||
return custGroupMapper.selectCustGroupList(dto, SecurityUtils.getUsername(), String.valueOf(SecurityUtils.getDeptId()));
|
dto.setHeadRole(isHeadCustGroupAdmin());
|
||||||
|
return custGroupMapper.selectCustGroupList(
|
||||||
|
dto,
|
||||||
|
SecurityUtils.getUsername(),
|
||||||
|
String.valueOf(SecurityUtils.getDeptId()),
|
||||||
|
SecurityUtils.getHeadId()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CustGroupVO getCustGroup(Long id) {
|
public CustGroupVO getCustGroup(Long id) {
|
||||||
CustGroupVO custGroup = custGroupMapper.selectCustGroupById(id, SecurityUtils.getUsername(), String.valueOf(SecurityUtils.getDeptId()));
|
CustGroupVO custGroup = custGroupMapper.selectCustGroupById(
|
||||||
|
id,
|
||||||
|
SecurityUtils.getUsername(),
|
||||||
|
String.valueOf(SecurityUtils.getDeptId()),
|
||||||
|
isHeadCustGroupAdmin(),
|
||||||
|
SecurityUtils.getHeadId()
|
||||||
|
);
|
||||||
if (custGroup == null) {
|
if (custGroup == null) {
|
||||||
throw new ServiceException("客群不存在");
|
throw new ServiceException("客群不存在");
|
||||||
}
|
}
|
||||||
@@ -82,6 +94,7 @@ public class CustGroupServiceImpl implements ICustGroupService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public String createCustGroupByTemplate(CustGroup custGroup, MultipartFile file) {
|
public String createCustGroupByTemplate(CustGroup custGroup, MultipartFile file) {
|
||||||
|
assertHeadCustGroupAdmin();
|
||||||
// 检查客群名称是否存在
|
// 检查客群名称是否存在
|
||||||
if (checkGroupNameExist(custGroup.getGroupName())) {
|
if (checkGroupNameExist(custGroup.getGroupName())) {
|
||||||
throw new ServiceException("客群名称已存在");
|
throw new ServiceException("客群名称已存在");
|
||||||
@@ -117,6 +130,7 @@ public class CustGroupServiceImpl implements ICustGroupService {
|
|||||||
if (existGroup == null) {
|
if (existGroup == null) {
|
||||||
throw new ServiceException("客群不存在");
|
throw new ServiceException("客群不存在");
|
||||||
}
|
}
|
||||||
|
assertOperatePermission(existGroup);
|
||||||
// 检查客群是否正在创建或更新
|
// 检查客群是否正在创建或更新
|
||||||
if ("0".equals(existGroup.getCreateStatus())) {
|
if ("0".equals(existGroup.getCreateStatus())) {
|
||||||
throw new ServiceException("客群正在处理中,请稍后再试");
|
throw new ServiceException("客群正在处理中,请稍后再试");
|
||||||
@@ -167,6 +181,11 @@ public class CustGroupServiceImpl implements ICustGroupService {
|
|||||||
throw new ServiceException("请选择要删除的客群");
|
throw new ServiceException("请选择要删除的客群");
|
||||||
}
|
}
|
||||||
for (Long id : idList) {
|
for (Long id : idList) {
|
||||||
|
CustGroup custGroup = custGroupMapper.selectById(id);
|
||||||
|
if (custGroup == null) {
|
||||||
|
throw new ServiceException("客群不存在");
|
||||||
|
}
|
||||||
|
assertOperatePermission(custGroup);
|
||||||
// 删除客群客户关联
|
// 删除客群客户关联
|
||||||
LambdaQueryWrapper<CustGroupMember> memberWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<CustGroupMember> memberWrapper = new LambdaQueryWrapper<>();
|
||||||
memberWrapper.eq(CustGroupMember::getGroupId, id);
|
memberWrapper.eq(CustGroupMember::getGroupId, id);
|
||||||
@@ -196,12 +215,39 @@ public class CustGroupServiceImpl implements ICustGroupService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkCustGroupViewPermission(Long id) {
|
public void checkCustGroupViewPermission(Long id) {
|
||||||
Long count = custGroupMapper.countVisibleCustGroup(id, SecurityUtils.getUsername(), String.valueOf(SecurityUtils.getDeptId()));
|
Long count = custGroupMapper.countVisibleCustGroup(
|
||||||
|
id,
|
||||||
|
SecurityUtils.getUsername(),
|
||||||
|
String.valueOf(SecurityUtils.getDeptId()),
|
||||||
|
isHeadCustGroupAdmin(),
|
||||||
|
SecurityUtils.getHeadId()
|
||||||
|
);
|
||||||
if (count == null || count <= 0) {
|
if (count == null || count <= 0) {
|
||||||
throw new ServiceException("客群不存在或无查看权限");
|
throw new ServiceException("客群不存在或无查看权限");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHeadCustGroupAdmin() {
|
||||||
|
return SecurityUtils.hasRole("headAdmin")
|
||||||
|
|| SecurityUtils.hasRole("headPublic")
|
||||||
|
|| SecurityUtils.hasRole("headPrivate")
|
||||||
|
|| SecurityUtils.hasRole("headOps");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertHeadCustGroupAdmin() {
|
||||||
|
if (!isHeadCustGroupAdmin()) {
|
||||||
|
throw new ServiceException("当前用户无权限操作该功能");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertOperatePermission(CustGroup custGroup) {
|
||||||
|
assertHeadCustGroupAdmin();
|
||||||
|
Long count = custGroupMapper.countHeadOperableCustGroup(custGroup.getId(), SecurityUtils.getHeadId());
|
||||||
|
if (count == null || count <= 0) {
|
||||||
|
throw new ServiceException("无权限操作该客群");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateDynamicCustGroups() {
|
public void updateDynamicCustGroups() {
|
||||||
log.info("开始更新动态客群...");
|
log.info("开始更新动态客群...");
|
||||||
|
|||||||
@@ -6,7 +6,22 @@
|
|||||||
|
|
||||||
<sql id="custGroupVisibleBaseCondition">
|
<sql id="custGroupVisibleBaseCondition">
|
||||||
AND (
|
AND (
|
||||||
cg.user_name = #{userName}
|
<choose>
|
||||||
|
<when test="headRole != null and headRole">
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys_user su
|
||||||
|
LEFT JOIN sys_user_role sur ON su.user_id = sur.user_id
|
||||||
|
LEFT JOIN sys_role sr ON sur.role_id = sr.role_id
|
||||||
|
WHERE su.user_name = cg.user_name
|
||||||
|
AND LEFT(CAST(cg.dept_id AS CHAR), 3) = #{headId}
|
||||||
|
AND sr.role_key IN ('headAdmin', 'headPublic', 'headPrivate', 'headOps')
|
||||||
|
)
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
1 = 2
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
OR (
|
OR (
|
||||||
cg.share_enabled = 1
|
cg.share_enabled = 1
|
||||||
AND cg.group_status = '0'
|
AND cg.group_status = '0'
|
||||||
@@ -20,7 +35,22 @@
|
|||||||
<sql id="custGroupVisibleCondition">
|
<sql id="custGroupVisibleCondition">
|
||||||
<choose>
|
<choose>
|
||||||
<when test="dto != null and dto.viewType == 'mine'">
|
<when test="dto != null and dto.viewType == 'mine'">
|
||||||
AND cg.user_name = #{userName}
|
<choose>
|
||||||
|
<when test="dto.headRole">
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys_user su
|
||||||
|
LEFT JOIN sys_user_role sur ON su.user_id = sur.user_id
|
||||||
|
LEFT JOIN sys_role sr ON sur.role_id = sr.role_id
|
||||||
|
WHERE su.user_name = cg.user_name
|
||||||
|
AND LEFT(CAST(cg.dept_id AS CHAR), 3) = #{headId}
|
||||||
|
AND sr.role_key IN ('headAdmin', 'headPublic', 'headPrivate', 'headOps')
|
||||||
|
)
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
AND 1 = 2
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</when>
|
</when>
|
||||||
<when test="dto != null and dto.viewType == 'sharedToMe'">
|
<when test="dto != null and dto.viewType == 'sharedToMe'">
|
||||||
AND cg.share_enabled = 1
|
AND cg.share_enabled = 1
|
||||||
@@ -116,6 +146,22 @@
|
|||||||
<include refid="custGroupVisibleBaseCondition"/>
|
<include refid="custGroupVisibleBaseCondition"/>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="countHeadOperableCustGroup" resultType="java.lang.Long">
|
||||||
|
SELECT COUNT(1)
|
||||||
|
FROM ibs_cust_group cg
|
||||||
|
WHERE cg.id = #{id}
|
||||||
|
AND cg.del_flag = '0'
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys_user su
|
||||||
|
LEFT JOIN sys_user_role sur ON su.user_id = sur.user_id
|
||||||
|
LEFT JOIN sys_role sr ON sur.role_id = sr.role_id
|
||||||
|
WHERE su.user_name = cg.user_name
|
||||||
|
AND LEFT(CAST(cg.dept_id AS CHAR), 3) = #{headId}
|
||||||
|
AND sr.role_key IN ('headAdmin', 'headPublic', 'headPrivate', 'headOps')
|
||||||
|
)
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectAllGroupTags" resultType="java.lang.String">
|
<select id="selectAllGroupTags" resultType="java.lang.String">
|
||||||
SELECT DISTINCT group_tags
|
SELECT DISTINCT group_tags
|
||||||
FROM ibs_cust_group
|
FROM ibs_cust_group
|
||||||
|
|||||||
@@ -24,6 +24,17 @@
|
|||||||
<where>
|
<where>
|
||||||
cgm.group_id = #{groupId}
|
cgm.group_id = #{groupId}
|
||||||
AND cgm.del_flag = '0'
|
AND cgm.del_flag = '0'
|
||||||
|
<choose>
|
||||||
|
<when test="dto != null and dto.userRole == 'branch'">
|
||||||
|
AND cgm.branch_id = #{dto.currentDeptId}
|
||||||
|
</when>
|
||||||
|
<when test="dto != null and dto.userRole == 'outlet'">
|
||||||
|
AND cgm.outlet_id = #{dto.currentDeptId}
|
||||||
|
</when>
|
||||||
|
<when test="dto != null and dto.userRole == 'manager'">
|
||||||
|
AND cgm.user_name = #{dto.currentUserName}
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
<if test="dto != null and dto.custType != null and dto.custType != ''">
|
<if test="dto != null and dto.custType != null and dto.custType != ''">
|
||||||
AND cgm.cust_type = #{dto.custType}
|
AND cgm.cust_type = #{dto.custType}
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.common.annotation.Log;
|
|||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.ibs.cmpm.domain.dto.CustLevelDTO;
|
import com.ruoyi.ibs.cmpm.domain.dto.CustLevelDTO;
|
||||||
import com.ruoyi.ibs.cmpm.domain.dto.CustManagerDTO;
|
import com.ruoyi.ibs.cmpm.domain.dto.CustManagerDTO;
|
||||||
@@ -104,6 +105,17 @@ public class GridCmpmController extends BaseController {
|
|||||||
return success(gridCmpmService.getCustLevelListForManager());
|
return success(gridCmpmService.getCustLevelListForManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/custManager/export")
|
||||||
|
@Log(title = "绩效网格-管户报表异步导出", businessType = BusinessType.EXPORT)
|
||||||
|
@ApiOperation("管户报表异步导出")
|
||||||
|
public AjaxResult exportCustManager(@RequestBody(required = false) CustManagerDTO custManagerDTO) {
|
||||||
|
if (custManagerDTO == null) {
|
||||||
|
custManagerDTO = new CustManagerDTO();
|
||||||
|
}
|
||||||
|
String taskId = gridCmpmService.exportCustManagerAsync(custManagerDTO);
|
||||||
|
return AjaxResult.success("导出任务创建成功,请稍后前往下载中心下载", taskId);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/custLevel/count")
|
@GetMapping("/custLevel/count")
|
||||||
@Log(title = "绩效网格-查询客户分层等级")
|
@Log(title = "绩效网格-查询客户分层等级")
|
||||||
@ApiOperation("查询客户分层等级")
|
@ApiOperation("查询客户分层等级")
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ruoyi.ibs.cmpm.domain.vo;
|
package com.ruoyi.ibs.cmpm.domain.vo;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -24,74 +23,92 @@ public class DwbRetailCustLevelManagerDetailVO {
|
|||||||
|
|
||||||
/** 网点号 */
|
/** 网点号 */
|
||||||
@ApiModelProperty(value = "网点号")
|
@ApiModelProperty(value = "网点号")
|
||||||
|
@ExcelProperty("网点号")
|
||||||
private String outletId;
|
private String outletId;
|
||||||
|
|
||||||
/** 网点名 */
|
/** 网点名 */
|
||||||
@ApiModelProperty(value = "网点名")
|
@ApiModelProperty(value = "网点名")
|
||||||
|
@ExcelProperty("网点名")
|
||||||
private String outletName;
|
private String outletName;
|
||||||
|
|
||||||
/** 支行号 */
|
/** 支行号 */
|
||||||
@ApiModelProperty(value = "支行号")
|
@ApiModelProperty(value = "支行号")
|
||||||
|
@ExcelProperty("支行号")
|
||||||
private String branchId;
|
private String branchId;
|
||||||
|
|
||||||
/** 支行名 */
|
/** 支行名 */
|
||||||
@ApiModelProperty(value = "支行名")
|
@ApiModelProperty(value = "支行名")
|
||||||
|
@ExcelProperty("支行名")
|
||||||
private String branchName;
|
private String branchName;
|
||||||
|
|
||||||
/** 客户名称 */
|
/** 客户名称 */
|
||||||
@ApiModelProperty(value = "客户名称")
|
@ApiModelProperty(value = "客户名称")
|
||||||
|
@ExcelProperty("客户名称")
|
||||||
private String custName;
|
private String custName;
|
||||||
|
|
||||||
/** 客户证件号 */
|
/** 客户证件号 */
|
||||||
@ApiModelProperty(value = "客户证件号")
|
@ApiModelProperty(value = "客户证件号")
|
||||||
|
@ExcelProperty("客户证件号")
|
||||||
private String custIdc;
|
private String custIdc;
|
||||||
|
|
||||||
/** 客户内码 */
|
/** 客户内码 */
|
||||||
@ApiModelProperty(value = "客户内码")
|
@ApiModelProperty(value = "客户内码")
|
||||||
|
@ExcelProperty("客户内码")
|
||||||
private String custIsn;
|
private String custIsn;
|
||||||
|
|
||||||
/** 年龄 */
|
/** 年龄 */
|
||||||
@ApiModelProperty(value = "年龄")
|
@ApiModelProperty(value = "年龄")
|
||||||
|
@ExcelProperty("年龄")
|
||||||
private String custAge;
|
private String custAge;
|
||||||
|
|
||||||
/** 性别 */
|
/** 性别 */
|
||||||
@ApiModelProperty(value = "性别")
|
@ApiModelProperty(value = "性别")
|
||||||
|
@ExcelProperty("性别")
|
||||||
private String custSex;
|
private String custSex;
|
||||||
|
|
||||||
/** 联系电话 */
|
/** 联系电话 */
|
||||||
@ApiModelProperty(value = "联系电话")
|
@ApiModelProperty(value = "联系电话")
|
||||||
|
@ExcelProperty("联系电话")
|
||||||
private String custPhone;
|
private String custPhone;
|
||||||
|
|
||||||
/** 联系地址 */
|
/** 联系地址 */
|
||||||
@ApiModelProperty(value = "联系地址")
|
@ApiModelProperty(value = "联系地址")
|
||||||
|
@ExcelProperty("联系地址")
|
||||||
private String custAddress;
|
private String custAddress;
|
||||||
|
|
||||||
/** 总资产余额 */
|
/** 总资产余额 */
|
||||||
@ApiModelProperty(value = "总资产余额")
|
@ApiModelProperty(value = "总资产余额")
|
||||||
|
@ExcelProperty("总资产余额")
|
||||||
private BigDecimal custAumBal;
|
private BigDecimal custAumBal;
|
||||||
|
|
||||||
/** 总资产余额较上月变动 */
|
/** 总资产余额较上月变动 */
|
||||||
@ApiModelProperty(value = "总资产余额较上月变动")
|
@ApiModelProperty(value = "总资产余额较上月变动")
|
||||||
|
@ExcelProperty("总资产余额较上月变动")
|
||||||
private BigDecimal aumBalCompLm;
|
private BigDecimal aumBalCompLm;
|
||||||
|
|
||||||
/** 总资产月日均 */
|
/** 总资产月日均 */
|
||||||
@ApiModelProperty(value = "总资产月日均")
|
@ApiModelProperty(value = "总资产月日均")
|
||||||
|
@ExcelProperty("总资产余额月日均")
|
||||||
private BigDecimal custAumMonthAvg;
|
private BigDecimal custAumMonthAvg;
|
||||||
|
|
||||||
/** 客户星级 */
|
/** 客户星级 */
|
||||||
@ApiModelProperty(value = "客户星级")
|
@ApiModelProperty(value = "客户星级")
|
||||||
|
@ExcelProperty("客户星级")
|
||||||
private String custLevel;
|
private String custLevel;
|
||||||
|
|
||||||
/** 星级较上月变动 */
|
/** 星级较上月变动 */
|
||||||
@ApiModelProperty(value = "星级较上月变动")
|
@ApiModelProperty(value = "星级较上月变动")
|
||||||
|
@ExcelProperty("星级较上月变动")
|
||||||
private String custLevelCompLm;
|
private String custLevelCompLm;
|
||||||
|
|
||||||
/** 责任人 */
|
/** 责任人 */
|
||||||
@ApiModelProperty(value = "责任人")
|
@ApiModelProperty(value = "责任人")
|
||||||
|
@ExcelProperty("责任人")
|
||||||
private String managerName;
|
private String managerName;
|
||||||
|
|
||||||
/** 责任人柜员号 */
|
/** 责任人柜员号 */
|
||||||
@ApiModelProperty(value = "责任人柜员号")
|
@ApiModelProperty(value = "责任人柜员号")
|
||||||
|
@ExcelProperty("责任人柜员号")
|
||||||
private String managerId;
|
private String managerId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ public interface GridCmpmMapper {
|
|||||||
|
|
||||||
List<DwbRetailCustLevelManagerDetailVO> getCustManagerList(CustManagerDTO custManagerDTO);
|
List<DwbRetailCustLevelManagerDetailVO> getCustManagerList(CustManagerDTO custManagerDTO);
|
||||||
|
|
||||||
|
List<DwbRetailCustLevelManagerDetailVO> getCustManagerListByPage(@Param("dto") CustManagerDTO custManagerDTO,
|
||||||
|
@Param("headId") String headId,
|
||||||
|
@Param("offset") Integer offset,
|
||||||
|
@Param("pageSize") Integer pageSize);
|
||||||
|
|
||||||
int getCustLevelCount(CustManagerDTO custManagerDTO);
|
int getCustLevelCount(CustManagerDTO custManagerDTO);
|
||||||
|
|
||||||
List<CustBaseInfo> selectCustInfoFromGridCmpm(CustBaseInfo custBaseInfo);
|
List<CustBaseInfo> selectCustInfoFromGridCmpm(CustBaseInfo custBaseInfo);
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
package com.ruoyi.ibs.cmpm.service;
|
package com.ruoyi.ibs.cmpm.service;
|
||||||
|
|
||||||
|
import com.alibaba.excel.EasyExcel;
|
||||||
|
import com.alibaba.excel.ExcelWriter;
|
||||||
|
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.bean.BeanUtils;
|
import com.ruoyi.common.utils.bean.BeanUtils;
|
||||||
|
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||||
import com.ruoyi.ibs.cmpm.domain.dto.CustLevelDTO;
|
import com.ruoyi.ibs.cmpm.domain.dto.CustLevelDTO;
|
||||||
import com.ruoyi.ibs.cmpm.domain.dto.CustManagerDTO;
|
import com.ruoyi.ibs.cmpm.domain.dto.CustManagerDTO;
|
||||||
import com.ruoyi.ibs.cmpm.domain.dto.GridCmpmListDTO;
|
import com.ruoyi.ibs.cmpm.domain.dto.GridCmpmListDTO;
|
||||||
@@ -14,11 +18,19 @@ import com.ruoyi.ibs.cmpm.domain.vo.DwbRetailCustLevelManagerDetailVO;
|
|||||||
import com.ruoyi.ibs.cmpm.domain.vo.DwbRetailResultVO;
|
import com.ruoyi.ibs.cmpm.domain.vo.DwbRetailResultVO;
|
||||||
import com.ruoyi.ibs.cmpm.domain.vo.GridCmpmVO;
|
import com.ruoyi.ibs.cmpm.domain.vo.GridCmpmVO;
|
||||||
import com.ruoyi.ibs.cmpm.mapper.GridCmpmMapper;
|
import com.ruoyi.ibs.cmpm.mapper.GridCmpmMapper;
|
||||||
|
import com.ruoyi.ibs.task.domain.entity.ImportExportTask;
|
||||||
|
import com.ruoyi.ibs.task.mapper.ImportExportTaskMapper;
|
||||||
|
import com.ruoyi.system.enums.OssFileEnum;
|
||||||
|
import com.ruoyi.system.service.OssFileService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.io.File;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -27,6 +39,7 @@ import java.util.stream.Collectors;
|
|||||||
* @Date 2025/10/15
|
* @Date 2025/10/15
|
||||||
**/
|
**/
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
public class GridCmpmService {
|
public class GridCmpmService {
|
||||||
|
|
||||||
|
|
||||||
@@ -39,6 +52,15 @@ public class GridCmpmService {
|
|||||||
@Resource
|
@Resource
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ImportExportTaskMapper importExportTaskMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OssFileService ossFileService;
|
||||||
|
|
||||||
|
@Resource(name = "excelExportExecutor")
|
||||||
|
private ExecutorService executorService;
|
||||||
|
|
||||||
private final String CUST_LEVEL_COUNT_KEY = "GRID_CMPM_CUST_LEVEL_COUNT_";
|
private final String CUST_LEVEL_COUNT_KEY = "GRID_CMPM_CUST_LEVEL_COUNT_";
|
||||||
|
|
||||||
public List<GridCmpmVO> selectManageList(GridCmpmListDTO gridCmpmRetailListDTO){
|
public List<GridCmpmVO> selectManageList(GridCmpmListDTO gridCmpmRetailListDTO){
|
||||||
@@ -94,33 +116,32 @@ public class GridCmpmService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<DwbRetailCustLevelManagerDetailVO> selectCustManagerList(CustManagerDTO custManagerDTO) {
|
public List<DwbRetailCustLevelManagerDetailVO> selectCustManagerList(CustManagerDTO custManagerDTO) {
|
||||||
String userRole = SecurityUtils.userRole();
|
applyCustManagerScope(custManagerDTO);
|
||||||
if (userRole.equals("manager")){
|
|
||||||
//客户经理查自己
|
|
||||||
custManagerDTO.setManagerId(SecurityUtils.getUsername());
|
|
||||||
}else if (userRole.equals("outlet")){
|
|
||||||
//网点管理员查网点
|
|
||||||
custManagerDTO.setOutletId(String.valueOf(SecurityUtils.getDeptId()));
|
|
||||||
}else if (userRole.equals("branch")){
|
|
||||||
//支行管理员查支行
|
|
||||||
custManagerDTO.setBranchId(String.valueOf(SecurityUtils.getDeptId()));
|
|
||||||
}
|
|
||||||
//其他角色查全部
|
|
||||||
return gridCmpmMapper.getCustManagerList(custManagerDTO);
|
return gridCmpmMapper.getCustManagerList(custManagerDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String exportCustManagerAsync(CustManagerDTO custManagerDTO) {
|
||||||
|
applyCustManagerScope(custManagerDTO);
|
||||||
|
String headId = SecurityUtils.getHeadId();
|
||||||
|
|
||||||
|
ImportExportTask task = new ImportExportTask();
|
||||||
|
String taskId = IdUtils.randomUUID();
|
||||||
|
task.setId(taskId);
|
||||||
|
task.setStatus("0");
|
||||||
|
Date now = new Date();
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
task.setFileName(sdf.format(now) + "管户报表导出");
|
||||||
|
task.setUserName(SecurityUtils.getUsername());
|
||||||
|
task.setCreateTime(now);
|
||||||
|
importExportTaskMapper.insert(task);
|
||||||
|
|
||||||
|
String userName = SecurityUtils.getUsername();
|
||||||
|
executorService.submit(() -> doExportCustManager(taskId, custManagerDTO, userName, headId));
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
public int custLevelCount(CustManagerDTO custManagerDTO) {
|
public int custLevelCount(CustManagerDTO custManagerDTO) {
|
||||||
String userRole = SecurityUtils.userRole();
|
applyCustManagerScope(custManagerDTO);
|
||||||
if (userRole.equals("manager")){
|
|
||||||
//客户经理查自己
|
|
||||||
custManagerDTO.setManagerId(SecurityUtils.getUsername());
|
|
||||||
}else if (userRole.equals("outlet")){
|
|
||||||
//网点管理员查网点
|
|
||||||
custManagerDTO.setOutletId(String.valueOf(SecurityUtils.getDeptId()));
|
|
||||||
}else if (userRole.equals("branch")){
|
|
||||||
//支行管理员查支行
|
|
||||||
custManagerDTO.setBranchId(String.valueOf(SecurityUtils.getDeptId()));
|
|
||||||
}
|
|
||||||
return gridCmpmMapper.getCustLevelCount(custManagerDTO);
|
return gridCmpmMapper.getCustLevelCount(custManagerDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,6 +295,64 @@ public class GridCmpmService {
|
|||||||
return custLevelCountMap;
|
return custLevelCountMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyCustManagerScope(CustManagerDTO custManagerDTO) {
|
||||||
|
String userRole = SecurityUtils.userRole();
|
||||||
|
if (userRole.equals("manager")) {
|
||||||
|
custManagerDTO.setManagerId(SecurityUtils.getUsername());
|
||||||
|
} else if (userRole.equals("outlet")) {
|
||||||
|
custManagerDTO.setOutletId(String.valueOf(SecurityUtils.getDeptId()));
|
||||||
|
} else if (userRole.equals("branch")) {
|
||||||
|
custManagerDTO.setBranchId(String.valueOf(SecurityUtils.getDeptId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doExportCustManager(String taskId, CustManagerDTO custManagerDTO, String userName, String headId) {
|
||||||
|
ImportExportTask task = importExportTaskMapper.selectById(taskId);
|
||||||
|
File tempFile = null;
|
||||||
|
try {
|
||||||
|
tempFile = File.createTempFile("管户报表导出_" + taskId + "-", ".xlsx");
|
||||||
|
ExcelWriter excelWriter = EasyExcel.write(tempFile, DwbRetailCustLevelManagerDetailVO.class).build();
|
||||||
|
WriteSheet writeSheet = EasyExcel.writerSheet("管户报表").build();
|
||||||
|
int pageSize = 1000;
|
||||||
|
int pageNum = 0;
|
||||||
|
List<DwbRetailCustLevelManagerDetailVO> pageData;
|
||||||
|
|
||||||
|
do {
|
||||||
|
pageData = gridCmpmMapper.getCustManagerListByPage(custManagerDTO, headId, pageNum * pageSize, pageSize);
|
||||||
|
if (!pageData.isEmpty()) {
|
||||||
|
excelWriter.write(pageData, writeSheet);
|
||||||
|
}
|
||||||
|
pageNum++;
|
||||||
|
} while (pageData.size() == pageSize);
|
||||||
|
|
||||||
|
excelWriter.finish();
|
||||||
|
|
||||||
|
String ossUUId = ossFileService.uploadFileToOss(
|
||||||
|
OssFileEnum.CUST_MANAGER_REPORT,
|
||||||
|
tempFile,
|
||||||
|
"管户报表导出_" + taskId + ".xlsx",
|
||||||
|
userName
|
||||||
|
);
|
||||||
|
|
||||||
|
task.setStatus("1");
|
||||||
|
task.setFileUrl(ossUUId);
|
||||||
|
task.setFinishTime(new Date());
|
||||||
|
importExportTaskMapper.updateById(task);
|
||||||
|
} catch (Exception e) {
|
||||||
|
task.setStatus("2");
|
||||||
|
task.setFinishTime(new Date());
|
||||||
|
task.setErrorMsg(e.getMessage());
|
||||||
|
importExportTaskMapper.updateById(task);
|
||||||
|
} finally {
|
||||||
|
if (Objects.nonNull(tempFile)) {
|
||||||
|
boolean deleted = tempFile.delete();
|
||||||
|
if (!deleted) {
|
||||||
|
log.warn("临时文件删除失败: {}", tempFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 计算客户等级变化情况
|
// 计算客户等级变化情况
|
||||||
private Map<String, Integer> calculateLevelChanges(Map<String, Integer> historyMap, Map<String, Integer> currentMap) {
|
private Map<String, Integer> calculateLevelChanges(Map<String, Integer> historyMap, Map<String, Integer> currentMap) {
|
||||||
Map<String, Integer> changesMap = new HashMap<>();
|
Map<String, Integer> changesMap = new HashMap<>();
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package com.ruoyi.ibs.task.controller;
|
package com.ruoyi.ibs.task.controller;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||||
|
import com.ruoyi.ibs.task.domain.dto.AlterForwardRequest;
|
||||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||||
import com.ruoyi.ibs.task.domain.entity.Alter;
|
import com.ruoyi.ibs.task.domain.entity.Alter;
|
||||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||||
@@ -95,12 +98,37 @@ public class WorkRecordController extends BaseController {
|
|||||||
@GetMapping("/alter/allList")
|
@GetMapping("/alter/allList")
|
||||||
@Log(title = "工作台-查询预警信息")
|
@Log(title = "工作台-查询预警信息")
|
||||||
@ApiOperation("查询所有预警信息")
|
@ApiOperation("查询所有预警信息")
|
||||||
public TableDataPageInfo<AlterVO> allAlterList(String status, String alterType) {
|
public TableDataPageInfo<AlterVO> allAlterList(String status, String alterType, String forwardFlag) {
|
||||||
Page<Object> page = startPage();
|
Page<Object> page = startPage();
|
||||||
List<AlterVO> list = workRecordService.getAllAlterList(status, alterType);
|
List<AlterVO> list = workRecordService.getAllAlterList(status, alterType, forwardFlag);
|
||||||
return getDataTable(list, page);
|
return getDataTable(list, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/alter/forward/meta")
|
||||||
|
@Log(title = "工作台-查询预警转发元数据")
|
||||||
|
@ApiOperation("查询预警转发元数据")
|
||||||
|
public AjaxResult getAlterForwardMeta(@RequestParam String ids) {
|
||||||
|
List<Long> idList = Arrays.stream(ids.split(","))
|
||||||
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
||||||
|
.map(Long::valueOf)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return AjaxResult.success(workRecordService.getAlterForwardMeta(idList));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/alter/forward")
|
||||||
|
@Log(title = "工作台-转发预警信息")
|
||||||
|
@ApiOperation("批量转发预警信息")
|
||||||
|
public AjaxResult forwardAlter(@Validated @RequestBody AlterForwardRequest request) {
|
||||||
|
AlterForwardResultVO result = workRecordService.forwardAlter(request);
|
||||||
|
if (result.getSuccessCount() > 0 && result.getFailCount() > 0) {
|
||||||
|
return AjaxResult.success("成功转发" + result.getSuccessCount() + "条,失败" + result.getFailCount() + "条", result);
|
||||||
|
}
|
||||||
|
if (result.getSuccessCount() > 0) {
|
||||||
|
return AjaxResult.success("成功转发" + result.getSuccessCount() + "条", result);
|
||||||
|
}
|
||||||
|
return AjaxResult.error("未能成功转发,失败" + result.getFailCount() + "条");
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/alter/count")
|
@GetMapping("/alter/count")
|
||||||
@Log(title = "工作台-查询预警推送次数")
|
@Log(title = "工作台-查询预警推送次数")
|
||||||
@ApiOperation("查询预警推送次数")
|
@ApiOperation("查询预警推送次数")
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.ruoyi.ibs.task.domain.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AlterForwardRequest {
|
||||||
|
|
||||||
|
@NotEmpty(message = "请选择需要转发的预警")
|
||||||
|
private List<Long> ids;
|
||||||
|
|
||||||
|
@NotBlank(message = "请选择转发目标类型")
|
||||||
|
private String targetType;
|
||||||
|
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
private Boolean useHistory;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.ruoyi.ibs.task.domain.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ForwardTarget {
|
||||||
|
|
||||||
|
private String targetType;
|
||||||
|
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
private String targetName;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.ruoyi.ibs.task.domain.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("alter_assign_history")
|
||||||
|
public class AlterAssignHistory implements Serializable {
|
||||||
|
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty("预警类型")
|
||||||
|
private String alterType;
|
||||||
|
|
||||||
|
@ApiModelProperty("客户号")
|
||||||
|
private String custId;
|
||||||
|
|
||||||
|
@ApiModelProperty("客户姓名")
|
||||||
|
private String custName;
|
||||||
|
|
||||||
|
@ApiModelProperty("所属支行/当前操作机构ID")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@ApiModelProperty("最近一次转发目标类型:dept/user")
|
||||||
|
private String lastAssignTargetType;
|
||||||
|
|
||||||
|
@ApiModelProperty("最近一次转发目标部门ID")
|
||||||
|
private Long lastAssignTargetDeptId;
|
||||||
|
|
||||||
|
@ApiModelProperty("最近一次转发目标用户账号")
|
||||||
|
private String lastAssignTargetUser;
|
||||||
|
|
||||||
|
@ApiModelProperty("最近一次转发目标名称")
|
||||||
|
private String lastAssignTargetName;
|
||||||
|
|
||||||
|
@ApiModelProperty("最近一次转发操作人账号")
|
||||||
|
private String lastAssignByUser;
|
||||||
|
|
||||||
|
@ApiModelProperty("最近一次转发操作人角色")
|
||||||
|
private String lastAssignByRole;
|
||||||
|
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
||||||
@@ -94,4 +94,8 @@ public class WorkRecord implements Serializable {
|
|||||||
@ApiModelProperty(value = "是否逾期", notes = "")
|
@ApiModelProperty(value = "是否逾期", notes = "")
|
||||||
private Integer isOverdue;
|
private Integer isOverdue;
|
||||||
|
|
||||||
|
/** 当前承接部门ID,仅转发到网点时使用 */
|
||||||
|
@ApiModelProperty(value = "当前承接部门ID", notes = "")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.ruoyi.ibs.task.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AlterAssignTargetVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("目标编码")
|
||||||
|
private String targetCode;
|
||||||
|
|
||||||
|
@ApiModelProperty("目标名称")
|
||||||
|
private String targetName;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.ruoyi.ibs.task.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AlterForwardMetaVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("可选网点列表")
|
||||||
|
private List<AlterAssignTargetVO> deptOptions = new ArrayList<>();
|
||||||
|
|
||||||
|
@ApiModelProperty("可选客户经理列表")
|
||||||
|
private List<AlterAssignTargetVO> userOptions = new ArrayList<>();
|
||||||
|
|
||||||
|
@ApiModelProperty("历史推荐目标类型:dept/user")
|
||||||
|
private String recommendedTargetType;
|
||||||
|
|
||||||
|
@ApiModelProperty("历史推荐目标编码")
|
||||||
|
private String recommendedTargetCode;
|
||||||
|
|
||||||
|
@ApiModelProperty("历史推荐目标名称")
|
||||||
|
private String recommendedTargetName;
|
||||||
|
|
||||||
|
@ApiModelProperty("是否仅允许按历史推荐转发")
|
||||||
|
private Boolean historyOnly = false;
|
||||||
|
|
||||||
|
@ApiModelProperty("是否存在历史推荐")
|
||||||
|
private Boolean hasHistoryRecommend = false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.ruoyi.ibs.task.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AlterForwardResultVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("成功数量")
|
||||||
|
private int successCount;
|
||||||
|
|
||||||
|
@ApiModelProperty("失败数量")
|
||||||
|
private int failCount;
|
||||||
|
}
|
||||||
@@ -47,6 +47,14 @@ public class AlterVO {
|
|||||||
@ApiModelProperty(value = "客户内码", notes = "")
|
@ApiModelProperty(value = "客户内码", notes = "")
|
||||||
private String custIsn;
|
private String custIsn;
|
||||||
|
|
||||||
|
/** 当前承接部门ID */
|
||||||
|
@ApiModelProperty(value = "当前承接部门ID", notes = "")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/** 当前承接网点名称 */
|
||||||
|
@ApiModelProperty(value = "当前承接网点名称", notes = "")
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
/** 状态 */
|
/** 状态 */
|
||||||
@ApiModelProperty(value = "状态", notes = "")
|
@ApiModelProperty(value = "状态", notes = "")
|
||||||
private String status;
|
private String status;
|
||||||
@@ -62,4 +70,12 @@ public class AlterVO {
|
|||||||
/** 是否需要反馈 */
|
/** 是否需要反馈 */
|
||||||
@ApiModelProperty(value = "是否需要反馈", notes = "")
|
@ApiModelProperty(value = "是否需要反馈", notes = "")
|
||||||
private String isFeedback;
|
private String isFeedback;
|
||||||
|
|
||||||
|
/** 转发标识:1需要转发,0无需转发 */
|
||||||
|
@ApiModelProperty(value = "转发标识", notes = "")
|
||||||
|
private String forwardFlag;
|
||||||
|
|
||||||
|
/** 是否可转发 */
|
||||||
|
@ApiModelProperty(value = "是否可转发", notes = "")
|
||||||
|
private Boolean canForward;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.ruoyi.ibs.task.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.ruoyi.ibs.task.domain.entity.AlterAssignHistory;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface AlterAssignHistoryMapper extends BaseMapper<AlterAssignHistory> {
|
||||||
|
}
|
||||||
@@ -6,9 +6,9 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
||||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||||
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
|
||||||
import com.ruoyi.ibs.task.domain.vo.*;
|
import com.ruoyi.ibs.task.domain.vo.*;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
@@ -86,10 +86,26 @@ public interface WorkRecordMapper extends BaseMapper<WorkRecord> {
|
|||||||
* @return 预警信息
|
* @return 预警信息
|
||||||
*/
|
*/
|
||||||
List<AlterVO> selectAllAlterList(@Param("deptId") String deptId, @Param("role") String role,
|
List<AlterVO> selectAllAlterList(@Param("deptId") String deptId, @Param("role") String role,
|
||||||
@Param("status") String status, @Param("alterType") String alterType, @Param("username") String username);
|
@Param("status") String status, @Param("alterType") String alterType,
|
||||||
|
@Param("username") String username, @Param("forwardFlag") String forwardFlag);
|
||||||
|
|
||||||
AlterCountVO selectAlterCount(@Param("reportTime") Date reportTime, @Param("role") String role, @Param("deptId") String deptId);
|
AlterCountVO selectAlterCount(@Param("reportTime") Date reportTime, @Param("role") String role, @Param("deptId") String deptId);
|
||||||
|
|
||||||
|
List<AlterAssignTargetVO> selectForwardDeptTargets(@Param("branchDeptId") Long branchDeptId);
|
||||||
|
|
||||||
|
List<AlterAssignTargetVO> selectForwardUserTargets(@Param("deptId") Long deptId, @Param("role") String role);
|
||||||
|
|
||||||
|
int updateAlterForwardToDept(@Param("id") Long id, @Param("sourceUserName") String sourceUserName,
|
||||||
|
@Param("targetDeptId") Long targetDeptId, @Param("updateBy") String updateBy);
|
||||||
|
|
||||||
|
int updateAlterForwardToUserByBranch(@Param("id") Long id, @Param("sourceUserName") String sourceUserName,
|
||||||
|
@Param("targetUserName") String targetUserName, @Param("targetNickName") String targetNickName,
|
||||||
|
@Param("updateBy") String updateBy);
|
||||||
|
|
||||||
|
int updateAlterForwardToUserByOutlet(@Param("id") Long id, @Param("sourceDeptId") Long sourceDeptId,
|
||||||
|
@Param("targetUserName") String targetUserName, @Param("targetNickName") String targetNickName,
|
||||||
|
@Param("updateBy") String updateBy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置工作清单为过期
|
* 设置工作清单为过期
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||||
|
import com.ruoyi.ibs.task.domain.dto.AlterForwardRequest;
|
||||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||||
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
||||||
import com.ruoyi.ibs.task.domain.vo.*;
|
import com.ruoyi.ibs.task.domain.vo.*;
|
||||||
@@ -61,7 +62,23 @@ public interface WorkRecordService{
|
|||||||
* @param alterType
|
* @param alterType
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<AlterVO> getAllAlterList(String status, String alterType);
|
List<AlterVO> getAllAlterList(String status, String alterType, String forwardFlag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取预警转发元数据
|
||||||
|
*
|
||||||
|
* @param id 预警ID
|
||||||
|
* @return 转发元数据
|
||||||
|
*/
|
||||||
|
AlterForwardMetaVO getAlterForwardMeta(List<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量转发预警
|
||||||
|
*
|
||||||
|
* @param request 转发请求
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
AlterForwardResultVO forwardAlter(AlterForwardRequest request);
|
||||||
/**
|
/**
|
||||||
* 定时任务生成工作清单
|
* 定时任务生成工作清单
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -11,20 +11,29 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.ruoyi.common.core.page.TableDataPageInfo;
|
import com.ruoyi.common.core.page.TableDataPageInfo;
|
||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.utils.PageUtils;
|
import com.ruoyi.common.utils.PageUtils;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.ibs.task.domain.dto.AlterForwardRequest;
|
||||||
|
import com.ruoyi.ibs.task.domain.dto.ForwardTarget;
|
||||||
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
import com.ruoyi.ibs.task.domain.dto.WorkRecordDTO;
|
||||||
|
import com.ruoyi.ibs.task.domain.entity.AlterAssignHistory;
|
||||||
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
import com.ruoyi.ibs.task.domain.entity.AlterConfig;
|
||||||
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
import com.ruoyi.ibs.task.domain.entity.WorkRecord;
|
||||||
import com.ruoyi.ibs.task.domain.vo.*;
|
import com.ruoyi.ibs.task.domain.vo.*;
|
||||||
|
import com.ruoyi.ibs.task.mapper.AlterAssignHistoryMapper;
|
||||||
import com.ruoyi.ibs.task.mapper.WorkRecordMapper;
|
import com.ruoyi.ibs.task.mapper.WorkRecordMapper;
|
||||||
import com.ruoyi.ibs.task.service.WorkRecordService;
|
import com.ruoyi.ibs.task.service.WorkRecordService;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.system.domain.SysPost;
|
import com.ruoyi.system.domain.SysPost;
|
||||||
import com.ruoyi.system.service.ISysDeptService;
|
import com.ruoyi.system.service.ISysDeptService;
|
||||||
import com.ruoyi.system.service.ISysPostService;
|
import com.ruoyi.system.service.ISysPostService;
|
||||||
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -41,16 +50,31 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
public class WorkRecordServiceImpl implements WorkRecordService {
|
public class WorkRecordServiceImpl implements WorkRecordService {
|
||||||
|
|
||||||
private final static String alterTypesRedisKey = "work:record:alter:types";
|
private final static String alterTypesRedisKey = "work:record:alter:types";
|
||||||
|
private static final String ROLE_MANAGER = "manager";
|
||||||
|
private static final String ROLE_BRANCH = "branch";
|
||||||
|
private static final String ROLE_OUTLET = "outlet";
|
||||||
|
private static final String TARGET_TYPE_DEPT = "dept";
|
||||||
|
private static final String TARGET_TYPE_USER = "user";
|
||||||
|
private static final Set<String> FORWARD_ALTER_TYPES = new HashSet<>(Arrays.asList(
|
||||||
|
"个人资产客户定期存款",
|
||||||
|
"个人资产客户封闭式理财"
|
||||||
|
));
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WorkRecordMapper workRecordMapper;
|
private WorkRecordMapper workRecordMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AlterAssignHistoryMapper alterAssignHistoryMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysPostService sysPostService;
|
private ISysPostService sysPostService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysDeptService sysDeptService;
|
private ISysDeptService sysDeptService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysUserService sysUserService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
|
|
||||||
@@ -143,7 +167,9 @@ public class WorkRecordServiceImpl implements WorkRecordService {
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public List<AlterVO> getAlterList(String status, String alterType) {
|
public List<AlterVO> getAlterList(String status, String alterType) {
|
||||||
String username = SecurityUtils.getUsername();
|
String username = SecurityUtils.getUsername();
|
||||||
return workRecordMapper.selectAlterList(username, status, alterType);
|
List<AlterVO> alterVOS = workRecordMapper.selectAlterList(username, status, alterType);
|
||||||
|
fillAlterExtFields(alterVOS);
|
||||||
|
return alterVOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,27 +182,98 @@ public class WorkRecordServiceImpl implements WorkRecordService {
|
|||||||
* @return 预警信息
|
* @return 预警信息
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<AlterVO> getAllAlterList(String status, String alterType) {
|
public List<AlterVO> getAllAlterList(String status, String alterType, String forwardFlag) {
|
||||||
List<AlterVO> alterVOS = workRecordMapper.selectAllAlterList(String.valueOf(SecurityUtils.getDeptId()), SecurityUtils.userRole(), status, alterType, SecurityUtils.getUsername());
|
List<AlterVO> alterVOS = workRecordMapper.selectAllAlterList(
|
||||||
// 将 userName 和 nickName 以 "userName-nickName" 的方式拼接后设置到 custInfo 字段
|
String.valueOf(SecurityUtils.getDeptId()),
|
||||||
if (alterVOS != null && !alterVOS.isEmpty()) {
|
SecurityUtils.userRole(),
|
||||||
alterVOS.forEach(alterVO -> {
|
status,
|
||||||
String userName = alterVO.getUserName();
|
alterType,
|
||||||
String nickName = alterVO.getNickName();
|
SecurityUtils.getUsername(),
|
||||||
if (userName != null && nickName != null) {
|
forwardFlag
|
||||||
alterVO.setUserInfo(nickName + "-" + userName);
|
);
|
||||||
} else if (userName != null) {
|
fillAlterExtFields(alterVOS);
|
||||||
alterVO.setUserInfo(userName);
|
|
||||||
} else if (nickName != null) {
|
|
||||||
alterVO.setUserInfo(nickName);
|
|
||||||
} else {
|
|
||||||
alterVO.setUserInfo("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return alterVOS;
|
return alterVOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询转发弹窗所需元数据。
|
||||||
|
* 单选时返回手动选项并附带历史推荐;多选时根据是否存在历史记录决定走手动分配还是历史推荐模式。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AlterForwardMetaVO getAlterForwardMeta(List<Long> ids) {
|
||||||
|
if (ids == null || ids.isEmpty()) {
|
||||||
|
throw new ServiceException("请选择需要转发的预警");
|
||||||
|
}
|
||||||
|
AlterForwardMetaVO metaVO = new AlterForwardMetaVO();
|
||||||
|
String role = requireForwardRole();
|
||||||
|
Long currentDeptId = SecurityUtils.getDeptId();
|
||||||
|
String currentUser = SecurityUtils.getUsername();
|
||||||
|
List<WorkRecord> workRecords = workRecordMapper.selectBatchIds(ids);
|
||||||
|
if (workRecords == null || workRecords.size() != ids.size()) {
|
||||||
|
throw new ServiceException("存在预警记录已不存在,请刷新后重试");
|
||||||
|
}
|
||||||
|
workRecords.forEach(item -> validateRecordBeforeForward(item, role, currentUser, currentDeptId));
|
||||||
|
if (ids.size() > 1) {
|
||||||
|
boolean hasAnyHistory = workRecords.stream()
|
||||||
|
.map(item -> getHistoryRecommend(item.getCustId(), currentDeptId, role))
|
||||||
|
.anyMatch(Objects::nonNull);
|
||||||
|
metaVO.setHasHistoryRecommend(hasAnyHistory);
|
||||||
|
metaVO.setHistoryOnly(hasAnyHistory);
|
||||||
|
if (!hasAnyHistory) {
|
||||||
|
fillManualOptions(metaVO, role, currentDeptId);
|
||||||
|
}
|
||||||
|
return metaVO;
|
||||||
|
}
|
||||||
|
WorkRecord workRecord = workRecords.get(0);
|
||||||
|
fillManualOptions(metaVO, role, currentDeptId);
|
||||||
|
fillHistoryRecommend(metaVO, workRecord.getCustId(), currentDeptId, role);
|
||||||
|
return metaVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行预警转发。
|
||||||
|
* 支持手动分配和按历史推荐分配两种模式,并分别统计成功和失败数量。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public AlterForwardResultVO forwardAlter(AlterForwardRequest request) {
|
||||||
|
String role = requireForwardRole();
|
||||||
|
String currentUser = SecurityUtils.getUsername();
|
||||||
|
Long currentDeptId = SecurityUtils.getDeptId();
|
||||||
|
AlterForwardResultVO result = new AlterForwardResultVO();
|
||||||
|
boolean useHistory = Boolean.TRUE.equals(request.getUseHistory());
|
||||||
|
ForwardTarget manualTarget = useHistory ? null : resolveManualTarget(request, role, currentDeptId);
|
||||||
|
|
||||||
|
List<WorkRecord> workRecords = workRecordMapper.selectBatchIds(request.getIds());
|
||||||
|
if (workRecords == null || workRecords.size() != request.getIds().size()) {
|
||||||
|
throw new ServiceException("存在预警记录已不存在,请刷新后重试");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (WorkRecord workRecord : workRecords) {
|
||||||
|
validateRecordBeforeForward(workRecord, role, currentUser, currentDeptId);
|
||||||
|
AlterAssignHistory history = useHistory ? getHistoryRecommend(workRecord.getCustId(), currentDeptId, role) : null;
|
||||||
|
ForwardTarget target = useHistory ? resolveHistoryTarget(history, role, currentDeptId) : manualTarget;
|
||||||
|
if (target == null) {
|
||||||
|
result.setFailCount(result.getFailCount() + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int row = doForward(workRecord.getId(), currentUser, currentDeptId, role, target);
|
||||||
|
if (row <= 0) {
|
||||||
|
result.setFailCount(result.getFailCount() + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.setSuccessCount(result.getSuccessCount() + row);
|
||||||
|
if (useHistory) {
|
||||||
|
if (history != null) {
|
||||||
|
saveAssignHistoryByHistory(workRecord, history, role, currentDeptId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
saveAssignHistory(workRecord, manualTarget, role, currentDeptId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务生成工作清单
|
* 定时任务生成工作清单
|
||||||
*
|
*
|
||||||
@@ -351,4 +448,306 @@ public class WorkRecordServiceImpl implements WorkRecordService {
|
|||||||
return java.sql.Timestamp.valueOf(endTime);
|
return java.sql.Timestamp.valueOf(endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fillAlterExtFields(List<AlterVO> alterVOS) {
|
||||||
|
if (alterVOS == null || alterVOS.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String role = SecurityUtils.userRole();
|
||||||
|
Long currentDeptId = SecurityUtils.getDeptId();
|
||||||
|
String currentUser = SecurityUtils.getUsername();
|
||||||
|
alterVOS.forEach(alterVO -> {
|
||||||
|
alterVO.setForwardFlag(parseForwardFlag(alterVO.getAlterDetail()));
|
||||||
|
alterVO.setAlterDetail(stripForwardPrefix(alterVO.getAlterDetail()));
|
||||||
|
alterVO.setUserInfo(buildUserInfo(alterVO.getUserName(), alterVO.getNickName()));
|
||||||
|
alterVO.setCanForward(canForward(alterVO, role, currentDeptId, currentUser));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildUserInfo(String userName, String nickName) {
|
||||||
|
if (StringUtils.isNotEmpty(userName) && StringUtils.isNotEmpty(nickName)) {
|
||||||
|
return nickName + "-" + userName;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(userName)) {
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(nickName)) {
|
||||||
|
return nickName;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseForwardFlag(String alterDetail) {
|
||||||
|
if (StringUtils.isEmpty(alterDetail)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (alterDetail.startsWith("[FORWARD=1]")) {
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
if (alterDetail.startsWith("[FORWARD=0]")) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String stripForwardPrefix(String alterDetail) {
|
||||||
|
if (StringUtils.isEmpty(alterDetail)) {
|
||||||
|
return alterDetail;
|
||||||
|
}
|
||||||
|
if (alterDetail.startsWith("[FORWARD=1] ")) {
|
||||||
|
return alterDetail.substring(12);
|
||||||
|
}
|
||||||
|
if (alterDetail.startsWith("[FORWARD=0] ")) {
|
||||||
|
return alterDetail.substring(12);
|
||||||
|
}
|
||||||
|
if (alterDetail.startsWith("[FORWARD=1]") || alterDetail.startsWith("[FORWARD=0]")) {
|
||||||
|
return alterDetail.substring(11);
|
||||||
|
}
|
||||||
|
return alterDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean canForward(AlterVO alterVO, String role, Long currentDeptId, String currentUser) {
|
||||||
|
if (!FORWARD_ALTER_TYPES.contains(alterVO.getAlterType())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!"1".equals(alterVO.getForwardFlag())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ("2".equals(alterVO.getStatus())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ROLE_BRANCH.equals(role)) {
|
||||||
|
return StringUtils.equals(currentUser, alterVO.getUserName()) && alterVO.getDeptId() == null;
|
||||||
|
}
|
||||||
|
if (ROLE_OUTLET.equals(role)) {
|
||||||
|
return alterVO.getDeptId() != null && alterVO.getDeptId().equals(currentDeptId) && StringUtils.isEmpty(alterVO.getUserName());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验当前登录角色是否具备预警转发能力,并返回角色标识。
|
||||||
|
*/
|
||||||
|
private String requireForwardRole() {
|
||||||
|
String role = SecurityUtils.userRole();
|
||||||
|
if (!ROLE_BRANCH.equals(role) && !ROLE_OUTLET.equals(role)) {
|
||||||
|
throw new ServiceException("当前角色不支持转发预警");
|
||||||
|
}
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验预警记录当前是否仍处于登录人可转发范围内,防止页面停留期间数据状态已变化。
|
||||||
|
*/
|
||||||
|
private void validateRecordBeforeForward(WorkRecord workRecord, String role, String currentUser, Long currentDeptId) {
|
||||||
|
if (workRecord == null || workRecord.getId() == null) {
|
||||||
|
throw new ServiceException("预警记录不存在");
|
||||||
|
}
|
||||||
|
if (!Integer.valueOf(1).equals(workRecord.getIsAlter())) {
|
||||||
|
throw new ServiceException("当前记录不是预警信息");
|
||||||
|
}
|
||||||
|
if (!FORWARD_ALTER_TYPES.contains(workRecord.getAlterType())) {
|
||||||
|
throw new ServiceException("当前预警类型不支持转发");
|
||||||
|
}
|
||||||
|
if (!"1".equals(parseForwardFlag(workRecord.getAlterDetail()))) {
|
||||||
|
throw new ServiceException("当前预警已有管户,无需转发");
|
||||||
|
}
|
||||||
|
if ("2".equals(workRecord.getStatus())) {
|
||||||
|
throw new ServiceException("当前预警已完成,不能转发");
|
||||||
|
}
|
||||||
|
if (ROLE_BRANCH.equals(role)) {
|
||||||
|
if (!StringUtils.equals(currentUser, workRecord.getUserName()) || workRecord.getDeptId() != null) {
|
||||||
|
throw new ServiceException("当前预警已不在您的待转发范围内");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ROLE_OUTLET.equals(role)) {
|
||||||
|
if (workRecord.getDeptId() == null || !workRecord.getDeptId().equals(currentDeptId) || StringUtils.isNotEmpty(workRecord.getUserName())) {
|
||||||
|
throw new ServiceException("当前预警已不在本网点待转发范围内");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new ServiceException("当前角色不支持转发预警");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析手动转发目标,并顺带完成目标权限范围校验。
|
||||||
|
*/
|
||||||
|
private ForwardTarget resolveManualTarget(AlterForwardRequest request, String role, Long currentDeptId) {
|
||||||
|
if (TARGET_TYPE_DEPT.equals(request.getTargetType())) {
|
||||||
|
if (request.getDeptId() == null) {
|
||||||
|
throw new ServiceException("请选择转发网点");
|
||||||
|
}
|
||||||
|
if (!ROLE_BRANCH.equals(role)) {
|
||||||
|
throw new ServiceException("网点管理员只能转发给客户经理");
|
||||||
|
}
|
||||||
|
String deptName = getAllowedDeptName(request.getDeptId(), currentDeptId);
|
||||||
|
return new ForwardTarget(TARGET_TYPE_DEPT, request.getDeptId(), null, null, deptName);
|
||||||
|
}
|
||||||
|
if (!TARGET_TYPE_USER.equals(request.getTargetType()) || StringUtils.isEmpty(request.getUserName())) {
|
||||||
|
throw new ServiceException("请选择转发客户经理");
|
||||||
|
}
|
||||||
|
SysUser user = getAllowedTargetUser(request.getUserName(), role, currentDeptId);
|
||||||
|
String targetName = StringUtils.isNotEmpty(user.getNickName()) ? user.getNickName() : user.getUserName();
|
||||||
|
return new ForwardTarget(TARGET_TYPE_USER, null, user.getUserName(), user.getNickName(), targetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将历史分配记录转换成可执行的转发目标;若历史目标已失效,则返回空。
|
||||||
|
*/
|
||||||
|
private ForwardTarget resolveHistoryTarget(AlterAssignHistory history, String role, Long currentDeptId) {
|
||||||
|
if (history == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (TARGET_TYPE_DEPT.equals(history.getLastAssignTargetType())) {
|
||||||
|
if (history.getLastAssignTargetDeptId() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String deptName = getAllowedDeptName(history.getLastAssignTargetDeptId(), currentDeptId);
|
||||||
|
return new ForwardTarget(TARGET_TYPE_DEPT, history.getLastAssignTargetDeptId(), null, null, deptName);
|
||||||
|
}
|
||||||
|
if (!TARGET_TYPE_USER.equals(history.getLastAssignTargetType()) || StringUtils.isEmpty(history.getLastAssignTargetUser())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
SysUser user = getAllowedTargetUser(history.getLastAssignTargetUser(), role, currentDeptId);
|
||||||
|
String targetName = StringUtils.isNotEmpty(user.getNickName()) ? user.getNickName() : user.getUserName();
|
||||||
|
return new ForwardTarget(TARGET_TYPE_USER, null, user.getUserName(), user.getNickName(), targetName);
|
||||||
|
} catch (ServiceException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按目标类型执行真正的转发落库更新。
|
||||||
|
*/
|
||||||
|
private int doForward(Long workRecordId, String currentUser, Long currentDeptId, String role, ForwardTarget target) {
|
||||||
|
if (TARGET_TYPE_DEPT.equals(target.getTargetType())) {
|
||||||
|
return workRecordMapper.updateAlterForwardToDept(workRecordId, currentUser, target.getDeptId(), currentUser);
|
||||||
|
}
|
||||||
|
if (ROLE_BRANCH.equals(role)) {
|
||||||
|
return workRecordMapper.updateAlterForwardToUserByBranch(
|
||||||
|
workRecordId, currentUser, target.getUserName(), target.getNickName(), currentUser
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return workRecordMapper.updateAlterForwardToUserByOutlet(
|
||||||
|
workRecordId, currentDeptId, target.getUserName(), target.getNickName(), currentUser
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验目标网点是否在当前支行管理员的可转发范围内,并返回网点名称。
|
||||||
|
*/
|
||||||
|
private String getAllowedDeptName(Long targetDeptId, Long currentDeptId) {
|
||||||
|
List<AlterAssignTargetVO> deptOptions = workRecordMapper.selectForwardDeptTargets(currentDeptId);
|
||||||
|
return deptOptions.stream()
|
||||||
|
.filter(item -> String.valueOf(targetDeptId).equals(item.getTargetCode()))
|
||||||
|
.map(AlterAssignTargetVO::getTargetName)
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new ServiceException("所选网点不在当前支行可转发范围内"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验目标客户经理是否在当前管理员可转发范围内,并返回用户信息。
|
||||||
|
*/
|
||||||
|
private SysUser getAllowedTargetUser(String targetUserName, String role, Long currentDeptId) {
|
||||||
|
List<AlterAssignTargetVO> userOptions = workRecordMapper.selectForwardUserTargets(currentDeptId, ROLE_MANAGER);
|
||||||
|
boolean matched = userOptions.stream().anyMatch(item -> StringUtils.equals(targetUserName, item.getTargetCode()));
|
||||||
|
if (!matched) {
|
||||||
|
if (ROLE_BRANCH.equals(role)) {
|
||||||
|
throw new ServiceException("所选客户经理不在当前支行可转发范围内");
|
||||||
|
}
|
||||||
|
throw new ServiceException("所选客户经理不在当前网点可转发范围内");
|
||||||
|
}
|
||||||
|
SysUser user = sysUserService.selectUserByUserName(targetUserName);
|
||||||
|
if (user == null || StringUtils.isEmpty(user.getUserName())) {
|
||||||
|
throw new ServiceException("转发目标客户经理不存在");
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 填充手动分配弹窗可选项;支行管理员可选网点和客户经理,网点管理员仅可选客户经理。
|
||||||
|
*/
|
||||||
|
private void fillManualOptions(AlterForwardMetaVO metaVO, String role, Long currentDeptId) {
|
||||||
|
if (ROLE_BRANCH.equals(role)) {
|
||||||
|
metaVO.setDeptOptions(workRecordMapper.selectForwardDeptTargets(currentDeptId));
|
||||||
|
metaVO.setUserOptions(workRecordMapper.selectForwardUserTargets(currentDeptId, ROLE_MANAGER));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ROLE_OUTLET.equals(role)) {
|
||||||
|
metaVO.setUserOptions(workRecordMapper.selectForwardUserTargets(currentDeptId, ROLE_MANAGER));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new ServiceException("当前角色不支持转发预警");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按客户、当前部门和当前角色查询历史推荐,并回填到前端元数据中。
|
||||||
|
*/
|
||||||
|
private void fillHistoryRecommend(AlterForwardMetaVO metaVO, String custId, Long deptId, String role) {
|
||||||
|
AlterAssignHistory history = getHistoryRecommend(custId, deptId, role);
|
||||||
|
if (history == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
metaVO.setHasHistoryRecommend(true);
|
||||||
|
metaVO.setRecommendedTargetType(history.getLastAssignTargetType());
|
||||||
|
if (TARGET_TYPE_DEPT.equals(history.getLastAssignTargetType())) {
|
||||||
|
metaVO.setRecommendedTargetCode(history.getLastAssignTargetDeptId() == null ? "" : String.valueOf(history.getLastAssignTargetDeptId()));
|
||||||
|
} else {
|
||||||
|
metaVO.setRecommendedTargetCode(history.getLastAssignTargetUser());
|
||||||
|
}
|
||||||
|
metaVO.setRecommendedTargetName(history.getLastAssignTargetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存本次手动分配结果;同一客户在同部门、同角色下只维护一条最新历史。
|
||||||
|
*/
|
||||||
|
private void saveAssignHistory(WorkRecord workRecord, ForwardTarget target, String role, Long currentDeptId) {
|
||||||
|
AlterAssignHistory history = getHistoryRecommend(workRecord.getCustId(), currentDeptId, role);
|
||||||
|
if (history == null) {
|
||||||
|
history = new AlterAssignHistory();
|
||||||
|
history.setCustId(workRecord.getCustId());
|
||||||
|
}
|
||||||
|
history.setAlterType(workRecord.getAlterType());
|
||||||
|
history.setCustName(workRecord.getCustName());
|
||||||
|
history.setDeptId(currentDeptId);
|
||||||
|
history.setLastAssignTargetType(target.getTargetType());
|
||||||
|
history.setLastAssignTargetDeptId(target.getDeptId());
|
||||||
|
history.setLastAssignTargetUser(target.getUserName());
|
||||||
|
history.setLastAssignTargetName(target.getTargetName());
|
||||||
|
history.setLastAssignByUser(SecurityUtils.getUsername());
|
||||||
|
history.setLastAssignByRole(role);
|
||||||
|
history.setUpdateTime(new Date());
|
||||||
|
if (history.getId() == null) {
|
||||||
|
alterAssignHistoryMapper.insert(history);
|
||||||
|
} else {
|
||||||
|
alterAssignHistoryMapper.updateById(history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按历史推荐成功转发后,刷新该客户最新一次分配历史的更新时间和目标信息。
|
||||||
|
*/
|
||||||
|
private void saveAssignHistoryByHistory(WorkRecord workRecord, AlterAssignHistory sourceHistory, String role, Long currentDeptId) {
|
||||||
|
ForwardTarget target = new ForwardTarget(
|
||||||
|
sourceHistory.getLastAssignTargetType(),
|
||||||
|
sourceHistory.getLastAssignTargetDeptId(),
|
||||||
|
sourceHistory.getLastAssignTargetUser(),
|
||||||
|
null,
|
||||||
|
sourceHistory.getLastAssignTargetName()
|
||||||
|
);
|
||||||
|
saveAssignHistory(workRecord, target, role, currentDeptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前角色在当前部门下,对指定客户的最近一次分配历史。
|
||||||
|
*/
|
||||||
|
private AlterAssignHistory getHistoryRecommend(String custId, Long deptId, String role) {
|
||||||
|
return alterAssignHistoryMapper.selectOne(new LambdaQueryWrapper<AlterAssignHistory>()
|
||||||
|
.eq(AlterAssignHistory::getCustId, custId)
|
||||||
|
.eq(AlterAssignHistory::getDeptId, deptId)
|
||||||
|
.eq(AlterAssignHistory::getLastAssignByRole, role)
|
||||||
|
.last("limit 1"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,19 +184,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<select id="selectAlterList" resultType="AlterVO">
|
<select id="selectAlterList" resultType="AlterVO">
|
||||||
select id, user_name, nick_name, alter_type, alter_detail, cust_id, cust_name, read_time, status, remark, is_feedback, cust_isn
|
select wr.id, wr.user_name, wr.nick_name, wr.alter_type, wr.alter_detail, wr.cust_id, wr.cust_name,
|
||||||
from work_record
|
wr.read_time, wr.status, wr.remark, wr.is_feedback, wr.cust_isn, wr.dept_id, sd.dept_name
|
||||||
|
from work_record wr
|
||||||
|
left join sys_dept sd on wr.dept_id = sd.dept_id
|
||||||
<where>
|
<where>
|
||||||
is_alter = 1
|
wr.is_alter = 1
|
||||||
and user_name= #{username}
|
and wr.user_name= #{username}
|
||||||
<if test="status != null and status != ''">
|
<if test="status != null and status != ''">
|
||||||
and status = #{status}
|
and wr.status = #{status}
|
||||||
</if>
|
</if>
|
||||||
<if test="alterType != null and alterType != ''">
|
<if test="alterType != null and alterType != ''">
|
||||||
and alter_type = #{alterType}
|
and wr.alter_type = #{alterType}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
order by create_time desc, status asc
|
order by wr.create_time desc, wr.status asc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectAlterCount" resultType="AlterCountVO">
|
<select id="selectAlterCount" resultType="AlterCountVO">
|
||||||
@@ -209,24 +211,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
from work_record wr
|
from work_record wr
|
||||||
left join sys_user su on su.user_name = wr.user_name
|
left join sys_user su on su.user_name = wr.user_name
|
||||||
left join sys_dept d on su.dept_id = d.dept_id
|
left join sys_dept d on su.dept_id = d.dept_id
|
||||||
|
left join sys_dept wd on wr.dept_id = wd.dept_id
|
||||||
where wr.is_alter = 1
|
where wr.is_alter = 1
|
||||||
and wr.create_time <= #{reportTime}
|
and wr.create_time <= #{reportTime}
|
||||||
and (
|
and (
|
||||||
<choose>
|
<choose>
|
||||||
<when test="role != null and role == 'outlet'"> su.dept_id = #{deptId} </when>
|
<when test="role != null and role == 'outlet'"> (su.dept_id = #{deptId} or wr.dept_id = #{deptId}) </when>
|
||||||
<when test="role != null and role == 'branch'"> (su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) </when>
|
<when test="role != null and role == 'branch'"> ((su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) or (wr.dept_id = #{deptId} or find_in_set(#{deptId},wd.ancestors))) </when>
|
||||||
<when test="role != null and role == 'private'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type in ('0', '1')) </when>
|
<when test="role != null and role == 'private'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type in ('0', '1')) </when>
|
||||||
<when test="role != null and role == 'public'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type = '2') </when>
|
<when test="role != null and role == 'public'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type = '2') </when>
|
||||||
<when test="role != null and role == 'ops'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
<when test="role != null and role == 'ops'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||||
<when test="role != null and role == 'head'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
<when test="role != null and role == 'head'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||||
</choose>)
|
</choose>)
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectAllAlterList" resultType="AlterVO">
|
<select id="selectAllAlterList" resultType="AlterVO">
|
||||||
select wr.id, wr.user_name, wr.nick_name, wr.alter_type, wr.alter_detail, wr.cust_id, wr.cust_name, wr.read_time, wr.status, wr.remark, wr.cust_type, wr.is_feedback, wr.cust_isn
|
select wr.id, wr.user_name, wr.nick_name, wr.alter_type, wr.alter_detail, wr.cust_id, wr.cust_name, wr.read_time,
|
||||||
|
wr.status, wr.remark, wr.cust_type, wr.is_feedback, wr.cust_isn, wr.dept_id, wd.dept_name
|
||||||
from work_record wr
|
from work_record wr
|
||||||
left join sys_user su on su.user_name = wr.user_name
|
left join sys_user su on su.user_name = wr.user_name
|
||||||
left join sys_dept d on su.dept_id = d.dept_id
|
left join sys_dept d on su.dept_id = d.dept_id
|
||||||
|
left join sys_dept wd on wr.dept_id = wd.dept_id
|
||||||
where wr.is_alter = 1
|
where wr.is_alter = 1
|
||||||
<if test="status != null and status != ''">
|
<if test="status != null and status != ''">
|
||||||
and wr.status = #{status}
|
and wr.status = #{status}
|
||||||
@@ -234,20 +239,120 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="alterType != null and alterType != ''">
|
<if test="alterType != null and alterType != ''">
|
||||||
and wr.alter_type = #{alterType}
|
and wr.alter_type = #{alterType}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="forwardFlag != null and forwardFlag != ''">
|
||||||
|
<choose>
|
||||||
|
<when test='forwardFlag == "1"'>
|
||||||
|
and wr.alter_type in ('个人资产客户定期存款', '个人资产客户封闭式理财')
|
||||||
|
and wr.alter_detail like '[FORWARD=1]%'
|
||||||
|
</when>
|
||||||
|
<when test='forwardFlag == "0"'>
|
||||||
|
and (
|
||||||
|
(wr.alter_type in ('个人资产客户定期存款', '个人资产客户封闭式理财')
|
||||||
|
and wr.alter_detail like '[FORWARD=0]%')
|
||||||
|
or wr.alter_type not in ('个人资产客户定期存款', '个人资产客户封闭式理财')
|
||||||
|
)
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
|
</if>
|
||||||
<!-- "走访异常提醒"类型直接通过用户名匹配,其他类型按角色权限处理 -->
|
<!-- "走访异常提醒"类型直接通过用户名匹配,其他类型按角色权限处理 -->
|
||||||
and ((wr.alter_type = '走访异常提醒' and wr.user_name = #{username}) or
|
and ((wr.alter_type = '走访异常提醒' and wr.user_name = #{username}) or
|
||||||
(wr.alter_type != '走访异常提醒' and (
|
(wr.alter_type != '走访异常提醒' and (
|
||||||
<choose>
|
<choose>
|
||||||
<when test="role != null and role == 'outlet'"> su.dept_id = #{deptId} </when>
|
<when test="role != null and role == 'outlet'"> (su.dept_id = #{deptId} or wr.dept_id = #{deptId}) </when>
|
||||||
<when test="role != null and role == 'branch'"> (su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) </when>
|
<when test="role != null and role == 'branch'"> ((su.dept_id = #{deptId} or find_in_set(#{deptId},d.ancestors)) or (wr.dept_id = #{deptId} or find_in_set(#{deptId},wd.ancestors))) </when>
|
||||||
<when test="role != null and role == 'private'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type in ('0', '1')) </when>
|
<when test="role != null and role == 'private'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type in ('0', '1')) </when>
|
||||||
<when test="role != null and role == 'public'"> (left(su.dept_id,3) = left(#{deptId},3) and wr.cust_type = '2') </when>
|
<when test="role != null and role == 'public'"> ((left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) and wr.cust_type = '2') </when>
|
||||||
<when test="role != null and role == 'ops'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
<when test="role != null and role == 'ops'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||||
<when test="role != null and role == 'head'"> left(su.dept_id,3) = left(#{deptId},3) </when>
|
<when test="role != null and role == 'head'"> (left(su.dept_id,3) = left(#{deptId},3) or left(wr.dept_id,3) = left(#{deptId},3)) </when>
|
||||||
</choose> )))
|
</choose> )))
|
||||||
order by wr.create_time desc, wr.status asc, wr.user_name desc
|
order by wr.create_time desc, wr.status asc, wr.user_name desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectForwardDeptTargets" resultType="AlterAssignTargetVO">
|
||||||
|
select cast(sd.dept_id as char) as targetCode, sd.dept_name as targetName
|
||||||
|
from sys_dept sd
|
||||||
|
where sd.del_flag = '0'
|
||||||
|
and sd.status = '0'
|
||||||
|
and sd.dept_type = 'outlet'
|
||||||
|
and sd.parent_id = #{branchDeptId}
|
||||||
|
order by sd.order_num, sd.dept_id
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectForwardUserTargets" resultType="AlterAssignTargetVO">
|
||||||
|
select su.user_name as targetCode, concat(su.nick_name, '-', su.user_name) as targetName
|
||||||
|
from sys_user su
|
||||||
|
where su.del_flag = '0'
|
||||||
|
and su.status = '0'
|
||||||
|
and su.dept_id = #{deptId}
|
||||||
|
<choose>
|
||||||
|
<when test="role == 'manager'">
|
||||||
|
and su.role_id = 102
|
||||||
|
</when>
|
||||||
|
<when test="role == 'branch'">
|
||||||
|
and su.role_id = 101
|
||||||
|
</when>
|
||||||
|
<when test="role == 'outlet'">
|
||||||
|
and su.role_id = 116
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
and 1 = 2
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
order by su.nick_name, su.user_name
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<update id="updateAlterForwardToDept">
|
||||||
|
update work_record
|
||||||
|
set user_name = null,
|
||||||
|
nick_name = null,
|
||||||
|
dept_id = #{targetDeptId},
|
||||||
|
read_time = null,
|
||||||
|
update_time = sysdate(),
|
||||||
|
update_by = #{updateBy}
|
||||||
|
where id = #{id}
|
||||||
|
and user_name = #{sourceUserName}
|
||||||
|
and dept_id is null
|
||||||
|
and is_alter = 1
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateAlterForwardToUserByBranch">
|
||||||
|
update work_record
|
||||||
|
set user_name = #{targetUserName},
|
||||||
|
nick_name = #{targetNickName},
|
||||||
|
alter_detail = case
|
||||||
|
when alter_detail like '[FORWARD=1] %' then concat('[FORWARD=0] ', substring(alter_detail, 13))
|
||||||
|
when alter_detail like '[FORWARD=1]%' then concat('[FORWARD=0]', substring(alter_detail, 12))
|
||||||
|
else alter_detail
|
||||||
|
end,
|
||||||
|
dept_id = null,
|
||||||
|
read_time = null,
|
||||||
|
update_time = sysdate(),
|
||||||
|
update_by = #{updateBy}
|
||||||
|
where id = #{id}
|
||||||
|
and user_name = #{sourceUserName}
|
||||||
|
and dept_id is null
|
||||||
|
and is_alter = 1
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateAlterForwardToUserByOutlet">
|
||||||
|
update work_record
|
||||||
|
set user_name = #{targetUserName},
|
||||||
|
nick_name = #{targetNickName},
|
||||||
|
alter_detail = case
|
||||||
|
when alter_detail like '[FORWARD=1] %' then concat('[FORWARD=0] ', substring(alter_detail, 13))
|
||||||
|
when alter_detail like '[FORWARD=1]%' then concat('[FORWARD=0]', substring(alter_detail, 12))
|
||||||
|
else alter_detail
|
||||||
|
end,
|
||||||
|
dept_id = null,
|
||||||
|
read_time = null,
|
||||||
|
update_time = sysdate(),
|
||||||
|
update_by = #{updateBy}
|
||||||
|
where id = #{id}
|
||||||
|
and dept_id = #{sourceDeptId}
|
||||||
|
and user_name is null
|
||||||
|
and is_alter = 1
|
||||||
|
</update>
|
||||||
|
|
||||||
<select id="selectAlterConfigList" resultType="AlterConfigVO">
|
<select id="selectAlterConfigList" resultType="AlterConfigVO">
|
||||||
select id, alter_type, prod_type, warn_role, warn_threshold, update_time, update_by, type
|
select id, alter_type, prod_type, warn_role, warn_threshold, update_time, update_by, type
|
||||||
from alter_config
|
from alter_config
|
||||||
@@ -278,4 +383,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
order by alter_type
|
order by alter_type
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -167,6 +167,36 @@
|
|||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getCustManagerListByPage" resultType="DwbRetailCustLevelManagerDetailVO">
|
||||||
|
select id, outlet_id, outlet_name, branch_id, branch_name, cust_name, cust_idc, cust_isn, cust_age, cust_sex, cust_phone, cust_address, cust_aum_bal,
|
||||||
|
aum_bal_comp_lm, cust_aum_month_avg, cust_level, cust_level_comp_lm, manager_name, manager_id
|
||||||
|
from dwb_retail_cust_level_manager_detail_${headId}
|
||||||
|
<where>
|
||||||
|
<if test="dto.managerId != null and dto.managerId !='' ">and manager_id = #{dto.managerId}</if>
|
||||||
|
<if test="dto.outletId != null and dto.outletId !='' ">and outlet_id = #{dto.outletId}</if>
|
||||||
|
<if test="dto.branchId != null and dto.branchId !='' ">and branch_id = #{dto.branchId}</if>
|
||||||
|
<if test="dto.statusType != null and dto.statusType !=''">
|
||||||
|
<choose>
|
||||||
|
<when test="dto.statusType == 'current'">
|
||||||
|
and cust_level = #{dto.custLevel}
|
||||||
|
</when>
|
||||||
|
<when test="dto.statusType == 'last'">
|
||||||
|
and cust_level_lm = #{dto.custLevel}
|
||||||
|
</when>
|
||||||
|
<when test="dto.statusType == 'rise'">
|
||||||
|
and cust_level = #{dto.custLevel}
|
||||||
|
and cust_level_comp_lm like '上升%'
|
||||||
|
</when>
|
||||||
|
<when test="dto.statusType == 'fall'">
|
||||||
|
and cust_level_lm = #{dto.custLevel}
|
||||||
|
and cust_level_comp_lm like '下降%'
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
limit #{offset}, #{pageSize}
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="getCustLevelCount" resultType="Integer">
|
<select id="getCustLevelCount" resultType="Integer">
|
||||||
select count(1)
|
select count(1)
|
||||||
from dwb_retail_cust_level_manager_detail
|
from dwb_retail_cust_level_manager_detail
|
||||||
@@ -521,4 +551,4 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ spring:
|
|||||||
username: root
|
username: root
|
||||||
password: Kfcx@1234
|
password: Kfcx@1234
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
|
# url: jdbc:mysql://rm-bp17634n45cj631s0ao.mysql.rds.aliyuncs.com/ibs?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
|
||||||
|
# username: znsj
|
||||||
|
# password: Znsj@123456
|
||||||
|
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
# 从库数据源
|
# 从库数据源
|
||||||
slave:
|
slave:
|
||||||
# 从数据源开关/默认关闭
|
# 从数据源开关/默认关闭
|
||||||
@@ -78,12 +82,14 @@ spring:
|
|||||||
redis:
|
redis:
|
||||||
# 地址
|
# 地址
|
||||||
host: 116.62.17.81
|
host: 116.62.17.81
|
||||||
|
# host: r-bp1mmtcknvsscsrjrypd.redis.rds.aliyuncs.com
|
||||||
# 端口,默认为6379
|
# 端口,默认为6379
|
||||||
port: 6379
|
port: 6379
|
||||||
# 数据库索引
|
# 数据库索引
|
||||||
database: 0
|
database: 0
|
||||||
# 密码
|
# 密码
|
||||||
password: Kfcx@1234
|
password: Kfcx@1234
|
||||||
|
# password: N0f3d12c4a927eee1+
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
lettuce:
|
lettuce:
|
||||||
@@ -121,5 +127,9 @@ oss:
|
|||||||
accessKeyId: LTAI5tMsUgorcgnpTxZDV1wS
|
accessKeyId: LTAI5tMsUgorcgnpTxZDV1wS
|
||||||
accessKeySecret: c7qIjXIPx8Cz2CriJpYGyCFwFjRxeB
|
accessKeySecret: c7qIjXIPx8Cz2CriJpYGyCFwFjRxeB
|
||||||
bucketName: oss-wkc
|
bucketName: oss-wkc
|
||||||
|
# endpoint: oss-cn-hangzhou.aliyuncs.comBucket:znjgoss.oss-cn-hangzhou.aliyuncs.com
|
||||||
|
# accessKeyId: LTAI5tCRocKhQaCtFnYKp46w
|
||||||
|
# accessKeySecret: 0ovFbMQWas1wOZTG91mpKbV70JgR32
|
||||||
|
# bucketName: oss-wkc
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ public enum OssFileEnum {
|
|||||||
|
|
||||||
VISIT_RECORD("VISIT_RECORD/"),
|
VISIT_RECORD("VISIT_RECORD/"),
|
||||||
|
|
||||||
CUST_MAP_EXPORT("CUST_MAP_EXPORT/");
|
CUST_MAP_EXPORT("CUST_MAP_EXPORT/"),
|
||||||
|
|
||||||
|
CUST_MANAGER_REPORT("CUST_MANAGER_REPORT/");
|
||||||
|
|
||||||
private String PREFIX;
|
private String PREFIX;
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,12 @@ export function getCustLevelList() {
|
|||||||
url: '/grid/cmpm/custManager/custLevel/list',
|
url: '/grid/cmpm/custManager/custLevel/list',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function exportCustManagerReport(data) {
|
||||||
|
return request({
|
||||||
|
url: '/grid/cmpm/custManager/export',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -204,12 +204,22 @@ export function warningworkRecordList(query) {
|
|||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
//更新预警工作清单
|
|
||||||
export function warningworkRecordSubmit(data) {
|
// 查询预警转发元数据
|
||||||
|
export function getAlterForwardMeta(query) {
|
||||||
return request({
|
return request({
|
||||||
url: `/work/record/alter/edit`,
|
url: `/work/record/alter/forward/meta`,
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预警转发
|
||||||
|
export function forwardAlter(data) {
|
||||||
|
return request({
|
||||||
|
url: `/work/record/alter/forward`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,4 +275,4 @@ export function getAlterTypes() {
|
|||||||
url: '/work/record/alter/types',
|
url: '/work/record/alter/types',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,14 @@
|
|||||||
|
|
||||||
<div class="right-menu">
|
<div class="right-menu">
|
||||||
<template v-if="device !== 'mobile'">
|
<template v-if="device !== 'mobile'">
|
||||||
|
<el-badge v-if="downloadUnreadCount > 0" :value="downloadUnreadCount" class="item download-item">
|
||||||
|
<i
|
||||||
|
class="el-icon-download right-menu-item notice"
|
||||||
|
@click="openDownload"
|
||||||
|
/>
|
||||||
|
</el-badge>
|
||||||
<i
|
<i
|
||||||
|
v-else
|
||||||
class="el-icon-download right-menu-item notice"
|
class="el-icon-download right-menu-item notice"
|
||||||
@click="openDownload"
|
@click="openDownload"
|
||||||
/>
|
/>
|
||||||
@@ -168,11 +175,14 @@ export default {
|
|||||||
notReadCount: 0,
|
notReadCount: 0,
|
||||||
noticeCenterList: [],
|
noticeCenterList: [],
|
||||||
open2: false,
|
open2: false,
|
||||||
downCenterList: []
|
downCenterList: [],
|
||||||
|
downloadUnreadCount: 0,
|
||||||
|
downloadPollingTimer: null,
|
||||||
|
downloadStatusMap: {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['sidebar', 'avatar', 'device', 'nickName']),
|
...mapGetters(['sidebar', 'avatar', 'device', 'nickName', 'userName']),
|
||||||
setting: {
|
setting: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.state.settings.showSettings;
|
return this.$store.state.settings.showSettings;
|
||||||
@@ -192,10 +202,14 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getCenterList();
|
this.getCenterList();
|
||||||
|
this.refreshDownloadCenterList();
|
||||||
window.addEventListener('notice-center-refresh', this.getCenterList);
|
window.addEventListener('notice-center-refresh', this.getCenterList);
|
||||||
|
window.addEventListener('download-center-refresh', this.handleDownloadCenterRefresh);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('notice-center-refresh', this.getCenterList);
|
window.removeEventListener('notice-center-refresh', this.getCenterList);
|
||||||
|
window.removeEventListener('download-center-refresh', this.handleDownloadCenterRefresh);
|
||||||
|
this.stopDownloadPolling();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openModal() {
|
openModal() {
|
||||||
@@ -203,8 +217,9 @@ export default {
|
|||||||
this.open = true;
|
this.open = true;
|
||||||
},
|
},
|
||||||
openDownload() {
|
openDownload() {
|
||||||
this.getDownCenterList();
|
this.refreshDownloadCenterList(false, true).finally(() => {
|
||||||
this.open2 = true;
|
this.open2 = true;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
// 消息已读
|
// 消息已读
|
||||||
handleHasRead(uuid) {
|
handleHasRead(uuid) {
|
||||||
@@ -237,10 +252,115 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleDownloadCenterRefresh() {
|
||||||
|
this.refreshDownloadCenterList(false, false, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
startDownloadPolling() {
|
||||||
|
if (this.downloadPollingTimer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.downloadPollingTimer = setInterval(() => {
|
||||||
|
this.refreshDownloadCenterList(true);
|
||||||
|
}, 10000);
|
||||||
|
},
|
||||||
|
|
||||||
|
stopDownloadPolling() {
|
||||||
|
if (this.downloadPollingTimer) {
|
||||||
|
clearInterval(this.downloadPollingTimer);
|
||||||
|
this.downloadPollingTimer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getDownloadReadStorageKey() {
|
||||||
|
return `download-center-read-${this.userName || 'default'}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
getReadTaskIds() {
|
||||||
|
try {
|
||||||
|
const cache = localStorage.getItem(this.getDownloadReadStorageKey());
|
||||||
|
const ids = cache ? JSON.parse(cache) : [];
|
||||||
|
return Array.isArray(ids) ? ids : [];
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setReadTaskIds(ids) {
|
||||||
|
localStorage.setItem(this.getDownloadReadStorageKey(), JSON.stringify(ids));
|
||||||
|
},
|
||||||
|
|
||||||
|
getDownloadInitStorageKey() {
|
||||||
|
return `download-center-init-${this.userName || 'default'}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
hasInitializedDownloadReadState() {
|
||||||
|
return localStorage.getItem(this.getDownloadInitStorageKey()) === '1';
|
||||||
|
},
|
||||||
|
|
||||||
|
markDownloadReadStateInitialized() {
|
||||||
|
localStorage.setItem(this.getDownloadInitStorageKey(), '1');
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDownloadUnreadCount(taskList = []) {
|
||||||
|
const readSet = new Set(this.getReadTaskIds());
|
||||||
|
this.downloadUnreadCount = taskList.filter(item => item.status !== '0' && !readSet.has(item.id)).length;
|
||||||
|
},
|
||||||
|
|
||||||
|
markDownloadTasksAsRead(taskList = []) {
|
||||||
|
const readSet = new Set(this.getReadTaskIds());
|
||||||
|
taskList.filter(item => item.status !== '0').forEach(item => readSet.add(item.id));
|
||||||
|
this.setReadTaskIds(Array.from(readSet));
|
||||||
|
this.updateDownloadUnreadCount(taskList);
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshDownloadCenterList(showStatusMessage = false, markAsRead = false, allowPolling = false) {
|
||||||
|
return getDownCenterList({}).then((res) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
const rows = res.rows || [];
|
||||||
|
const hasPendingTask = rows.some(item => item.status === '0');
|
||||||
|
|
||||||
|
if (!this.hasInitializedDownloadReadState()) {
|
||||||
|
const initialReadIds = rows.filter(item => item.status !== '0').map(item => item.id);
|
||||||
|
this.setReadTaskIds(initialReadIds);
|
||||||
|
this.markDownloadReadStateInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showStatusMessage) {
|
||||||
|
rows.forEach(item => {
|
||||||
|
const prevStatus = this.downloadStatusMap[item.id];
|
||||||
|
if (prevStatus === '0' && item.status === '1') {
|
||||||
|
Message.success(`${item.fileName}导出成功,请前往下载中心下载`);
|
||||||
|
} else if (prevStatus === '0' && item.status === '2') {
|
||||||
|
Message.warning(`${item.fileName}导出失败,请前往下载中心查看`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.downloadStatusMap = rows.reduce((acc, item) => {
|
||||||
|
acc[item.id] = item.status;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
this.downCenterList = rows;
|
||||||
|
|
||||||
|
if (markAsRead) {
|
||||||
|
this.markDownloadTasksAsRead(rows);
|
||||||
|
} else {
|
||||||
|
this.updateDownloadUnreadCount(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowPolling && hasPendingTask) {
|
||||||
|
this.startDownloadPolling();
|
||||||
|
} else {
|
||||||
|
this.stopDownloadPolling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// 消息列表下载文件
|
// 消息列表下载文件
|
||||||
downLoadFile(item) {
|
downLoadFile(item) {
|
||||||
const {fileUrl, fileName, status} = item
|
const {fileUrl, fileName, status} = item
|
||||||
if (!fileUrl) return;
|
|
||||||
if (status === '0') {
|
if (status === '0') {
|
||||||
Message.warning('正在导出,请稍后下载');
|
Message.warning('正在导出,请稍后下载');
|
||||||
return
|
return
|
||||||
@@ -249,9 +369,11 @@ export default {
|
|||||||
Message.warning('导出失败,无法下载');
|
Message.warning('导出失败,无法下载');
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (!fileUrl) return;
|
||||||
downCenterDownload({ fileUrl }).then((res) => {
|
downCenterDownload({ fileUrl }).then((res) => {
|
||||||
downloadFiles(res, `${fileName}.xlsx`);
|
downloadFiles(res, `${fileName}.xlsx`);
|
||||||
Message.success('下载成功');
|
Message.success('下载成功');
|
||||||
|
this.markDownloadTasksAsRead(this.downCenterList);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -382,6 +504,12 @@ export default {
|
|||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.download-item {
|
||||||
|
::v-deep .el-badge__content.is-fixed {
|
||||||
|
top: 18px;
|
||||||
|
right: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.page-common-wrap {
|
.page-common-wrap {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button type="primary" icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -150,7 +151,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { gridCmpmCustManagerList, gridCmpmCustManagerResult, getCustLevelList } from '@/api/gridSearch/accountManageReport/index'
|
import { gridCmpmCustManagerList, gridCmpmCustManagerResult, getCustLevelList, exportCustManagerReport } from '@/api/gridSearch/accountManageReport/index'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -209,6 +210,19 @@ import { gridCmpmCustManagerList, gridCmpmCustManagerResult, getCustLevelList }
|
|||||||
this.queryParams.statusType = null
|
this.queryParams.statusType = null
|
||||||
this.handleQuery()
|
this.handleQuery()
|
||||||
},
|
},
|
||||||
|
handleExport() {
|
||||||
|
exportCustManagerReport({
|
||||||
|
custLevel: this.queryParams.custLevel,
|
||||||
|
statusType: this.queryParams.statusType
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
window.dispatchEvent(new Event('download-center-refresh'))
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(err?.msg || '导出失败')
|
||||||
|
})
|
||||||
|
},
|
||||||
getData() {
|
getData() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
gridCmpmCustManagerList(this.queryParams).then(res => {
|
gridCmpmCustManagerList(this.queryParams).then(res => {
|
||||||
@@ -354,4 +368,4 @@ import { gridCmpmCustManagerList, gridCmpmCustManagerResult, getCustLevelList }
|
|||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -329,6 +329,14 @@ export default {
|
|||||||
visible(val) {
|
visible(val) {
|
||||||
if (val) {
|
if (val) {
|
||||||
this.init()
|
this.init()
|
||||||
|
if (this.shareEnabled && this.deptOptions.length === 0) {
|
||||||
|
this.loadDeptOptions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shareEnabled(val) {
|
||||||
|
if (val && this.deptOptions.length === 0) {
|
||||||
|
this.loadDeptOptions()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
groupData: {
|
groupData: {
|
||||||
@@ -370,7 +378,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.loadDeptOptions()
|
|
||||||
this.loadAllTags()
|
this.loadAllTags()
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
|||||||
@@ -101,6 +101,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listCustGroupMembers, removeMembers } from '@/api/group/custGroup'
|
import { listCustGroupMembers, removeMembers } from '@/api/group/custGroup'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CustGroupDetail',
|
name: 'CustGroupDetail',
|
||||||
@@ -119,9 +120,28 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'$route.query.groupId'(newGroupId) {
|
||||||
|
if (newGroupId && newGroupId !== this.groupId) {
|
||||||
|
this.groupId = newGroupId
|
||||||
|
this.viewType = this.resolveViewType(this.$route.query.viewType)
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['roles']),
|
||||||
|
isHeadCustGroupAdmin() {
|
||||||
|
return ['headAdmin', 'headPublic', 'headPrivate', 'headOps'].some(role => this.roles.includes(role))
|
||||||
|
},
|
||||||
|
isMineView() {
|
||||||
|
return this.viewType === 'mine'
|
||||||
|
}
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.groupId = this.$route.query.groupId
|
this.groupId = this.$route.query.groupId
|
||||||
this.viewType = this.$route.query.viewType || 'mine'
|
this.viewType = this.resolveViewType(this.$route.query.viewType)
|
||||||
if (this.groupId) {
|
if (this.groupId) {
|
||||||
this.getList()
|
this.getList()
|
||||||
} else {
|
} else {
|
||||||
@@ -129,22 +149,14 @@ export default {
|
|||||||
this.goBack()
|
this.goBack()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
'$route.query.groupId'(newGroupId) {
|
|
||||||
if (newGroupId && newGroupId !== this.groupId) {
|
|
||||||
this.groupId = newGroupId
|
|
||||||
this.viewType = this.$route.query.viewType || 'mine'
|
|
||||||
this.queryParams.pageNum = 1
|
|
||||||
this.getList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isMineView() {
|
|
||||||
return this.viewType === 'mine'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
|
resolveViewType(viewType) {
|
||||||
|
if (!this.isHeadCustGroupAdmin) {
|
||||||
|
return 'sharedToMe'
|
||||||
|
}
|
||||||
|
return viewType === 'sharedToMe' ? 'sharedToMe' : 'mine'
|
||||||
|
},
|
||||||
|
|
||||||
/** 查询客户列表 */
|
/** 查询客户列表 */
|
||||||
getList(param) {
|
getList(param) {
|
||||||
if (param) {
|
if (param) {
|
||||||
@@ -189,17 +201,20 @@ export default {
|
|||||||
goBack() {
|
goBack() {
|
||||||
const fromPerformance = this.$route.query.fromPerformance
|
const fromPerformance = this.$route.query.fromPerformance
|
||||||
if (fromPerformance === '1') {
|
if (fromPerformance === '1') {
|
||||||
// 从网格业绩统计页进入,返回网格业绩统计页的客群报表
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/center/performance/list',
|
path: '/center/performance/list',
|
||||||
query: { isActive: '8' }
|
query: { isActive: '8' }
|
||||||
})
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 返回上一级客群列表;没有历史记录时兜底跳客群列表
|
||||||
|
if (window.history.length > 1) {
|
||||||
|
this.$router.back()
|
||||||
} else {
|
} else {
|
||||||
// 从客群列表进入,返回客群列表
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/group/custGroup',
|
path: '/group/custGroup',
|
||||||
query: {
|
query: {
|
||||||
tab: this.viewType,
|
tab: this.resolveViewType(this.viewType),
|
||||||
refresh: Date.now()
|
refresh: Date.now()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,8 +2,20 @@
|
|||||||
<div class="customer-wrap">
|
<div class="customer-wrap">
|
||||||
<div class="nav_box">
|
<div class="nav_box">
|
||||||
<el-radio-group v-model="activeTab" class="header-radio" @input="handleTabChange">
|
<el-radio-group v-model="activeTab" class="header-radio" @input="handleTabChange">
|
||||||
<el-radio-button label="mine">我创建的</el-radio-button>
|
<el-radio-button
|
||||||
<el-radio-button label="sharedToMe">下发给我的</el-radio-button>
|
label="mine"
|
||||||
|
:disabled="!isHeadCustGroupAdmin"
|
||||||
|
:class="{ 'btn-disabled': !isHeadCustGroupAdmin }"
|
||||||
|
>
|
||||||
|
我创建的
|
||||||
|
</el-radio-button>
|
||||||
|
<el-radio-button
|
||||||
|
label="sharedToMe"
|
||||||
|
:disabled="isHeadCustGroupAdmin"
|
||||||
|
:class="{ 'btn-disabled': isHeadCustGroupAdmin }"
|
||||||
|
>
|
||||||
|
下发给我的
|
||||||
|
</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -190,6 +202,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listCustGroup, getCustGroup, deleteCustGroup, getAllGroupTags } from '@/api/group/custGroup'
|
import { listCustGroup, getCustGroup, deleteCustGroup, getAllGroupTags } from '@/api/group/custGroup'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
import CreateDialog from './components/create-dialog'
|
import CreateDialog from './components/create-dialog'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -223,26 +236,43 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapGetters(['roles']),
|
||||||
|
isHeadCustGroupAdmin() {
|
||||||
|
return ['headAdmin', 'headPublic', 'headPrivate', 'headOps'].some(role => this.roles.includes(role))
|
||||||
|
},
|
||||||
isMineTab() {
|
isMineTab() {
|
||||||
return this.activeTab === 'mine'
|
return this.activeTab === 'mine'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.activeTab = this.$route.query.tab || 'mine'
|
this.activeTab = this.resolveTab(this.$route.query.tab)
|
||||||
this.getList()
|
this.getList()
|
||||||
this.loadAllTags()
|
this.loadAllTags()
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.query.refresh'() {
|
'$route.query.refresh'() {
|
||||||
this.activeTab = this.$route.query.tab || 'mine'
|
this.activeTab = this.resolveTab(this.$route.query.tab)
|
||||||
this.queryParams.pageNum = 1
|
this.queryParams.pageNum = 1
|
||||||
this.getList()
|
this.getList()
|
||||||
|
},
|
||||||
|
roles() {
|
||||||
|
const nextTab = this.resolveTab(this.activeTab)
|
||||||
|
if (nextTab !== this.activeTab) {
|
||||||
|
this.activeTab = nextTab
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.clearRefreshTimer()
|
this.clearRefreshTimer()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resolveTab(tab) {
|
||||||
|
if (!this.isHeadCustGroupAdmin) {
|
||||||
|
return 'sharedToMe'
|
||||||
|
}
|
||||||
|
return tab === 'sharedToMe' ? 'sharedToMe' : 'mine'
|
||||||
|
},
|
||||||
|
|
||||||
clearRefreshTimer() {
|
clearRefreshTimer() {
|
||||||
if (this.refreshTimer) {
|
if (this.refreshTimer) {
|
||||||
clearTimeout(this.refreshTimer)
|
clearTimeout(this.refreshTimer)
|
||||||
@@ -264,6 +294,7 @@ export default {
|
|||||||
|
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
this.activeTab = this.resolveTab(this.activeTab)
|
||||||
this.queryParams.viewType = this.activeTab
|
this.queryParams.viewType = this.activeTab
|
||||||
listCustGroup(this.queryParams).then(response => {
|
listCustGroup(this.queryParams).then(response => {
|
||||||
this.groupList = response.rows
|
this.groupList = response.rows
|
||||||
@@ -284,6 +315,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleTabChange() {
|
handleTabChange() {
|
||||||
|
this.activeTab = this.resolveTab(this.activeTab)
|
||||||
this.ids = []
|
this.ids = []
|
||||||
this.single = true
|
this.single = true
|
||||||
this.multiple = true
|
this.multiple = true
|
||||||
@@ -336,7 +368,7 @@ export default {
|
|||||||
handleView(row) {
|
handleView(row) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/group/custGroup/detail',
|
path: '/group/custGroup/detail',
|
||||||
query: { groupId: row.id, viewType: this.activeTab }
|
query: { groupId: row.id, viewType: this.resolveTab(this.activeTab) }
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -397,6 +429,14 @@ export default {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border-bottom: 1px solid #ebebeb;
|
border-bottom: 1px solid #ebebeb;
|
||||||
|
|
||||||
|
.btn-disabled {
|
||||||
|
::v-deep .el-radio-button__inner {
|
||||||
|
background-color: #e7e7e7;
|
||||||
|
color: #999999;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.el-radio-button {
|
.el-radio-button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
|
|||||||
@@ -64,13 +64,37 @@
|
|||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="有无管户" prop="forwardFlag">
|
||||||
|
<el-select
|
||||||
|
v-model="searchArray.forwardFlag"
|
||||||
|
placeholder="请选择"
|
||||||
|
clearable
|
||||||
|
style="width:100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in forwardFlagOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="searchFn">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="searchFn">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetFn">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetFn">重置</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="canForwardByRole"
|
||||||
|
type="warning"
|
||||||
|
icon="el-icon-share"
|
||||||
|
size="mini"
|
||||||
|
:disabled="!canBatchForward"
|
||||||
|
@click="openForwardDialog()"
|
||||||
|
>批量转发</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-table v-loading="loading" :data="tableData">
|
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
|
||||||
<template>
|
<template>
|
||||||
|
<el-table-column v-if="canForwardByRole" type="selection" width="55" :selectable="canSelectForwardRow" />
|
||||||
<el-table-column label="序号" prop="xh" width="80">
|
<el-table-column label="序号" prop="xh" width="80">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.$index+1 }}</span>
|
<span>{{ scope.$index+1 }}</span>
|
||||||
@@ -80,6 +104,7 @@
|
|||||||
<el-table-column label="客户号" width="230" prop="custId" min-width="140" show-overflow-tooltip />
|
<el-table-column label="客户号" width="230" prop="custId" min-width="140" show-overflow-tooltip />
|
||||||
<el-table-column label="客户内码" width="200" prop="custIsn" min-width="140" show-overflow-tooltip />
|
<el-table-column label="客户内码" width="200" prop="custIsn" min-width="140" show-overflow-tooltip />
|
||||||
<el-table-column label="客户经理" width="200" prop="userInfo" min-width="140" show-overflow-tooltip />
|
<el-table-column label="客户经理" width="200" prop="userInfo" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column label="承接网点" width="180" prop="deptName" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column label="预警类型" width="250" prop="alterType" min-width="100" show-overflow-tooltip />
|
<el-table-column label="预警类型" width="250" prop="alterType" min-width="100" show-overflow-tooltip />
|
||||||
<el-table-column label="预警详情" prop="alterDetail" min-width="100" show-overflow-tooltip />
|
<el-table-column label="预警详情" prop="alterDetail" min-width="100" show-overflow-tooltip />
|
||||||
<el-table-column label="是否已读" prop="isReed" min-width="100" show-overflow-tooltip>
|
<el-table-column label="是否已读" prop="isReed" min-width="100" show-overflow-tooltip>
|
||||||
@@ -94,11 +119,18 @@
|
|||||||
<span>{{ scope.row.status | formatFilter('status',statusList) }}</span>
|
<span>{{ scope.row.status | formatFilter('status',statusList) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- <el-table-column label="操作" align="center" width="160">
|
<el-table-column v-if="canForwardByRole" label="操作" align="center" width="120">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="editFn(scope.row)">处理</el-button>
|
<el-button
|
||||||
|
v-if="scope.row.canForward"
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-share"
|
||||||
|
@click="openForwardDialog(scope.row)"
|
||||||
|
>转发</el-button>
|
||||||
|
<span v-else>-</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column> -->
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
</el-table>
|
</el-table>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@@ -112,92 +144,65 @@
|
|||||||
></el-pagination>
|
></el-pagination>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:title="dialogTitle"
|
title="转发预警"
|
||||||
:visible.sync="visibleFlag"
|
:visible.sync="forwardVisible"
|
||||||
width="800px"
|
width="520px"
|
||||||
append-to-body
|
append-to-body
|
||||||
v-if="visibleFlag"
|
v-if="forwardVisible"
|
||||||
>
|
>
|
||||||
<el-form ref="dialogFormRef" :model="dialogForm" :rules="dialogFormRules" label-width="120px">
|
<el-form ref="forwardFormRef" :model="forwardForm" :rules="forwardRules" label-width="100px">
|
||||||
<el-row>
|
<el-form-item v-if="forwardMeta.historyOnly" label="转发方式">
|
||||||
<el-col :span="24">
|
<span>按历史推荐转发</span>
|
||||||
<el-form-item label="客户姓名" prop="custName">
|
</el-form-item>
|
||||||
<el-input
|
<el-form-item v-if="isBranchAdmin" label="转发类型" prop="targetType">
|
||||||
v-model="dialogForm.custName"
|
<template v-if="!forwardMeta.historyOnly">
|
||||||
placeholder="请输入客户姓名"
|
<el-radio-group v-model="forwardForm.targetType">
|
||||||
clearable
|
<el-radio label="dept">转给网点</el-radio>
|
||||||
style="width:100%"
|
<el-radio label="user">转给客户经理</el-radio>
|
||||||
>
|
</el-radio-group>
|
||||||
</el-input>
|
</template>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
<el-form-item v-if="!forwardMeta.historyOnly && forwardForm.targetType === 'dept'" label="目标网点" prop="deptId">
|
||||||
<el-col :span="24">
|
<el-select v-model="forwardForm.deptId" placeholder="请选择网点" style="width:100%">
|
||||||
<el-form-item label="客户号" prop="custId">
|
<el-option
|
||||||
<el-input
|
v-for="item in forwardMeta.deptOptions"
|
||||||
v-model="dialogForm.custId"
|
:key="item.targetCode"
|
||||||
placeholder="请输入客户号"
|
:label="item.targetName"
|
||||||
clearable
|
:value="Number(item.targetCode)"
|
||||||
style="width:100%"
|
></el-option>
|
||||||
/>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
<el-form-item v-else-if="!forwardMeta.historyOnly" label="客户经理" prop="userName">
|
||||||
</el-row>
|
<el-select
|
||||||
<el-row>
|
v-model="forwardForm.userName"
|
||||||
<el-col :span="24">
|
placeholder="请选择客户经理"
|
||||||
<el-form-item label="预警类型" prop="alterType">
|
filterable
|
||||||
<el-input
|
style="width:100%"
|
||||||
v-model="dialogForm.alterType"
|
>
|
||||||
placeholder="请输入预警类型"
|
<el-option
|
||||||
clearable
|
v-for="item in forwardMeta.userOptions"
|
||||||
style="width:100%"
|
:key="item.targetCode"
|
||||||
>
|
:label="item.targetName"
|
||||||
</el-input>
|
:value="item.targetCode"
|
||||||
</el-form-item>
|
></el-option>
|
||||||
</el-col>
|
</el-select>
|
||||||
<el-col :span="24">
|
</el-form-item>
|
||||||
<el-form-item label="预警详情" prop="alterDetail">
|
<el-form-item
|
||||||
<el-input
|
v-if="forwardMeta.recommendedTargetCode && !isBatchForward && !forwardMeta.historyOnly"
|
||||||
v-model="dialogForm.alterDetail"
|
label="历史推荐"
|
||||||
placeholder="请输入预警详情"
|
>
|
||||||
clearable
|
<div class="recommend-row">
|
||||||
style="width:100%"
|
<span>{{ recommendLabel }}</span>
|
||||||
>
|
<el-button type="text" @click="applyRecommend">使用历史推荐</el-button>
|
||||||
</el-input>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
<el-form-item v-if="forwardMeta.historyOnly && isBatchForward" label="提示">
|
||||||
<el-col :span="24">
|
<span>本次多选中包含有历史分配记录的客户,将按各自历史推荐自动转发;没有历史记录的预警将保留不动。</span>
|
||||||
<el-form-item label="状态" prop="status">
|
</el-form-item>
|
||||||
<el-select
|
|
||||||
v-model="dialogForm.status"
|
|
||||||
placeholder="请选择状态"
|
|
||||||
clearable
|
|
||||||
style="width:100%"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in statusList"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input
|
|
||||||
v-model="dialogForm.remark"
|
|
||||||
placeholder="请输入备注"
|
|
||||||
clearable
|
|
||||||
style="width:100%"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer">
|
<div slot="footer">
|
||||||
<el-button type="primary" @click="dialogOkfn">确 定</el-button>
|
<el-button type="primary" :loading="forwardSubmitting" @click="submitForward">确 定</el-button>
|
||||||
<el-button @click="dialogCancelfn">取 消</el-button>
|
<el-button @click="closeForwardDialog">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
@@ -206,9 +211,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
warningworkRecordList,
|
warningworkRecordList,
|
||||||
warningworkRecordSubmit,
|
|
||||||
warningCardNum,
|
warningCardNum,
|
||||||
getAlterTypes
|
getAlterTypes,
|
||||||
|
getAlterForwardMeta,
|
||||||
|
forwardAlter
|
||||||
} from "@/api/system/home";
|
} from "@/api/system/home";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
@@ -232,6 +238,24 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
isBranchAdmin() {
|
||||||
|
return this.roles.includes("branchAdmin");
|
||||||
|
},
|
||||||
|
isOutletAdmin() {
|
||||||
|
return this.roles.includes("outletAdmin");
|
||||||
|
},
|
||||||
|
canForwardByRole() {
|
||||||
|
return this.isBranchAdmin || this.isOutletAdmin;
|
||||||
|
},
|
||||||
|
canBatchForward() {
|
||||||
|
return this.selectedRows.length > 0 && this.selectedRows.every(item => item.canForward);
|
||||||
|
},
|
||||||
|
recommendLabel() {
|
||||||
|
if (!this.forwardMeta.recommendedTargetCode) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return `${this.forwardMeta.recommendedTargetType === "dept" ? "网点" : "客户经理"}:${this.forwardMeta.recommendedTargetName}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -253,35 +277,45 @@ export default {
|
|||||||
],
|
],
|
||||||
|
|
||||||
alterTypeOptions: [],
|
alterTypeOptions: [],
|
||||||
|
forwardFlagOptions: [
|
||||||
|
{ label: "有管户", value: "0" },
|
||||||
|
{ label: "无管户", value: "1" }
|
||||||
|
],
|
||||||
|
|
||||||
searchArray: {
|
searchArray: {
|
||||||
status: "",
|
status: "",
|
||||||
alterType: ""
|
alterType: "",
|
||||||
|
forwardFlag: ""
|
||||||
},
|
},
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
|
selectedRows: [],
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
dialogTitle: '',
|
forwardVisible: false,
|
||||||
dialogForm: {
|
forwardSubmitting: false,
|
||||||
custName: '',
|
isBatchForward: false,
|
||||||
custId: '',
|
forwardMeta: {
|
||||||
alterType: '',
|
deptOptions: [],
|
||||||
alterDetail: '',
|
userOptions: [],
|
||||||
status: ''
|
recommendedTargetType: "",
|
||||||
|
recommendedTargetCode: "",
|
||||||
|
recommendedTargetName: "",
|
||||||
|
historyOnly: false,
|
||||||
|
hasHistoryRecommend: false
|
||||||
},
|
},
|
||||||
visibleFlag: false,
|
forwardForm: {
|
||||||
dialogFormRules: {
|
ids: [],
|
||||||
status: [{ required: true, message: "不能为空", trigger: "blur" }],
|
targetType: "user",
|
||||||
custName: [{ required: true, message: "不能为空", trigger: "blur" }],
|
deptId: "",
|
||||||
custId: [{ required: true, message: "不能为空", trigger: "blur" }],
|
userName: "",
|
||||||
alterType: [
|
useHistory: false
|
||||||
{ required: true, message: "不能为空", trigger: "blur" }
|
},
|
||||||
],
|
forwardRules: {
|
||||||
alterDetail: [
|
targetType: [{ required: true, message: "请选择转发类型", trigger: "change" }],
|
||||||
{ required: true, message: "不能为空", trigger: "blur" }
|
deptId: [{ required: true, message: "请选择目标网点", trigger: "change" }],
|
||||||
]
|
userName: [{ required: true, message: "请选择客户经理", trigger: "change" }]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -314,7 +348,8 @@ export default {
|
|||||||
resetFn() {
|
resetFn() {
|
||||||
this.searchArray = {
|
this.searchArray = {
|
||||||
status: "",
|
status: "",
|
||||||
alterType: ""
|
alterType: "",
|
||||||
|
forwardFlag: ""
|
||||||
};
|
};
|
||||||
this.searchFn();
|
this.searchFn();
|
||||||
},
|
},
|
||||||
@@ -335,6 +370,7 @@ export default {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
if (response.code == 200) {
|
if (response.code == 200) {
|
||||||
this.tableData = response.rows || [];
|
this.tableData = response.rows || [];
|
||||||
|
this.selectedRows = [];
|
||||||
this.total = response.total || 0;
|
this.total = response.total || 0;
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(response.msg || "操作失败");
|
this.$message.error(response.msg || "操作失败");
|
||||||
@@ -349,33 +385,95 @@ export default {
|
|||||||
this.pageSize = val;
|
this.pageSize = val;
|
||||||
this.queryListFn();
|
this.queryListFn();
|
||||||
},
|
},
|
||||||
editFn(row) {
|
handleSelectionChange(rows) {
|
||||||
this.dialogTitle = "修改";
|
this.selectedRows = rows || [];
|
||||||
this.dialogForm = row;
|
|
||||||
this.visibleFlag = true;
|
|
||||||
// this.$nextTick(() => {
|
|
||||||
// this.$refs.dialogFormRef.resetFields();
|
|
||||||
// });
|
|
||||||
},
|
},
|
||||||
dialogOkfn() {
|
canSelectForwardRow(row) {
|
||||||
this.$refs["dialogFormRef"].validate(valid => {
|
return !!row.canForward;
|
||||||
if (valid) {
|
},
|
||||||
warningworkRecordSubmit(this.dialogForm).then(response => {
|
openForwardDialog(row) {
|
||||||
if (response.code == "200") {
|
const rows = row ? [row] : this.selectedRows.filter(item => item.canForward);
|
||||||
let msg = "修改成功";
|
if (!rows.length) {
|
||||||
this.$message.success(msg);
|
this.$message.warning("请先选择可转发的预警信息");
|
||||||
this.visibleFlag = false;
|
return;
|
||||||
this.resetFn();
|
}
|
||||||
} else {
|
this.isBatchForward = rows.length > 1;
|
||||||
this.$message.error(response.msg || "操作失败");
|
this.forwardVisible = true;
|
||||||
}
|
this.forwardSubmitting = false;
|
||||||
});
|
this.forwardForm = {
|
||||||
|
ids: rows.map(item => item.id),
|
||||||
|
targetType: this.isBranchAdmin ? "dept" : "user",
|
||||||
|
deptId: "",
|
||||||
|
userName: "",
|
||||||
|
useHistory: false
|
||||||
|
};
|
||||||
|
this.forwardMeta = {
|
||||||
|
deptOptions: [],
|
||||||
|
userOptions: [],
|
||||||
|
recommendedTargetType: "",
|
||||||
|
recommendedTargetCode: "",
|
||||||
|
recommendedTargetName: "",
|
||||||
|
historyOnly: false,
|
||||||
|
hasHistoryRecommend: false
|
||||||
|
};
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.forwardFormRef && this.$refs.forwardFormRef.clearValidate();
|
||||||
|
});
|
||||||
|
getAlterForwardMeta({ ids: rows.map(item => item.id).join(",") }).then(res => {
|
||||||
|
if (res.code !== 200) {
|
||||||
|
this.$message.error(res.msg || "获取转发信息失败");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.forwardMeta = res.data || this.forwardMeta;
|
||||||
|
this.forwardForm.useHistory = !!this.forwardMeta.historyOnly;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
dialogCancelfn() {
|
applyRecommend() {
|
||||||
this.visibleFlag = false;
|
if (!this.forwardMeta.recommendedTargetCode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.forwardMeta.recommendedTargetType === "dept" && this.isOutletAdmin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.forwardForm.targetType = this.forwardMeta.recommendedTargetType || this.forwardForm.targetType;
|
||||||
|
if (this.forwardForm.targetType === "dept") {
|
||||||
|
this.forwardForm.deptId = Number(this.forwardMeta.recommendedTargetCode);
|
||||||
|
this.forwardForm.userName = "";
|
||||||
|
} else {
|
||||||
|
this.forwardForm.userName = this.forwardMeta.recommendedTargetCode;
|
||||||
|
this.forwardForm.deptId = "";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
submitForward() {
|
||||||
|
if (this.forwardMeta.historyOnly) {
|
||||||
|
this.forwardForm.useHistory = true;
|
||||||
|
}
|
||||||
|
if (!this.forwardMeta.historyOnly && this.forwardForm.targetType === "dept" && !this.forwardForm.deptId) {
|
||||||
|
this.$message.warning("请选择目标网点");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.forwardMeta.historyOnly && this.forwardForm.targetType === "user" && !this.forwardForm.userName) {
|
||||||
|
this.$message.warning("请选择客户经理");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.forwardSubmitting = true;
|
||||||
|
forwardAlter(this.forwardForm).then(response => {
|
||||||
|
this.forwardSubmitting = false;
|
||||||
|
if (response.code == 200) {
|
||||||
|
this.$message.success(response.msg || "转发完成");
|
||||||
|
this.closeForwardDialog();
|
||||||
|
this.queryListFn();
|
||||||
|
this.initCardList();
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.msg || "操作失败");
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.forwardSubmitting = false;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeForwardDialog() {
|
||||||
|
this.forwardVisible = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -509,4 +607,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
.recommend-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user