Browse Source

Merge branch 'feature/0812_opt' into develop-new

Eric 11 months ago
parent
commit
58fc08c94e
15 changed files with 310 additions and 183 deletions
  1. 10 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java
  2. 13 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java
  3. 8 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/EmployeeController.java
  4. 0 4
      cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/open/ImController.java
  5. 11 13
      cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/service/impl/SysUserServiceImpl.java
  6. 5 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/TeacherSearch.java
  7. 9 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CustomerServiceBatchSending.java
  8. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImSendStatus.java
  9. 7 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/EmployeeService.java
  10. 192 141
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceBatchSendingServiceImpl.java
  11. 31 16
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/EmployeeServiceImpl.java
  12. 3 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/StudentServiceImpl.java
  13. 11 6
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherServiceImpl.java
  14. 2 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CustomerServiceBatchSendingMapper.xml
  15. 7 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/TeacherMapper.xml

+ 10 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java

@@ -217,4 +217,14 @@ public interface AdminFeignService {
 
     @PostMapping("/sysUser/logoffQuitImGroup")
     HttpResponseResult<Boolean> logoffQuitImGroup(@RequestParam(value = "phone") String phone);
+
+    /**
+     * 清除客服绑定关系
+     * @param userId 用户ID
+     * @param sysUserType 用户类型
+     *
+     * @return HttpResponseResult<Boolean>
+     */
+    @GetMapping("/employee/clearCustomerService")
+    HttpResponseResult<Boolean> clearCustomerService(Long userId, String sysUserType);
 }

+ 13 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java

@@ -215,4 +215,17 @@ public class AdminFeignServiceFallback implements AdminFeignService {
     public HttpResponseResult<Boolean> logoffQuitImGroup(String phone) {
         return null;
     }
+
+    /**
+     * 清除客服绑定关系
+     *
+     * @param userId      用户ID
+     * @param sysUserType 用户类型
+     *
+     * @return HttpResponseResult<Boolean>
+     */
+    @Override
+    public HttpResponseResult<Boolean> clearCustomerService(Long userId, String sysUserType) {
+        return null;
+    }
 }

+ 8 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/EmployeeController.java

@@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
@@ -163,4 +164,11 @@ public class EmployeeController extends BaseController {
         return failed("获取用户信息失败");
     }
 
+    @ApiOperation(value = "员工客服绑定关系清除")
+    @GetMapping("/clearCustomerService")
+    public HttpResponseResult<Boolean> clearCustomerService(@RequestParam("userId") Long userId,
+                                                            @RequestParam("sysUserType") String sysUserType) {
+        // 清除客服绑定关系
+        return succeed(employeeService.clearCustomerService(userId, sysUserType));
+    }
 }

+ 0 - 4
cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/open/ImController.java

@@ -2,7 +2,6 @@ package com.yonge.cooleshow.admin.controller.open;
 
 import com.alibaba.fastjson.JSON;
 import com.google.common.collect.Lists;
-import com.microsvc.toolkit.middleware.im.properties.ImConfigProperties;
 import com.microsvc.toolkit.middleware.live.LivePluginContext;
 import com.microsvc.toolkit.middleware.live.LivePluginService;
 import com.microsvc.toolkit.middleware.live.impl.TencentCloudLivePlugin;
@@ -71,9 +70,6 @@ public class ImController extends BaseController {
     @Autowired
     private ImGroupService imGroupService;
 
-    @Autowired
-    private ImConfigProperties imConfig;
-
 
     @ApiOperation("新用户添加客服")
     @PostMapping(value = "/im/customerService")

+ 11 - 13
cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/service/impl/SysUserServiceImpl.java

@@ -1,10 +1,6 @@
 package com.yonge.cooleshow.auth.service.impl;
 
-import com.alibaba.fastjson.JSON;
-import com.google.common.collect.Lists;
 import com.yonge.cooleshow.api.feign.AdminFeignService;
-import com.yonge.cooleshow.api.feign.TeacherFeignService;
-import com.yonge.cooleshow.api.feign.dto.UserFriendInfoVO;
 import com.yonge.cooleshow.auth.api.dto.QRLoginDto;
 import com.yonge.cooleshow.auth.api.dto.RealnameAuthReq;
 import com.yonge.cooleshow.auth.api.dto.SysUserInfo;
@@ -12,7 +8,6 @@ import com.yonge.cooleshow.auth.api.dto.SysUserQueryInfo;
 import com.yonge.cooleshow.auth.api.dto.UserSetReq;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.auth.api.vo.UserSetVo;
-import com.yonge.cooleshow.auth.config.CustomerServiceConfig;
 import com.yonge.cooleshow.auth.config.RongCloudConfig;
 import com.yonge.cooleshow.auth.core.service.CustomTokenServices;
 import com.yonge.cooleshow.auth.dal.dao.SysUserDao;
@@ -27,8 +22,8 @@ import com.yonge.cooleshow.common.entity.ImUserModel;
 import com.yonge.cooleshow.common.enums.CacheNameEnum;
 import com.yonge.cooleshow.common.enums.SysUserType;
 import com.yonge.cooleshow.common.enums.UserFirstTimeTypeEnum;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.exception.BizException;
-import com.yonge.toolset.base.util.ThreadPool;
 import com.yonge.toolset.mybatis.dal.BaseDAO;
 import com.yonge.toolset.mybatis.service.impl.BaseServiceImpl;
 import io.rong.models.response.TokenResult;
@@ -44,12 +39,9 @@ import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
 import java.text.MessageFormat;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.Random;
-import java.util.stream.Collectors;
 
 @Slf4j
 @Service
@@ -68,8 +60,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<Long, SysUser> implement
     private RedissonClient redissonClient;
     @Resource
     private AdminFeignService adminFeignService;
-    @Autowired
-    private CustomerServiceConfig customerServiceConfig;
+
     @Resource
     private CustomTokenServices tokenService;
 
@@ -215,7 +206,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<Long, SysUser> implement
      */
     public void sendSysCustomerServiceFriendMessage(SysUser sysUser, String clientType) {
 
-        try {
+        /*try {
 
             ThreadPool.getExecutor().submit(() -> {
 
@@ -234,7 +225,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<Long, SysUser> implement
 
         } catch (Exception e) {
             log.error("sendSysCustomerServiceFriendMessage userId={}", sysUser.getId(), e);
-        }
+        }*/
 
     }
 
@@ -359,9 +350,16 @@ public class SysUserServiceImpl extends BaseServiceImpl<Long, SysUser> implement
         sysUserDao.logoffById(id, maxVersion);
     }
 
+    @Transactional(rollbackFor = Exception.class)
     @Override
     public void updateLockStatus(Long userId, Integer lockFlag, String sysUserType) {
         sysUserDao.updateLockStatus(userId, lockFlag, sysUserType);
+
+        // 系统员工锁定,清除客服绑定关系
+        if (lockFlag == YesOrNoEnum.YES.getCode().intValue() && SysUserType.SYSTEM.getCode().equals(sysUserType)) {
+            // 清除客服绑定关系
+            adminFeignService.clearCustomerService(userId, sysUserType);
+        }
     }
 
     /**

+ 5 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/TeacherSearch.java

@@ -12,6 +12,7 @@ import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.util.Date;
+import java.util.List;
 
 /**
  * @Author: liweifan
@@ -41,6 +42,10 @@ public class TeacherSearch extends QueryInfo{
     
     @ApiModelProperty("声部编号")
     private Long subjectId;
+
+
+    @ApiModelProperty("声部编号")
+    private List<Long> subjectIds;
 	
     @ApiModelProperty("是否结算")
 	private Boolean isSettlement;

+ 9 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CustomerServiceBatchSending.java

@@ -56,10 +56,19 @@ public class CustomerServiceBatchSending implements Serializable {
 	@TableField(value = "send_status_")
     private EImSendStatus sendStatus;
 
+    @ApiModelProperty("是否发送")
+    @TableField(value = "send_flag_")
+    private Boolean sendFlag;
+
     @ApiModelProperty("发送时间") 
 	@TableField(value = "send_time_")
     private Date sendTime;
 
+
+    @ApiModelProperty("发送完成时间")
+    @TableField(value = "send_end_time_")
+    private Date sendEndTime;
+
     @ApiModelProperty("发送条件")
     @TableField(value = "condition_")
     private String condition;

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImSendStatus.java

@@ -12,6 +12,7 @@ import lombok.Getter;
 public enum EImSendStatus implements BaseEnum<String, EImSendStatus> {
 
     WAIT("待发送"),
+    SENDING("发送中"),
     SEND("已发送"),
     DISABLE("已停用"),
     EXPIRE("已失效"),

+ 7 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/EmployeeService.java

@@ -58,4 +58,11 @@ public interface EmployeeService extends BaseService<Long, Employee> {
 
     int insertSysRole(SysRole sysRole);
 
+    /**
+     * 清除客服绑定关系
+     * @param userId 用户ID
+     * @param sysUserType 用户类型
+     * @return Boolean
+     */
+    Boolean clearCustomerService(Long userId, String sysUserType);
 }

+ 192 - 141
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceBatchSendingServiceImpl.java

@@ -25,6 +25,7 @@ import com.yonge.cooleshow.biz.dal.enums.im.EImSendStatus;
 import com.yonge.cooleshow.biz.dal.enums.im.EImSendType;
 import com.yonge.cooleshow.biz.dal.mapper.CustomerServiceBatchSendingMapper;
 import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
+import com.yonge.cooleshow.biz.dal.redisson.RedissonMessageService;
 import com.yonge.cooleshow.biz.dal.service.CustomerServiceBatchSendingService;
 import com.yonge.cooleshow.biz.dal.service.CustomerServiceReceiveService;
 import com.yonge.cooleshow.biz.dal.service.ImGroupService;
@@ -34,6 +35,7 @@ import com.yonge.cooleshow.biz.dal.service.TeacherService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceBatchSendingWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
 import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.base.util.ImUtil;
@@ -48,6 +50,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.joda.time.DateTime;
+import org.redisson.api.RBucket;
+import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -96,6 +100,8 @@ public class CustomerServiceBatchSendingServiceImpl extends ServiceImpl<Customer
     @Autowired
     private SysConfigService sysConfigService;
 
+    @Autowired
+    private RedissonMessageService redissonMessageService;
 	/**
      * 查询详情
      * @param id 详情ID
@@ -453,154 +459,198 @@ public class CustomerServiceBatchSendingServiceImpl extends ServiceImpl<Customer
      * @param info CustomerServiceBatchSending
      */
     private void asyncBatchSendingMessage(CustomerServiceBatchSending info) {
-        String lockName = MessageFormat.format("batchSending:{0}", String.valueOf(info.getId()));
-        // 消息状态判定,且不能重复发送
-        DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
-
-            // 异步发送消息且同步更新已发送人数,稍后可在页面刷新查看已发送用户数
-            ThreadPool.getExecutor().submit(() -> {
-                // 接收消息用户数
-                List<Integer> receiveNums = Lists.newCopyOnWriteArrayList();
-                // 分页数限制
-                int limit = 500;
-
-                try {
-
-                    // 消息发送数量,默认只发送1类消息(文字或图片)
-                    int messageNum = 1;
-                    if (StringUtils.isNoneBlank(info.getTextMessage(), info.getImgMessage())) {
-                        // 同时发送图片和文字消息
-                        messageNum += 1;
+
+        // 改状态为发送中,标记为发送中但是未发送
+        if (info.getId() == null) {
+            return;
+        }
+
+        CustomerServiceBatchSending byId = getById(info.getId());
+        if (byId == null) {
+            return;
+        }else if (byId.getSendStatus() == EImSendStatus.SEND) {
+            return;
+        } else if (byId.getSendStatus() == EImSendStatus.SENDING && byId.getSendFlag()) {
+            return;
+        }
+
+        CustomerServiceBatchSending customerServiceBatchSending = new CustomerServiceBatchSending();
+        customerServiceBatchSending.setId(info.getId());
+        customerServiceBatchSending.setSendFlag(false);
+        customerServiceBatchSending.setSendTime(new Date());
+        customerServiceBatchSending.setSendStatus(EImSendStatus.SENDING);
+        updateById(customerServiceBatchSending);
+
+        // 如果有发送中,不再发送
+        Integer count = lambdaQuery()
+            .eq(CustomerServiceBatchSending::getSendStatus, EImSendStatus.SENDING)
+            .eq(CustomerServiceBatchSending::getSendFlag, 1)
+            .count();
+        if (count > 0) {
+            return;
+        }
+
+        // 异步发送消息且同步更新已发送人数,稍后可在页面刷新查看已发送用户数
+        ThreadPool.getExecutor().submit(() -> {
+
+            // 加锁, 同时只能有一个在发送
+
+            String lockName = MessageFormat.format("batchSending:{0}", String.valueOf(info.getId()));
+            // 消息状态判定,且不能重复发送
+
+
+            DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> sendMessage(info), 30L, TimeUnit.MINUTES);
+
+
+        });
+    }
+
+    private void sendMessage(CustomerServiceBatchSending info) {
+
+        lambdaUpdate()
+            .eq(CustomerServiceBatchSending::getId, info.getId())
+            .set(CustomerServiceBatchSending::getSendFlag, 1)
+            .update();
+
+        // 接收消息用户数
+        List<Integer> receiveNums = Lists.newCopyOnWriteArrayList();
+        // 分页数限制
+        int limit = 500;
+
+        try {
+
+            // 消息发送数量,默认只发送1类消息(文字或图片)
+            int messageNum = 1;
+            if (StringUtils.isNoneBlank(info.getTextMessage(), info.getImgMessage())) {
+                // 同时发送图片和文字消息
+                messageNum += 1;
+            }
+
+            int messageSendLimit; // 默认发送10000/分钟
+            // 群发消息频率限制
+            SysConfig config = sysConfigService.findByParamName(SysConfigConstant.MESSAGE_SEND_LIMIT);
+            // 群发消息频率限制不能超过10000/分钟,超过当前值默认取值为10000
+            if (config != null && config.getParamValue().matches("\\d+")) {
+                int sendLimit = Integer.parseInt(config.getParamValue());
+                if (sendLimit > 0 && sendLimit < 10000) {
+                    // 消息发送频率限制
+                    messageSendLimit = Integer.parseInt(config.getParamValue());
+                } else {
+                    // 默认发送10000/分钟
+                    messageSendLimit = 10000;
+                }
+            } else {
+                // 默认发送10000/分钟
+                messageSendLimit = 10000;
+            }
+
+            int finalMessageNum = messageNum;
+            if (EImReceiveType.ALL == info.getReceiveType()) {
+
+                // 推送消息给匹配用户
+                List<String> targetGroups = Arrays.stream(info.getTargetGroup().split(",")).collect(Collectors.toList());
+
+                targetGroups.forEach(clientType -> {
+                    boolean tenantFlag = false;
+                    switch (clientType) {
+                        case "TEACHER":
+                            clientType = "TEACHER";
+                            break;
+                        case "STUDENT":
+                            clientType = "STUDENT";
+                            break;
+                        case "TENANT_TEACHER":
+                            clientType = "TEACHER";
+                            tenantFlag = true;
+                            break;
+                        case "TENANT_STUDENT":
+                            clientType = "STUDENT";
+                            tenantFlag = true;
+                            break;
                     }
 
-                    int messageSendLimit; // 默认发送10000/分钟
-                    // 群发消息频率限制
-                    SysConfig config = sysConfigService.findByParamName(SysConfigConstant.MESSAGE_SEND_LIMIT);
-                    // 群发消息频率限制不能超过10000/分钟,超过当前值默认取值为10000
-                    if (config != null && config.getParamValue().matches("\\d+")) {
-                        int sendLimit = Integer.parseInt(config.getParamValue());
-                        if (sendLimit > 0 && sendLimit < 10000) {
-                            // 消息发送频率限制
-                            messageSendLimit = Integer.parseInt(config.getParamValue());
-                        } else {
-                            // 默认发送10000/分钟
-                            messageSendLimit = 10000;
-                        }
-                    } else {
-                        // 默认发送10000/分钟
-                        messageSendLimit = 10000;
+                    CustomerService.NotifyMessage receiveQuery = CustomerService.NotifyMessage.builder()
+                        .clientType(ClientEnum.valueOf(clientType))
+                        .tenantFlag(tenantFlag)
+                        .lockFlag(0)
+                        .delFlag(0)
+                        //.subjectIds(Arrays.stream(info.getSendSubject().split(",")).collect(Collectors.toList()))
+                        .build();
+                    if (StringUtils.isNotBlank(info.getSendSubject())) {
+                        receiveQuery.setSubjectIds(Arrays.stream(info.getSendSubject().split(",")).collect(Collectors.toList()));
                     }
 
-                    int finalMessageNum = messageNum;
-                    if (EImReceiveType.ALL == info.getReceiveType()) {
-
-                        // 推送消息给匹配用户
-                        List<String> targetGroups = Arrays.stream(info.getTargetGroup().split(",")).collect(Collectors.toList());
-
-                        targetGroups.forEach(clientType -> {
-                            boolean tenantFlag = false;
-                            switch (clientType) {
-                                case "TEACHER":
-                                    clientType = "TEACHER";
-                                    break;
-                                case "STUDENT":
-                                    clientType = "STUDENT";
-                                    break;
-                                case "TENANT_TEACHER":
-                                    clientType = "TEACHER";
-                                    tenantFlag = true;
-                                    break;
-                                case "TENANT_STUDENT":
-                                    clientType = "STUDENT";
-                                    tenantFlag = true;
-                                    break;
-                            }
-
-                            CustomerService.NotifyMessage receiveQuery = CustomerService.NotifyMessage.builder()
-                                .clientType(ClientEnum.valueOf(clientType))
-                                .tenantFlag(tenantFlag)
-                                .lockFlag(0)
-                                .delFlag(0)
-                                //.subjectIds(Arrays.stream(info.getSendSubject().split(",")).collect(Collectors.toList()))
-                                .build();
-                            if (StringUtils.isNotBlank(info.getSendSubject())) {
-                                receiveQuery.setSubjectIds(Arrays.stream(info.getSendSubject().split(",")).collect(Collectors.toList()));
-                            }
-
-                            Page<CustomerService.MessageReceives> page = PageUtil.getPage(1, 10);
-                            // 统计当前匹配用户数量
-                            getBaseMapper().selectMessageReceives(page, receiveQuery);
-
-                            // 计算总页数
-                            int pages = (int) (page.getTotal() - 1) / limit + 1;
-
-                            List<Integer> collect = IntStream.iterate(1, i -> i + 1).limit(pages).boxed().collect(Collectors.toList());
-
-                            // 线程休眠计算器
-                            int sleepCount = 0;
-                            for (Integer pageNum : collect) {
-
-                                List<String> receiveUserIds = getBaseMapper().selectMessageReceives(PageUtil.getPage(pageNum, limit), receiveQuery).stream()
-                                        .map(x -> String.valueOf(x.getUserId()))
-                                        .collect(Collectors.toList());
-
-                                String finalClientType = clientType;
-                                receiveUserIds = receiveUserIds.stream()
-                                        .map(x -> imGroupService.getImUserId(x, finalClientType))
-                                        .collect(Collectors.toList());
-
-                                // 累加线程休眠计算器,若大于指定阀值时,线程休眠1分钟
-                                sleepCount = messageSendSleepCondition(info, sleepCount, receiveUserIds.size(), finalMessageNum, messageSendLimit);
-
-                                batchSendCustomerServiceMessage(info, receiveNums, receiveUserIds);
-                            }
-                        });
-
-                    } else {
-
-                        // 查询条件
-                        CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery receiveQuery = CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery
-                                .builder().batchSendingId(info.getId()).build();
-
-                        Page<CustomerServiceReceiveWrapper.CustomerServiceReceive> page = PageUtil.getPage(1, 10);
-                        // 推送消息给指定用户
-                        customerServiceReceiveService.selectPage(page, receiveQuery);
-
-                        // 计算总页数
-                        int pages = (int) (page.getTotal() - 1) / limit + 1;
-
-                        List<Integer> collect = IntStream.iterate(1, i -> i + 1).limit(pages).boxed().collect(Collectors.toList());
-
-                        // 线程休眠计算器
-                        int sleepCount = 0;
-                        for (Integer pageNum : collect) {
-
-                            List<String> receiveUserIds = customerServiceReceiveService.selectPage(PageUtil.getPage(pageNum, limit), receiveQuery).getRecords().stream()
-                                    .map(x -> imGroupService.getImUserId(String.valueOf(x.getUserId()), x.getClientType()))
-                                    .collect(Collectors.toList());
-
-                            // 累加线程休眠计算器,若大于指定阀值时,线程休眠1分钟
-                            sleepCount = messageSendSleepCondition(info, sleepCount, receiveUserIds.size(), finalMessageNum, messageSendLimit);
-
-                            batchSendCustomerServiceMessage(info, receiveNums, receiveUserIds);
-                        }
+                    Page<CustomerService.MessageReceives> page = PageUtil.getPage(1, 10);
+                    // 统计当前匹配用户数量
+                    getBaseMapper().selectMessageReceives(page, receiveQuery);
+
+                    // 计算总页数
+                    int pages = (int) (page.getTotal() - 1) / limit + 1;
+
+                    List<Integer> collect = IntStream.iterate(1, i -> i + 1).limit(pages).boxed().collect(Collectors.toList());
+
+                    // 线程休眠计算器
+                    int sleepCount = 0;
+                    for (Integer pageNum : collect) {
+
+                        List<String> receiveUserIds = getBaseMapper().selectMessageReceives(PageUtil.getPage(pageNum, limit), receiveQuery).stream()
+                                .map(x -> String.valueOf(x.getUserId()))
+                                .collect(Collectors.toList());
+
+                        String finalClientType = clientType;
+                        receiveUserIds = receiveUserIds.stream()
+                                .map(x -> imGroupService.getImUserId(x, finalClientType))
+                                .collect(Collectors.toList());
+
+                        // 累加线程休眠计算器,若大于指定阀值时,线程休眠1分钟
+                        sleepCount = messageSendSleepCondition(info, sleepCount, receiveUserIds.size(), finalMessageNum, messageSendLimit);
+
+                        batchSendCustomerServiceMessage(info, receiveNums, receiveUserIds);
                     }
+                });
+
+            } else {
 
-                    // 更新消息状态为已发送
-                    lambdaUpdate()
-                            .eq(CustomerServiceBatchSending::getId, info.getId())
-                            .set(CustomerServiceBatchSending::getSendStatus, EImSendStatus.SEND)
-                            .set(CustomerServiceBatchSending::getReceiveNumber, receiveNums.stream().mapToInt(Integer::intValue).sum())
-                            .set(CustomerServiceBatchSending::getSendTime, DateTime.now().toDate())
-                            .update();
+                // 查询条件
+                CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery receiveQuery = CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery
+                        .builder().batchSendingId(info.getId()).build();
 
-                } catch (Exception e) {
-                    log.error("sendMessage id={}", info.getId(), e);
+                Page<CustomerServiceReceiveWrapper.CustomerServiceReceive> page = PageUtil.getPage(1, 10);
+                // 推送消息给指定用户
+                customerServiceReceiveService.selectPage(page, receiveQuery);
+
+                // 计算总页数
+                int pages = (int) (page.getTotal() - 1) / limit + 1;
+
+                List<Integer> collect = IntStream.iterate(1, i -> i + 1).limit(pages).boxed().collect(Collectors.toList());
+
+                // 线程休眠计算器
+                int sleepCount = 0;
+                for (Integer pageNum : collect) {
+
+                    List<String> receiveUserIds = customerServiceReceiveService.selectPage(PageUtil.getPage(pageNum, limit), receiveQuery).getRecords().stream()
+                            .map(x -> imGroupService.getImUserId(String.valueOf(x.getUserId()), x.getClientType()))
+                            .collect(Collectors.toList());
+
+                    // 累加线程休眠计算器,若大于指定阀值时,线程休眠1分钟
+                    sleepCount = messageSendSleepCondition(info, sleepCount, receiveUserIds.size(), finalMessageNum, messageSendLimit);
+
+                    batchSendCustomerServiceMessage(info, receiveNums, receiveUserIds);
                 }
+            }
 
-            });
 
-        }, 30L, TimeUnit.MINUTES);
+        } catch (Exception e) {
+            log.error("sendMessage id={}", info.getId(), e);
+        } finally {
+            // 更新消息状态为已发送
+            lambdaUpdate()
+                .eq(CustomerServiceBatchSending::getId, info.getId())
+                .set(CustomerServiceBatchSending::getSendStatus, EImSendStatus.SEND)
+                .set(CustomerServiceBatchSending::getReceiveNumber, receiveNums.stream().mapToInt(Integer::intValue).sum())
+                .set(CustomerServiceBatchSending::getSendEndTime, DateTime.now().toDate())
+                .update();
+        }
     }
 
     /**
@@ -788,9 +838,10 @@ public class CustomerServiceBatchSendingServiceImpl extends ServiceImpl<Customer
             Date endTime = DateTime.now().toDate();
 
             List<CustomerServiceBatchSending> batchSendings = lambdaQuery()
-                    .between(CustomerServiceBatchSending::getSendTime, startTime, endTime)
-                    .eq(CustomerServiceBatchSending::getSendType, EImSendType.SCHEDULED)
-                    .eq(CustomerServiceBatchSending::getSendStatus, EImSendStatus.WAIT)
+                    .lt(CustomerServiceBatchSending::getSendTime, endTime)
+//                    .eq(CustomerServiceBatchSending::getSendType, EImSendType.SCHEDULED)
+                    .in(CustomerServiceBatchSending::getSendStatus, EImSendStatus.WAIT,EImSendStatus.SENDING)
+                    .ne(CustomerServiceBatchSending::getSendFlag,1)
                     .list();
 
             if (CollectionUtils.isNotEmpty(batchSendings)) {

+ 31 - 16
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/EmployeeServiceImpl.java

@@ -149,22 +149,8 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Long, Employee> impleme
                 || sysUser.getLockFlag().equals(YesOrNoEnum.YES.getCode())
                 || employee.getLockFlag() == UserLockFlag.LOCKED) {
 
-                String imCustomerServiceId = imGroupCoreService.getImUserId(String.valueOf(param.getUserId()),
-                    ClientEnum.SYSTEM.getCode());
-
-                // 更新老师表的客服ID
-                teacherService.lambdaUpdate()
-                    .eq(Teacher::getImCustomerId, imCustomerServiceId)
-                    .set(Teacher::getCustomerId, null)
-                    .set(Teacher::getImCustomerId, "")
-                    .update();
-
-                // 更新学生表的客服ID
-                studentService.lambdaUpdate()
-                    .eq(Student::getImCustomerId, imCustomerServiceId)
-                    .set(Student::getCustomerId, null)
-                    .set(Student::getImCustomerId, "")
-                    .update();
+                // 清除客服绑定关系
+                clearCustomerService(param.getUserId(), SysUserType.SYSTEM.getCode());
             }
         }
         return HttpResponseResult.succeed(param);
@@ -202,4 +188,33 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Long, Employee> impleme
         return employeeDao.insertSysRole(sysRole);
     }
 
+    /**
+     * 清除客服绑定关系
+     *
+     * @param userId      用户ID
+     * @param sysUserType 用户类型
+     * @return Boolean
+     */
+    @Override
+    public Boolean clearCustomerService(Long userId, String sysUserType) {
+        // 清除客服绑定关系
+        String imCustomerServiceId = imGroupCoreService.getImUserId(String.valueOf(userId), sysUserType);
+
+        // 更新老师表的客服ID
+        teacherService.lambdaUpdate()
+            .eq(Teacher::getImCustomerId, imCustomerServiceId)
+            .set(Teacher::getCustomerId, null)
+            .set(Teacher::getImCustomerId, "")
+            .update();
+
+        // 更新学生表的客服ID
+        studentService.lambdaUpdate()
+            .eq(Student::getImCustomerId, imCustomerServiceId)
+            .set(Student::getCustomerId, null)
+            .set(Student::getImCustomerId, "")
+            .update();
+
+        return true;
+    }
+
 }

+ 3 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/StudentServiceImpl.java

@@ -34,7 +34,6 @@ import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
 import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.VipCardRecordWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupWrapper;
-import com.yonge.cooleshow.biz.dal.wrapper.teacher.TeacherWrapper;
 import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.CacheNameEnum;
@@ -907,12 +906,13 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> impleme
 
         save(student);
         //  与好友数量最少的客服建立好友关系
-        List<TeacherWrapper.TeacherFriend> customerServiceFriendNums = teacherDao.getCustomerServiceFriendNums();
+        /*List<TeacherWrapper.TeacherFriend> customerServiceFriendNums = teacherDao.getCustomerServiceFriendNums();
         if (!customerServiceFriendNums.isEmpty()) {
             Long teacherId = customerServiceFriendNums.get(0).getTeacherId();
             imUserFriendService.registerUserBindCustomerService(student.getUserId(),
                     Collections.singletonList(teacherId), ClientEnum.STUDENT);
-        }
+        }*/
+
         try {
             // 注册IM
             imGroupCoreService.register(String.valueOf(student.getUserId()),ClientEnum.STUDENT.getCode(), sysUser.getUsername(), avatar);

+ 11 - 6
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherServiceImpl.java

@@ -250,6 +250,10 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
 
         // 系统客服数量
         detail.setCustomerServiceNum(baseMapper.selectCustomerServiceV2().size());
+        if (Optional.ofNullable(detail.getCustomerService()).orElse(false)) {
+            // 老师本身是客服,不显示客服入口;重置客服数量为0
+            detail.setCustomerServiceNum(0);
+        }
 
         return detail;
     }
@@ -643,14 +647,14 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
             sendBindUnBindSMS(teacher.getUserId(), teacherSubmitReq.getPhone(), MessageTypeEnum.TEACHER_BIND_TENANT, teacher.getTenantId());
 
             //  与客服建立好友
-            if (!Boolean.TRUE.equals(teacher.getCustomerService())) {
+            /*if (!Boolean.TRUE.equals(teacher.getCustomerService())) {
                 List<TeacherWrapper.TeacherFriend> customerServiceFriendNums = this.getBaseMapper().getCustomerServiceFriendNums();
                 if (!customerServiceFriendNums.isEmpty()) {
                     Long teacherId = customerServiceFriendNums.get(0).getTeacherId();
                     imUserFriendService.registerUserBindCustomerService(teacher.getUserId(),
                             Collections.singletonList(teacherId), ClientEnum.TEACHER);
                 }
-            }
+            }*/
         } else {
             // 客服状态变更,移交好友信息
             Boolean customerService = teacher.getCustomerService();
@@ -736,7 +740,7 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
                 .set(Student::getCustomerId, null));
     }
 
-    private List<TeacherWrapper.CustomerServiceSendMsg2User> transferFriendV2(Long userId, boolean saveGroupFriend){
+    /*private List<TeacherWrapper.CustomerServiceSendMsg2User> transferFriendV2(Long userId, boolean saveGroupFriend){
         List<TeacherWrapper.CustomerServiceSendMsg2User> result = new ArrayList<>();
         // 所有的好友
         List<ImUserFriend> userFriendList = imUserFriendService.lambdaQuery()
@@ -862,9 +866,9 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
 //            imUserFriendService.sendCustomerServiceAddFriendMessage(teacherId, customerTitle, customerMessage, new ArrayList<>(studentIds), ClientEnum.STUDENT);
         });
         return result;
-    }
+    }*/
 
-    private List<Long> getSameTenant(Long teacherId, Set<Long> userIds, ClientEnum clientEnum) {
+    /*private List<Long> getSameTenant(Long teacherId, Set<Long> userIds, ClientEnum clientEnum) {
         Teacher teacher = this.getById(teacherId);
         Long tenantId = teacher.getTenantId();
         if (tenantId == null || tenantId <= 0) {
@@ -881,7 +885,8 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
                     .map(Teacher::getUserId).collect(Collectors.toList());
         }
         return new ArrayList<>();
-    }
+    }*/
+
     /***
      * 封装用户信息
      * @author liweifan

+ 2 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/CustomerServiceBatchSendingMapper.xml

@@ -15,12 +15,14 @@
         , t.send_type_ AS sendType
         , t.send_status_ AS sendStatus
         , t.send_time_ AS sendTime
+        , t.send_end_time_ AS sendEndTime
         , t.condition_ AS `condition`
         , t.title_ AS title
         , t.text_message_ AS textMessage
         , t.img_message_ AS imgMessage
         , t.img_url_ AS imgUrl
         , t.sender_id_ AS senderId
+        , t.send_flag_ AS sendFlag
         , t.create_by_ AS createBy
         , t.create_time_ AS createTime
     </sql>

+ 7 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/TeacherMapper.xml

@@ -179,6 +179,13 @@
             <if test="param.subjectId != null">
                 and find_in_set(#{param.subjectId},t.subject_id_)
             </if>
+            <if test="param.subjectIds != null and param.subjectIds.size() != 0">
+                and (
+                <foreach collection="param.subjectIds" item="subjectId" separator=" or " open="(" close=")">
+                    find_in_set(#{subjectId},t.subject_id_)
+                </foreach>
+                )
+            </if>
             <if test="param.isSettlement != null">
                 and t.is_settlement_ = #{param.isSettlement}
             </if>