소스 검색

fix 群成员人数限制

Eric 1 년 전
부모
커밋
0cbc7df886

+ 12 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentPaymentDao.java

@@ -87,5 +87,17 @@ public interface CourseScheduleStudentPaymentDao extends BaseMapper<CourseSchedu
     List<CourseScheduleStudentVo> selectUser();
 
     List<BasicUserInfoDto> queryNoJoinStu(@Param("scheduleId") String scheduleId, @Param("studentIds") List<String> studentIds);
+
+    /**
+     * 更新用户入群状态
+     * @param courseGroupId 课程组id
+     * @param courseGroupType 课程组类型
+     * @param groupJoin 入群状态
+     * @param studentIds 学员id
+     */
+    void updateGroupJoinStatus(@Param("courseGroupId") Long courseGroupId,
+                               @Param("courseGroupType") String courseGroupType,
+                               @Param("groupJoin") Boolean groupJoin,
+                               @Param("studentIds") List<Long> studentIds);
 }
 

+ 4 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseScheduleStudentPayment.java

@@ -65,5 +65,9 @@ public class CourseScheduleStudentPayment implements Serializable {
     @ApiModelProperty(value = "类型 practice陪练课 live直播课")
     private String courseType;
 
+    @TableField(value = "group_join_")
+    @ApiModelProperty("入群标记")
+    private Boolean groupJoin;
+
 }
 

+ 20 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java

@@ -10,11 +10,21 @@ import com.yonge.cooleshow.biz.dal.dto.search.PracticeTeacherSearch;
 import com.yonge.cooleshow.biz.dal.entity.CourseCalendarEntity;
 import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
 import com.yonge.cooleshow.biz.dal.entity.TeacherSubjectPrice;
-import com.yonge.cooleshow.biz.dal.entity.UserOrderDetail;
-import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.vo.ArrangeCourseVo;
+import com.yonge.cooleshow.biz.dal.vo.CourseAdjustVo;
+import com.yonge.cooleshow.biz.dal.vo.CourseScheduleRecordVo;
+import com.yonge.cooleshow.biz.dal.vo.CourseStudent;
+import com.yonge.cooleshow.biz.dal.vo.CourseStudentVo;
+import com.yonge.cooleshow.biz.dal.vo.MyCourseVo;
+import com.yonge.cooleshow.biz.dal.vo.PianoClassVo;
+import com.yonge.cooleshow.biz.dal.vo.PianoRoomTimeVo;
+import com.yonge.cooleshow.biz.dal.vo.PracticeTeacherVo;
+import com.yonge.cooleshow.biz.dal.vo.StudentHomePage;
+import com.yonge.cooleshow.biz.dal.vo.TeacherLiveCourseInfoVo;
+import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
 import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
-import com.yonge.cooleshow.biz.dal.wrapper.course.CourseScheduleWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.course.CourseScheduleWrapper;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.page.PageInfo;
@@ -249,6 +259,13 @@ public interface CourseScheduleService extends IService<CourseSchedule> {
 
     void arrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId);
 
+    /**
+     * 校验排课
+     * @param arrangeCourseVo 排课参数
+     * @param teacherId 老师id
+     */
+    String checkArrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId);
+
     Map<String, Object> selectConsumeTime(String month, Long teacherId);
 
     PageInfo<CourseScheduleRecordVo> selectConsumeTimeList(Map<String, Object> param);

+ 2 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImGroupService.java

@@ -85,10 +85,11 @@ public interface ImGroupService extends IService<ImGroup> {
     * @description: 成课后自动创建群聊,建议放在最后执行
      * @param courseGroupId 课程组编号
      * @param courseGroupType 课程组类型
+     * @param noGroupJoinUserIds 未加入群聊的用户编号
     * @author zx
     * @date 2022/3/22 11:17
     */
-    String autoCreate(Long courseGroupId,String courseGroupType) throws Exception;
+    String autoCreate(Long courseGroupId,String courseGroupType, List<Long> noGroupJoinUserIds) throws Exception;
 
     List<GroupMemberWrapper.ImGroupMember> getImGroupMembers(List<ImGroupMember> groupMemberList);
 

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseGroupServiceImpl.java

@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.beust.jcommander.internal.Lists;
+import com.google.common.collect.Lists;
 import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
@@ -1251,7 +1251,7 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
                     //人数达标则修改课程组为进行中状态
                     courseGroup.setStatus(CourseGroupEnum.ING.getCode());
                     //创建群聊 并添加人员到群中
-                    String imGroupId = imGroupService.autoCreate(courseGroup.getId(), courseGroup.getType());
+                    String imGroupId = imGroupService.autoCreate(courseGroup.getId(), courseGroup.getType(), Lists.newArrayList());
 
                     imGroupMemberService.initGroupMembers(imGroupId, userIds, ImGroupMemberRoleType.STUDENT);
                     //添加老师进群

+ 34 - 14
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java

@@ -10,9 +10,12 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.microsvc.toolkit.common.spring.SpringContextHolder;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dao.*;
+import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.dto.PracticeScheduleDto;
 import com.yonge.cooleshow.biz.dal.dto.UserAccountRecordDto;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
@@ -1955,15 +1958,23 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
      * @Date: 2022/5/27
      */
     public void arrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId) {
-        DistributedLock.of(redissonClient)
-                .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey("teacherId:" + teacherId)
-                        , () -> this.checkArrangeCourse(arrangeCourseVo, teacherId), 60L, TimeUnit.SECONDS);
+
+        // 返回未加入群用户消息
+        String message = DistributedLock.of(redissonClient)
+            .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey("teacherId:" + teacherId)
+                , () -> SpringContextHolder.getBean(CourseScheduleServiceImpl.class).checkArrangeCourse(arrangeCourseVo, teacherId),
+                60L, TimeUnit.SECONDS);
     }
 
+    /**
+     * 校验排课
+     * @param arrangeCourseVo 排课参数
+     * @param teacherId 老师id
+     */
     @Transactional(rollbackFor = Exception.class)
-    public void checkArrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId) {
+    public String checkArrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId) {
         Integer classNum = arrangeCourseVo.getClassNum();//课时数
-        Integer singleClssTime = arrangeCourseVo.getSingleClssTime();//单课时长
+        Integer singleClassTime = arrangeCourseVo.getSingleClssTime();//单课时长
         List<Long> studentIds = arrangeCourseVo.getStudentIds();//学员id集合
 
         String formula = sysConfigService.findConfigValue(SysConfigConstant.PIANO_ROOM_TIME_FORMULA);
@@ -1971,13 +1982,13 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         if (n == null) {
             throw new BizException("公式转换失败");
         }
-        Integer consumTime = classNum * singleClssTime * n;//消耗时长 课程数*单课时长*人数
+        Integer consumTime = classNum * singleClassTime * n;//消耗时长 课程数*单课时长*人数
 
         List<CourseTimeEntity> timeList = arrangeCourseVo.getTimeList();//选课时间
         Integer consumeTime = arrangeCourseVo.getConsumeTime();
 
         log.info("classNum:" + classNum);
-        log.info("singleClssTime:" + singleClssTime);
+        log.info("singleClssTime:" + singleClassTime);
         log.info("n:" + n);
         log.info("消耗时长:" + consumTime);
         log.info("传入时长:" + consumeTime);
@@ -2002,7 +2013,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
             if (timeList.get(i).getStartTime().before(new Date())) {
                 throw new BizException("上课时间必须大于当前时间");
             }
-            if (!DateUtil.offsetMinute(timeList.get(i).getStartTime(), singleClssTime).equals(timeList.get(i).getEndTime())) {
+            if (!DateUtil.offsetMinute(timeList.get(i).getStartTime(), singleClassTime).equals(timeList.get(i).getEndTime())) {
                 throw new BizException("第{}节课结束时间计算错误", i + 1);
             }
         }
@@ -2059,7 +2070,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         courseGroup.setTeacherId(teacherId);
         courseGroup.setName(arrangeCourseVo.getCourseName());
         courseGroup.setSubjectId(arrangeCourseVo.getSubjectId());
-        courseGroup.setSingleCourseMinutes(singleClssTime);
+        courseGroup.setSingleCourseMinutes(singleClassTime);
         courseGroup.setCourseNum(classNum);
         courseGroup.setStatus(CourseGroupEnum.ING.getCode());
         courseGroup.setCreatedBy(teacherId);
@@ -2079,7 +2090,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
             schedule.setLock(0);
             schedule.setStatus(CourseScheduleEnum.NOT_START.getCode());
             schedule.setCreatedBy(teacherId);
-            schedule.setSingleCourseTime(singleClssTime);
+            schedule.setSingleCourseTime(singleClassTime);
             baseMapper.insert(schedule);
 
             //添加payment
@@ -2113,14 +2124,14 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
                             roomTimeLock.setFrozenTime(frozenTimeLock + consumTime);
                             pianoRoomTimeDao.update(roomTimeLock, Wrappers.<PianoRoomTime>lambdaQuery().eq(PianoRoomTime::getTeacherId, teacherId));
                             return null;
-                        }, null, 10l);
+                        }, null, 10L);
 
+        List<Long> noGroupJoinUserIds = Lists.newArrayList();
         //创建群聊
         try {
-            imGroupService.autoCreate(courseGroup.getId(), CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
+            imGroupService.autoCreate(courseGroup.getId(), CourseScheduleEnum.PIANO_ROOM_CLASS.getCode(), noGroupJoinUserIds);
         } catch (Exception e) {
-            log.error("琴房课程组id:{},创建群聊失败:{}", courseGroup.getId(), e);
-            e.printStackTrace();
+            log.error("琴房课程组id:{},创建群聊失败", courseGroup.getId(), e);
         }
 
         for (Long studentId : studentIds) {
@@ -2131,6 +2142,15 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         }
         //清除老师缓存
         redissonClient.getBucket(CacheNameEnum.TEACHER_TOTAL.getRedisKey(teacherId)).delete();
+
+        String message = "";
+        if (CollectionUtils.isNotEmpty(noGroupJoinUserIds)) {
+            String collect = teacherService.getDao().findBasicUserInfo(Sets.newHashSet(noGroupJoinUserIds)).stream()
+                .map(BasicUserInfo::getUsername).collect(Collectors.joining());
+            // 返回未加入群用户消息
+            message = collect + "由于群成员人数达到上限,未能进入课程群";
+        }
+        return message;
     }
 
     /**

+ 18 - 14
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImGroupMemberAuditServiceImpl.java

@@ -100,12 +100,7 @@ public class ImGroupMemberAuditServiceImpl extends ServiceImpl<ImGroupMemberAudi
         DistributedLock.of(redissonClient).runIfLockToFunction(lockName, (x)-> {
 
             // 统计群成员数量,大于等于群组最大人数时,不允许加入
-            int memberCount = imGroupMemberService.countGroupMember(groupId);
-            // 查询群成员人数限制
-            SysConfig byParamName = sysConfigService.findByParamName(SysConfigConstant.GROUP_MEMBER_LIMIT);
-            if (Objects.nonNull(byParamName) && memberCount >= Integer.parseInt(byParamName.getParamValue())) {
-                throw new BizException("群成员数量已达上限");
-            }
+            verifyGroupMemberJoinLimit(groupId);
 
             try {
                 Date date = new Date();
@@ -158,14 +153,8 @@ public class ImGroupMemberAuditServiceImpl extends ServiceImpl<ImGroupMemberAudi
         String lockName = "klx:group_member_audit_lock:" + groupId;
         DistributedLock.of(redissonClient).runIfLockToFunction(lockName, (x)-> {
 
-            // 统计群成员数量,大于等于群组最大人数时,不允许加入
-            int memberCount = imGroupMemberService.countGroupMember(groupId);
-            // 查询群成员人数限制
-            SysConfig config = sysConfigService.findByParamName(SysConfigConstant.GROUP_MEMBER_LIMIT);
-            if (Objects.nonNull(config) && memberCount >= Integer.parseInt(config.getParamValue())) {
-                throw new BizException("群成员数量已达上限");
-            }
-
+            // 校验群成员加入限制
+            verifyGroupMemberJoinLimit(groupId);
             try {
                 //修改审核状态
                 baseMapper.batchUpdateAuditStatus(auditIds,auditStatus.getCode());
@@ -189,6 +178,21 @@ public class ImGroupMemberAuditServiceImpl extends ServiceImpl<ImGroupMemberAudi
     }
 
     /**
+     * 校验群成员加入限制
+     * @param groupId 群组ID
+     */
+    private void verifyGroupMemberJoinLimit(String groupId) {
+        // 统计群成员数量,大于等于群组最大人数时,不允许加入
+        int memberCount = imGroupMemberService.countGroupMember(groupId);
+        // 查询群成员人数限制
+        SysConfig config = sysConfigService.findByParamName(SysConfigConstant.GROUP_MEMBER_LIMIT);
+        if (Objects.nonNull(config) && Integer.parseInt(config.getParamValue()) > 0
+            && memberCount > Integer.parseInt(config.getParamValue())) {
+            throw new BizException("群成员数量已达上限");
+        }
+    }
+
+    /**
      * 发送通过消息
      *
      * @param auditIds

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

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import com.microsvc.toolkit.middleware.common.http.ImageUtil;
 import com.microsvc.toolkit.middleware.im.ImPluginContext;
 import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
@@ -33,6 +34,7 @@ import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.TeacherSearch;
 import com.yonge.cooleshow.biz.dal.entity.*;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
 import com.yonge.cooleshow.biz.dal.enums.ImGroupMemberRoleType;
 import com.yonge.cooleshow.biz.dal.enums.ImGroupType;
 import com.yonge.cooleshow.biz.dal.enums.RoleEnum;
@@ -376,14 +378,15 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public String autoCreate(Long courseGroupId, String courseGroupType) throws Exception {
+    public String autoCreate(Long courseGroupId, String courseGroupType, List<Long> noGroupJoinUserIds) throws Exception {
         //获取课程组
         CourseGroup courseGroup = courseGroupService.getById(courseGroupId);
         if (courseGroup.getTeacherId() == null) {
             return null;
         }
-        //获取学员列表
+        //获取学员列表,按购买时间顺序升序排列返回
         Set<Long> studentIds = courseScheduleStudentPaymentDao.queryStudentIds(courseGroupId, courseGroupType);
+        // studentIds集合中所有null元素移除
         studentIds.removeAll(Collections.singleton(null));
         if (CollectionUtils.isEmpty(studentIds)) {
             return null;
@@ -408,11 +411,32 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
         imGroup.setCourseGroupId(courseGroupId);
 //        this.baseMapper.insert(imGroup);
 
-
         String groupId = createImGroup(imGroup);
-//        // 添加学生
-        List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMembers(groupId, studentIds,
-                ImGroupMemberRoleType.STUDENT);
+
+        // 直播课、琴房课校验群成员人数限制
+        if (CourseScheduleEnum.PIANO_ROOM_CLASS.getCode().equals(courseGroupType)
+            || CourseScheduleEnum.LIVE.getCode().equals(courseGroupType)) {
+
+            // 增加群成员人数限制,若超过限制则不添加到群组
+            SysConfig config = sysConfigService.findByParamName(SysConfigConstant.GROUP_MEMBER_LIMIT);
+            if (Objects.nonNull(config) && Integer.parseInt(config.getParamValue()) > 0) {
+                int groupMemberLimit = Integer.parseInt(config.getParamValue());
+                if (CollectionUtils.size(studentIds) > groupMemberLimit) {
+
+                    // 已加入群组用户标记
+                    List<Long> userIds = Lists.newArrayList(studentIds);
+                    studentIds = Sets.newHashSet(userIds.subList(0, groupMemberLimit));
+                    // 未加入群组用户标记
+                    noGroupJoinUserIds.addAll(userIds.subList(groupMemberLimit, userIds.size()));
+                    // 重置用户入群加入标记
+                    courseScheduleStudentPaymentDao.updateGroupJoinStatus(courseGroupId, courseGroupType, false,
+                        noGroupJoinUserIds);
+                }
+            }
+        }
+
+        // 添加学生
+        List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMembers(groupId, studentIds, ImGroupMemberRoleType.STUDENT);
         List<com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupMemberWrapper.ImGroupMember> groupMemberList = Lists.newArrayList();
         for (ImGroupMember groupMember : groupMembers) {
             groupMemberList.add(com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupMemberWrapper.ImGroupMember.builder()
@@ -436,7 +460,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 //        this.rtcCreate(courseGroup.getTeacherId(), imGroupId, imGroup.getName(),imGroup.getImg());
 //        //加入融云群
 //        imGroupMemberService.join(groupMembers, imGroupId);
-        return groupId.toString();
+        return groupId;
     }
 
 

+ 23 - 1
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleStudentPaymentMapper.xml

@@ -13,12 +13,13 @@
         <result column="created_time_" jdbcType="TIMESTAMP" property="createdTime"/>
         <result column="updated_time_" jdbcType="TIMESTAMP" property="updatedTime"/>
         <result column="course_type_" jdbcType="VARCHAR" property="courseType"/>
+        <result column="group_join_" jdbcType="TINYINT" property="groupJoin"/>
     </resultMap>
 
     <sql id="Base_Column_List">
         id_
         , user_id_, course_group_id_, course_id_, order_no_, original_price_, expect_price_,
-        actual_price_, created_time_, updated_time_, course_type_
+        actual_price_, created_time_, updated_time_, course_type_, group_join_
     </sql>
 
     <insert id="insertBatch" keyColumn="id_" keyProperty="id" useGeneratedKeys="true"
@@ -77,6 +78,26 @@
             </if>
         </where>
     </update>
+    <!--更新用户课程组入群状态-->
+    <update id="updateGroupJoinStatus">
+        UPDATE course_schedule_student_payment cssp
+        <set>
+            <if test="groupJoin != null">
+                cssp.group_join_ = #{groupJoin}
+            </if>
+        </set>
+        <where>
+            <if test="courseGroupId != null">
+                AND cssp.course_group_id_ = #{courseGroupId}
+            </if>
+            <if test="courseGroupType != null and courseGroupType != ''">
+                AND cssp.course_type_ = #{courseGroupType}
+            </if>
+            <if test="studentIds != null and studentIds.size > 0">
+                AND cssp.user_id_ IN <foreach collection="studentIds" item="studentId" open="(" close=")" separator=",">#{studentId}</foreach>
+            </if>
+        </where>
+    </update>
     <select id="queryStudentIds" resultType="java.lang.Long">
         SELECT DISTINCT user_id_ FROM course_schedule_student_payment
         <where>
@@ -87,6 +108,7 @@
                 AND course_type_ = #{courseGroupType}
             </if>
         </where>
+        ORDER BY created_time_ ASC
     </select>
     <select id="queryByCourseId" resultMap="BaseResultMap">
         SELECT <include refid="Base_Column_List"/> FROM course_schedule_student_payment