Browse Source

群发发送记录人数统计;标签查询被删除客户数属性;重构活码、获客链接客服关系

zoujiajian 2 năm trước cách đây
mục cha
commit
5f27b08a42
38 tập tin đã thay đổi với 537 bổ sung76 xóa
  1. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  2. 5 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpCustomerAcquisitionLinkMapper.java
  3. 5 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpFollowActiveCodeMapper.java
  4. 2 1
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpUserTagMapper.java
  5. 6 1
      netflix-dao/src/main/java/com/cyksj/model/dto/CorpFollowActiveCodeDto.java
  6. 22 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SysServiceChangeDto.java
  7. 24 0
      netflix-dao/src/main/java/com/cyksj/model/dto/YhServiceNameDto.java
  8. 1 1
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpFollowActiveCode.java
  9. 1 1
      netflix-dao/src/main/java/com/cyksj/model/views/CorpFollowActiveCodeView.java
  10. 3 2
      netflix-dao/src/main/java/com/cyksj/model/views/CorpMsgBulkTaskSendRecordView.java
  11. 37 0
      netflix-dao/src/main/java/com/cyksj/model/views/CorpTagUserOrderDataView.java
  12. 18 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributeGoodsGeneralRateView.java
  13. 1 2
      netflix-dao/src/main/java/com/cyksj/model/views/DistributePopularizeView.java
  14. 8 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserOrderDetailView.java
  15. 14 0
      netflix-dao/src/main/resources/mapper/CorpCustomerAcquisitionLinkMapper.xml
  16. 15 0
      netflix-dao/src/main/resources/mapper/CorpFollowActiveCodeMapper.xml
  17. 3 2
      netflix-dao/src/main/resources/mapper/CorpUserTagMapper.xml
  18. 33 1
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  19. 1 1
      netflix-service/src/main/java/com/cyksj/service/corp/CorpFollowDynamicConfigService.java
  20. 2 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpTagService.java
  21. 20 7
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java
  22. 11 6
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquistionServiceImpl.java
  23. 13 7
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowActiveCodeFrontServiceImpl.java
  24. 6 4
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowDynamicConfigServiceImpl.java
  25. 18 12
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowServiceImpl.java
  26. 12 1
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpTagServiceImpl.java
  27. 6 1
      netflix-service/src/main/java/com/cyksj/service/sys/SysConfigChangeRecordService.java
  28. 1 1
      netflix-service/src/main/java/com/cyksj/service/sys/SysConfigService.java
  29. 24 0
      netflix-service/src/main/java/com/cyksj/service/sys/SysCorpServiceRelateService.java
  30. 99 5
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigChangeRecordServiceImpl.java
  31. 5 7
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigServiceImpl.java
  32. 69 0
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpServiceRelateServiceImpl.java
  33. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CmsCorpFollowActiveCodeController.java
  34. 14 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkController.java
  35. 5 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpMsgBulkTaskController.java
  36. 11 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpTagController.java
  37. 7 2
      netflix-web/src/main/java/com/cyksj/web/controller/sys/SysConfigController.java
  38. 12 6
      netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java

@@ -68,4 +68,6 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
 	UserOrderDetailView getTagUserData(@Param("tagIdStr") String tagIdStr, @Param("startTime") String startTime, @Param("endTime") String endTime);
 
 	Page<UserOrderDetailView> getTagUserDataPage(@Param("page") Page<UserOrderDetailView> page, @Param("tagIdStr") String tagIdStr, @Param("startTime") String startTime, @Param("endTime") String endTime);
+
+	Page<CorpTagUserOrderDataView> getTagUserTimeOrderData(@Param("page") Page<Object> objectPage, @Param("tagIdStr") String tagIdStr, @Param("toDate") String toDate, @Param("startTime") String startTime, @Param("endTime") String endTime);
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpCustomerAcquisitionLinkMapper.java

@@ -2,8 +2,11 @@ package com.cyksj.mapper.corp;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
+import java.util.List;
+
 /**
  * @author chan
  * @date 2023/11/28 14:21
@@ -12,4 +15,6 @@ public interface CorpCustomerAcquisitionLinkMapper extends BaseMapper<CorpCustom
 
     @Select("select cl.* from corp_customer_acquisition_link cl, corp_customer_acquisition_link_popularize clp where cl.id = clp.customer_acquistion_link_id and clp.id = #{linkId}")
     CorpCustomerAcquisitionLink getByLinkPopularizeId(Long linkId);
+
+	List<CorpCustomerAcquisitionLink> selectActiveCodeByFollowIndx(@Param("list") List<Integer> updateFollowIndx);
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpFollowActiveCodeMapper.java

@@ -2,6 +2,9 @@ package com.cyksj.mapper.corp;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.entity.CorpFollowActiveCode;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * 项目名: yhlxj
@@ -10,4 +13,6 @@ import com.cyksj.model.entity.CorpFollowActiveCode;
  * 创建时间:2023/10/9 16:27
  */
 public interface CorpFollowActiveCodeMapper extends BaseMapper<CorpFollowActiveCode> {
+
+	List<CorpFollowActiveCode> selectActiveCodeByFollowIndx(@Param("list") List<Integer> indx);
 }

+ 2 - 1
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpUserTagMapper.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.cyksj.model.entity.CorpUserTag;
 import com.cyksj.model.excel.CorpUserTagExcelData;
 import com.cyksj.model.views.CorpUserView;
+import com.cyksj.model.views.UserOrderDetailView;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -19,5 +20,5 @@ public interface CorpUserTagMapper extends BaseMapper<CorpUserTag> {
 
 	List<CorpUserTagExcelData> exportUserTagDetail(@Param("tagIds") String[] tagIds, @Param("groupIds") String[] groupIds, @Param("wxCorpId") Long wxCorpId);
 
-	Integer countTagUser(@Param("tagIdStr") String tagIdStr, @Param("startTime") String startTime, @Param("endTime") String endTime);
+	UserOrderDetailView countTagUser(@Param("tagIdStr") String tagIdStr, @Param("startTime") String startTime, @Param("endTime") String endTime);
 }

+ 6 - 1
netflix-dao/src/main/java/com/cyksj/model/dto/CorpFollowActiveCodeDto.java

@@ -15,10 +15,15 @@ import lombok.Setter;
 public class CorpFollowActiveCodeDto {
 
 	/**
-	 * 企业微信的客服id 数组
+	 * 客服id 数组
 	 */
 	private String followIds;
 
+	/**
+	 * 最新 值班客服id
+	 */
+	private String userIndxList;
+
 	/**
 	 * 对应系统配置的客服
 	 */

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SysServiceChangeDto.java

@@ -0,0 +1,22 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: SysServiceChangeDto
+ * 创建者: JavaZou
+ * 创建时间:2024/1/11 16:47
+ */
+@Getter
+@Setter
+public class SysServiceChangeDto {
+	private Boolean changeCsImg = false;
+
+	private Boolean changeCsName = false;
+
+	private List<Integer> updateFollowIndxs;
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/YhServiceNameDto.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: YhServiceNameDto
+ * 创建者: JavaZou
+ * 创建时间:2024/1/11 15:45
+ */
+@Getter
+@Setter
+public class YhServiceNameDto {
+	private String name;
+
+	private String img;
+
+	private Integer indx;
+
+	private String url;
+
+	private String followId;
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/CorpFollowActiveCode.java

@@ -27,7 +27,7 @@ public class CorpFollowActiveCode extends BaseEntity{
 	@TableField(exist = false)
 	@DbIgnore
 	@NotNull(message = "请选择对应客服")
-	private List<String> followIds;
+	private List<Integer> userIndxList;
 
 	/**
 	 * 客服

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/views/CorpFollowActiveCodeView.java

@@ -36,7 +36,7 @@ public class CorpFollowActiveCodeView {
 	private String followStr;
 
 	@DbIgnore
-	private List<String> followIds;
+	private List<Integer> userIndxList;
 
 	/**
 	 * 欢迎语内容 文本、附件

+ 3 - 2
netflix-dao/src/main/java/com/cyksj/model/views/CorpMsgBulkTaskSendRecordView.java

@@ -1,6 +1,7 @@
 package com.cyksj.model.views;
 
 import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import lombok.Getter;
 import lombok.Setter;
@@ -25,7 +26,7 @@ public class CorpMsgBulkTaskSendRecordView {
 	/**
 	 * 总数
 	 */
-	@DbField("count(cr.id)")
+	@DbIgnore
 	private Integer total;
 
 	/**
@@ -37,7 +38,7 @@ public class CorpMsgBulkTaskSendRecordView {
 	/**
 	 * 未送达
 	 */
-	@DbField("count(if(cr.status != 1,cr.id,null))")
+	@DbIgnore
 	private Integer notSend;
 
 	@DbField("any_value(cmr.created_time)")

+ 37 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CorpTagUserOrderDataView.java

@@ -0,0 +1,37 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpTagUserOrderDataView
+ * 创建者: JavaZou
+ * 创建时间:2024/1/11 14:57
+ */
+@Getter
+@Setter
+public class CorpTagUserOrderDataView {
+	private Long orderId;
+
+	private Long userId;
+
+	private String nickname;
+
+	private String orderNo;
+
+	private Long goodsId;
+
+	private String title;
+
+	private Long skuId;
+
+	private String specVal;
+
+	private BigDecimal money;
+
+	private Date createdTime;
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributeGoodsGeneralRateView.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: DistributeGoodsGeneralRateView
+ * 创建者: JavaZou
+ * 创建时间:2024/1/11 14:26
+ */
+@Getter
+@Setter
+public class DistributeGoodsGeneralRateView {
+	private Integer rate;
+
+	private String goodsInfo;
+}

+ 1 - 2
netflix-dao/src/main/java/com/cyksj/model/views/DistributePopularizeView.java

@@ -1,6 +1,5 @@
 package com.cyksj.model.views;
 
-import com.cyksj.model.entity.GoodsDon;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -68,5 +67,5 @@ public class DistributePopularizeView {
 	/**
 	 * 普通低分销比例
 	 */
-	private List<GoodsDon> generalDistributes;
+	private List<DistributeGoodsGeneralRateView> generalDistributes;
 }

+ 8 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserOrderDetailView.java

@@ -17,6 +17,14 @@ import java.math.BigDecimal;
 public class UserOrderDetailView {
 	private Integer numOfUser;
 
+	private Integer delNumOfUser;
+
+	private Integer numOfEpOrder;
+
+	private Integer epOrderMoney;
+
+	private BigDecimal orderRate;
+
 	private Integer numOfOrder;
 
 	private BigDecimal orderMoney;

+ 14 - 0
netflix-dao/src/main/resources/mapper/CorpCustomerAcquisitionLinkMapper.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkMapper">
+
+    <select id="selectActiveCodeByFollowIndx" resultType="com.cyksj.model.entity.CorpCustomerAcquisitionLink">
+        select *
+        from corp_customer_acquisition_link
+        where user_list != '[]' and
+        <foreach collection="list" item="item" separator="OR">
+            JSON_CONTAINS(user_list, '${item}')
+        </foreach>
+    </select>
+</mapper>

+ 15 - 0
netflix-dao/src/main/resources/mapper/CorpFollowActiveCodeMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.corp.CorpFollowActiveCodeMapper">
+
+    <select id="selectActiveCodeByFollowIndx" resultType="com.cyksj.model.entity.CorpFollowActiveCode">
+        select *
+        from corp_follow_active_code
+        where deleted is true
+        and follow_str != '' and
+        <foreach collection="list" item="item" separator="OR">
+            JSON_CONTAINS(follow_str, '${item}')
+        </foreach>
+    </select>
+</mapper>

+ 3 - 2
netflix-dao/src/main/resources/mapper/CorpUserTagMapper.xml

@@ -61,8 +61,9 @@
         group by cu.id, cu.unionid)s order by s.tagTime desc, s.userId asc
     </select>
 
-    <select id="countTagUser" resultType="java.lang.Integer">
-        select count(distinct ca.corp_user_id)
+    <select id="countTagUser" resultType="com.cyksj.model.views.UserOrderDetailView">
+        select count(distinct ca.corp_user_id) as numOfUser,
+        count(distinct if(cufr.status = 0,ca.corp_user_id,NULL)) as delNumOfUser
         from (select relation_id
         from `corp_user_tag` ct
         where tag_id = #{tagIdStr}

+ 33 - 1
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -315,7 +315,9 @@
 
     <select id="getTagUserData" resultType="com.cyksj.model.views.UserOrderDetailView">
         select count(if(status != 'refund', 1, NULL)) as numOfOrder, (sum(money) - sum(ifnull(refund_money, 0))) / 100
-        as orderMoney
+        as orderMoney,
+        count(if(status != 'refund' and o.goods_id = 15,1,NULL)) as numOfEpOrder,
+        (sum(if(o.goods_id = 15,money,0)) - sum(ifnull(if(o.goods_id = 15,refund_money,0), 0))) / 100 as epOrderMoney
         from (select cu.user_id
         from (select relation_id
         from `corp_user_tag` ct
@@ -357,4 +359,34 @@
         group by date_format(o.created_time,'%Y-%m-%d')
         order by date_format(o.created_time,'%Y-%m-%d') desc
     </select>
+
+    <select id="getTagUserTimeOrderData" resultType="com.cyksj.model.views.CorpTagUserOrderDataView">
+        select o.id as order_id,o.user_id,
+        (select nickname from user u where u.id = o.user_id limit 1),
+        o.order_no,o.goods_id,g.title,o.sku_id,sku.spec_val,
+        o.money/100 as money,o.created_time
+        from (select
+        cu.user_id
+        from (select relation_id
+        from `corp_user_tag` ct
+        where tag_id = #{tagIdStr}
+        <if test="startTime != null">
+            and ct.created_time >= #{startTime}
+        </if>
+        <if test="endTime != null">
+            and ct.created_time &lt; #{endTime}
+        </if>) s
+        left join corp_user_follow_relation cufr on cufr.id = s.relation_id
+        left join corp_user_auth ca on ca.external_userid = cufr.corp_user_id
+        left join corp_user cu on cu.id = ca.corp_user_id where cu.user_id != 0) s inner join order_don o on o.user_id =
+        s.user_id
+        and o.status not in ('close', 'noPayment','refund')
+        and o.money > 0
+        <if test="toDate != null and toDate != ''">
+            and date_format(o.created_time,'%Y-%m-%d') = #{toDate}
+        </if>
+        left join goods_don g on g.id = o.goods_id
+        left join goods_don_sku sku on sku.id = o.sku_id
+        order by o.created_time desc
+    </select>
 </mapper>

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/corp/CorpFollowDynamicConfigService.java

@@ -13,7 +13,7 @@ import java.util.List;
 public interface CorpFollowDynamicConfigService {
 	String corpFollowContactConfig(CorpFollowContact corpFollowContact) throws Exception;
 
-	String createCorpFollowActiveCode(List<String> followIds, String state, Boolean isDuty) throws Exception;
+	String createCorpFollowActiveCode(List<String> followIds, List<Integer> userIndxList, String state, Boolean isDuty) throws Exception;
 
 	void updateCorpFollowActiveCode(String oldMarkTag, String markTag) throws Exception;
 }

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpTagService.java

@@ -46,4 +46,6 @@ public interface CorpTagService {
 	CorpTagGroupView addGroup(CorpTagGroupView tagGroup) throws Exception;
 
 	UserOrderDetailView getTagUserData(Integer start, Integer limit, String tagIdStr, String startTime, String endTime);
+
+	Page<CorpTagUserOrderDataView> getTagUserTimeOrderData(Integer start, Integer limit, String tagIdStr, String toDate, String startTime, String endTime);
 }

+ 20 - 7
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java

@@ -1,11 +1,11 @@
 package com.cyksj.service.corp.impl;
 
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkMapper;
 import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkPopularizeMapper;
 import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
@@ -16,6 +16,7 @@ import com.cyksj.model.request.corp.link.WxCpLinkAddResp;
 import com.cyksj.model.request.corp.link.WxCpLinkUpd;
 import com.cyksj.service.corp.CorpCustomerAcquisitionLinkService;
 import com.cyksj.service.corp.WxCorpOps;
+import com.cyksj.service.sys.SysCorpServiceRelateService;
 import com.cyksj.xxljob.XxlJobInfo;
 import com.cyksj.xxljob.XxlJobUtil;
 import lombok.RequiredArgsConstructor;
@@ -23,6 +24,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.List;
 import java.util.Optional;
 
 /**
@@ -38,6 +40,8 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
 
     private final CorpCustomerAcquisitionLinkPopularizeMapper corpCustomerAcquisitionLinkPopularizeMapper;
 
+    private final SysCorpServiceRelateService sysCorpServiceRelateService;
+
     @Override
     @Transactional(rollbackFor = Throwable.class)
     public void add(CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception {
@@ -45,7 +49,10 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
         wxCpLinkAdd.setLinkName(corpCustomerAcquisitionLink.getLinkName());
         wxCpLinkAdd.setSkipVerify(corpCustomerAcquisitionLink.getSkipVerify());
         Range range = new Range();
-        range.setUserList(JSONUtil.parseArray(corpCustomerAcquisitionLink.getUserList()).toList(String.class));
+        String userList = corpCustomerAcquisitionLink.getUserList();
+        //值班客服
+        List<String> followIds = sysCorpServiceRelateService.getFollowIdsByRelateIds(Jsons.parseList(userList, Integer.class));
+        range.setUserList(followIds);
         wxCpLinkAdd.setRange(range);
         WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionCreateLink(null, wxCpLinkAdd);
         corpCustomerAcquisitionLink.setUrl(wxCpLinkAddResp.getLink().getUrl());
@@ -72,7 +79,15 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
         wxCpLinkUpd.setLinkId(corpCustomerAcquisitionLink.getLinkId());
         wxCpLinkUpd.setSkipVerify(corpCustomerAcquisitionLink.getSkipVerify());
         Range range = new Range();
-        range.setUserList(JSONUtil.parseArray(corpCustomerAcquisitionLink.getUserList()).toList(String.class));
+        String userList;
+        if (link.getIsDuty()) {
+            userList = corpCustomerAcquisitionLink.getChooseDutyUsers();
+        } else {
+            userList = corpCustomerAcquisitionLink.getUserList();
+        }
+        //值班客服
+        List<String> followIds = sysCorpServiceRelateService.getFollowIdsByRelateIds(Jsons.parseList(userList, Integer.class));
+        range.setUserList(followIds);
         wxCpLinkUpd.setRange(range);
 
         WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionUpdateLink(null, wxCpLinkUpd);
@@ -83,10 +98,8 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
         Boolean isDuty = Optional.ofNullable(corpCustomerAcquisitionLink.getIsDuty()).orElse(false);
         if (!isDuty) {
             corpCustomerAcquisitionLink.setChooseDutyUsers(null);
-        } else {
-            if (StrUtil.isEmpty(corpCustomerAcquisitionLink.getChooseDutyUsers())) {
-                corpCustomerAcquisitionLink.setChooseDutyUsers(corpCustomerAcquisitionLink.getUserList());
-            }
+        } else if (StrUtil.isEmpty(corpCustomerAcquisitionLink.getChooseDutyUsers())) {
+            corpCustomerAcquisitionLink.setChooseDutyUsers(corpCustomerAcquisitionLink.getUserList());
         }
 
         this.updateById(corpCustomerAcquisitionLink);

+ 11 - 6
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquistionServiceImpl.java

@@ -2,7 +2,6 @@ package com.cyksj.service.corp.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.snowflake.Sequence;
 import com.cyksj.common.util.Jsons;
@@ -16,6 +15,7 @@ import com.cyksj.redis.RedisService;
 import com.cyksj.service.corp.CorpCustomerAcquistionService;
 import com.cyksj.service.corp.WxCorpOps;
 import com.cyksj.service.sys.SysConfigService;
+import com.cyksj.service.sys.SysCorpServiceRelateService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -45,6 +45,8 @@ public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistion
 
     private final SysConfigService sysConfigService;
 
+    private final SysCorpServiceRelateService sysCorpServiceRelateService;
+
     private final WxCorpOps corpOps;
 
 
@@ -94,9 +96,9 @@ public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistion
         if (corpCustomerAcquisitionLink.getIsDuty()) {
             String userList = corpCustomerAcquisitionLink.getUserList();
 
-            List<String> users = Jsons.parseList(userList, String.class);
+            List<Integer> users = Jsons.parseList(userList, Integer.class);
             if (users.size() > 1) {
-                List<String> dutyServices = sysConfigService.getDutyServices();
+                List<Integer> dutyServices = sysConfigService.getDutyServices();
                 //值班
                 if (CollUtil.isNotEmpty(dutyServices)) {
 
@@ -104,9 +106,9 @@ public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistion
                     if (chooseDutyUsers == null) {
                         chooseDutyUsers = userList;
                     }
-                    List<String> chooseUserList = Jsons.parseList(chooseDutyUsers, String.class);
+                    List<Integer> chooseUserList = Jsons.parseList(chooseDutyUsers, Integer.class);
 
-                    Set<String> fitUsers = dutyServices.stream().filter(e -> users.contains(e)).collect(Collectors.toSet());
+                    Set<Integer> fitUsers = dutyServices.stream().filter(e -> users.contains(e)).collect(Collectors.toSet());
                     if (CollUtil.isNotEmpty(fitUsers) && (fitUsers.size() != chooseUserList.size() || !chooseUserList.containsAll(fitUsers))) {
 
                         corpCustomerAcquisitionLink.setChooseDutyUsers(Jsons.toJson(fitUsers));
@@ -117,7 +119,10 @@ public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistion
                         wxCpLinkUpd.setLinkId(corpCustomerAcquisitionLink.getLinkId());
                         wxCpLinkUpd.setSkipVerify(corpCustomerAcquisitionLink.getSkipVerify());
                         Range range = new Range();
-                        range.setUserList(JSONUtil.parseArray(corpCustomerAcquisitionLink.getChooseDutyUsers()).toList(String.class));
+                        List<Integer> userIndxList = Jsons.parseList(corpCustomerAcquisitionLink.getChooseDutyUsers(), Integer.class);
+                        List<String> followIds = sysCorpServiceRelateService.getFollowIdsByRelateIds(userIndxList);
+
+                        range.setUserList(followIds);
                         wxCpLinkUpd.setRange(range);
                         corpOps.customerAcquisitionUpdateLink(null, wxCpLinkUpd);
 

+ 13 - 7
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowActiveCodeFrontServiceImpl.java

@@ -91,19 +91,19 @@ public class CorpFollowActiveCodeFrontServiceImpl implements CorpFollowActiveCod
 		if (activeCodeDtos.size() == 1) {
 			return activeCodeDtos.get(0).getQrCode();
 		}
-		List<String> dutyServices = sysConfigService.getDutyServices();
-		String chooseFollowId = null;
+		List<Integer> dutyServices = sysConfigService.getDutyServices();
+		Integer chooseFollowId = null;
 		//值班
 		if (CollUtil.isNotEmpty(dutyServices)) {
-			List<String> collectFollow = new ArrayList<>();
+			List<Integer> collectFollow = new ArrayList<>();
 			activeCodeDtos.stream().forEach(e -> {
 				try {
-					collectFollow.addAll(JSONUtil.parseArray(e.getFollowIds()).toList(String.class));
+					collectFollow.addAll(JSONUtil.parseArray(e.getUserIndxList()).toList(Integer.class));
 				} catch (Exception ex) {
 					System.out.println(ex.getMessage());
 				}
 			});
-			List<String> collect = dutyServices.stream().filter(fid -> collectFollow.contains(fid)).collect(Collectors.toList());
+			List<Integer> collect = dutyServices.stream().filter(fid -> collectFollow.contains(fid)).collect(Collectors.toList());
 			if (CollUtil.isNotEmpty(collect)) {
 				chooseFollowId = collect.get(RandomUtil.randomInt(collect.size()));
 			}
@@ -112,8 +112,14 @@ public class CorpFollowActiveCodeFrontServiceImpl implements CorpFollowActiveCod
 		CorpFollowActiveCodeDto activeCodeDto = null;
 		if (chooseFollowId != null) {
 			log.info("寻找合适值班客服:{}", chooseFollowId);
-			final String csFollowId = chooseFollowId;
-			activeCodeDto = activeCodeDtos.stream().filter(active -> active.getFollowIds().contains(csFollowId)).findFirst().get();
+			final Integer csFollowId = chooseFollowId;
+			activeCodeDto = activeCodeDtos.stream().filter(active -> {
+				try {
+					return Jsons.parseList(active.getUserIndxList(), Integer.class).contains(csFollowId);
+				} catch (Exception e) {
+				}
+				return false;
+			}).findFirst().get();
 		}
 
 		if (activeCodeDto == null) {

+ 6 - 4
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowDynamicConfigServiceImpl.java

@@ -62,7 +62,7 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 	}
 
 	@Override
-	public String createCorpFollowActiveCode(List<String> followIds, String state, Boolean isDuty) throws Exception {
+	public String createCorpFollowActiveCode(List<String> followIds, List<Integer> userIndxList, String state, Boolean isDuty) throws Exception {
 		List<CorpFollowActiveCodeDto> codeList = new ArrayList<>();
 		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
 				.eq(SysConfig::getSysKey, Constant.serviceKeys.get(1)).last("limit 1"));
@@ -84,7 +84,7 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 			if (StrUtil.isEmpty(serviceNames)) {
 				throw BusinessRuntimeException.getInstance("存在被删除的客服,请刷新页面重试");
 			}
-			CorpFollowActiveCodeDto corpFollowActiveCodeDto = createCorpFollowActiveCode(followIds, state, type, serviceNames);
+			CorpFollowActiveCodeDto corpFollowActiveCodeDto = createCorpFollowActiveCode(followIds, userIndxList, state, type, serviceNames);
 			codeList.add(corpFollowActiveCodeDto);
 		} else {
 			Map<String, List<CorpFollowServiceDto>> csMap = null;
@@ -95,7 +95,8 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 				throw BusinessRuntimeException.getInstance("存在被删除的客服,请刷新页面重试");
 			}
 			for (String followId : followIds) {
-				CorpFollowActiveCodeDto corpFollowActiveCodeDto = createCorpFollowActiveCode(List.of(followId), state, type, csMap.get(followId).get(0).getName());
+				CorpFollowServiceDto corpFollowServiceDto = csMap.get(followId).get(0);
+				CorpFollowActiveCodeDto corpFollowActiveCodeDto = createCorpFollowActiveCode(List.of(followId), List.of(corpFollowServiceDto.getIndx()), state, type, corpFollowServiceDto.getName());
 				codeList.add(corpFollowActiveCodeDto);
 			}
 		}
@@ -117,7 +118,7 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 		}
 	}
 
-	public CorpFollowActiveCodeDto createCorpFollowActiveCode(List<String> followIds, String state, Integer type, String serviceName) throws Exception {
+	public CorpFollowActiveCodeDto createCorpFollowActiveCode(List<String> followIds, List<Integer> userIndxList, String state, Integer type, String serviceName) throws Exception {
 		CorpFollowContact c = new CorpFollowContact();
 		c.setType(type);
 		c.setScene(2);
@@ -131,6 +132,7 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 		String configId = jsonObject.getStr("config_id");
 		CorpFollowActiveCodeDto corpFollowActiveCodeDto = new CorpFollowActiveCodeDto();
 		corpFollowActiveCodeDto.setFollowIds(followIds.toString());
+		corpFollowActiveCodeDto.setUserIndxList(userIndxList.toString());
 		corpFollowActiveCodeDto.setServiceNames(serviceName);
 		corpFollowActiveCodeDto.setQrCode(qrCode);
 		corpFollowActiveCodeDto.setConfigId(configId);

+ 18 - 12
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowServiceImpl.java

@@ -19,6 +19,7 @@ import com.cyksj.service.corp.CorpFollowDynamicConfigService;
 import com.cyksj.service.corp.CorpFollowService;
 import com.cyksj.service.corp.WxCorpOps;
 import com.cyksj.service.mange.cms.CmsUserManager;
+import com.cyksj.service.sys.SysCorpServiceRelateService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
@@ -51,6 +52,8 @@ public class CorpFollowServiceImpl implements CorpFollowService {
 
 	private final RedisService redisService;
 
+	private final SysCorpServiceRelateService sysCorpServiceRelateService;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void postActiveCode(Long adminId, CorpFollowActiveCode activeCode) throws Exception {
@@ -59,11 +62,13 @@ public class CorpFollowServiceImpl implements CorpFollowService {
 			activeCode.setOperator(cmsUser.getNickname());
 		}
 		Boolean isDuty = Optional.ofNullable(activeCode.getIsDuty()).orElse(false);
-		List<String> followIds = activeCode.getFollowIds();
-		if (CollUtil.isEmpty(followIds)) {
+		List<Integer> userIndxList = activeCode.getUserIndxList();
+
+		if (CollUtil.isEmpty(userIndxList)) {
 			throw BusinessRuntimeException.getInstance("请选择对应客服");
 		}
-		activeCode.setFollowStr(Jsons.toJson(followIds));
+		activeCode.setFollowStr(Jsons.toJson(userIndxList));
+		List<String> followStrList = sysCorpServiceRelateService.getFollowIdsByRelateIds(userIndxList);
 		activeCode.setMarkTag(activeCode.getMarkTag().trim());
 		String text = activeCode.getText();
 		if (StrUtil.isNotBlank(text) && text.length() > 4000) {
@@ -83,9 +88,9 @@ public class CorpFollowServiceImpl implements CorpFollowService {
 		}
 		if (!isDuty) {
 			//生成一个活码 一个客服或多个客服
-			codeStr = corpFollowDynamicConfigService.createCorpFollowActiveCode(followIds, Constant.AC_CODE_KEY + activeCode.getId(), isDuty);
+			codeStr = corpFollowDynamicConfigService.createCorpFollowActiveCode(followStrList, userIndxList, Constant.AC_CODE_KEY + activeCode.getId(), isDuty);
 		} else {
-			codeStr = corpFollowDynamicConfigService.createCorpFollowActiveCode(followIds, Constant.AC_CODE_KEY + activeCode.getId(), isDuty);
+			codeStr = corpFollowDynamicConfigService.createCorpFollowActiveCode(followStrList, userIndxList, Constant.AC_CODE_KEY + activeCode.getId(), isDuty);
 		}
 		activeCode.setCodeStr(codeStr);
 		corpFollowActiveCodeMapper.updateById(activeCode);
@@ -102,22 +107,23 @@ public class CorpFollowServiceImpl implements CorpFollowService {
 			throw BusinessRuntimeException.getInstance("对应的数据已不存在");
 		}
 		String db_followStr = dbActiveCode.getFollowStr();
-		List<String> up_corpFollows = activeCode.getFollowIds();
-		if (CollUtil.isEmpty(up_corpFollows)) {
+		List<Integer> upUserIndxList = activeCode.getUserIndxList();
+		if (CollUtil.isEmpty(upUserIndxList)) {
 			throw BusinessRuntimeException.getInstance("请选择对应客服");
 		}
-		activeCode.setFollowStr(Jsons.toJson(up_corpFollows));
+		activeCode.setFollowStr(Jsons.toJson(upUserIndxList));
+		List<String> up_followStrList = sysCorpServiceRelateService.getFollowIdsByRelateIds(upUserIndxList);
 		if (StrUtil.isEmpty(activeCode.getMarkTag())) {
 			throw BusinessRuntimeException.getInstance("请输入标签");
 		}
-		List<String> db_followIds = Jsons.parseList(db_followStr, String.class);
+		List<Integer> db_followIds = Jsons.parseList(db_followStr, Integer.class);
 		Boolean isReCreateAcCode = false;
 		Boolean isUpdateAcCode = false;
-		if (db_followIds.size() != up_corpFollows.size()) {
+		if (db_followIds.size() != upUserIndxList.size()) {
 			isReCreateAcCode = true;
 		}
 		if (!isReCreateAcCode) {
-			for (String upFollowId : up_corpFollows) {
+			for (Integer upFollowId : upUserIndxList) {
 				if (!db_followIds.contains(upFollowId)) {
 					isReCreateAcCode = true;
 					break;
@@ -143,7 +149,7 @@ public class CorpFollowServiceImpl implements CorpFollowService {
 
 		//重新构建活码配置
 		if (isReCreateAcCode) {
-			String code_str = corpFollowDynamicConfigService.createCorpFollowActiveCode(up_corpFollows, Constant.AC_CODE_KEY + activeCode.getId(), up_isDuty);
+			String code_str = corpFollowDynamicConfigService.createCorpFollowActiveCode(up_followStrList, upUserIndxList, Constant.AC_CODE_KEY + activeCode.getId(), up_isDuty);
 			activeCode.setCodeStr(code_str);
 			Set<String> keys = redisService.keys(RedisService.key.CORP_FOLLOW_ACTIVE_CODE_KEY.getNameFormat(activeCode.getId(), "*"));
 			redisService.del(keys.toArray(String[]::new));

+ 12 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpTagServiceImpl.java

@@ -24,6 +24,8 @@ import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -422,11 +424,20 @@ public class CorpTagServiceImpl implements CorpTagService {
 	public UserOrderDetailView getTagUserData(Integer start, Integer limit, String tagIdStr, String startTime, String endTime) {
 		UserOrderDetailView u = orderDonMapper.getTagUserData(tagIdStr, startTime, endTime);
 
-		u.setNumOfUser(corpUserTagMapper.countTagUser(tagIdStr, startTime, endTime));
+		UserOrderDetailView u2 = corpUserTagMapper.countTagUser(tagIdStr, startTime, endTime);
 
+		u.setNumOfUser(u2.getNumOfUser());
+		u.setDelNumOfUser(u2.getDelNumOfUser());
+		u.setOrderRate(u.getNumOfUser() == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(u.getNumOfEpOrder()).divide(BigDecimal.valueOf(u.getNumOfUser()), 2, RoundingMode.HALF_DOWN));
 		Page<UserOrderDetailView> records = orderDonMapper.getTagUserDataPage(new Page<>(start, limit), tagIdStr, startTime, endTime);
 
 		u.setRecords(records);
 		return u;
 	}
+
+	@Override
+	public Page<CorpTagUserOrderDataView> getTagUserTimeOrderData(Integer start, Integer limit, String tagIdStr, String toDate, String startTime, String endTime) {
+		Page<CorpTagUserOrderDataView> records = orderDonMapper.getTagUserTimeOrderData(new Page<>(start, limit), tagIdStr, toDate, startTime, endTime);
+		return records;
+	}
 }

+ 6 - 1
netflix-service/src/main/java/com/cyksj/service/sys/SysConfigChangeRecordService.java

@@ -1,8 +1,11 @@
 package com.cyksj.service.sys;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.dto.SysServiceChangeDto;
 import com.cyksj.model.entity.SysConfigChangeRecord;
 
+import java.util.List;
+
 /**
  * 项目名: yhlxj
  * 文件名: SysConfigChangeRecordService
@@ -10,5 +13,7 @@ import com.cyksj.model.entity.SysConfigChangeRecord;
  * 创建时间:2023/11/24 10:44
  */
 public interface SysConfigChangeRecordService extends IService<SysConfigChangeRecord> {
-	Boolean changeRecord(Long adminId, String sysKey, String sysValue, String updateValue) throws Exception;
+	SysServiceChangeDto changeRecord(Long adminId, String sysKey, String sysValue, String updateValue) throws Exception;
+
+	void updateCorpFollowLinkConfig(List<Integer> updateFollowIndx) throws Exception;
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/sys/SysConfigService.java

@@ -17,5 +17,5 @@ public interface SysConfigService extends IService<SysConfig> {
 	 */
 	String getDefaultShopConfigByType(String type);
 
-	List<String> getDutyServices() throws Exception;
+	List<Integer> getDutyServices() throws Exception;
 }

+ 24 - 0
netflix-service/src/main/java/com/cyksj/service/sys/SysCorpServiceRelateService.java

@@ -0,0 +1,24 @@
+package com.cyksj.service.sys;
+
+import com.cyksj.model.dto.CorpFollowServiceDto;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: SysCorpServiceRelateService
+ * 创建者: JavaZou
+ * 创建时间:2024/1/11 12:07
+ */
+public interface SysCorpServiceRelateService {
+
+	List<String> getFollowIdsByRelateIds(List<Integer> indxIds) throws Exception;
+
+	List<String> getFollowIdsByRelateIds(List<Integer> indxIds, Map<Integer, List<CorpFollowServiceDto>> corpYhFollowService) throws Exception;
+
+	/**
+	 * 获取客服对照关系
+	 */
+	Map<Integer, List<CorpFollowServiceDto>> getCorpYhFollowService() throws Exception;
+}

+ 99 - 5
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigChangeRecordServiceImpl.java

@@ -9,14 +9,25 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.SmsUtil;
 import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkMapper;
+import com.cyksj.mapper.corp.CorpFollowActiveCodeMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.sys.SysConfigChangeRecordMapper;
-import com.cyksj.model.dto.YhServiceChangeDto;
-import com.cyksj.model.dto.YhServiceDto;
+import com.cyksj.model.dto.*;
 import com.cyksj.model.entity.CmsUser;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+import com.cyksj.model.entity.CorpFollowActiveCode;
 import com.cyksj.model.entity.SysConfigChangeRecord;
+import com.cyksj.model.request.corp.link.Range;
+import com.cyksj.model.request.corp.link.WxCpLinkAddResp;
+import com.cyksj.model.request.corp.link.WxCpLinkUpd;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.corp.CorpFollowDynamicConfigService;
+import com.cyksj.service.corp.WxCorpOps;
 import com.cyksj.service.sys.SysConfigChangeRecordService;
+import com.cyksj.service.sys.SysCorpServiceRelateService;
+import com.cyksj.xxljob.XxlJobInfo;
+import com.cyksj.xxljob.XxlJobUtil;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
@@ -25,6 +36,8 @@ import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
@@ -43,12 +56,23 @@ public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChang
 
 	private final RedisService redisService;
 
+	private final CorpFollowActiveCodeMapper corpFollowActiveCodeMapper;
+
+	private final CorpFollowDynamicConfigService corpFollowDynamicConfigService;
+
+	private final SysCorpServiceRelateService sysCorpServiceRelateService;
+
+	private final CorpCustomerAcquisitionLinkMapper corpCustomerAcquisitionLinkMapper;
+
+	private final WxCorpOps corpOps;
+
 	@Override
-	public Boolean changeRecord(Long adminId, String sysKey, String sysValue, String updateValue) throws Exception {
+	public SysServiceChangeDto changeRecord(Long adminId, String sysKey, String sysValue, String updateValue) throws Exception {
 		CmsUser cmsUser = cmsUserMapper.selectById(adminId);
 		if (cmsUser == null) {
 			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
 		}
+		SysServiceChangeDto sysServiceChangeDto = new SysServiceChangeDto();
 		//保存客服系统配置key前后更新数据
 		if (Constant.serviceKeys.contains(sysKey)) {
 			if (!StrUtil.equals(sysValue, updateValue)) {
@@ -57,6 +81,8 @@ public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChang
 				sysConfigChangeRecord.setPreValue(sysValue);
 				sysConfigChangeRecord.setBackValue(updateValue);
 				sysConfigChangeRecord.setOperator(cmsUser.getNickname());
+
+				List<Integer> updateFollowIndxList = new ArrayList<>();
 				if (Constant.serviceKeys.get(0).equals(sysKey)) {
 					//变更记录
 					List<YhServiceDto> before = Jsons.parseList(sysValue, YhServiceDto.class);
@@ -106,12 +132,28 @@ public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChang
 							SmsUtil.sendLuoKey2Msg(Constant.DUTY_SERVICE_CHANGE_NOTIFY_PHONE, String.format(Constant.DUTY_SERVICE_CHANGE_MSG, weekdayMsgNotifySb));
 						}
 					}
+					sysServiceChangeDto.setChangeCsImg(true);
+				} else {
+					List<YhServiceNameDto> before = Jsons.parseList(sysValue, YhServiceNameDto.class);
+					Map<Integer, List<YhServiceNameDto>> afterIndxMap = Jsons.parseList(updateValue, YhServiceNameDto.class).stream().collect(Collectors.groupingBy(YhServiceNameDto::getIndx));
+					before.forEach(e1 -> {
+						List<YhServiceNameDto> serviceNameDtos = afterIndxMap.get(e1.getIndx());
+						if (CollUtil.isNotEmpty(serviceNameDtos)) {
+							YhServiceNameDto e2 = serviceNameDtos.get(0);
+							if (e1.getIndx() == e2.getIndx() && !StrUtil.equals(e1.getFollowId(), e2.getFollowId())) {
+								updateFollowIndxList.add(e1.getIndx());
+							}
+						}
+					});
+					if (CollUtil.isNotEmpty(updateFollowIndxList)) {
+						sysServiceChangeDto.setChangeCsName(true);
+						sysServiceChangeDto.setUpdateFollowIndxs(updateFollowIndxList);
+					}
 				}
 				this.save(sysConfigChangeRecord);
-				return true;
 			}
 		}
-		return false;
+		return sysServiceChangeDto;
 	}
 
 
@@ -152,4 +194,56 @@ public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChang
 		}
 		return null;
 	}
+
+	@Override
+	public void updateCorpFollowLinkConfig(List<Integer> updateFollowIndx) throws Exception {
+		List<CorpFollowActiveCode> corpFollowActiveCodes = corpFollowActiveCodeMapper.selectActiveCodeByFollowIndx(updateFollowIndx);
+		Map<Integer, List<CorpFollowServiceDto>> corpYhFollowService = sysCorpServiceRelateService.getCorpYhFollowService();
+		//去更新活码对应客服 成员id
+		corpFollowActiveCodes.forEach(data -> {
+			try {
+				List<Integer> upUserIndxList = Jsons.parseList(data.getFollowStr(), Integer.class);
+				List<String> up_followStrList = sysCorpServiceRelateService.getFollowIdsByRelateIds(upUserIndxList, corpYhFollowService);
+				String code_str = corpFollowDynamicConfigService.createCorpFollowActiveCode(up_followStrList, upUserIndxList, Constant.AC_CODE_KEY + data.getId(), data.getIsDuty());
+				data.setCodeStr(code_str);
+				Set<String> keys = redisService.keys(RedisService.key.CORP_FOLLOW_ACTIVE_CODE_KEY.getNameFormat(data.getId(), "*"));
+				redisService.del(keys.toArray(String[]::new));
+				corpFollowActiveCodeMapper.updateById(data);
+			} catch (Exception e) {
+			}
+		});
+
+		//去更新获客链接 成员id
+		List<CorpCustomerAcquisitionLink> acquisitionLinks = corpCustomerAcquisitionLinkMapper.selectActiveCodeByFollowIndx(updateFollowIndx);
+		AtomicBoolean isDutyTask = new AtomicBoolean(false);
+		acquisitionLinks.forEach(link -> {
+			try {
+				WxCpLinkUpd wxCpLinkUpd = new WxCpLinkUpd();
+				wxCpLinkUpd.setLinkName(link.getLinkName());
+				wxCpLinkUpd.setLinkId(link.getLinkId());
+				wxCpLinkUpd.setSkipVerify(link.getSkipVerify());
+				Range range = new Range();
+				//值班客服
+				String userList;
+				if (link.getIsDuty()) {
+					userList = link.getChooseDutyUsers();
+				} else {
+					userList = link.getUserList();
+				}
+				List<String> followIds = sysCorpServiceRelateService.getFollowIdsByRelateIds(Jsons.parseList(userList, Integer.class), corpYhFollowService);
+				range.setUserList(followIds);
+				wxCpLinkUpd.setRange(range);
+				WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionUpdateLink(null, wxCpLinkUpd);
+
+				corpCustomerAcquisitionLinkMapper.updateById(link);
+
+			} catch (Exception e) {
+
+			}
+		});
+		if (isDutyTask.get()) {
+			//立即执行客服值班定时任务
+			XxlJobUtil.executeMarkDynamicRuleTagJob(XxlJobInfo.getExecuteTaskInstance(Constant.CORP_LINK_JOB_ID, StrUtil.EMPTY).toString());
+		}
+	}
 }

+ 5 - 7
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigServiceImpl.java

@@ -61,7 +61,7 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper,SysConfig>
 
 
 	@Override
-	public List<String> getDutyServices() throws Exception {
+	public List<Integer> getDutyServices() throws Exception {
 		SysConfig sysConfig = this.getOne(Wrappers.lambdaQuery(SysConfig.class)
 				.eq(SysConfig::getSysKey, Constant.serviceKeys.get(0))
 				.last("limit 1"));
@@ -91,13 +91,11 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper,SysConfig>
 			}
 		}
 		LocalDateTime now = LocalDateTime.now();
-		List<String> dutyServices = getDutyServices(workdayServices, saturdayServices, sundayServices, holidayDateMap, now);
+		List<Integer> dutyServices = getDutyServices(workdayServices, saturdayServices, sundayServices, holidayDateMap, now);
 		return dutyServices;
 	}
 
-
-
-	public List<String> getDutyServices(List<YhServiceDto> workday, List<YhServiceDto> saturday, List<YhServiceDto> sunday, Map<String, List<YhServiceDto>> holidayDateMap, LocalDateTime now) {
+	public List<Integer> getDutyServices(List<YhServiceDto> workday, List<YhServiceDto> saturday, List<YhServiceDto> sunday, Map<String, List<YhServiceDto>> holidayDateMap, LocalDateTime now) {
 		if (CollUtil.isNotEmpty(workday)) {
 			DayOfWeek currentDayOfWeek = now.getDayOfWeek();
 
@@ -105,9 +103,9 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper,SysConfig>
 			//获取值班客服
 			List<YhServiceDto> dutyServiceCodes = getTimeDutyServices(carryServices, workday, saturday, sunday, holidayDateMap, currentDayOfWeek, now);
 			if (CollUtil.isNotEmpty(dutyServiceCodes)) {
-				Set<String> collectFollow = new HashSet<>();
+				Set<Integer> collectFollow = new HashSet<>();
 				for (YhServiceDto dutyServiceCode : dutyServiceCodes) {
-					dutyServiceCode.getSelect().stream().filter(e -> StrUtil.isNotBlank(e.getFollowId())).forEach(cs -> collectFollow.add(cs.getFollowId()));
+					dutyServiceCode.getSelect().stream().filter(e -> e.getIndex() != null).forEach(cs -> collectFollow.add(cs.getIndex()));
 				}
 				return new ArrayList<>(collectFollow);
 			}

+ 69 - 0
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpServiceRelateServiceImpl.java

@@ -0,0 +1,69 @@
+package com.cyksj.service.sys.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.sys.SysConfigMapper;
+import com.cyksj.model.dto.CorpFollowServiceDto;
+import com.cyksj.model.entity.SysConfig;
+import com.cyksj.service.sys.SysCorpServiceRelateService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: SysCorpServiceRelateServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/1/11 12:07
+ */
+@Service
+@RequiredArgsConstructor
+public class SysCorpServiceRelateServiceImpl implements SysCorpServiceRelateService {
+	private final SysConfigMapper sysConfigMapper;
+
+
+	@Override
+	public List<String> getFollowIdsByRelateIds(List<Integer> indxIds) throws Exception {
+		//值班客服
+		Map<Integer, List<CorpFollowServiceDto>> corpYhFollowService = this.getCorpYhFollowService();
+		return getFollowIdsByIndxs(indxIds, corpYhFollowService);
+	}
+
+	@Override
+	public List<String> getFollowIdsByRelateIds(List<Integer> indxIds, Map<Integer, List<CorpFollowServiceDto>> corpYhFollowService) throws Exception {
+		return getFollowIdsByIndxs(indxIds, corpYhFollowService);
+	}
+
+
+	@Override
+	public Map<Integer, List<CorpFollowServiceDto>> getCorpYhFollowService() throws Exception {
+		SysConfig config = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.serviceKeys.get(1)).last("limit 1"));
+		if (config == null || StrUtil.isEmpty(config.getSysValue())) {
+			throw BusinessRuntimeException.getInstance("未配置对应系统值班客服");
+		}
+		String sysValue = config.getSysValue();
+		List<CorpFollowServiceDto> corpFollowServiceDtos = Jsons.parseList(sysValue, CorpFollowServiceDto.class);
+		return corpFollowServiceDtos.stream().collect(Collectors.groupingBy(CorpFollowServiceDto::getIndx));
+	}
+
+	private List<String> getFollowIdsByIndxs(List<Integer> indxIds, Map<Integer, List<CorpFollowServiceDto>> corpYhFollowService) {
+		List<String> followIds = new ArrayList<>();
+		indxIds.forEach(indx -> {
+			List<CorpFollowServiceDto> corpFollowServiceDtos = corpYhFollowService.get(indx);
+			if (CollUtil.isEmpty(corpFollowServiceDtos)) {
+				throw BusinessRuntimeException.getInstance("存在被删除的值班客服");
+			}
+			followIds.add(corpFollowServiceDtos.get(0).getFollowId());
+		});
+		return followIds;
+	}
+}

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CmsCorpFollowActiveCodeController.java

@@ -153,7 +153,7 @@ public class CmsCorpFollowActiveCodeController {
 			Integer orderNum = orderDonMapper.selectCountActiveCodeOrderByAcId(data.getId());
 			data.setOrderNum(orderNum);
 			try {
-				data.setFollowIds(Jsons.parseList(data.getFollowStr(), String.class));
+				data.setUserIndxList(Jsons.parseList(data.getFollowStr(), Integer.class));
 				if (StrUtil.isNotBlank(data.getAttachmentsStr())) {
 					data.setAttachments(Jsons.parseList(data.getAttachmentsStr(), Attachments.class));
 				}

+ 14 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkController.java

@@ -88,11 +88,23 @@ public class CorpCustomerAcquistionLinkController {
 
         search.getDataList().forEach(e->{
             try {
-                List<String> userStrList = corpFollowServiceDtos.stream().filter(cf -> e.getUserList().contains(cf.getFollowId())).map(CorpFollowServiceDto::getName).collect(Collectors.toList());
+                List<String> userStrList = corpFollowServiceDtos.stream().filter(cf -> {
+                    try {
+                        return Jsons.parseList(e.getUserList(), Integer.class).contains(cf.getIndx());
+                    } catch (Exception ex) {
+                    }
+                    return false;
+                }).map(CorpFollowServiceDto::getName).collect(Collectors.toList());
                 e.setUserStrList(userStrList);
 
                 if (StrUtil.isNotEmpty(e.getChooseDutyUsers())) {
-                    List<String> dutyUserList = corpFollowServiceDtos.stream().filter(cf -> e.getChooseDutyUsers().contains(cf.getFollowId())).map(CorpFollowServiceDto::getName).collect(Collectors.toList());
+                    List<String> dutyUserList = corpFollowServiceDtos.stream().filter(cf -> {
+                        try {
+                            return Jsons.parseList(e.getChooseDutyUsers(), Integer.class).contains(cf.getIndx());
+                        } catch (Exception ex) {
+                        }
+                        return false;
+                    }).map(CorpFollowServiceDto::getName).collect(Collectors.toList());
 
                     e.setChooseDutyUserList(dutyUserList);
                 }

+ 5 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpMsgBulkTaskController.java

@@ -16,6 +16,7 @@ import com.cyksj.mapper.manage.coupon.CouponMapper;
 import com.cyksj.model.dto.CornMetaDto;
 import com.cyksj.model.entity.CorpMsgBulkTask;
 import com.cyksj.model.entity.CorpMsgBulkTaskCategory;
+import com.cyksj.model.entity.CorpMsgBulkTaskRecord;
 import com.cyksj.model.entity.CorpTag;
 import com.cyksj.model.excel.ExcelCorpMsgBulkTaskSendRecordData;
 import com.cyksj.model.request.CorpActiveBulkMsg;
@@ -186,6 +187,10 @@ public class CorpMsgBulkTaskController {
 		SearchResult<CorpMsgBulkTaskSendRecordView> search = beanSearcher.search(CorpMsgBulkTaskSendRecordView.class, builder
 				.orderBy(CorpMsgBulkTaskSendRecordView::getCreateTime).desc()
 				.build());
+		search.getDataList().forEach(e -> {
+			e.setTotal(beanSearcher.searchSum(CorpMsgBulkTaskRecord.class, MapUtils.builder().field(CorpMsgBulkTaskRecord::getSendId, e.getSenId()).build(), "total").intValue());
+			e.setNotSend(e.getTotal() - e.getSend());
+		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 

+ 11 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpTagController.java

@@ -120,8 +120,8 @@ public class CorpTagController {
 	 * 标签管理详情
 	 */
 	@GetMapping("/get/corpTag")
-	public Result<Page<CorpTagBackView>> getCorpTagBackView(@RequestParam(defaultValue = "0") Integer start, @RequestParam(defaultValue = "10") Integer limit, @RequestParam(required = false, defaultValue = "1") Integer type, String name,  String[] groupIds, String sort, String order) throws Exception {
-		Page<CorpTagBackView> corpTagBackViews = corpTagService.getCorpTagBackView(start, limit, type, name,groupIds, sort, order);
+	public Result<Page<CorpTagBackView>> getCorpTagBackView(@RequestParam(defaultValue = "0") Integer start, @RequestParam(defaultValue = "10") Integer limit, @RequestParam(required = false, defaultValue = "1") Integer type, String name, String[] groupIds, String sort, String order) throws Exception {
+		Page<CorpTagBackView> corpTagBackViews = corpTagService.getCorpTagBackView(start, limit, type, name, groupIds, sort, order);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(corpTagBackViews);
 	}
 
@@ -178,4 +178,13 @@ public class CorpTagController {
 		UserOrderDetailView userOrderDetailView = corpTagService.getTagUserData(start, limit, tagIdStr, startTime, endTime);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(userOrderDetailView);
 	}
+
+	/**
+	 * 标签用户订单详情
+	 */
+	@GetMapping("/get/tagUser/time/orderData")
+	public Result<Page<CorpTagUserOrderDataView>> getTagUserTimeOrderData(@RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "10") Integer limit, @RequestParam(required = true) String tagIdStr, String toDate, String startTime, String endTime) {
+		Page<CorpTagUserOrderDataView> page = corpTagService.getTagUserTimeOrderData(start, limit, tagIdStr, toDate, startTime, endTime);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(page);
+	}
 }

+ 7 - 2
netflix-web/src/main/java/com/cyksj/web/controller/sys/SysConfigController.java

@@ -15,6 +15,7 @@ import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.manage.help.HelpQuestionClassificationMapper;
 import com.cyksj.mapper.manage.help.HelpQuestionMapper;
 import com.cyksj.model.dto.EquipmentConfigDto;
+import com.cyksj.model.dto.SysServiceChangeDto;
 import com.cyksj.model.entity.HelpQuestion;
 import com.cyksj.model.entity.HelpQuestionClassification;
 import com.cyksj.model.entity.SysConfig;
@@ -100,15 +101,19 @@ public class SysConfigController {
 			}
 		}
 
-		Boolean isChanged = sysConfigChangeRecordService.changeRecord(adminId, sysConfig.getSysKey(), byId.getSysValue(), sysConfig.getSysValue());
+		SysServiceChangeDto changeRecord = sysConfigChangeRecordService.changeRecord(adminId, sysConfig.getSysKey(), byId.getSysValue(), sysConfig.getSysValue());
 
 		sysConfigService.updateById(sysConfig);
 
-		if (isChanged) {
+		if (changeRecord.getChangeCsImg()) {
 			//立即执行客服值班定时任务
 			XxlJobUtil.executeMarkDynamicRuleTagJob(XxlJobInfo.getExecuteTaskInstance(Constant.CORP_LINK_JOB_ID, StrUtil.EMPTY).toString());
 		}
 
+		if (changeRecord.getChangeCsName()) {
+			sysConfigChangeRecordService.updateCorpFollowLinkConfig(changeRecord.getUpdateFollowIndxs());
+		}
+
 		return GatewayResponse.SUCCESS.newBuilder().toResult(sysConfig);
 	}
 

+ 12 - 6
netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java

@@ -40,9 +40,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /*
@@ -274,15 +272,23 @@ public class DistributePopularizeController {
 	 */
 	@GetMapping("/get/general/distribute/detail")
 	public Result<DistributePopularizeView> getGeneralDistributeDetail() {
-		Long userId = StpUserUtil.getLoginIdAsLong();
-		List<GoodsDon> goodsDons = goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getDeleted, true).gt(GoodsDon::getRate, 0).orderByAsc(GoodsDon::getRate).select(GoodsDon::getRate, GoodsDon::getTitle));
+		List<GoodsDon> goodsDons = goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getDeleted, true).eq(GoodsDon::getStatus, true).eq(GoodsDon::getType, 1).orderByAsc(GoodsDon::getRate).select(GoodsDon::getRate, GoodsDon::getTitle));
 		if (goodsDons.isEmpty()) {
 			return GatewayResponse.SUCCESS.newBuilder().toResult();
 		}
 		DistributePopularizeView distributePopularizeView = new DistributePopularizeView();
 		GoodsDon highestRateGoods = goodsDons.get(goodsDons.size() - 1);
 		distributePopularizeView.setHighestRate(highestRateGoods.getRate());
-		List<GoodsDon> generalDistributes = goodsDons.stream().filter(gd -> !gd.getRate().equals(highestRateGoods.getRate())).collect(Collectors.toList());
+		Map<Integer, List<GoodsDon>> rateMap = goodsDons.stream().filter(gd -> !gd.getRate().equals(highestRateGoods.getRate())).collect(Collectors.groupingBy(GoodsDon::getRate));
+		List<DistributeGoodsGeneralRateView> generalDistributes = new ArrayList<>();
+		rateMap.forEach((rate, v) -> {
+			DistributeGoodsGeneralRateView rateView = new DistributeGoodsGeneralRateView();
+			rateView.setRate(rate);
+			String goodsInfo = v.stream().map(GoodsDon::getTitle).collect(Collectors.joining("/"));
+			rateView.setGoodsInfo(goodsInfo);
+			generalDistributes.add(rateView);
+		});
+		generalDistributes.sort(Comparator.comparing(DistributeGoodsGeneralRateView::getRate).reversed());
 		distributePopularizeView.setGeneralDistributes(generalDistributes);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(distributePopularizeView);
 	}