Browse Source

动态排队提示

zoujiajian 1 year ago
parent
commit
90d9e7bcb2

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/kf/CorpKfServicerSessionRecordMapper.java

@@ -6,6 +6,7 @@ import com.cyksj.model.entity.CorpKfServicerSessionRecord;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * 项目名: yhlxj2
@@ -17,4 +18,6 @@ public interface CorpKfServicerSessionRecordMapper extends BaseMapper<CorpKfServ
 	List<CorpKfServicerDto> getAvailableServicer(@Param("openKfId") String openKfId);
 
 	List<CorpKfServicerSessionRecord> selectSessionByCondition(@Param("openKfId") String openKfId, @Param("servicerUserid") String servicerUserid, @Param("transUserIds") List<String> transUserIds, @Param("transNum") Integer transNum);
+
+	Integer selectServiceCorpUserNum(@Param("openKfId") String openKfId, @Param("dutyFollowIds") Set<String> dutyFollowIds);
 }

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

@@ -34,6 +34,11 @@ public class CorpKfAccountSessionConfig extends BaseEntity{
 	 */
 	private String welcomeContent;
 
+	/**
+	 * 动态排队提示
+	 */
+	private String dynamicQueueTips;
+
 	/**
 	 * 排队提示
 	 */
@@ -43,4 +48,4 @@ public class CorpKfAccountSessionConfig extends BaseEntity{
 	 * 非值班提示
 	 */
 	private String noDutyTips;
-}
+}

+ 18 - 2
netflix-dao/src/main/java/com/cyksj/model/entity/CorpKfUser.java

@@ -1,5 +1,8 @@
 package com.cyksj.model.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.cyksj.model.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -11,7 +14,7 @@ import lombok.Setter;
  */
 @Getter
 @Setter
-public class CorpKfUser extends BaseEntity{
+public class CorpKfUser extends BaseEntity {
 	private String externalUserid;
 
 	private String unionid;
@@ -21,4 +24,17 @@ public class CorpKfUser extends BaseEntity{
 	private Integer gender;
 
 	private String avatar;
-}
+
+	private String remark;
+
+	/**
+	 * 是否是设备用户
+	 */
+	private Boolean isDevice;
+
+	/**
+	 * 标记用户设备客服
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String followId;
+}

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

@@ -27,4 +27,18 @@
             order by rand() limit #{transNum}
         </if>
     </select>
+
+    <select id="selectServiceCorpUserNum" resultType="java.lang.Integer">
+        select count(1) as num
+        from corp_kf_servicer_session_record
+        where open_kf_id = #{openKfId}
+        and service_state = 0
+        and servicer_userid in
+        <foreach collection="dutyFollowIds" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        group by servicer_userid
+        order by num asc
+        limit 1
+    </select>
 </mapper>

+ 98 - 6
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java

@@ -913,21 +913,32 @@ public class CorpServiceImpl implements CorpService {
 				corpKfServiceIds.add(servicer.getUserid());
 			}
 		});
-		//客服是否已经开始值班
+		//客服已经开始值班
 		//没有值班人员
 		if (CollUtil.isEmpty(corpKfServiceIds)) {
 			log.info("当前客服账号:{}无值班人员,将客户:{}移入等待池", openKfId, externalUserid);
-			sendCorpKfTextTips(corpId, externalUserid, openKfId, corpKfAccountSessionConfig.getQueueTips());
+			String dynamicQueueTipsGroupsMsg = getDynamicQueueTipsGroups(openKfId, dutyFollowIds, corpKfAccountSessionConfig.getDynamicQueueTips(), corpKfAccountSessionConfig.getQueueTips());
+			sendCorpKfTextTips(corpId, externalUserid, openKfId, dynamicQueueTipsGroupsMsg);
 			//接入等待池
 			moveWaitingQueue(corpId, openKfId, externalUserid);
 			return;
 		}
+		//如果目前有排队的用户 后续进入会话的用户排队
+		if (enterQueueIfExistsQueues(openKfId, externalUserid, corpKfAccountSessionConfig, dutyFollowIds)) {
+			return;
+		}
+		//指定客服
+		List<String> deviceFollowIds = getDeviceFollowIdsIfSet(externalUserid);
 		//是否有空闲接待人员
 		List<CorpKfServicerDto> corpKfServicerDtos = corpKfServicerSessionRecordMapper.getAvailableServicer(openKfId);
 		//暂无分配会话 初始化
 		if (CollUtil.isEmpty(corpKfServicerDtos)) {
-			//随机分配一个客服
-			String servicerUserid = corpKfServiceIds.get(RandomUtil.randomInt(corpKfServiceIds.size()));
+			//从指定接待人员获取
+			String servicerUserid = getDeviceFolloIdsFromDutyServicerIds(deviceFollowIds, corpKfServiceIds);
+			if (StrUtil.isEmpty(servicerUserid)) {
+				//随机分配一个客服
+				servicerUserid = corpKfServiceIds.get(RandomUtil.randomInt(corpKfServiceIds.size()));
+			}
 			//变更会话状态
 			transCorpKfSessionToServicer(corpId, openKfId, null, servicerUserid, externalUserid, null, 3, sendDate, msgid);
 			return;
@@ -948,11 +959,21 @@ public class CorpServiceImpl implements CorpService {
 		//默认接入最少的优先分配 接待人最少的在集合前面
 		//不超过最多接待人数 默认30
 		Integer maxNum = Optional.ofNullable(corpKfAccountSessionConfig.getMaxNum()).orElse(30);
-		List<CorpKfServicerDto> filterKfCs = corpKfServicerDtos.stream().filter(kfCs -> corpKfServiceIds.contains(kfCs.getServicerUserid()) && kfCs.getNum() < maxNum).collect(Collectors.toList());
+		List<CorpKfServicerDto> filterKfCs = corpKfServicerDtos.stream().filter(kfCs -> {
+			if (corpKfServiceIds.contains(kfCs.getServicerUserid()) && kfCs.getNum() < maxNum) {
+				if (CollUtil.isNotEmpty(deviceFollowIds) && !deviceFollowIds.contains(kfCs.getServicerUserid())) {
+					return false;
+				}
+				return true;
+			}
+			return false;
+		}).collect(Collectors.toList());
 		if (CollUtil.isEmpty(filterKfCs)) {
 			log.info("当前客服账号:{}值班接待上限:{},将客户:{}移入等待池", openKfId, maxNum, externalUserid);
+			//动态排队信息
+			String dynamicQueueTipsGroupsMsg = getDynamicQueueTipsGroups(openKfId, dutyFollowIds, corpKfAccountSessionConfig.getDynamicQueueTips(), corpKfAccountSessionConfig.getQueueTips());
 			//发送进入等待池消息
-			sendCorpKfTextTips(corpId, externalUserid, openKfId, corpKfAccountSessionConfig.getQueueTips());
+			sendCorpKfTextTips(corpId, externalUserid, openKfId, dynamicQueueTipsGroupsMsg);
 			//移入等待池
 			moveWaitingQueue(corpId, openKfId, externalUserid);
 			return;
@@ -963,6 +984,35 @@ public class CorpServiceImpl implements CorpService {
 		transCorpKfSessionToServicer(corpId, openKfId, null, corpKfServicerDto.getServicerUserid(), externalUserid, null, 3, sendDate, msgid);
 	}
 
+	private Boolean enterQueueIfExistsQueues(String openKfId, String externalUserid, CorpKfAccountSessionConfig corpKfAccountSessionConfig, Set<String> dutyFollowIds) throws Exception {
+		Integer selectCount = corpKfWaitingQueueUserMapper.selectCount(Wrappers.lambdaQuery(CorpKfWaitingQueueUser.class)
+				.eq(CorpKfWaitingQueueUser::getOpenKfId, openKfId));
+		if (selectCount > 0) {
+			//动态排队信息
+			String dynamicQueueTipsGroupsMsg = getDynamicQueueTipsGroups(openKfId, dutyFollowIds, corpKfAccountSessionConfig.getDynamicQueueTips(), corpKfAccountSessionConfig.getQueueTips());
+			//发送进入等待池消息
+			sendCorpKfTextTips(null, externalUserid, openKfId, dynamicQueueTipsGroupsMsg);
+			//移入等待池
+			moveWaitingQueue(null, openKfId, externalUserid);
+			//进行排队
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 获取动态排队提示组合信息
+	 * 前方等待人数:当前接待客户数最少的客服正在接待的人员数量+等待池中排在当前用户之前的等待人数。
+	 */
+	private String getDynamicQueueTipsGroups(String openKfId, Set<String> dutyFollowIds, String dynamicQueueTips, String queueTips) {
+		if (StrUtil.isEmpty(dynamicQueueTips)) {
+			return queueTips;
+		}
+		Integer serviceCorpUserNum = corpKfServicerSessionRecordMapper.selectServiceCorpUserNum(openKfId, dutyFollowIds);
+		Integer count = corpKfWaitingQueueUserMapper.selectCount(Wrappers.lambdaQuery(CorpKfWaitingQueueUser.class).eq(CorpKfWaitingQueueUser::getOpenKfId, openKfId));
+		return dynamicQueueTips.replaceAll("#", "" + serviceCorpUserNum + count) + queueTips;
+	}
+
 	private void moveWaitingQueue(String corpId, String openKfId, String externalUserId) throws Exception {
 		CorpKfWaitingQueueUser corpKfWaitingQueueUser = new CorpKfWaitingQueueUser();
 		corpKfWaitingQueueUser.setOpenKfId(openKfId);
@@ -1078,4 +1128,46 @@ public class CorpServiceImpl implements CorpService {
 				.eq(CorpKfAccountSessionChat::getExternalUserid, externalUserid)
 				.isNull(CorpKfAccountSessionChat::getSessionId));
 	}
+
+	/**
+	 * 若设置了设备 获取指定客服
+	 * @param externalUserid
+	 * @return
+	 */
+	public List<String> getDeviceFollowIdsIfSet(String externalUserid) {
+		CorpKfUser corpKfUser = corpKfUserMapper.selectOne(Wrappers.lambdaQuery(CorpKfUser.class)
+				.eq(CorpKfUser::getExternalUserid, externalUserid)
+				.last("limit 1"));
+		if (corpKfUser != null) {
+			String deviceFollowId = corpKfUser.getFollowId();
+			if (StrUtil.isNotBlank(deviceFollowId)) {
+				CorpFollow corpFollow = corpFollowMapper.selectOne(Wrappers.lambdaQuery(CorpFollow.class)
+						.eq(CorpFollow::getUserid, deviceFollowId)
+						.last("limit 1"));
+				if (corpFollow != null && corpFollow.getCmsUserId() != null) {
+					return corpFollowMapper.selectList(Wrappers.lambdaQuery(CorpFollow.class)
+									.eq(CorpFollow::getCmsUserId, corpFollow.getCmsUserId()))
+							.stream().map(CorpFollow::getUserid).collect(Collectors.toList());
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 从接待人员获取指定客服
+	 * @param deviceFollowIds
+	 * @param corpKfServiceIds
+	 * @return
+	 */
+	public String getDeviceFolloIdsFromDutyServicerIds(List<String> deviceFollowIds, List<String> corpKfServiceIds) {
+		if (CollUtil.isNotEmpty(deviceFollowIds)) {
+			for (String deviceFollowId : deviceFollowIds) {
+				if (corpKfServiceIds.contains(deviceFollowId)) {
+					return deviceFollowId;
+				}
+			}
+		}
+		return null;
+	}
 }