Răsfoiți Sursa

系统客服改版

zoujiajian 2 ani în urmă
părinte
comite
2f5c0ec5d4
32 a modificat fișierele cu 703 adăugiri și 124 ștergeri
  1. 19 0
      netflix-common/src/main/java/com/cyksj/common/util/StringUtil.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/SysCorpFollowMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/SysCorpFollowRelateMapper.java
  4. 1 1
      netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java
  5. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpUserFollowRelationMapper.java
  6. 2 0
      netflix-dao/src/main/java/com/cyksj/model/dto/CorpFollowServiceDto.java
  7. 2 0
      netflix-dao/src/main/java/com/cyksj/model/dto/YhServiceDto.java
  8. 2 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpCustomerAcquisitionLinkExtraCustomer.java
  9. 18 0
      netflix-dao/src/main/java/com/cyksj/model/entity/SysCorpFollow.java
  10. 29 0
      netflix-dao/src/main/java/com/cyksj/model/entity/SysCorpFollowRelate.java
  11. 40 0
      netflix-dao/src/main/java/com/cyksj/model/request/sys/SysCorpFollowReq.java
  12. 1 1
      netflix-dao/src/main/java/com/cyksj/model/views/CorpCustomerAcquisitionLinkExtraCustomerView.java
  13. 92 0
      netflix-dao/src/main/java/com/cyksj/model/views/SysCorpFollowView.java
  14. 24 0
      netflix-dao/src/main/java/com/cyksj/model/views/SysCorpMasterFollowView.java
  15. 1 1
      netflix-dao/src/main/resources/mapper/CorpCustomerAcquisitionLinkMapper.xml
  16. 4 0
      netflix-dao/src/main/resources/mapper/CorpUserFollowRelationMapper.xml
  17. 3 9
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java
  18. 1 5
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquistionServiceImpl.java
  19. 68 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java
  20. 10 16
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowDynamicConfigServiceImpl.java
  21. 18 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java
  22. 2 0
      netflix-service/src/main/java/com/cyksj/service/corp/msg/CorpEventActionService.java
  23. 17 0
      netflix-service/src/main/java/com/cyksj/service/sys/SysCorpFollowService.java
  24. 0 10
      netflix-service/src/main/java/com/cyksj/service/sys/SysCorpServiceRelateService.java
  25. 10 4
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigChangeRecordServiceImpl.java
  26. 21 1
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigServiceImpl.java
  27. 143 0
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpFollowServiceImpl.java
  28. 6 41
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpServiceRelateServiceImpl.java
  29. 14 5
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  30. 3 14
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CmsCorpFollowActiveCodeController.java
  31. 21 16
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkController.java
  32. 103 0
      netflix-web/src/main/java/com/cyksj/web/controller/sys/SysCorpFollowController.java

+ 19 - 0
netflix-common/src/main/java/com/cyksj/common/util/StringUtil.java

@@ -571,4 +571,23 @@ public final class StringUtil {
 		}
 		return StrUtil.EMPTY;
 	}
+
+	public static <T> List<List<T>> averageAssign(List<T> source, int n) {
+		List<List<T>> result = new ArrayList<List<T>>();
+		int remainder = source.size() % n;  //(先计算出余数)
+		int number = source.size() / n;  //然后是商
+		int offset = 0;//偏移量
+		for (int i = 0; i < n; i++) {
+			List<T> value = null;
+			if (remainder > 0) {
+				value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
+				remainder--;
+				offset++;
+			} else {
+				value = source.subList(i * number + offset, (i + 1) * number + offset);
+			}
+			result.add(value);
+		}
+		return result;
+	}
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/SysCorpFollowMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.SysCorpFollow;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:53
+ */
+public interface SysCorpFollowMapper extends BaseMapper<SysCorpFollow> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/SysCorpFollowRelateMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.SysCorpFollowRelate;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowRelateMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:54
+ */
+public interface SysCorpFollowRelateMapper extends BaseMapper<SysCorpFollowRelate> {
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java

@@ -31,7 +31,7 @@ public interface UserMapper extends BaseMapper<User> {
     @Update("update user set active_points = active_points - #{subPoints} where active_points > 0 and active_points >= #{subPoints} and id = #{userId}")
     Integer subActivePoints(@Param("userId") Long userId, @Param("subPoints") BigDecimal subPoints);
 
-    @Select("select id from user where nickname like concat(#{nickname},'%')")
+    @Select("select id from user where nickname like concat('%',#{nickname},'%')")
     List<Long> selectListByNickname(String nickname);
 
     @Update("update user set points = points - #{deductPoints} where id = #{id} and points = #{originalPoints}")

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

@@ -23,4 +23,6 @@ public interface CorpUserFollowRelationMapper extends BaseMapper<CorpUserFollowR
 	List<CorpUserFollowRelationDto> selectCorpUserNotUnderTagIds(@Param("list") List<String> tagIds, @Param("wxCorpId") Long wxCorpId, @Param("followIds") List<String> followIds, @Param("userScope") Integer userScope, @Param("consumerScope") Integer consumerScope, @Param("joinStartTime") Date joinStartTime, @Param("joinEndTime") Date joinEndTime);
 
 	CorpUserFollowRelation getCorpUserFollowRelation(@Param("unionId") String unionId, @Param("followId") String followId);
+
+	Integer selectNumOfCorpuserByFollowId(String followId);
 }

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/CorpFollowServiceDto.java

@@ -18,4 +18,6 @@ public class CorpFollowServiceDto {
 	private Integer indx;
 
 	private String followId;
+
+	private String img;
 }

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/YhServiceDto.java

@@ -55,6 +55,8 @@ public class YhServiceDto {
 		private String url;
 
 		private String followId;
+
+		private Integer status;
 	}
 
 	public Boolean isBetween(LocalTime currentTime) {

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpCustomerAcquisitionLinkExtraCustomer.java

@@ -20,6 +20,8 @@ public class CorpCustomerAcquisitionLinkExtraCustomer extends BaseEntity{
 	@NotNull
 	private Integer serviceId;
 
+	private String followId;
+
 	/**
 	 * 值班日期
 	 */

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/SysCorpFollow.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollow
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:51
+ */
+@Getter
+@Setter
+public class SysCorpFollow extends BaseEntity{
+	private String name;
+
+	private Boolean deleted;
+}

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/SysCorpFollowRelate.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowRelate
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:52
+ */
+@Getter
+@Setter
+public class SysCorpFollowRelate extends BaseEntity{
+	private Long mid;
+
+	private String name;
+
+	private String followId;
+
+	/**
+	 * 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业
+	 */
+	private Integer status;
+
+	private String img;
+
+	private Boolean deleted;
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/request/sys/SysCorpFollowReq.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.request.sys;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowReq
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:55
+ */
+@Getter
+@Setter
+public class SysCorpFollowReq {
+	private Long mid;
+
+	/**
+	 * 客服名
+	 */
+	private String name;
+
+	/**
+	 * 子账号id
+	 */
+	private Long sid;
+
+	/**
+	 * 企业客服名
+	 */
+	private String followName;
+
+	/**
+	 * 企业客服id
+	 */
+	private String followId;
+
+	private Integer status;
+
+	private String img;
+}

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

@@ -29,7 +29,7 @@ public class CorpCustomerAcquisitionLinkExtraCustomerView {
 	private String linkName;
 
 	@DbField("cc.service_id")
-	private Integer serviceId;
+	private Long serviceId;
 
 	@DbField("cc.duty_date")
 	private String dutyDate;

+ 92 - 0
netflix-dao/src/main/java/com/cyksj/model/views/SysCorpFollowView.java

@@ -0,0 +1,92 @@
+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;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 12:02
+ */
+@Getter
+@Setter
+@SearchBean(tables = "sys_corp_follow sf left join sys_corp_follow_relate sfr on sf.id = sfr.mid",
+		where = "sf.deleted is true and sfr.deleted is true",
+		orderBy = "sf.id,sfr.update_time desc")
+public class SysCorpFollowView {
+	@DbField("sf.id")
+	private Long mid;
+
+	@DbField("sf.name")
+	private String name;
+
+	@DbField("sfr.id")
+	private Long sid;
+
+	@DbField("sfr.name")
+	private String followName;
+
+	@DbField("sfr.follow_id")
+	private String followId;
+
+	@DbField("sfr.img")
+	private String img;
+
+	/**
+	 * 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业
+	 */
+	@DbField("sfr.status")
+	private Integer status;
+
+	@DbField("sfr.update_time")
+	private Date updateTime;
+
+	@DbIgnore
+	private Integer numOfCorpUser;
+
+	@DbIgnore
+	List<SysCorpFollowRelateView> subList;
+
+	public String getShowName() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(name).append("(").append(followName).append(")");
+		return sb.toString();
+	}
+
+
+	@Getter
+	@Setter
+	@SearchBean(tables = "sys_corp_follow_relate sfr",
+			where = "sfr.deleted is true"
+			, orderBy = "sfr.update_time desc")
+	public class SysCorpFollowRelateView {
+
+		@DbField("sfr.id")
+		private Long sid;
+
+		@DbField("sfr.mid")
+		private Long mid;
+
+		@DbField("sfr.name")
+		private String followName;
+
+		@DbField("sfr.follow_id")
+		private String followId;
+
+		@DbField("sfr.img")
+		private String img;
+
+		/**
+		 * 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业
+		 */
+		@DbField("sfr.status")
+		private Integer status;
+	}
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/views/SysCorpMasterFollowView.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpMasterFollowView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/19 11:20
+ */
+@Getter
+@Setter
+@SearchBean(tables = "sys_corp_follow sf",
+		where = "sf.deleted is true")
+public class SysCorpMasterFollowView {
+	@DbField("sf.id")
+	private Long mid;
+
+	@DbField("sf.name")
+	private String name;
+}

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

@@ -8,7 +8,7 @@
         from corp_customer_acquisition_link
         where user_list != '[]' and
         <foreach collection="list" item="item" open="(" separator="OR" close=")">
-            JSON_CONTAINS(user_list, '${item}')
+            JSON_CONTAINS(user_list, '"${item}"')
         </foreach>
     </select>
 

+ 4 - 0
netflix-dao/src/main/resources/mapper/CorpUserFollowRelationMapper.xml

@@ -137,4 +137,8 @@
                  inner join corp_user_follow_relation cufr on cufr.corp_user_id = ca.external_userid
         where cufr.follow_id = #{followId} limit 1
     </select>
+
+    <select id="selectNumOfCorpuserByFollowId" resultType="java.lang.Integer">
+        select count(distinct corp_user_id) from corp_user_follow_relation cufr where cufr.follow_id = #{followId} and status = 1
+    </select>
 </mapper>

+ 3 - 9
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java

@@ -70,7 +70,6 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
     @Transactional(rollbackFor = Throwable.class)
     public void up(CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception {
         CorpCustomerAcquisitionLink link = getById(corpCustomerAcquisitionLink.getId());
-        String oldUserList = link.getUserList();
         link.setLinkName(corpCustomerAcquisitionLink.getLinkName());
         link.setUserList(corpCustomerAcquisitionLink.getUserList());
 
@@ -79,12 +78,7 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
         wxCpLinkUpd.setLinkId(corpCustomerAcquisitionLink.getLinkId());
         wxCpLinkUpd.setSkipVerify(corpCustomerAcquisitionLink.getSkipVerify());
         Range range = new Range();
-        String userList;
-        if (corpCustomerAcquisitionLink.getIsDuty()) {
-            userList = corpCustomerAcquisitionLink.getChooseDutyUsers();
-        } else {
-            userList = corpCustomerAcquisitionLink.getUserList();
-        }
+        String userList = corpCustomerAcquisitionLink.getUserList();
         //值班客服
         List<String> followIds = sysCorpServiceRelateService.getFollowIdsByRelateIds(Jsons.parseList(userList, Integer.class));
         range.setUserList(followIds);
@@ -98,13 +92,13 @@ 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())) {
+        } else {
             corpCustomerAcquisitionLink.setChooseDutyUsers(corpCustomerAcquisitionLink.getUserList());
         }
 
         this.updateById(corpCustomerAcquisitionLink);
 
-        if (corpCustomerAcquisitionLink.getIsDuty() != null && corpCustomerAcquisitionLink.getIsDuty() && !StrUtil.equals(oldUserList, corpCustomerAcquisitionLink.getUserList())) {
+        if (corpCustomerAcquisitionLink.getIsDuty() != null && corpCustomerAcquisitionLink.getIsDuty()) {
             handleCorpLinkSchedulerJob();
         }
     }

+ 1 - 5
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquistionServiceImpl.java

@@ -55,8 +55,6 @@ public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistion
         CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectById(linkId);
         Long customerAcquistionLinkId = corpCustomerAcquisitionLinkPopularize.getCustomerAcquistionLinkId();
         CorpCustomerAcquisitionLink corpCustomerAcquisitionLink = corpCustomerAcquisitionLinkMapper.selectById(customerAcquistionLinkId);
-        //更新值班获客链接
-        resetAcLinkConfigIfDuty(corpCustomerAcquisitionLink);
         return corpCustomerAcquisitionLink.getUrl();
     }
 
@@ -83,7 +81,6 @@ public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistion
     @Override
     public String getActiveCustomerAcquistionById(Long acLinkId) throws Exception {
         CorpCustomerAcquisitionLink corpCustomerAcquisitionLink = corpCustomerAcquisitionLinkMapper.selectById(acLinkId);
-        resetAcLinkConfigIfDuty(corpCustomerAcquisitionLink);
         return corpCustomerAcquisitionLink.getUrl();
     }
 
@@ -106,10 +103,9 @@ public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistion
                     if (chooseDutyUsers == null) {
                         chooseDutyUsers = userList;
                     }
-                    List<Integer> chooseUserList = Jsons.parseList(chooseDutyUsers, Integer.class);
 
                     Set<Integer> fitUsers = dutyServices.stream().filter(e -> users.contains(e)).collect(Collectors.toSet());
-                    if (CollUtil.isNotEmpty(fitUsers) && (fitUsers.size() != chooseUserList.size() || !chooseUserList.containsAll(fitUsers))) {
+                    if (CollUtil.isNotEmpty(fitUsers)) {
 
                         corpCustomerAcquisitionLink.setChooseDutyUsers(Jsons.toJson(fitUsers));
 

+ 68 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java

@@ -137,6 +137,8 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 
 	private final CorpCustomerAcquistionCallbackMapper corpCustomerAcquistionCallbackMapper;
 
+	private final CorpFollowMapper corpFollowMapper;
+
 	private static final String DEFAULT_MSG = "您好,欢迎加入银河录像局";
 
 	/**
@@ -593,6 +595,30 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 		return null;
 	}
 
+	@Override
+	public CorpXmlOutMessage creatOrUpdateFollowUser(CorpXmlMessage message) throws Exception {
+		//corpId
+		String corpId = message.getToUserName();
+		//成员id
+		String userId = message.getUserId();
+
+		Long wxCorpId = WeChatCorpFactory.getCorpConfigStrategy(corpId).getId();
+		CorpFollow corpFollow = corpFollowMapper.selectOne(Wrappers.lambdaQuery(CorpFollow.class).eq(CorpFollow::getWxCorpId, wxCorpId).eq(CorpFollow::getUserid, userId));
+		CorpUserInfo userInfo = wxCorpOps.getFollowUser(corpId, userId);
+		if (corpFollow == null) {
+			corpFollow = new CorpFollow();
+			BeanUtil.copyProperties(userInfo, corpFollow);
+			corpFollow.setWxCorpId(wxCorpId);
+			corpFollowMapper.insert(corpFollow);
+			//同步客户列表
+			getCorpUserInfo(corpId, corpFollow.getUserid());
+		} else {
+			BeanUtil.copyProperties(userInfo, corpFollow);
+			corpFollowMapper.updateById(corpFollow);
+		}
+		return null;
+	}
+
 	/**
 	 * 修改客户成员关系,客户标签
 	 */
@@ -1227,4 +1253,46 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 		}
 		return corpWelcomeTemplate;
 	}
+
+	public void getCorpUserInfo(String corpId, String userId) {
+		THREAD_POOL.execute(() -> {
+			List<String> externalList = null;
+			try {
+				externalList = wxCorpOps.listExternalContacts(corpId, userId);
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+			if (externalList.size() > 1000) {
+				List<List<String>> lists = StringUtil.averageAssign(externalList, 5);
+				for (List<String> list : lists) {
+					THREAD_POOL.execute(() -> {
+						for (String externalUserid : list) {
+							try {
+								log.info("同步客户数据 corpId:{},externalUserid:{}", corpId, externalUserid);
+								//尝试添加客户
+								CorpXmlMessage message = new CorpXmlMessage();
+								message.setToUserName(corpId);
+								message.setExternalUserId(externalUserid);
+								addExternalContact(message, null);
+							} catch (Exception e) {
+								e.printStackTrace();
+							}
+						}
+					});
+				}
+			} else {
+				for (String externalUserid : externalList) {
+					try {
+						//尝试添加客户
+						CorpXmlMessage message = new CorpXmlMessage();
+						message.setToUserName(corpId);
+						message.setExternalUserId(externalUserid);
+						addExternalContact(message, null);
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+			}
+		});
+	}
 }

+ 10 - 16
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowDynamicConfigServiceImpl.java

@@ -3,20 +3,19 @@ package com.cyksj.service.corp.impl;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
 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.mapper.corp.CorpFollowConfigMapper;
 import com.cyksj.mapper.corp.CorpTagMapper;
 import com.cyksj.model.dto.CorpFollowActiveCodeDto;
-import com.cyksj.model.dto.CorpFollowServiceDto;
 import com.cyksj.model.entity.CorpFollowConfig;
 import com.cyksj.model.entity.CorpTag;
-import com.cyksj.model.entity.SysConfig;
 import com.cyksj.model.request.corp.CorpFollowContact;
+import com.cyksj.model.views.SysCorpFollowView;
 import com.cyksj.service.corp.CorpFollowDynamicConfigService;
 import com.cyksj.service.corp.WxCorpOps;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -42,7 +41,7 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 
 	private final CorpTagMapper corpTagMapper;
 
-	private final SysConfigMapper sysConfigMapper;
+	private final BeanSearcher beanSearcher;
 
 	@Override
 	public String corpFollowContactConfig(CorpFollowContact corpFollowContact) throws Exception {
@@ -64,12 +63,7 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 	@Override
 	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"));
-		List<CorpFollowServiceDto> corpFollowServiceDtos = null;
-		if (sysConfig != null && StrUtil.isNotBlank(sysConfig.getSysValue())) {
-			corpFollowServiceDtos = Jsons.parseList(sysConfig.getSysValue(), CorpFollowServiceDto.class);
-		}
+		List<SysCorpFollowView> corpFollowServiceDtos = beanSearcher.searchAll(SysCorpFollowView.class, MapUtils.builder().build());
 		Integer type = 1;
 		if (!isDuty) {
 			//不是值班 多人生成一个二维码
@@ -79,7 +73,7 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 			}
 			String serviceNames = null;
 			if (corpFollowServiceDtos != null) {
-				serviceNames = corpFollowServiceDtos.stream().filter(cs -> followIds.contains(cs.getFollowId())).map(CorpFollowServiceDto::getName).collect(Collectors.joining(","));
+				serviceNames = corpFollowServiceDtos.stream().filter(cs -> userIndxList.contains(Integer.parseInt(cs.getSid().toString()))).map(SysCorpFollowView::getShowName).collect(Collectors.joining(","));
 			}
 			if (StrUtil.isEmpty(serviceNames)) {
 				throw BusinessRuntimeException.getInstance("存在被删除的客服,请刷新页面重试");
@@ -87,16 +81,16 @@ public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConf
 			CorpFollowActiveCodeDto corpFollowActiveCodeDto = createCorpFollowActiveCode(followIds, userIndxList, state, type, serviceNames);
 			codeList.add(corpFollowActiveCodeDto);
 		} else {
-			Map<String, List<CorpFollowServiceDto>> csMap = null;
+			Map<String, List<SysCorpFollowView>> csMap = null;
 			if (corpFollowServiceDtos != null) {
-				csMap = corpFollowServiceDtos.stream().filter(cs -> followIds.contains(cs.getFollowId())).collect(Collectors.groupingBy(CorpFollowServiceDto::getFollowId));
+				csMap = corpFollowServiceDtos.stream().filter(cs -> userIndxList.contains(Integer.parseInt(cs.getSid().toString()))).collect(Collectors.groupingBy(SysCorpFollowView::getFollowId));
 			}
 			if (csMap == null || csMap.keySet().size() != followIds.size()) {
 				throw BusinessRuntimeException.getInstance("存在被删除的客服,请刷新页面重试");
 			}
 			for (String followId : followIds) {
-				CorpFollowServiceDto corpFollowServiceDto = csMap.get(followId).get(0);
-				CorpFollowActiveCodeDto corpFollowActiveCodeDto = createCorpFollowActiveCode(List.of(followId), List.of(corpFollowServiceDto.getIndx()), state, type, corpFollowServiceDto.getName());
+				SysCorpFollowView corpFollowServiceDto = csMap.get(followId).get(0);
+				CorpFollowActiveCodeDto corpFollowActiveCodeDto = createCorpFollowActiveCode(List.of(followId), List.of(Integer.parseInt(corpFollowServiceDto.getSid().toString())), state, type, corpFollowServiceDto.getShowName());
 				codeList.add(corpFollowActiveCodeDto);
 			}
 		}

+ 18 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java

@@ -190,6 +190,24 @@ public class CorpServiceImpl implements CorpService {
 					}
 				})
 				.end()
+				//新增成员
+				.rule().async(false).changeType("create_user")
+				.handler(new CorpMessageHandler() {
+					@Override
+					public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
+						return corpEventActionService.creatOrUpdateFollowUser(message);
+					}
+				})
+				.end()
+				//成员更新事件
+				.rule().async(false).changeType("update_user")
+				.handler(new CorpMessageHandler() {
+					@Override
+					public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
+						return corpEventActionService.creatOrUpdateFollowUser(message);
+					}
+				})
+				.end()
 		;
 
 	}

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

@@ -33,4 +33,6 @@ public interface CorpEventActionService {
     CorpXmlOutMessage msgAuditApproved(CorpXmlMessage message, Map<String, Object> context);
 
 	CorpXmlOutMessage customerStartChat(CorpXmlMessage message, Map<String, Object> context);
+
+	CorpXmlOutMessage creatOrUpdateFollowUser(CorpXmlMessage message) throws Exception;
 }

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/sys/SysCorpFollowService.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.sys;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.SysCorpFollow;
+import com.cyksj.model.request.sys.SysCorpFollowReq;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowService
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:58
+ */
+public interface SysCorpFollowService extends IService<SysCorpFollow> {
+	void saveOrUpdateFollow(SysCorpFollowReq req) throws Exception;
+
+	void delBySid(Long sid) throws Exception;
+}

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

@@ -1,9 +1,6 @@
 package com.cyksj.service.sys;
 
-import com.cyksj.model.dto.CorpFollowServiceDto;
-
 import java.util.List;
-import java.util.Map;
 
 /**
  * 项目名: yhlxj2
@@ -14,11 +11,4 @@ import java.util.Map;
 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;
 }

+ 10 - 4
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigChangeRecordServiceImpl.java

@@ -8,12 +8,16 @@ import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.SmsUtil;
+import com.cyksj.common.util.StringUtil;
 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.*;
+import com.cyksj.model.dto.SysServiceChangeDto;
+import com.cyksj.model.dto.YhServiceChangeDto;
+import com.cyksj.model.dto.YhServiceDto;
+import com.cyksj.model.dto.YhServiceNameDto;
 import com.cyksj.model.entity.CmsUser;
 import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
 import com.cyksj.model.entity.CorpFollowActiveCode;
@@ -29,6 +33,7 @@ import com.cyksj.service.sys.SysCorpServiceRelateService;
 import com.cyksj.xxljob.XxlJobInfo;
 import com.cyksj.xxljob.XxlJobUtil;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import java.time.DayOfWeek;
@@ -49,6 +54,7 @@ import java.util.stream.Collectors;
  */
 @Service
 @RequiredArgsConstructor
+@Slf4j
 public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChangeRecordMapper, SysConfigChangeRecord> implements SysConfigChangeRecordService {
 	private final CmsUserMapper cmsUserMapper;
 
@@ -198,18 +204,18 @@ public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChang
 	@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);
+				List<String> up_followStrList = sysCorpServiceRelateService.getFollowIdsByRelateIds(upUserIndxList);
 				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) {
+				log.error("更换活码客服失败:{}", StringUtil.getErrorText(e));
 			}
 		});
 
@@ -233,7 +239,7 @@ public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChang
 				} else {
 					userList = link.getUserList();
 				}
-				List<String> followIds = sysCorpServiceRelateService.getFollowIdsByRelateIds(Jsons.parseList(userList, Integer.class), corpYhFollowService);
+				List<String> followIds = sysCorpServiceRelateService.getFollowIdsByRelateIds(Jsons.parseList(userList, Integer.class));
 				range.setUserList(followIds);
 				wxCpLinkUpd.setRange(range);
 				WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionUpdateLink(null, wxCpLinkUpd);

+ 21 - 1
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigServiceImpl.java

@@ -8,12 +8,15 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.service.CropDutyServiceDateService;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.corp.CorpFollowMapper;
 import com.cyksj.mapper.sys.SysConfigMapper;
 import com.cyksj.model.dto.DefaultShopConfig;
 import com.cyksj.model.dto.YhServiceDto;
+import com.cyksj.model.entity.CorpFollow;
 import com.cyksj.model.entity.ShopConfig;
 import com.cyksj.model.entity.SysConfig;
 import com.cyksj.service.sys.SysConfigService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
@@ -29,7 +32,9 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 @Service
+@RequiredArgsConstructor
 public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper,SysConfig> implements SysConfigService {
+	private final CorpFollowMapper corpFollowMapper;
 
 	@Override
 	public String getDefaultShopConfigByType(String type) {
@@ -65,11 +70,26 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper,SysConfig>
 		SysConfig sysConfig = this.getOne(Wrappers.lambdaQuery(SysConfig.class)
 				.eq(SysConfig::getSysKey, Constant.serviceKeys.get(0))
 				.last("limit 1"));
-
+		//过滤被禁用的规格
+		Map<String, List<CorpFollow>> followMap = corpFollowMapper.selectList(Wrappers.lambdaQuery(CorpFollow.class)
+				.ne(CorpFollow::getStatus, 1)).stream().collect(Collectors.groupingBy(CorpFollow::getUserid));
 		List<YhServiceDto> yhServiceDtos = null;
 
 		if (sysConfig != null && StrUtil.isNotBlank(sysConfig.getSysValue())) {
 			yhServiceDtos = Jsons.parseList(sysConfig.getSysValue(), YhServiceDto.class);
+			yhServiceDtos.stream().forEach(s -> {
+				List<YhServiceDto.CustomerServiceDto> finalSelect = s.getSelect().stream().filter(select -> {
+					List<CorpFollow> corpFollows = followMap.get(select);
+					if (CollUtil.isNotEmpty(corpFollows)) {
+						CorpFollow corpFollow = corpFollows.get(0);
+						if (corpFollow.getStatus() != 1) {
+							return false;
+						}
+					}
+					return true;
+				}).collect(Collectors.toList());
+				s.setSelect(finalSelect);
+			});
 		}
 
 		final List<YhServiceDto> dtoCs = yhServiceDtos;

+ 143 - 0
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpFollowServiceImpl.java

@@ -0,0 +1,143 @@
+package com.cyksj.service.sys.impl;
+
+import cn.hutool.core.util.StrUtil;
+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.SysCorpFollowMapper;
+import com.cyksj.mapper.SysCorpFollowRelateMapper;
+import com.cyksj.mapper.sys.SysConfigMapper;
+import com.cyksj.model.dto.YhServiceDto;
+import com.cyksj.model.entity.SysConfig;
+import com.cyksj.model.entity.SysCorpFollow;
+import com.cyksj.model.entity.SysCorpFollowRelate;
+import com.cyksj.model.request.sys.SysCorpFollowReq;
+import com.cyksj.service.sys.SysConfigChangeRecordService;
+import com.cyksj.service.sys.SysCorpFollowService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:58
+ */
+@Service
+@RequiredArgsConstructor
+public class SysCorpFollowServiceImpl extends ServiceImpl<SysCorpFollowMapper, SysCorpFollow> implements SysCorpFollowService {
+	private final SysCorpFollowRelateMapper sysCorpFollowRelateMapper;
+
+	private final SysConfigMapper sysConfigMapper;
+
+	private final SysConfigChangeRecordService sysConfigChangeRecordService;
+
+	@Override
+	public void saveOrUpdateFollow(SysCorpFollowReq req) throws Exception {
+		SysCorpFollow sysCorpFollow = new SysCorpFollow();
+		sysCorpFollow.setId(req.getMid());
+		sysCorpFollow.setName(req.getName());
+		this.saveOrUpdate(sysCorpFollow);
+
+		SysCorpFollowRelate sysCorpFollowRelate = new SysCorpFollowRelate();
+		sysCorpFollowRelate.setId(req.getSid());
+		sysCorpFollowRelate.setMid(sysCorpFollow.getId());
+		sysCorpFollowRelate.setFollowId(req.getFollowId());
+		sysCorpFollowRelate.setName(req.getFollowName());
+		sysCorpFollowRelate.setImg(req.getImg());
+		sysCorpFollowRelate.setStatus(req.getStatus());
+		String followId = sysCorpFollowRelate.getFollowId();
+		Integer selectCount = sysCorpFollowRelateMapper.selectCount(Wrappers.lambdaQuery(SysCorpFollowRelate.class)
+				.eq(SysCorpFollowRelate::getFollowId, followId)
+				.ne(sysCorpFollowRelate.getId() != null, SysCorpFollowRelate::getId, sysCorpFollowRelate.getId())
+				.eq(SysCorpFollowRelate::getDeleted, 1));
+		if (selectCount > 0) {
+			throw BusinessRuntimeException.getInstance("已添加该客服");
+		}
+		if (sysCorpFollowRelate.getId() == null) {
+			sysCorpFollowRelateMapper.insert(sysCorpFollowRelate);
+		} else {
+			SysCorpFollowRelate db = sysCorpFollowRelateMapper.selectById(sysCorpFollowRelate.getId());
+			sysCorpFollowRelateMapper.updateById(sysCorpFollowRelate);
+			//更新获客。活码 企业客服
+			updateCorpFollowRelateConfig(sysCorpFollowRelate, db);
+			//更新客服图片
+			updateCorpFollowImg(sysCorpFollowRelate, req.getName());
+		}
+	}
+
+	@Override
+	public void delBySid(Long sid) throws Exception {
+		SysCorpFollowRelate sysCorpFollowRelate = sysCorpFollowRelateMapper.selectById(sid);
+		if (sysCorpFollowRelate == null || !sysCorpFollowRelate.getDeleted()) {
+			return;
+		}
+		//是否已被选择
+		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.serviceKeys.get(0))
+				.last("limit 1"));
+		List<YhServiceDto> yhServiceDtos = Jsons.parseList(sysConfig.getSysValue(), YhServiceDto.class);
+
+		yhServiceDtos.stream().forEach(s -> {
+			List<YhServiceDto.CustomerServiceDto> select = s.getSelect();
+			select.forEach(e -> {
+				String followId = e.getFollowId();
+				if (StrUtil.equals(followId, sysCorpFollowRelate.getFollowId())) {
+					throw BusinessRuntimeException.getInstance("请先移除对应值班客服");
+				}
+			});
+		});
+		sysCorpFollowRelate.setDeleted(false);
+		sysCorpFollowRelateMapper.updateById(sysCorpFollowRelate);
+	}
+
+	public void updateCorpFollowRelateConfig(SysCorpFollowRelate sysCorpFollowRelate, SysCorpFollowRelate db) {
+		Long sid = sysCorpFollowRelate.getId();
+		if (!StrUtil.equals(db.getFollowId(), sysCorpFollowRelate.getFollowId())) {
+			//更新活码,获客
+			try {
+				sysConfigChangeRecordService.updateCorpFollowLinkConfig(List.of(Integer.parseInt(sid.toString())));
+			} catch (Exception e) {
+			}
+
+		}
+	}
+
+	/**
+	 * 更新企业值班客服信息
+	 */
+	private void updateCorpFollowImg(SysCorpFollowRelate sysCorpFollowRelate, String mName) throws Exception {
+		int sid = sysCorpFollowRelate.getId().intValue();
+		//更新活码,获客
+		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.serviceKeys.get(0))
+				.last("limit 1"));
+
+		List<YhServiceDto> yhServiceDtos = Jsons.parseList(sysConfig.getSysValue(), YhServiceDto.class);
+		AtomicBoolean isFlag = new AtomicBoolean(false);
+		yhServiceDtos.forEach(ys -> {
+			ys.getSelect().forEach(select -> {
+				if (select.getIndex().intValue() == sid) {
+					select.setFollowId(sysCorpFollowRelate.getFollowId());
+					select.setImg(sysCorpFollowRelate.getImg());
+					StringBuilder showName = new StringBuilder();
+					showName.append(mName).append("(").append(sysCorpFollowRelate.getName()).append(")");
+					select.setName(showName.toString());
+					select.setStatus(sysCorpFollowRelate.getStatus());
+					if (!isFlag.get()) {
+						isFlag.set(true);
+					}
+				}
+			});
+		});
+		if (isFlag.get()) {
+			sysConfig.setSysValue(Jsons.toJson(yhServiceDtos));
+			sysConfigMapper.updateById(sysConfig);
+		}
+	}
+}

+ 6 - 41
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpServiceRelateServiceImpl.java

@@ -1,21 +1,14 @@
 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.SysCorpFollowRelateMapper;
 import com.cyksj.mapper.sys.SysConfigMapper;
-import com.cyksj.model.dto.CorpFollowServiceDto;
-import com.cyksj.model.entity.SysConfig;
+import com.cyksj.model.entity.SysCorpFollowRelate;
 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;
 
 /**
@@ -29,41 +22,13 @@ import java.util.stream.Collectors;
 public class SysCorpServiceRelateServiceImpl implements SysCorpServiceRelateService {
 	private final SysConfigMapper sysConfigMapper;
 
+	private final SysCorpFollowRelateMapper sysCorpFollowRelateMapper;
+
 
 	@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;
+		return sysCorpFollowRelateMapper.selectList(Wrappers.lambdaQuery(SysCorpFollowRelate.class)
+				.in(SysCorpFollowRelate::getId, indxIds)).stream().map(SysCorpFollowRelate::getFollowId).collect(Collectors.toList());
 	}
 }

+ 14 - 5
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -3,7 +3,6 @@ package com.cyksj.web.controller.manage;
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
@@ -37,7 +36,6 @@ import com.cyksj.model.manage.views.UpgradeOrderDonBackView;
 import com.cyksj.model.request.*;
 import com.cyksj.model.views.*;
 import com.cyksj.service.mange.CmsOrderDonService;
-import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.service.order.OrderDonCommentService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.web.util.EasyExcelUtils;
@@ -882,9 +880,20 @@ public class CmsOrderController {
 	 * 套餐退款订单列表
 	 */
 	@GetMapping("/get/upgrade/refund/list")
-	public Result<SearchResult<RefundUpdradeOrderDonView>> getRefundUpgradeOrderDonView() {
-		SearchResult<RefundUpdradeOrderDonView> search = beanSearcher.search(RefundUpdradeOrderDonView.class, MapUtils.flatBuilder(request.getParameterMap())
-				.build());
+	public Result<SearchResult<RefundUpdradeOrderDonView>> getRefundUpgradeOrderDonView(String nickname) {
+		List<Long> userIds = null;
+		if (StrUtil.isNotBlank(nickname)) {
+			userIds = userMapper.selectListByNickname(nickname);
+			if (CollUtil.isEmpty(userIds)) {
+				userIds.add(0l);
+			}
+		}
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+		if (CollUtil.isNotEmpty(userIds)) {
+			builder.field(RealGoodsInterestUserView::getUserId, userIds).op(Operator.InList);
+		}
+		SearchResult<RefundUpdradeOrderDonView> search = beanSearcher.search(RefundUpdradeOrderDonView.class,
+				builder.build());
 		search.getDataList().forEach(data -> {
 			Optional.ofNullable(userService.getById(data.getUserId()))
 					.ifPresent(user -> data.setNickname(user.getNickname()));

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

@@ -3,7 +3,6 @@ package com.cyksj.web.controller.manage.corp;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.constant.Constant;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
@@ -11,14 +10,10 @@ import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.corp.CorpUserMapper;
 import com.cyksj.mapper.corp.CorpWelcomeTemplateMapper;
 import com.cyksj.mapper.manage.coupon.CouponMapper;
-import com.cyksj.model.dto.CorpFollowServiceDto;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.corp.Attachments;
 import com.cyksj.model.request.corp.CorpFollowContact;
-import com.cyksj.model.views.CorpActiveCodeGoodsOrderView;
-import com.cyksj.model.views.CorpActiveCodeOrderView;
-import com.cyksj.model.views.CorpActiveCodeUserDayDataView;
-import com.cyksj.model.views.CorpFollowActiveCodeView;
+import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.corp.CorpFollowDynamicConfigService;
 import com.cyksj.service.corp.CorpFollowService;
@@ -95,14 +90,8 @@ public class CmsCorpFollowActiveCodeController {
 	 * 可选客服配置
 	 */
 	@GetMapping("/get/available/follow")
-	public Result<List<CorpFollowServiceDto>> getAvailableFollow() throws Exception {
-		SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
-				.eq(SysConfig::getSysKey, Constant.serviceKeys.get(1)).last("limit 1"));
-		if (config == null || StrUtil.isEmpty(config.getSysValue())) {
-			return GatewayResponse.SUCCESS.newBuilder().toResult();
-		}
-		String sysValue = config.getSysValue();
-		List<CorpFollowServiceDto> corpFollowServiceDtos = Jsons.parseList(sysValue, CorpFollowServiceDto.class);
+	public Result<List<SysCorpFollowView>> getAvailableFollow() {
+		List<SysCorpFollowView> corpFollowServiceDtos = beanSearcher.searchAll(SysCorpFollowView.class, MapUtils.builder().build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(corpFollowServiceDtos);
 	}
 

+ 21 - 16
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkController.java

@@ -2,17 +2,17 @@ package com.cyksj.web.controller.manage.corp;
 
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.constant.Constant;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.SysCorpFollowRelateMapper;
 import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkExtraCustomerMapper;
 import com.cyksj.mapper.corp.CorpFollowMapper;
 import com.cyksj.mapper.corp.CorpTagMapper;
 import com.cyksj.mapper.corp.CorpWelcomeTemplateMapper;
-import com.cyksj.model.dto.CorpFollowServiceDto;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.CorpCustomerAcquisitionLinkExtraCustomerView;
+import com.cyksj.model.views.SysCorpFollowView;
 import com.cyksj.service.corp.CorpCustomerAcquisitionLinkService;
 import com.cyksj.service.sys.SysConfigService;
 import com.ejlchina.searcher.BeanSearcher;
@@ -54,6 +54,8 @@ public class CorpCustomerAcquistionLinkController {
 
     private final CorpCustomerAcquisitionLinkExtraCustomerMapper corpCustomerAcquisitionLinkExtraCustomerMapper;
 
+    private final SysCorpFollowRelateMapper sysCorpFollowRelateMapper;
+
     /**
      * 新增获客助手链接
      */
@@ -89,35 +91,33 @@ public class CorpCustomerAcquistionLinkController {
     public Result<SearchResult<CorpCustomerAcquisitionLink>> get() throws Exception {
         SearchResult<CorpCustomerAcquisitionLink> search = beanSearcher.search(CorpCustomerAcquisitionLink.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 
-        SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
-                .eq(SysConfig::getSysKey, Constant.serviceKeys.get(1)).last("limit 1"));
-        List<CorpFollowServiceDto> corpFollowServiceDtos = Jsons.parseList(config.getSysValue(), CorpFollowServiceDto.class);
+        List<SysCorpFollowView> corpFollowServiceDtos = beanSearcher.searchAll(SysCorpFollowView.class, MapUtils.builder().build());
 
-        search.getDataList().forEach(e->{
+        search.getDataList().forEach(e -> {
             try {
                 List<String> userStrList = corpFollowServiceDtos.stream().filter(cf -> {
                     try {
-                        return Jsons.parseList(e.getUserList(), Integer.class).contains(cf.getIndx());
+                        return Jsons.parseList(e.getUserList(), Long.class).contains(cf.getSid());
                     } catch (Exception ex) {
                     }
                     return false;
-                }).map(CorpFollowServiceDto::getName).collect(Collectors.toList());
+                }).map(SysCorpFollowView::getShowName).collect(Collectors.toList());
                 e.setUserStrList(userStrList);
 
                 if (StrUtil.isNotEmpty(e.getChooseDutyUsers())) {
                     List<String> dutyUserList = corpFollowServiceDtos.stream().filter(cf -> {
                         try {
-                            return Jsons.parseList(e.getChooseDutyUsers(), Integer.class).contains(cf.getIndx());
+                            return Jsons.parseList(e.getChooseDutyUsers(), Long.class).contains(cf.getSid());
                         } catch (Exception ex) {
                         }
                         return false;
-                    }).map(CorpFollowServiceDto::getName).collect(Collectors.toList());
+                    }).map(SysCorpFollowView::getShowName).collect(Collectors.toList());
 
                     e.setChooseDutyUserList(dutyUserList);
                 }
 
                 List<String> tagStrList = corpTagMapper.selectList(Wrappers.lambdaQuery(CorpTag.class)
-                        .in(CorpTag::getId, Jsons.parseList(e.getTags(),Long.class))).stream().map(CorpTag::getName).collect(Collectors.toList());
+                        .in(CorpTag::getId, Jsons.parseList(e.getTags(), Long.class))).stream().map(CorpTag::getName).collect(Collectors.toList());
                 e.setTagStrList(tagStrList);
             } catch (Exception ex) {
             }
@@ -135,7 +135,10 @@ public class CorpCustomerAcquistionLinkController {
      */
     @PostMapping("/add/extra/service")
     public Result<String> addExtraService(@RequestBody @Validated CorpCustomerAcquisitionLinkExtraCustomer extraCustomer) throws Exception {
-	    corpCustomerAcquisitionLinkExtraCustomerMapper.insert(extraCustomer);
+        Integer serviceId = extraCustomer.getServiceId();
+        SysCorpFollowRelate sysCorpFollowRelate = sysCorpFollowRelateMapper.selectById(serviceId);
+        extraCustomer.setFollowId(sysCorpFollowRelate.getFollowId());
+        corpCustomerAcquisitionLinkExtraCustomerMapper.insert(extraCustomer);
         corpCustomerAcquisitionLinkService.handleCorpLinkSchedulerJob();
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
@@ -145,6 +148,9 @@ public class CorpCustomerAcquistionLinkController {
      */
     @PutMapping("/update/extra/service")
     public Result<String> updateExtraService(@RequestBody @Validated CorpCustomerAcquisitionLinkExtraCustomer extraCustomer) throws Exception {
+        Integer serviceId = extraCustomer.getServiceId();
+        SysCorpFollowRelate sysCorpFollowRelate = sysCorpFollowRelateMapper.selectById(serviceId);
+        extraCustomer.setFollowId(sysCorpFollowRelate.getFollowId());
 	    corpCustomerAcquisitionLinkExtraCustomerMapper.updateById(extraCustomer);
         corpCustomerAcquisitionLinkService.handleCorpLinkSchedulerJob();
         return GatewayResponse.SUCCESS.newBuilder().toResult();
@@ -178,12 +184,11 @@ public class CorpCustomerAcquistionLinkController {
                 .orderBy(CorpCustomerAcquisitionLinkExtraCustomerView::getAcId).asc()
                 .orderBy(CorpCustomerAcquisitionLinkExtraCustomerView::getCreatedTime).desc()
                 .build());
-        SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
-                .eq(SysConfig::getSysKey, Constant.serviceKeys.get(1)).last("limit 1"));
-        Map<Integer, List<CorpFollowServiceDto>> serviceMap = Jsons.parseList(config.getSysValue(), CorpFollowServiceDto.class).stream().collect(Collectors.groupingBy(CorpFollowServiceDto::getIndx));
+        List<SysCorpFollowView> corpFollowServiceDtos = beanSearcher.searchAll(SysCorpFollowView.class, MapUtils.builder().build());
+        Map<Long, List<SysCorpFollowView>> serviceMap = corpFollowServiceDtos.stream().collect(Collectors.groupingBy(SysCorpFollowView::getSid));
         search.getDataList().forEach(e->{
             Optional.ofNullable(serviceMap.get(e.getServiceId()))
-                    .ifPresent(service -> e.setServiceName(service.get(0).getName()));
+                    .ifPresent(service -> e.setServiceName(service.get(0).getShowName()));
         });
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }

+ 103 - 0
netflix-web/src/main/java/com/cyksj/web/controller/sys/SysCorpFollowController.java

@@ -0,0 +1,103 @@
+package com.cyksj.web.controller.sys;
+
+import com.cyksj.config.corp.YHLXWxCorpConfig;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.corp.CorpUserFollowRelationMapper;
+import com.cyksj.model.request.sys.SysCorpFollowReq;
+import com.cyksj.model.views.SysCorpFollowView;
+import com.cyksj.model.views.SysCorpMasterFollowView;
+import com.cyksj.service.corp.CorpService;
+import com.cyksj.service.sys.SysCorpFollowService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SysCorpFollowController
+ * 创建者: JavaZou
+ * 创建时间:2024/6/12 11:54
+ * 系统客服配置
+ */
+@Slf4j
+@RequestMapping("/sys/corp/follow")
+@RestController
+@RequiredArgsConstructor
+public class SysCorpFollowController {
+	private final SysCorpFollowService sysCorpFollowService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final YHLXWxCorpConfig yhlxWxCorpConfig;
+
+	private final CorpService corpService;
+
+	private final CorpUserFollowRelationMapper corpUserFollowRelationMapper;
+
+	private final HttpServletRequest request;
+
+	/**
+	 * 新增客服
+	 */
+	@PostMapping("/post")
+	public Result<String> post(@RequestBody SysCorpFollowReq req) throws Exception {
+		sysCorpFollowService.saveOrUpdateFollow(req);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除客服
+	 */
+	@DeleteMapping("/del/{sid}")
+	public Result<String> delBySId(@PathVariable Long sid) throws Exception {
+		sysCorpFollowService.delBySid(sid);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 修改客服
+	 */
+	@PutMapping("/put")
+	public Result<String> update(@RequestBody SysCorpFollowReq req) throws Exception {
+		sysCorpFollowService.saveOrUpdateFollow(req);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 客服列表
+	 */
+	@GetMapping("/get")
+	public Result<List<SysCorpFollowView>> get() {
+		List<SysCorpFollowView> sysCorpFollowViews = beanSearcher.searchAll(SysCorpFollowView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		sysCorpFollowViews.forEach(e->{
+			Integer num = corpUserFollowRelationMapper.selectNumOfCorpuserByFollowId(e.getFollowId());
+			e.setNumOfCorpUser(num);
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(sysCorpFollowViews);
+	}
+
+	/**
+	 * 主客服列表
+	 */
+	@GetMapping("/get/master")
+	public Result<List<SysCorpMasterFollowView>> getMasterFollow() {
+		List<SysCorpMasterFollowView> sysCorpMasterFollowViews = beanSearcher.searchAll(SysCorpMasterFollowView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(sysCorpMasterFollowViews);
+	}
+
+	/**
+	 * 同步企业客服
+	 */
+	@GetMapping("/dataInit")
+	public Result<String> dataInitByCorpId(String corpId) throws Exception {
+		corpId = Optional.ofNullable(corpId).orElse(yhlxWxCorpConfig.getCorpId());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(corpService.dataInitByCorpId(corpId));
+	}
+}