Browse Source

Merge branch 'saas_2022_05_17_activity' of http://git.dayaedu.com/yonge/mec into master_saas

zouxuan 3 years ago
parent
commit
780a586054
51 changed files with 1180 additions and 237 deletions
  1. 5 0
      mec-biz/pom.xml
  2. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImLiveBroadcastRoomDao.java
  3. 15 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImSendGroupMessageDao.java
  4. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/MusicGroupPaymentCalenderDetailDao.java
  5. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentPaymentOrderDao.java
  6. 12 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MemberPayParamDto.java
  7. 18 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImLiveBroadcastRoom.java
  8. 153 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImSendGroupMessage.java
  9. 27 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/vo/BaseRoomUserVo.java
  10. 1 30
      mec-biz/src/main/java/com/ym/mec/biz/dal/vo/RoomUserInfoVo.java
  11. 4 4
      mec-biz/src/main/java/com/ym/mec/biz/service/ImGroupMemberService.java
  12. 8 6
      mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveBroadcastRoomService.java
  13. 17 0
      mec-biz/src/main/java/com/ym/mec/biz/service/ImSendGroupMessageService.java
  14. 2 5
      mec-biz/src/main/java/com/ym/mec/biz/service/MemberRankSettingService.java
  15. 3 0
      mec-biz/src/main/java/com/ym/mec/biz/service/StudentPaymentOrderService.java
  16. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/service/StudentRegistrationService.java
  17. 36 1
      mec-biz/src/main/java/com/ym/mec/biz/service/SysMessageService.java
  18. 2 8
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ClassGroupServiceImpl.java
  19. 4 2
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupMemberServiceImpl.java
  20. 205 69
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java
  21. 100 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImSendGroupMessageServiceImpl.java
  22. 28 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MemberRankSettingServiceImpl.java
  23. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderDetailServiceImpl.java
  24. 3 3
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderServiceImpl.java
  25. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentManageServiceImpl.java
  26. 5 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentPaymentOrderServiceImpl.java
  27. 3 2
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentRegistrationServiceImpl.java
  28. 59 12
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMessageServiceImpl.java
  29. 3 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreServiceImpl.java
  30. 8 1
      mec-biz/src/main/resources/config/mybatis/ImLiveBroadcastRoomMapper.xml
  31. 106 0
      mec-biz/src/main/resources/config/mybatis/ImSendGroupMessageMapper.xml
  32. 3 0
      mec-biz/src/main/resources/config/mybatis/MusicGroupPaymentCalenderDetailMapper.xml
  33. 8 0
      mec-biz/src/main/resources/config/mybatis/StudentPaymentOrderMapper.xml
  34. 1 1
      mec-client-api/src/main/java/com/ym/mec/im/ImFeignService.java
  35. 1 1
      mec-client-api/src/main/java/com/ym/mec/im/fallback/ImFeignServiceFallback.java
  36. 60 0
      mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImFileMessage.java
  37. 85 0
      mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImMessageDto.java
  38. 4 4
      mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImMessageModel.java
  39. 58 11
      mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImTxtMessage.java
  40. 11 1
      mec-common/common-core/src/main/java/com/ym/mec/common/entity/UploadReturnBean.java
  41. 16 10
      mec-im/src/main/java/com/ym/controller/GroupController.java
  42. 2 2
      mec-im/src/main/java/com/ym/controller/PrivateController.java
  43. 2 2
      mec-im/src/main/java/com/ym/controller/SystemController.java
  44. 1 1
      mec-student/src/main/java/com/ym/mec/student/controller/DegreeController.java
  45. 6 0
      mec-student/src/main/java/com/ym/mec/student/controller/MemberRankController.java
  46. 26 31
      mec-web/src/main/java/com/ym/mec/web/controller/ImGroupController.java
  47. 5 4
      mec-web/src/main/java/com/ym/mec/web/controller/ImLiveBroadcastRoomController.java
  48. 36 0
      mec-web/src/main/java/com/ym/mec/web/controller/ImSendGroupMessageController.java
  49. 0 1
      mec-web/src/main/java/com/ym/mec/web/controller/StudentManageController.java
  50. 19 21
      mec-web/src/main/java/com/ym/mec/web/controller/TaskController.java
  51. 1 0
      mec-web/src/main/java/com/ym/mec/web/controller/UploadFileController.java

+ 5 - 0
mec-biz/pom.xml

@@ -46,5 +46,10 @@
             <artifactId>redisson-spring-boot-starter</artifactId>
             <version>${redisson.version}</version>
         </dependency>
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.11</version>
+        </dependency>
     </dependencies>
 </project>

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImLiveBroadcastRoomDao.java

@@ -24,5 +24,7 @@ public interface ImLiveBroadcastRoomDao extends BaseMapper<ImLiveBroadcastRoom>
 
     int insertBatch(@Param("entities") List<ImLiveBroadcastRoom> entities);
 
+    IPage<Map<Integer,Object>> queryUserPageByTenantId(Page<Map<Integer,Object>> page);
+
 }
 

+ 15 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImSendGroupMessageDao.java

@@ -0,0 +1,15 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.biz.dal.entity.ImSendGroupMessage;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+import java.util.List;
+
+public interface ImSendGroupMessageDao extends BaseDAO<Long, ImSendGroupMessage> {
+
+	List<ImSendGroupMessage> findBySendFlag(@Param("sendFlag") Boolean sendFlag, @Param("sendTime") Date sendTime);
+
+	void batchUpdateSendFlag(@Param("sendGroupMessages") List<ImSendGroupMessage> sendGroupMessages);
+}

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/MusicGroupPaymentCalenderDetailDao.java

@@ -246,7 +246,7 @@ public interface MusicGroupPaymentCalenderDetailDao extends BaseDAO<Long, MusicG
 	 * @param musicGroupId
 	 * @return
 	 */
-	List<Integer> queryNoPaymentUserIds(@Param("musicGroupId") String musicGroupId, @Param("userIds") List<Integer> userIds);
+	List<Integer> queryNoPaymentUserIds(@Param("musicGroupId") String musicGroupId, @Param("userIds") List<Integer> userIds, @Param("batchNo") String batchNo);
 
 	/**
 	 * @describe 未缴费学员列表

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentPaymentOrderDao.java

@@ -454,4 +454,6 @@ public interface StudentPaymentOrderDao extends BaseDAO<Long, StudentPaymentOrde
 
     //获取学员之前的乐团缴费订单数量
     int getStudentMusicOrderNum(@Param("musicGroupId") String musicGroupId, @Param("userId") Integer userId, @Param("orderId") Long orderId);
+
+    StudentPaymentOrder getMemberIngOrder(@Param("type") OrderTypeEnum type, @Param("status") DealStatusEnum status);
 }

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MemberPayParamDto.java

@@ -1,5 +1,7 @@
 package com.ym.mec.biz.dal.dto;
 
+import com.ym.mec.biz.dal.enums.PeriodEnum;
+
 import java.io.Serializable;
 import java.math.BigDecimal;
 
@@ -16,6 +18,16 @@ public class MemberPayParamDto extends PayParamBasicDto implements Serializable
     //如果isRepeatPay = true 则需要传入订单号
     private String orderNo;
 
+    private PeriodEnum periodEnum;
+
+    public PeriodEnum getPeriodEnum() {
+        return periodEnum;
+    }
+
+    public void setPeriodEnum(PeriodEnum periodEnum) {
+        this.periodEnum = periodEnum;
+    }
+
     public BigDecimal getAmount() {
         return amount;
     }

+ 18 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImLiveBroadcastRoom.java

@@ -169,26 +169,44 @@ public class ImLiveBroadcastRoom implements Serializable {
         this.roomConfig = roomConfig;
     }
 
+    /**
+     * 直播状态 0未开始 1开始 2已结束
+     */
     public Integer getLiveState() {
         return liveState;
     }
 
+    /**
+     * 直播状态 0未开始 1开始 2已结束
+     */
     public void setLiveState(Integer liveState) {
         this.liveState = liveState;
     }
 
+    /**
+     * 房间状态 0正常 1已删除 2销毁
+     */
     public Integer getRoomState() {
         return roomState;
     }
 
+    /**
+     * 房间状态 0正常 1已删除 2销毁
+     */
     public void setRoomState(Integer roomState) {
         this.roomState = roomState;
     }
 
+    /**
+     * 是否在首页推广 0否 1是 - 每个机构只能有一个直播间在首页推广
+     */
     public Integer getPopularize() {
         return popularize;
     }
 
+    /**
+     * 是否在首页推广 0否 1是 - 每个机构只能有一个直播间在首页推广
+     */
     public void setPopularize(Integer popularize) {
         this.popularize = popularize;
     }

+ 153 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImSendGroupMessage.java

@@ -0,0 +1,153 @@
+package com.ym.mec.biz.dal.entity;
+
+import com.ym.mec.biz.dal.enums.ImSendTypeEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+public class ImSendGroupMessage {
+
+    private Long id;
+
+    @ApiModelProperty(value = "消息内容")
+    private String messageContent;
+
+    @ApiModelProperty(value = "发送人")
+    @NotBlank(message = "发送人不能为空")
+    private String senderId;
+
+    @ApiModelProperty(value = "附加字段")
+    private String extra;
+
+    @ApiModelProperty(value = "目标用户(群组)")
+    @NotNull(message = "目标用户(群组)不能为空")
+    private String targetIds;
+
+    @ApiModelProperty(value = "文件地址")
+    private String fileUrl;
+
+    @ApiModelProperty(value = "文件名称")
+    private String fileName;
+
+    @ApiModelProperty(value = "文件大小")
+    private Long fileSize;
+
+    @ApiModelProperty(value = "消息类型(IMG,FILE)")
+    private ImSendTypeEnum messageType;
+
+    @ApiModelProperty(value = "是否发送")
+    private Boolean sendFlag = false;
+
+    @ApiModelProperty(value = "定时发送时间")
+    private Date sendTime;
+
+    private Date createTime;
+
+    private Date updateTime;
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Boolean getSendFlag() {
+        return sendFlag;
+    }
+
+    public void setSendFlag(Boolean sendFlag) {
+        this.sendFlag = sendFlag;
+    }
+
+    public Date getSendTime() {
+        return sendTime;
+    }
+
+    public void setSendTime(Date sendTime) {
+        this.sendTime = sendTime;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+
+    public ImSendTypeEnum getMessageType() {
+        return messageType;
+    }
+
+    public void setMessageType(ImSendTypeEnum messageType) {
+        this.messageType = messageType;
+    }
+
+    public String getMessageContent() {
+        return messageContent;
+    }
+
+    public void setMessageContent(String messageContent) {
+        this.messageContent = messageContent;
+    }
+
+    public String getSenderId() {
+        return senderId;
+    }
+
+    public void setSenderId(String senderId) {
+        this.senderId = senderId;
+    }
+
+    public String getExtra() {
+        return extra;
+    }
+
+    public void setExtra(String extra) {
+        this.extra = extra;
+    }
+
+    public String getTargetIds() {
+        return targetIds;
+    }
+
+    public void setTargetIds(String targetIds) {
+        this.targetIds = targetIds;
+    }
+
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public Long getFileSize() {
+        return fileSize;
+    }
+
+    public void setFileSize(Long fileSize) {
+        this.fileSize = fileSize;
+    }
+}

+ 27 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/vo/BaseRoomUserVo.java

@@ -0,0 +1,27 @@
+package com.ym.mec.biz.dal.vo;
+
+import java.io.Serializable;
+
+public class BaseRoomUserVo implements Serializable {
+
+    private Integer userId;
+
+    private String userName;
+
+    public Integer getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Integer userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+}

+ 1 - 30
mec-biz/src/main/java/com/ym/mec/biz/dal/vo/RoomUserInfoVo.java

@@ -9,10 +9,7 @@ import java.util.Date;
  * @author hgw
  * Created by 2022-02-24
  */
-public class RoomUserInfoVo implements Serializable {
-    private Integer userId;
-
-    private String userName;
+public class RoomUserInfoVo extends BaseRoomUserVo implements Serializable  {
 
     private Integer tenantId;
 
@@ -27,25 +24,6 @@ public class RoomUserInfoVo implements Serializable {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date dynamicLookTime;
 
-    //0:在房间 1:不在房间
-    private Integer state;
-
-    public Integer getUserId() {
-        return userId;
-    }
-
-    public void setUserId(Integer userId) {
-        this.userId = userId;
-    }
-
-    public String getUserName() {
-        return userName;
-    }
-
-    public void setUserName(String userName) {
-        this.userName = userName;
-    }
-
     public Integer getTotalViewTime() {
         return totalViewTime;
     }
@@ -78,11 +56,4 @@ public class RoomUserInfoVo implements Serializable {
         this.tenantId = tenantId;
     }
 
-    public Integer getState() {
-        return state;
-    }
-
-    public void setState(Integer state) {
-        this.state = state;
-    }
 }

+ 4 - 4
mec-biz/src/main/java/com/ym/mec/biz/service/ImGroupMemberService.java

@@ -1,14 +1,14 @@
 package com.ym.mec.biz.service;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.ImGroup;
 import com.ym.mec.biz.dal.entity.ImGroupMember;
+import com.ym.mec.biz.dal.entity.ImSendGroupMessage;
 import com.ym.mec.common.service.BaseService;
 
+import java.util.List;
+import java.util.Map;
+
 public interface ImGroupMemberService extends BaseService<Long, ImGroupMember> {
 
 	/**

+ 8 - 6
mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveBroadcastRoomService.java

@@ -3,8 +3,8 @@ package com.ym.mec.biz.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ym.mec.biz.dal.dto.ImLiveBroadcastRoomDto;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
+import com.ym.mec.biz.dal.vo.BaseRoomUserVo;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
-import com.ym.mec.biz.dal.vo.RoomUserInfoVo;
 import com.ym.mec.common.entity.ImUserState;
 import com.ym.mec.common.page.PageInfo;
 
@@ -67,14 +67,16 @@ public interface ImLiveBroadcastRoomService extends IService<ImLiveBroadcastRoom
     Map<String, Object> test(String roomUid);
 
     /**
-     * @param roomUid
-     * @return void
-     * @description: 分享直播链接
+     * @param roomUid 直播间uid
      * @author zx
-     * @date 2022/2/23 16:17
+     * @since 2022/2/23 16:17
+     * 分享直播链接
      */
     void shareGroup(String roomUid, String groupIds);
 
-    List<RoomUserInfoVo> queryRoomUserInfo(String roomUid);
+    List<BaseRoomUserVo> queryRoomOnlineUserInfo(String roomUid);
+
+    List<BaseRoomUserVo> queryRoomLimitOnlineUserInfo(String roomUid);
+
 }
 

+ 17 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/ImSendGroupMessageService.java

@@ -0,0 +1,17 @@
+package com.ym.mec.biz.service;
+
+import com.ym.mec.biz.dal.entity.ImSendGroupMessage;
+import com.ym.mec.common.service.BaseService;
+import org.springframework.transaction.annotation.Transactional;
+
+public interface ImSendGroupMessageService extends BaseService<Long, ImSendGroupMessage> {
+
+    @Transactional(rollbackFor = Exception.class)
+    void sendTimedMessages() throws Exception;
+
+    //发送群消息
+    void sendGroupMessage(ImSendGroupMessage imSendGroupMessage) throws Exception;
+
+    //修改未发送的群消息
+    void updateGroupMessage(ImSendGroupMessage imSendGroupMessage);
+}

+ 2 - 5
mec-biz/src/main/java/com/ym/mec/biz/service/MemberRankSettingService.java

@@ -18,13 +18,10 @@ public interface MemberRankSettingService extends BaseService<Integer, MemberRan
 
     List<MemberRankSetting> queryListByIsDefault(Boolean isDefault);
 
-    /**
-     * 会员购买
-     *
-     * @return
-     */
     HttpResponseResult buy(MemberPayParamDto memberPayParamDto) throws Exception;
 
+    HttpResponseResult buy1(MemberPayParamDto memberPayParamDto) throws Exception;
+
     HttpResponseResult buy2Qqhe(MemberPayParamDto memberPayParamDto) throws Exception;
 
     HttpResponseResult queryBuy2Qqhe();

+ 3 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/StudentPaymentOrderService.java

@@ -224,4 +224,7 @@ public interface StudentPaymentOrderService extends BaseService<Long, StudentPay
     * @date 2022/1/20 16:23
     */
     void returnBalanceAndCoupon(StudentPaymentOrder studentPaymentOrder,String memo);
+
+    //获取云教练订单
+    StudentPaymentOrder getMemberIngOrder(OrderTypeEnum member, DealStatusEnum status);
 }

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/service/StudentRegistrationService.java

@@ -137,7 +137,7 @@ public interface StudentRegistrationService extends BaseService<Long, StudentReg
      * @param newMusicGroupId 主乐团
      * @return
      */
-    void insertStudent(String studentIds, String oldMusicGroupId, String newMusicGroupId, Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect);
+    void insertStudent(String studentIds, String oldMusicGroupId, String newMusicGroupId, Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect,String batchNo);
 
     /**
      * 获取班级学生

+ 36 - 1
mec-biz/src/main/java/com/ym/mec/biz/service/SysMessageService.java

@@ -42,7 +42,7 @@ public interface SysMessageService extends BaseService<Long, SysMessage> {
 	void batchSendImMessage(MessageTypeEnum messageType,String senderId,String extra, String[] targetIds,String url, Object... args);
 
 	/**
-	 * 推送im文本消息,包含跳转链接
+	 * 推送im 模板文本消息,包含跳转链接
 	 * @param senderId
 	 * @param messageType
 	 * @return
@@ -50,6 +50,41 @@ public interface SysMessageService extends BaseService<Long, SysMessage> {
 	void batchSendImGroupMessage(MessageTypeEnum messageType,String senderId,String extra, String[] targetIds,String url, Object... args);
 
 	/**
+	 * 发送自定义消息
+	 * @param senderId
+	 * @param messageContent
+	 * @return
+	 */
+	void batchSendImGroupMessage(String messageContent,String senderId,String extra, String[] targetIds);
+
+
+	/**
+	* @description: 发送图片消息
+	 * @param senderId
+	 * @param extra
+	 * @param imgUrl
+	 * @param targetIds
+	* @return void
+	* @author zx
+	* @date 2022/5/17 10:05
+	*/
+	void batchSendImGroupMessage(String messageContent,String senderId,String extra,String imgUrl, String[] targetIds);
+
+	/**
+	* @description: 发送文件消息
+	 * @param senderId 发送者编号
+	 * @param extra 扩展字段
+	 * @param name	文件名称
+	 * @param targetIds	接收者编号
+	 * @param fileUrl	文件地址
+	 * @param size	文件大小
+	* @return void
+	* @author zx
+	* @date 2022/5/17 10:05
+	*/
+	void batchSendImGroupMessage(String senderId,String extra,String name, String[] targetIds, String fileUrl,Long size);
+
+	/**
 	 * 发送消息
 	 * @param senderTenantId 消息发送者所在的机构编号
 	 * @param messageSender 消息发送者

+ 2 - 8
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ClassGroupServiceImpl.java

@@ -3432,12 +3432,6 @@ public class ClassGroupServiceImpl extends BaseServiceImpl<Integer, ClassGroup>
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int batchUpdateLockByClassGroupIds(List<Integer> classGroupIds, int lockFlag) {
-        return classGroupDao.batchUpdateLockByClassGroupIds(classGroupIds,lockFlag);
-    }
-
-    @Override
     public PageInfo<MusicGroupCourseScheduleDto> queryMusicGroupCourseScheduleDetail(queryMusicGroupCourseScheduleQueryInfo queryInfo) {
         PageInfo<MusicGroupCourseScheduleDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
         Map<String, Object> params = new HashMap<>();
@@ -4136,7 +4130,7 @@ public class ClassGroupServiceImpl extends BaseServiceImpl<Integer, ClassGroup>
 
         MusicGroup musicGroup = musicGroupDao.findByClassGroupId(classGroupIds.get(0));
         //获取欠费学员列表
-        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroup.getId(), new ArrayList<>(studentIds));
+        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroup.getId(), new ArrayList<>(studentIds),null);
         if (noPaymentUserIds.size() > 0) {
             throw new BizException("操作失败:有欠费的学员不允许创建缴费");
         }
@@ -4715,7 +4709,7 @@ public class ClassGroupServiceImpl extends BaseServiceImpl<Integer, ClassGroup>
             Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect = calenderStudentDetails.stream().collect(Collectors.groupingBy(e -> e.getUserId()));
             for (Map<Integer, String> classGroupStudent : classGroupStudents) {
                 Integer classGroupId = classGroupStudent.keySet().iterator().next();
-                studentRegistrationService.insertStudent(classGroupStudent.get(classGroupId), musicGroupDao.findByClassGroupId(classGroupId).getId(), musicGroup.getId(), collect);
+                studentRegistrationService.insertStudent(classGroupStudent.get(classGroupId), musicGroupDao.findByClassGroupId(classGroupId).getId(), musicGroup.getId(), collect,paymentCalenderDto.getBatchNo());
             }
             List<Map> classGroupStudents1 = JSON.parseArray(musicGroupStudentClassAdjust.getClassGroupStudents(), Map.class);
             spanGroupClassAdjustPass(masterClassGroupId, studentIds, courseIds, classGroupStudents1, allLockCourseIds, paymentCalenderDto.getBatchNo(), masterTotalPrice);

+ 4 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupMemberServiceImpl.java

@@ -4,8 +4,10 @@ import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.enums.GroupType;
+import com.ym.mec.biz.dal.enums.ImSendTypeEnum;
 import com.ym.mec.biz.service.ImGroupMemberService;
 import com.ym.mec.biz.service.ImGroupService;
+import com.ym.mec.biz.service.SysMessageService;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
@@ -15,7 +17,6 @@ import com.ym.mec.im.entity.GroupModel;
 import com.ym.mec.util.collection.MapUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -47,6 +48,8 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 	private ClassGroupStudentMapperDao classGroupStudentMapperDao;
 	@Autowired
 	private ImFeignService imFeignService;
+	@Autowired
+	private SysMessageService sysMessageService;
 	@Override
 	public BaseDAO<Long, ImGroupMember> getDAO() {
 		return imGroupMemberDao;
@@ -362,5 +365,4 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 	public void delRepeat() {
 		imGroupMemberDao.delRepeat();
 	}
-
 }

+ 205 - 69
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java

@@ -8,6 +8,7 @@ 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.fasterxml.jackson.annotation.JsonFormat;
+import com.google.common.collect.Lists;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.ImLiveBroadcastRoomDao;
@@ -17,6 +18,7 @@ import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomData;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomMember;
 import com.ym.mec.biz.dal.enums.MessageTypeEnum;
+import com.ym.mec.biz.dal.vo.BaseRoomUserVo;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
 import com.ym.mec.biz.dal.vo.RoomUserInfoVo;
 import com.ym.mec.biz.service.*;
@@ -33,6 +35,7 @@ import com.ym.mec.util.http.HttpUtil;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.redisson.api.RBucket;
+import org.redisson.api.RLock;
 import org.redisson.api.RMap;
 import org.redisson.api.RedissonClient;
 import org.slf4j.Logger;
@@ -44,9 +47,11 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.io.Serializable;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -81,6 +86,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 
     //直播间累计用户信息-指只要进入到该房间的用户都要记录
     public static final String LIVE_ROOM_TOTAL_USER_LIST = "IM:LIVE_ROOM_TOTAL_USER_LIST:" + ROOM_UID;
+    //直播间在线用户信息
+    public static final String LIVE_ROOM_ONLINE_USER_LIST = "IM:LIVE_ROOM_ONLINE_USER_LIST:" + ROOM_UID;
     //主讲人信息
     public static final String LIVE_SPEAKER_INFO = "IM:LIVE_SPEAKER_INFO:" + USER_ID;
     //用户对应的直播间Uid
@@ -89,6 +96,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     public static final String LIVE_USER_STATE_TIME = "IM:LIVE_USER_STATE_TIME:" + USER_ID;
     //房间点赞数
     public static final String LIVE_ROOM_LIKE = "IM:LIVE_ROOM_LIKE:" + ROOM_UID;
+    //计算人员观看时长锁
+    public static final String LIVE_LOOK_LOCK = "IM:LIVE_LOOK_LOCK:" + ROOM_UID;
     //直播提前开始时间
     public static final int PRE_LIVE_TIME_MINUTE = 30;
 
@@ -135,15 +144,20 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
      */
     @Override
     public ImLiveBroadcastRoomVo queryRoomInfo(String roomUid) {
+        ImLiveBroadcastRoomVo roomVo = getImLiveBroadcastRoomVo(roomUid);
+        if (roomVo == null) return null;
+        getRoomData(roomVo);
+        return roomVo;
+    }
+
+    private ImLiveBroadcastRoomVo getImLiveBroadcastRoomVo(String roomUid) {
         List<ImLiveBroadcastRoomVo> list = baseMapper.queryPage(new HashMap<String, Object>() {{
             put("roomUid", roomUid);
         }});
         if (CollectionUtils.isEmpty(list)) {
             return null;
         }
-        ImLiveBroadcastRoomVo roomVo = list.get(0);
-        getRoomData(roomVo);
-        return roomVo;
+        return list.get(0);
     }
 
     /**
@@ -237,6 +251,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         obj.setRoomState(1);
         obj.setUpdatedBy(getSysUser().getId());
         obj.setUpdatedTime(new Date());
+        obj.setPopularize(0);
         this.updateById(obj);
     }
 
@@ -267,6 +282,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         if (popularize == 1) {
             this.update(Wrappers.<ImLiveBroadcastRoom>lambdaUpdate()
                     .set(ImLiveBroadcastRoom::getPopularize, 0)
+                    .eq(ImLiveBroadcastRoom::getRoomState, 0)
                     .eq(ImLiveBroadcastRoom::getTenantId, obj.getTenantId()));
         }
         //更新直播间推广状态
@@ -372,6 +388,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         if (room.getLiveState() == 2) {
             throw new BizException("直播已经结束,请刷新数据!");
         }
+        //销毁房间
         roomDestroy(room);
     }
 
@@ -386,7 +403,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         Integer speakerId = room.getSpeakerId();
 
         //获取所有直播间缓存数据并写入数据库后并清理缓存
-        insertAndCleanLiveData(roomUid, speakerId);
+        CompletableFuture.runAsync(() -> insertAndCleanLiveData(roomUid, speakerId));
         log.info("roomDestroy>>>> insertAndCleanLiveData {}", JSONObject.toJSONString(room));
 
         //将房间状态改为已销毁
@@ -422,10 +439,11 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 
     //获取该直播间所有数据写入数据库-并清理缓存
     private void insertAndCleanLiveData(String roomUid, Integer speakerId) {
+        Date now = new Date();
         //总观看人数
         List<ImLiveBroadcastRoomMember> memberList = new ArrayList<>();
         //获取直播间所有人数据写入 im_live_broadcast_room_member
-        RMap<Integer, RoomUserInfoVo> roomTotalUserCache = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
+        RMap<Integer, RoomUserInfoVo> roomTotalUserCache = getTotalUserCache(roomUid);
         if (roomTotalUserCache.isExists()) {
             List<RoomUserInfoVo> roomTotalUser = new ArrayList<>(roomTotalUserCache.values());
             for (RoomUserInfoVo v : roomTotalUser) {
@@ -434,7 +452,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                 member.setRoomUid(roomUid);
                 member.setUserId(v.getUserId());
                 member.setJoinTime(v.getFirstJoinTime());
-                member.setTotalTime(getLookMinutes(v.getDynamicLookTime(), v.getTotalViewTime()));
+                member.setTotalTime(getLookMinutes(v.getDynamicLookTime(), now, v.getTotalViewTime()));
                 memberList.add(member);
             }
         }
@@ -457,8 +475,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             liveData.setRoomUid(roomUid);
             liveData.setLikeNum(like);
             liveData.setTotalUserNum(CollectionUtils.isNotEmpty(memberList) ? memberList.size() : 0);
-            liveData.setUpdatedTime(new Date());
-            liveData.setLiveTime(getLookMinutes(speakerInfo.getStartLiveTime(), speakerInfo.getTotalLiveTime()));
+            liveData.setUpdatedTime(now);
+            liveData.setLiveTime(getLookMinutes(speakerInfo.getStartLiveTime(), now, speakerInfo.getTotalLiveTime()));
             liveBroadcastRoomDataService.save(liveData);
             //删除房间主讲人数据
             speakerCache.delete();
@@ -473,7 +491,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                     member.setTotalTime(speakerLiveTime);
                 }
             }
-            liveBroadcastRoomMemberService.getDao().insertBatch(memberList);
+            Lists.partition(memberList, 500)
+                    .forEach(list -> liveBroadcastRoomMemberService.getDao().insertBatch(list));
             //删除用户对应的直播间关系缓存
             memberList.stream()
                     .map(ImLiveBroadcastRoomMember::getUserId)
@@ -481,7 +500,9 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                     .forEach(id -> redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, id.toString())).delete());
         }
         //删除直播间所有用户数据
-        roomTotalUserCache.clear();
+        roomTotalUserCache.delete();
+        //删除在线用户数据
+        getOnlineUserCache(roomUid).delete();
     }
 
     /**
@@ -556,15 +577,19 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             Integer userId = Integer.valueOf(userid);
 
             //从房间累计用户信息中查询该用户的信息
-            RMap<Integer, RoomUserInfoVo> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
+            RMap<Integer, RoomUserInfoVo> roomTotalUser = getTotalUserCache(roomUid);
             //该房间未查询到用户数据则不处理
             if (!roomTotalUser.isExists() && !roomTotalUser.containsKey(userId)) {
                 return;
             }
             //查询到用户数据
             RoomUserInfoVo userInfo = roomTotalUser.get(userId);
+            //查询在线人员列表
+            RMap<Integer, BaseRoomUserVo> onlineUserInfo = getOnlineUserCache(roomUid);
+            //获取当前用户是否在房间状态 true在 false不在
+            boolean userOnline = onlineUserInfo.isExists() && onlineUserInfo.containsKey(userId);
             //用户是在房间的状态 并且 突然离线 - 那么融云会发送用户离线消息-此刻就发送退出房间消息给主讲人
-            if (userInfo.getState() == 0 && user.getStatus().equals("1")) {
+            if (userOnline && user.getStatus().equals("1")) {
                 ImRoomMessage message = new ImRoomMessage();
                 message.setFromUserId(userId.toString());
                 message.setToChatroomId(roomUid);
@@ -582,9 +607,9 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                 userInfo.setTotalViewTime(getLookMinutes(userInfo.getDynamicLookTime(), userInfo.getTotalViewTime()));
                 userInfo.setDynamicLookTime(null);
             }
-            //记录退出时间 并写入缓存
-            userInfo.setState(1);
             roomTotalUser.fastPut(userId, userInfo);
+            //从在线人员列表删除该人员
+            onlineUserInfo.fastRemove(userId);
             log.info("opsRoom>>>> looker userInfo: {}", JSONObject.toJSONString(userInfo));
         });
     }
@@ -623,15 +648,17 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
      */
     public void joinRoom(String roomUid, Integer userId) {
         //查询房间信息
-        ImLiveBroadcastRoomVo imLiveBroadcastRoomVo = queryRoomInfo(roomUid);
+        ImLiveBroadcastRoomVo imLiveBroadcastRoomVo = getImLiveBroadcastRoomVo(roomUid);
         if (Objects.isNull(imLiveBroadcastRoomVo)) {
             log.info("opsRoom>>>> joinRoom error roomUid: {}", roomUid);
             return;
         }
         //记录用户当前房间uid
-        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid);
+        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 12L, TimeUnit.HOURS);
+        //在线人员列表
+        RMap<Integer, BaseRoomUserVo> onlineUserInfo = getOnlineUserCache(roomUid);
         //房间累计用户信息-指只要进入到该房间的用户都要记录
-        RMap<Integer, RoomUserInfoVo> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
+        RMap<Integer, RoomUserInfoVo> roomTotalUser = getTotalUserCache(roomUid);
         //判断是否第一次进房间
         RoomUserInfoVo userInfo;
         Date now = new Date();
@@ -644,8 +671,6 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             userInfo.setFirstJoinTime(now);
             userInfo.setTotalViewTime(0);
         }
-        //0 进入房间
-        userInfo.setState(0);
         //查询主讲人信息
         RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, imLiveBroadcastRoomVo.getSpeakerId().toString()));
         if (speakerCache.isExists()) {
@@ -656,6 +681,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             }
         }
         roomTotalUser.fastPut(userId, userInfo);
+        //进入房间写如在线人员列表
+        onlineUserInfo.fastPut(userId, userInfo);
         log.info("joinRoom>>>> userInfo: {}", JSONObject.toJSONString(userInfo));
     }
 
@@ -672,11 +699,11 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         }
         RoomSpeakerInfo roomSpeakerInfo = speakerCache.get();
         //已是直播状态则直接返回
-        if (Objects.nonNull(roomSpeakerInfo.getState()) && roomSpeakerInfo.getState() == 0) {
+        if (intEquals(roomSpeakerInfo.getState(), 0)) {
             return;
         }
         //是否允许录像
-        if (Objects.nonNull(roomSpeakerInfo.getWhetherVideo()) && roomSpeakerInfo.getWhetherVideo() == 0) {
+        if (intEquals(roomSpeakerInfo.getWhetherVideo(), 0)) {
             //开始录制视频
             try {
                 imFeignService.startRecord(roomUid);
@@ -690,26 +717,15 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         roomSpeakerInfo.setStartLiveTime(now);
         speakerCache.set(roomSpeakerInfo);
         log.info("startLive>>>> roomSpeakerInfo: {}", JSONObject.toJSONString(roomSpeakerInfo));
-
         //主播开启直播,查询所有在直播间的用户并写入观看时间
-        RMap<Integer, RoomUserInfoVo> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomSpeakerInfo.getRoomUid()));
-        if (!roomTotalUser.isExists()) {
-            return;
-        }
-        roomTotalUser.forEach((id, userInfo) -> {
-            //对在房间的用户
-            if (Objects.nonNull(userInfo.getState()) && userInfo.getState() == 0) {
-                userInfo.setDynamicLookTime(now);
-                roomTotalUser.fastPut(id, userInfo);
-            }
-        });
-
+        CompletableFuture.runAsync(() -> this.asyncOpsLiveLookTime(roomUid, 1, now));
     }
 
     /**
      * 关闭直播-录像
      *
      * @param roomUid 房间uid
+     * @param userId  老师id
      */
     public void closeLive(String roomUid, Integer userId) {
         //查询房间主播信息
@@ -723,12 +739,16 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         speakerCache.set(roomSpeakerInfo);
     }
 
-
+    /**
+     * 关闭直播-录像
+     *
+     * @param roomSpeakerInfo 房间主播信息
+     */
     private void closeLive(RoomSpeakerInfo roomSpeakerInfo) {
         //直播状态 true 直播中 false关闭直播
-        boolean stateFlag = Objects.nonNull(roomSpeakerInfo.getState()) && roomSpeakerInfo.getState() == 0;
+        boolean stateFlag = intEquals(roomSpeakerInfo.getState(), 0);
         //是否录像 true允许 false不允许
-        boolean whetherVideoFlag = Objects.nonNull(roomSpeakerInfo.getWhetherVideo()) && roomSpeakerInfo.getWhetherVideo() == 0;
+        boolean whetherVideoFlag = intEquals(roomSpeakerInfo.getWhetherVideo(), 0);
         //允许录像并在直播中
         if (whetherVideoFlag && stateFlag) {
             try {
@@ -743,25 +763,55 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             Date now = new Date();
             roomSpeakerInfo.setEndLiveTime(now);
             roomSpeakerInfo.setState(1);
-            //写入本次直播时长
-            roomSpeakerInfo.setTotalLiveTime(getLookMinutes(roomSpeakerInfo.getStartLiveTime(), roomSpeakerInfo.getTotalLiveTime()));
+            //如果开播时间和本次操作结束播放时间小于1分钟则不计算观看时间
+            int liveMinutes = getLookMinutes(roomSpeakerInfo.getStartLiveTime(), null);
+            if (liveMinutes > 1) {
+                //写入本次直播时长
+                roomSpeakerInfo.setTotalLiveTime(getLookMinutes(roomSpeakerInfo.getStartLiveTime(), roomSpeakerInfo.getTotalLiveTime()));
+                //关闭直播后异步执行计算房间人员观看时长
+                CompletableFuture.runAsync(() -> this.asyncOpsLiveLookTime(roomSpeakerInfo.getRoomUid(), 2, now));
+            }
             //计算完后将开始直播时间设置为空,待下次开启后再计算
             roomSpeakerInfo.setStartLiveTime(null);
-            //主播关闭直播,查询所有在直播间的用户并计算观看时长
-            RMap<Integer, RoomUserInfoVo> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomSpeakerInfo.getRoomUid()));
+        }
+        log.info("closeLive>>>> roomSpeakerInfo: {}", JSONObject.toJSONString(roomSpeakerInfo));
+    }
+
+    /**
+     * 打开/关闭直播后-异步计算房间人员观看时长
+     *
+     * @param roomUid 房间uid
+     * @param type    type 1:开始直播-开始录像     2:关闭直播关闭录像
+     */
+    private void asyncOpsLiveLookTime(String roomUid, Integer type, Date now) {
+        //加锁-避免快速点击开启直播和关闭直后异步执行后直播数据错误
+        boolean b = this.runIfLockCanGet(LIVE_LOOK_LOCK.replace(ROOM_UID, roomUid), () -> {
+            //查询所有在直播间的用户并计算观看时长
+            RMap<Integer, RoomUserInfoVo> roomTotalUser = getTotalUserCache(roomUid);
             if (!roomTotalUser.isExists()) {
                 return;
             }
+            //查询在线人员列表
+            RMap<Integer, BaseRoomUserVo> onlineUserInfo = getOnlineUserCache(roomUid);
             roomTotalUser.forEach((id, userInfo) -> {
-                //对在房间的用户计算观看时长
-                if (Objects.nonNull(userInfo.getState()) && userInfo.getState() == 0) {
-                    userInfo.setTotalViewTime(getLookMinutes(userInfo.getDynamicLookTime(), userInfo.getTotalViewTime()));
-                    userInfo.setDynamicLookTime(null);
+                //获取当前用户是否在房间状态 true在 false不在
+                if (onlineUserInfo.isExists() && onlineUserInfo.containsKey(id)) {
+                    if (type.equals(1)) {
+                        //开启直播后对当前在房间的用户写入观看时间
+                        userInfo.setDynamicLookTime(new Date());
+                    } else if (type.equals(2)) {
+                        userInfo.setTotalViewTime(getLookMinutes(userInfo.getDynamicLookTime(), now, userInfo.getTotalViewTime()));
+                        userInfo.setDynamicLookTime(null);
+                    } else {
+                        return;
+                    }
                     roomTotalUser.fastPut(id, userInfo);
                 }
             });
+        }, 2, 1, TimeUnit.MINUTES);
+        if (!b) {
+            this.asyncOpsLiveLookTime(roomUid, type, now);
         }
-        log.info("closeLive>>>> roomSpeakerInfo: {}", JSONObject.toJSONString(roomSpeakerInfo));
     }
 
     /**
@@ -849,18 +899,24 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         }
         roomVo.setLikeNum((int) like);
         //累计总用户数量
-        List<RoomUserInfoVo> roomUserInfoVos = queryTotalRoomUserInfo(roomVo.getRoomUid());
-        if (CollectionUtils.isNotEmpty(roomUserInfoVos)) {
-            roomVo.setTotalLookNum(roomUserInfoVos.size());
-            //在房间观看用户数量
-            roomVo.setLookNum(queryRoomUserInfo(roomUserInfoVos).size());
-        } else {
-            roomVo.setTotalLookNum(0);
-            roomVo.setLookNum(0);
-        }
-
+        roomVo.setTotalLookNum(getNum.apply(this::getTotalUserCache, roomVo.getRoomUid()));
+        //在房间观看用户数量
+        roomVo.setLookNum(getNum.apply(this::getOnlineUserCache, roomVo.getRoomUid()));
     }
 
+    /**
+     * 获取房间缓存中的用户数量/观看人数
+     *
+     * <p> func:查询用户数量/观看人数的方法
+     * <p> roomUid :房间uid
+     * <p> return :用户数量/观看人数
+     */
+    private final BiFunction<Function<String, RMap<Integer, ?>>, String, Integer> getNum = (func, roomUid) -> Optional.of(roomUid)
+            .map(func)
+            .filter(RMap::isExists)
+            .map(RMap::size)
+            .orElse(0);
+
     private SysUser getSysUser(Integer userId) {
         return Optional.ofNullable(userId)
                 .map(sysUserFeignService::queryUserById)
@@ -888,13 +944,11 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 
         int totalLook = 0;
         int look = 0;
-        List<RoomUserInfoVo> inRoomUserInfo;
-
+        //正在房间观看的用户数据
+        List<BaseRoomUserVo> inRoomUserInfo = queryRoomOnlineUserInfo(roomUid);
         //累计总观看的用户数量
         List<RoomUserInfoVo> totalUserInfo = queryTotalRoomUserInfo(roomUid);
         if (CollectionUtils.isNotEmpty(totalUserInfo)) {
-            //正在房间观看的用户数据
-            inRoomUserInfo = queryRoomUserInfo(totalUserInfo);
             if (CollectionUtils.isNotEmpty(inRoomUserInfo)) {
                 look = inRoomUserInfo.size();
                 result.put("正在观看的人员信息", inRoomUserInfo);
@@ -940,29 +994,52 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     }
 
     /**
-     * 查询在观看直播的用户信息
+     * 查询直播间在线的用户
      *
      * @param roomUid 直播间uid
      */
     @Override
-    public List<RoomUserInfoVo> queryRoomUserInfo(String roomUid) {
-        List<RoomUserInfoVo> roomUserInfoVos = queryTotalRoomUserInfo(roomUid);
-        return queryRoomUserInfo(roomUserInfoVos);
+    public List<BaseRoomUserVo> queryRoomLimitOnlineUserInfo(String roomUid) {
+        RMap<Integer, BaseRoomUserVo> onlineUserCache = getOnlineUserCache(roomUid);
+        return onlineUserCache.values().stream()
+                .filter(Objects::nonNull)
+                .limit(200)
+                .collect(Collectors.toList());
     }
 
-    public List<RoomUserInfoVo> queryRoomUserInfo(List<RoomUserInfoVo> totalUserInfo) {
-        return totalUserInfo.stream()
-                .filter(o -> Objects.nonNull(o.getState()) && o.getState() == 0)
+    /**
+     * 查询直播间在线的用户
+     *
+     * @param roomUid 直播间uid
+     */
+    @Override
+    public List<BaseRoomUserVo> queryRoomOnlineUserInfo(String roomUid) {
+        RMap<Integer, BaseRoomUserVo> onlineUserInfo = getOnlineUserCache(roomUid);
+        return onlineUserInfo.values().stream()
+                .filter(Objects::nonNull)
                 .collect(Collectors.toList());
     }
 
-    public List<RoomUserInfoVo> queryTotalRoomUserInfo(String roomUid) {
-        RMap<Integer, RoomUserInfoVo> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
+    /**
+     * 查询直播间所有用户信息
+     *
+     * @param roomUid 直播间uid
+     */
+    private List<RoomUserInfoVo> queryTotalRoomUserInfo(String roomUid) {
+        RMap<Integer, RoomUserInfoVo> roomTotalUser = getTotalUserCache(roomUid);
         return roomTotalUser.values().stream()
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
     }
 
+    private RMap<Integer, BaseRoomUserVo> getOnlineUserCache(String roomUid) {
+        return redissonClient.getMap(LIVE_ROOM_ONLINE_USER_LIST.replace(ROOM_UID, roomUid));
+    }
+
+    private RMap<Integer, RoomUserInfoVo> getTotalUserCache(String roomUid) {
+        return redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
+    }
+
     private RoomUserInfoVo getUserInfo(Integer userId) {
         RoomUserInfoVo userInfo = new RoomUserInfoVo();
         userInfo.setUserId(userId);
@@ -1016,6 +1093,59 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     }
 
     /**
+     * 判断Integer是否相等-null值不相等
+     *
+     * @param key1 第一个Integer
+     * @param key2 第二个Integer
+     * @return 相等 true 不相等 false
+     */
+    private boolean intEquals(Integer key1, Integer key2) {
+        return Objects.nonNull(key1) && Objects.nonNull(key2) && Objects.equals(key1, key2);
+    }
+
+    /**
+     * 分布式锁
+     *
+     * @param lockName lockKey
+     * @param runnable 任务
+     * @param waitTime 等待抢锁的时间,若该key已被占用则等待抢锁。
+     * @param timeout  超时时间
+     * @param unit     时间单位
+     * @return true 锁成功  false 锁失败
+     */
+    public boolean runIfLockCanGet(final String lockName, Runnable runnable, final long waitTime, final long timeout, TimeUnit unit) {
+        RLock lock = redissonClient.getLock(lockName);
+        if (Objects.isNull(lock)) {
+            log.info("runIfLockCanGet lock is null lockName : {}", lockName);
+            return false;
+        }
+        try {
+            if (lock.tryLock(waitTime, timeout, unit)) {
+                if (Objects.nonNull(runnable)) {
+                    runnable.run();
+                }
+                return true;
+            } else {
+                return false;
+            }
+        } catch (Exception e) {
+            log.error("runIfLockCanGet error lockName : {}", lockName, e);
+            throw new RuntimeException("runIfLockCanGet error lockName :" + lockName, e);
+        } finally {
+            this.unlock(lock);
+        }
+    }
+
+    /**
+     * 解锁
+     */
+    public void unlock(RLock lock) {
+        if (lock.getHoldCount() != 0) {
+            lock.unlock();
+        }
+    }
+
+    /**
      * 主讲人信息
      */
     public static class RoomSpeakerInfo implements Serializable {
@@ -1064,10 +1194,16 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             this.speakerName = speakerName;
         }
 
+        /**
+         * 直播状态 0 直播中 1关闭直播
+         */
         public Integer getState() {
             return state;
         }
 
+        /**
+         * 直播状态 0 直播中 1关闭直播
+         */
         public void setState(Integer state) {
             this.state = state;
         }

+ 100 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImSendGroupMessageServiceImpl.java

@@ -0,0 +1,100 @@
+package com.ym.mec.biz.service.impl;
+
+import com.ym.mec.biz.dal.dao.ImSendGroupMessageDao;
+import com.ym.mec.biz.dal.entity.ImSendGroupMessage;
+import com.ym.mec.biz.dal.enums.ImSendTypeEnum;
+import com.ym.mec.biz.service.ImSendGroupMessageService;
+import com.ym.mec.biz.service.SysMessageService;
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.service.impl.BaseServiceImpl;
+import net.coobird.thumbnailator.Thumbnails;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+@Service
+public class ImSendGroupMessageServiceImpl extends BaseServiceImpl<Long, ImSendGroupMessage>  implements ImSendGroupMessageService {
+	
+	@Autowired
+	private ImSendGroupMessageDao imSendGroupMessageDao;
+	@Autowired
+	private SysMessageService sysMessageService;
+
+	@Override
+	public BaseDAO<Long, ImSendGroupMessage> getDAO() {
+		return imSendGroupMessageDao;
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void sendTimedMessages() throws Exception {
+		List<ImSendGroupMessage> sendGroupMessages = imSendGroupMessageDao.findBySendFlag(false, new Date());
+		if(sendGroupMessages.size() > 0){
+			for(ImSendGroupMessage messageDto : sendGroupMessages){
+				messageDto.setSendFlag(true);
+				send(messageDto);
+			}
+			imSendGroupMessageDao.batchUpdateSendFlag(sendGroupMessages);
+		}
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void sendGroupMessage(ImSendGroupMessage messageDto) throws Exception {
+		if(Objects.isNull(messageDto.getSendTime())){
+			messageDto.setSendFlag(true);
+			send(messageDto);
+		}
+		imSendGroupMessageDao.insert(messageDto);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void updateGroupMessage(ImSendGroupMessage imSendGroupMessage) {
+		ImSendGroupMessage message = imSendGroupMessageDao.get(imSendGroupMessage.getId());
+		if(Objects.isNull(message)){
+			throw new BizException("消息不存在");
+		}
+		if(message.getSendFlag()){
+			throw new BizException("消息已发送");
+		}
+		imSendGroupMessageDao.update(imSendGroupMessage);
+	}
+
+	private void send(ImSendGroupMessage messageDto) throws Exception {
+		if (Objects.equals(messageDto.getMessageType(), ImSendTypeEnum.IMG)) {
+			String content = imageToBase64(Thumbnails.of(new URL(messageDto.getFileUrl())).scale(0.5f).outputQuality(0.25f).asBufferedImage());
+			sysMessageService.batchSendImGroupMessage(content,messageDto.getSenderId(),
+					messageDto.getExtra(),messageDto.getFileUrl(),messageDto.getTargetIds().split(","));
+		} else if (Objects.equals(messageDto.getMessageType(),ImSendTypeEnum.FILE)) {
+			sysMessageService.batchSendImGroupMessage(messageDto.getSenderId(),
+					messageDto.getExtra(),messageDto.getFileName(),messageDto.getTargetIds().split(","),messageDto.getFileUrl(),messageDto.getFileSize());
+		}
+		if(StringUtils.isNotEmpty(messageDto.getMessageContent())){
+			sysMessageService.batchSendImGroupMessage(messageDto.getMessageContent(),messageDto.getSenderId(),messageDto.getExtra(),messageDto.getTargetIds().split(","));
+		}
+	}
+
+	public static String imageToBase64(BufferedImage bufferedImage) {
+		Base64 encoder = new Base64();
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		try {
+			ImageIO.write(bufferedImage, "jpg", baos);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return new String(encoder.encode((baos.toByteArray())));
+	}
+}

+ 28 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MemberRankSettingServiceImpl.java

@@ -79,6 +79,8 @@ public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, Membe
     private TenantConfigService tenantConfigService;
     @Autowired
     private ActivityUserMapperDao activityUserMapperDao;
+    @Autowired
+    private MemberFeeSettingService memberFeeSettingService;
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
@@ -177,6 +179,32 @@ public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, Membe
         return BaseController.succeed(result);
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HttpResponseResult buy1(MemberPayParamDto memberPayParamDto) throws Exception {
+        logger.info("团练宝购买:memberPayParamDto:{} ", memberPayParamDto);
+        SysUser sysUser = Optional.of(sysUserFeignService.queryUserInfo()).orElseThrow(() -> new BizException("用户信息不存在"));
+        //判断用户是否已存在订单
+        StudentPaymentOrder memberIngOrder = studentPaymentOrderService.getMemberIngOrder(OrderTypeEnum.MEMBER, DealStatusEnum.ING);
+        if (Objects.nonNull(memberIngOrder)) {
+            HttpResponseResult result = studentPaymentOrderService.checkRepeatPay(memberIngOrder, memberPayParamDto.getRepeatPay());
+            if (result.getCode() != 200) {
+                return result;
+            }
+        }
+        //获取团练宝价格
+        BigDecimal actualAmount = memberFeeSettingService.getAmount(sysUser.getOrganId(),1,
+                memberPayParamDto.getPeriodEnum(),new BigDecimal(1),
+                MemberFeeSettingServiceImpl::getOriginalFee);
+        //优惠券使用范围
+        String[] checkCoupon = CouponDetailTypeEnum.getAllowType(MEMBER);
+        //校验优惠券
+        StudentPaymentOrder studentPaymentOrder = sysCouponCodeService.use(memberPayParamDto.getCouponIdList(), actualAmount, true, checkCoupon);
+        studentPaymentOrder.setMemo("学员团练宝购买");
+        Map<String, Object> result = getMap(memberPayParamDto.getAmount(), memberPayParamDto.getUseBalancePayment(), sysUser.getId(), sysUser.getOrganId(), studentPaymentOrder);
+        return BaseController.succeed(result);
+    }
+
     public static final String BUY_2_QQHE_LOCK = "BUY_2_QQHE_LOCK:";
 
     @Override

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderDetailServiceImpl.java

@@ -186,7 +186,7 @@ public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<
 			throw new BizException("当前乐团存在未排课的缴费项目,请先完成排课再操作");
 		}*/
 		//获取欠费学员列表
-		List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroupId, new ArrayList<>(userIdList));
+		List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroupId, new ArrayList<>(userIdList),null);
 		if(noPaymentUserIds.size() > 0){
 			throw new BizException("操作失败:有欠费的学员不允许创建缴费");
 		}

+ 3 - 3
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderServiceImpl.java

@@ -554,7 +554,7 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
         //获取默认的学员缴费详情
         List<Integer> studentIdList = JSON.parseArray(adjust.getStudentIds(), Integer.class);
         //获取欠费学员列表
-        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroup.getId(), studentIdList);
+        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroup.getId(), studentIdList,null);
         if (noPaymentUserIds.size() > 0) {
             throw new BizException("操作失败:有欠费的学员不允许创建缴费");
         }
@@ -963,7 +963,7 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
                 }
                 List<Integer> userIds = Arrays.stream(calender.getStudentIds().split(",")).mapToInt(Integer::valueOf).boxed().collect(Collectors.toList());
                 //获取欠费学员列表
-                List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(calender.getMusicGroupId(), userIds);
+                List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(calender.getMusicGroupId(), userIds,null);
                 if (noPaymentUserIds.size() > 0) {
                     throw new BizException("{} 有欠费的学员不允许创建缴费", musicGroup.getName());
                 }
@@ -1012,7 +1012,7 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
                 List<Map> classGroupStudents = JSON.parseArray(adjust.getClassGroupStudents(), Map.class);
                 for (Map<Integer, String> classGroupStudent : classGroupStudents) {
                     Integer classGroupId = classGroupStudent.keySet().iterator().next();
-                    studentRegistrationService.insertStudent(classGroupStudent.get(classGroupId), musicGroupDao.findByClassGroupId(classGroupId).getId(), musicGroup.getId(), collect);
+                    studentRegistrationService.insertStudent(classGroupStudent.get(classGroupId), musicGroupDao.findByClassGroupId(classGroupId).getId(), musicGroup.getId(), collect,null);
                 }
                 //删除和解冻班级,课程信息
                 List<Integer> studentIds = JSON.parseArray(adjust.getStudentIds(), Integer.class);

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentManageServiceImpl.java

@@ -500,7 +500,7 @@ public class StudentManageServiceImpl implements StudentManageService {
             }
         }
         if(userIds.size() > 0 && queryInfo.getOweFlag() != null){
-            List<Integer> studentIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(queryInfo.getMusicGroupId(),userIds);
+            List<Integer> studentIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(queryInfo.getMusicGroupId(),userIds,null);
             if(queryInfo.getOweFlag()){
                 userIds = studentIds;
             }else {

+ 5 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentPaymentOrderServiceImpl.java

@@ -901,5 +901,10 @@ public class StudentPaymentOrderServiceImpl extends BaseServiceImpl<Long, Studen
         sysCouponCodeService.quit(studentPaymentOrder.getCouponCodeId());
     }
 
+    @Override
+    public StudentPaymentOrder getMemberIngOrder(OrderTypeEnum member, DealStatusEnum status) {
+        return studentPaymentOrderDao.getMemberIngOrder(member, status);
+    }
+
 
 }

+ 3 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentRegistrationServiceImpl.java

@@ -977,10 +977,11 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
 
     @Override
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
-    public void insertStudent(String studentIds, String oldMusicGroupId, String newMusicGroupId, Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect) {
+    public void insertStudent(String studentIds, String oldMusicGroupId, String newMusicGroupId,
+                              Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect,String batchNo) {
         //获取欠费学员列表
         List<Integer> studentIdList = Arrays.asList(studentIds.split(",")).stream().mapToInt(idStr -> Integer.valueOf(idStr)).boxed().collect(Collectors.toList());
-        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(newMusicGroupId, studentIdList);
+        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(newMusicGroupId, studentIdList,batchNo);
         if (noPaymentUserIds.size() > 0) {
             throw new BizException("操作失败:有欠费的学员不允许创建缴费");
         }

+ 59 - 12
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMessageServiceImpl.java

@@ -16,6 +16,7 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+import com.ym.mec.common.entity.*;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -44,9 +45,6 @@ import com.ym.mec.biz.dal.enums.SendStatusEnum;
 import com.ym.mec.biz.service.SysMessageConfigService;
 import com.ym.mec.biz.service.SysMessageService;
 import com.ym.mec.common.dal.BaseDAO;
-import com.ym.mec.common.entity.ImGroupMessage;
-import com.ym.mec.common.entity.ImPrivateMessage;
-import com.ym.mec.common.entity.ImTxtMessage;
 import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.page.QueryInfo;
@@ -246,24 +244,73 @@ public class SysMessageServiceImpl extends BaseServiceImpl<Long, SysMessage> imp
 	}
 
 	@Override
-	@Async
 	public void batchSendImGroupMessage(MessageTypeEnum type, String senderId,String extra, String[] targetIds, String url, Object... args) {
+		String messageContent = checkMessageConfig(type);
+		String content = getContent(messageContent,url, args);
+		ExecutorService executor = Executors.newCachedThreadPool();
+		CompletableFuture.runAsync(()->{
+			imFeignService.groupSend(getImGroupMessage("RC:TxtMsg",senderId,targetIds,content,extra));
+		},executor);
+	}
+
+	@Override
+	public void batchSendImGroupMessage(String messageContent, String senderId,String extra, String[] targetIds) {
+		ExecutorService executor = Executors.newCachedThreadPool();
+		CompletableFuture.runAsync(()->{
+			imFeignService.groupSend(getImGroupMessage("RC:TxtMsg",senderId,targetIds,messageContent,extra));
+		},executor);
+	}
+
+	@Override
+	public void batchSendImGroupMessage(String messageContent,String senderId,String extra,String imgUrl, String[] targetIds) {
+		ImMessageDto imMessageDto =
+				getImGroupMessage("RC:ImgMsg",senderId,targetIds,messageContent,extra);
+		imMessageDto.setFileUrl(imgUrl);
+		ExecutorService executor = Executors.newCachedThreadPool();
+		CompletableFuture.runAsync(()->{
+			imFeignService.groupSend(imMessageDto);
+		},executor);
+	}
+
+	@Override
+	public void batchSendImGroupMessage(String senderId,String extra,String name, String[] targetIds, String fileUrl,Long size) {
+		ImMessageDto imMessageDto =
+				getImGroupMessage("RC:FileMsg",senderId,targetIds,"",extra);
+		imMessageDto.setFileUrl(fileUrl);
+		imMessageDto.setFileSize(size);
+		imMessageDto.setFileName(name);
+		ExecutorService executor = Executors.newCachedThreadPool();
+		CompletableFuture.runAsync(()->{
+			imFeignService.groupSend(imMessageDto);
+		},executor);
+	}
+
+	private String checkMessageConfig(MessageTypeEnum type){
 		SysMessageConfig messageConfig = sysMessageConfigService.queryByType(type);
 		if (messageConfig == null) {
 			throw new BizException("消息类型错误");
 		}else if(messageConfig.getSendFlag() == null || messageConfig.getSendFlag() == 0){
-			return;
+			throw new BizException("消息类型未开启");
 		}
-		String content = MessageFormatter.arrayFormat(messageConfig.getContent(), args);
+		return messageConfig.getContent();
+	}
+
+	private String getContent(String messageContent, String url, Object... args) {
+		String content = MessageFormatter.arrayFormat(messageContent, args);
 		if(StringUtils.isNotEmpty(url)){
 			content += url;
 		}
-		ImGroupMessage groupMessage = new ImGroupMessage();
-		groupMessage.setObjectName("RC:TxtMsg");
-		groupMessage.setTargetId(targetIds);
-		groupMessage.setSenderId(senderId);
-		groupMessage.setContent(new ImTxtMessage(content,extra));
-		imFeignService.groupSend(groupMessage);
+		return content;
+	}
+
+	private ImMessageDto getImGroupMessage(String objectName, String senderId, String[] targetIds, String content, String extra) {
+		ImMessageDto imMessageDto = new ImMessageDto();
+		imMessageDto.setObjectName(objectName);
+		imMessageDto.setTargetIds(targetIds);
+		imMessageDto.setSenderId(senderId);
+		imMessageDto.setExtra(extra);
+		imMessageDto.setMessageContent(content);
+		return imMessageDto;
 	}
 
 	@Override

+ 3 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreServiceImpl.java

@@ -105,6 +105,9 @@ public class SysMusicScoreServiceImpl extends BaseServiceImpl<Integer, SysMusicS
 		sysMusicScoreDao.insert(sysMusicScore);
 		List<SysMusicScoreAccompaniment> sysMusicScoreAccompaniments = musicScoreDto.getSysMusicScoreAccompaniments();
 		if(sysMusicScoreAccompaniments != null && sysMusicScoreAccompaniments.size() > 0){
+			sysMusicScoreAccompaniments.forEach(e -> {
+				e.setIsOpenMetronome(sysMusicScore.getIsOpenMetronome());
+			});
 			sysMusicScoreAccompanimentDao.batchInsert(sysMusicScoreAccompaniments,sysMusicScore.getId(),sysMusicScore.getIsOpenMetronome());
 		}
 		Integer categoriesId = sysMusicScore.getMusicScoreCategoriesId();

+ 8 - 1
mec-biz/src/main/resources/config/mybatis/ImLiveBroadcastRoomMapper.xml

@@ -87,10 +87,17 @@
                 <![CDATA[ AND a.live_start_time_  <= #{param.endTime} ]]>
             </if>
             <if test="param.popularize != null">
-                and a.a.popularize_ = 1
+                and a.popularize_ = #{param.popularize}
             </if>
         </where>
 
     </select>
 
+    <select id="queryUserPageByTenantId" resultType="map">
+        SELECT id_,username_
+        FROM sys_user
+        WHERE tenant_id_ = 1 and user_type_ = 'STUDENT' and lock_flag_=0 and del_flag_= 0 and is_super_admin_=0
+        and username_ is not null and username_ != ''
+    </select>
+
 </mapper>

+ 106 - 0
mec-biz/src/main/resources/config/mybatis/ImSendGroupMessageMapper.xml

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!--
+这个文件是自动生成的。
+不要修改此文件。所有改动将在下次重新自动生成时丢失。
+-->
+<mapper namespace="com.ym.mec.biz.dal.dao.ImSendGroupMessageDao">
+	
+	<resultMap type="com.ym.mec.biz.dal.entity.ImSendGroupMessage" id="ImSendGroupMessage">
+		<result column="id_" property="id" />
+		<result column="message_content_" property="messageContent" />
+		<result column="sender_id_" property="senderId" />
+		<result column="extra" property="extra" />
+		<result column="target_ids_" property="targetIds" />
+		<result column="file_url_" property="fileUrl" />
+		<result column="file_name_" property="fileName" />
+		<result column="file_size_" property="fileSize" />
+		<result column="message_type_" property="messageType" />
+		<result column="send_flag_" property="sendFlag" />
+		<result column="send_time_" property="sendTime" />
+		<result column="create_time_" property="createTime" />
+		<result column="update_time_" property="updateTime" />
+	</resultMap>
+	
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="ImSendGroupMessage" >
+		SELECT * FROM im_send_group_message WHERE id_ = #{id} 
+	</select>
+	
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="ImSendGroupMessage">
+		SELECT * FROM im_send_group_message ORDER BY id_
+	</select>
+	
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.ImSendGroupMessage" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		INSERT INTO im_send_group_message (message_content_,sender_id_,extra,target_ids_,file_url_,file_name_,file_size_,message_type_,send_flag_,send_time_,create_time_,update_time_)
+		VALUES(#{messageContent},#{senderId},#{extra},#{targetIds},#{fileUrl},#{fileName},#{fileSize},#{messageType},#{sendFlag},#{sendTime},NOW(),NOW())
+	</insert>
+	
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.ym.mec.biz.dal.entity.ImSendGroupMessage">
+		UPDATE im_send_group_message <set>
+			<if test="senderId != null">
+			sender_id_ = #{senderId},
+			</if>
+			<if test="messageType != null">
+			message_type_ = #{messageType},
+			</if>
+			<if test="sendTime != null">
+			send_time_ = #{sendTime},
+			</if>
+			<if test="sendFlag != null">
+			send_flag_ = #{sendFlag},
+			</if>
+			<if test="targetIds != null">
+			target_ids_ = #{targetIds},
+			</if>
+			<if test="fileName != null">
+			file_name_ = #{fileName},
+			</if>
+			<if test="fileSize != null">
+			file_size_ = #{fileSize},
+			</if>
+			<if test="messageContent != null">
+			message_content_ = #{messageContent},
+			</if>
+			<if test="extra != null">
+			extra = #{extra},
+			</if>
+			<if test="updateTime != null">
+			update_time_ = #{updateTime},
+			</if>
+			<if test="fileUrl != null">
+			file_url_ = #{fileUrl},
+			</if>
+			</set> WHERE id_ = #{id}
+	</update>
+	<update id="batchUpdateSendFlag">
+		<foreach collection="sendGroupMessages" item="item" separator=";">
+			UPDATE im_send_group_message SET send_flag_ = #{item.sendFlag},update_time_ = NOW() WHERE id_ = #{item.id}
+		</foreach>
+	</update>
+
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete" >
+		DELETE FROM im_send_group_message WHERE id_ = #{id} 
+	</delete>
+	
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="ImSendGroupMessage" parameterType="map">
+		SELECT * FROM im_send_group_message ORDER BY id_
+		<include refid="global.limit"/>
+	</select>
+	
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM im_send_group_message
+	</select>
+    <select id="findBySendFlag" resultMap="ImSendGroupMessage">
+		SELECT * FROM im_send_group_message WHERE send_flag_ = #{sendFlag}
+		<if test="sendTime != null">
+		AND send_time_ &lt;= #{sendTime}
+		</if>
+	</select>
+</mapper>

+ 3 - 0
mec-biz/src/main/resources/config/mybatis/MusicGroupPaymentCalenderDetailMapper.xml

@@ -417,6 +417,9 @@
 				#{item}
 			</foreach>
 		</if>
+		<if test="batchNo != null and batchNo != ''">
+			AND mgpc.batch_no_ != #{batchNo}
+		</if>
 		GROUP BY mgpcd.user_id_
 	</select>
 

+ 8 - 0
mec-biz/src/main/resources/config/mybatis/StudentPaymentOrderMapper.xml

@@ -1060,6 +1060,14 @@
         SELECT COUNT(0) FROM student_payment_order spo
         WHERE spo.music_group_id_ = #{musicGroupId} AND spo.user_id_ = #{userId} AND group_type_ = 'MUSIC' AND status_ = 'SUCCESS' AND spo.id_ &lt; #{orderId}
     </select>
+    <select id="getMemberIngOrder" resultType="com.ym.mec.biz.dal.entity.StudentPaymentOrder">
+        SELECT *
+        FROM student_payment_order
+        WHERE music_group_id_ IS NULL
+          AND type_ = #{type,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+          AND status_ = #{status,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+        LIMIT 1
+    </select>
 
 
 </mapper>

+ 1 - 1
mec-client-api/src/main/java/com/ym/mec/im/ImFeignService.java

@@ -115,7 +115,7 @@ public interface ImFeignService {
     Object privateSend(@RequestBody ImPrivateMessage privateMessage);
 
     @PostMapping(value = "group/send")
-    Object groupSend(@RequestBody ImGroupMessage imGroupMessage);
+    Object groupSend(@RequestBody ImMessageDto imMessageDto);
 
     /**
      * 获取历史消息记录

+ 1 - 1
mec-client-api/src/main/java/com/ym/mec/im/fallback/ImFeignServiceFallback.java

@@ -66,7 +66,7 @@ public class ImFeignServiceFallback implements ImFeignService {
     }
 
     @Override
-    public Object groupSend(ImGroupMessage imGroupMessage) {
+    public Object groupSend(ImMessageDto imMessageDto) {
         return null;
     }
 

+ 60 - 0
mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImFileMessage.java

@@ -0,0 +1,60 @@
+package com.ym.mec.common.entity;
+
+import com.alibaba.fastjson.JSONObject;
+
+public class ImFileMessage extends ImBaseMessage {
+    private String name;
+    private Long size;
+    private String fileUrl;
+    private String extra;
+
+    private static final transient String TYPE = "RC:FileMsg";
+
+    public ImFileMessage(String name, Long size, String fileUrl, String extra) {
+        this.name = name;
+        this.size = size;
+        this.fileUrl = fileUrl;
+        this.extra = extra;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Long getSize() {
+        return size;
+    }
+
+    public void setSize(Long size) {
+        this.size = size;
+    }
+
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public String getExtra() {
+        return extra;
+    }
+
+    public void setExtra(String extra) {
+        this.extra = extra;
+    }
+
+    @Override
+    public String getType() {
+        return TYPE;
+    }
+
+    public String toString() {
+        return JSONObject.toJSONString(this);
+    }
+}

+ 85 - 0
mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImMessageDto.java

@@ -0,0 +1,85 @@
+package com.ym.mec.common.entity;
+
+import com.alibaba.fastjson.JSONObject;
+
+public class ImMessageDto {
+    private String objectName;
+
+    private String messageContent;
+
+    private String extra;
+
+    private String fileUrl;
+
+    private Long fileSize;
+
+    private String fileName;
+
+    private String[] targetIds;
+
+    private String senderId;
+
+    public String getObjectName() {
+        return objectName;
+    }
+
+    public void setObjectName(String objectName) {
+        this.objectName = objectName;
+    }
+
+    public String getMessageContent() {
+        return messageContent;
+    }
+
+    public void setMessageContent(String messageContent) {
+        this.messageContent = messageContent;
+    }
+
+    public String getExtra() {
+        return extra;
+    }
+
+    public void setExtra(String extra) {
+        this.extra = extra;
+    }
+
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public Long getFileSize() {
+        return fileSize;
+    }
+
+    public void setFileSize(Long fileSize) {
+        this.fileSize = fileSize;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+
+    public String[] getTargetIds() {
+        return targetIds;
+    }
+
+    public void setTargetIds(String[] targetIds) {
+        this.targetIds = targetIds;
+    }
+
+    public String getSenderId() {
+        return senderId;
+    }
+
+    public void setSenderId(String senderId) {
+        this.senderId = senderId;
+    }
+}

+ 4 - 4
mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImMessageModel.java

@@ -8,7 +8,7 @@ public class ImMessageModel {
     //消息类型, 分为两类: 内置消息类型 、自定义消息类型  RC:TxtMsg,RC:ImgMsg,RC:VcMsg,RC:ImgTextMsg,RC:FileMsg,RC:LBSMsg  必填
     private String objectName;
     //消息内容  必填
-    private ImBaseMessage content;
+    private ImTxtMessage content;
     //push 内容, 分为两类 内置消息 Push 、自定义消息 Push  RC:TxtMsg,RC:ImgMsg,RC:VcMsg,RC:ImgTextMsg,RC:FileMsg,RC:LBSMsg
     private String pushContent;
     private String pushData;
@@ -16,7 +16,7 @@ public class ImMessageModel {
     public ImMessageModel() {
     }
 
-    public ImMessageModel(String senderId, String[] targetId, String objectName, ImBaseMessage content, String pushContent, String pushData) {
+    public ImMessageModel(String senderId, String[] targetId, String objectName, ImTxtMessage content, String pushContent, String pushData) {
         this.senderId = senderId;
         this.targetId = targetId;
         this.objectName = objectName;
@@ -43,11 +43,11 @@ public class ImMessageModel {
         return this;
     }
 
-    public ImBaseMessage getContent() {
+    public ImTxtMessage getContent() {
         return this.content;
     }
 
-    public ImMessageModel setContent(ImBaseMessage content) {
+    public ImMessageModel setContent(ImTxtMessage content) {
         this.content = content;
         return this;
     }

+ 58 - 11
mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImTxtMessage.java

@@ -2,26 +2,73 @@ package com.ym.mec.common.entity;
 
 import com.alibaba.fastjson.JSONObject;
 
-public class ImTxtMessage extends ImBaseMessage {
-    private String content = "";
-    private String extra = "";
-    private static final transient String TYPE = "RC:TxtMsg";
+public class ImTxtMessage{
+    private String messageContent;
+    private String extra;
+    private String name;
+    private Long size;
+    private String fileUrl;
+    private String type;
 
-    public ImTxtMessage(String content, String extra) {
-        this.content = content;
+    public ImTxtMessage(String messageContent, String extra) {
+        this.type = "RC:TxtMsg";
+        this.messageContent = messageContent;
+        this.extra = extra;
+    }
+
+    public ImTxtMessage(String messageContent, String extra, String fileUrl) {
+        this.type = "RC:ImgMsg";
+        this.messageContent = messageContent;
+        this.extra = extra;
+        this.fileUrl = fileUrl;
+    }
+
+    public ImTxtMessage(String name, Long size, String fileUrl, String extra) {
+        this.type = "RC:FileMsg";
+        this.name = name;
+        this.size = size;
+        this.fileUrl = fileUrl;
         this.extra = extra;
     }
 
     public String getType() {
-        return TYPE;
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Long getSize() {
+        return size;
+    }
+
+    public void setSize(Long size) {
+        this.size = size;
+    }
+
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
     }
 
-    public String getContent() {
-        return this.content;
+    public String getMessageContent() {
+        return messageContent;
     }
 
-    public void setContent(String content) {
-        this.content = content;
+    public void setMessageContent(String messageContent) {
+        this.messageContent = messageContent;
     }
 
     public String getExtra() {

+ 11 - 1
mec-common/common-core/src/main/java/com/ym/mec/common/entity/UploadReturnBean.java

@@ -20,7 +20,17 @@ public class UploadReturnBean {
 
 	private String message;// 上传失败 返回原因
 
-	private String name;
+	private String name;// 上传文件名
+
+	private Long size;//文件大小
+
+	public Long getSize() {
+		return size;
+	}
+
+	public void setSize(Long size) {
+		this.size = size;
+	}
 
 	public String getName() {
 		return name;

+ 16 - 10
mec-im/src/main/java/com/ym/controller/GroupController.java

@@ -1,10 +1,11 @@
 package com.ym.controller;
 
-import com.ym.mec.common.entity.ImGroupMessage;
-import com.ym.mec.common.entity.ImTxtMessage;
+import com.ym.mec.common.entity.ImMessageDto;
 import com.ym.pojo.NoticeMessage;
 import com.ym.service.GroupService;
 import com.ym.service.MessageService;
+import io.rong.messages.FileMessage;
+import io.rong.messages.ImgMessage;
 import io.rong.messages.TxtMessage;
 import io.rong.models.group.GroupMember;
 import io.rong.models.group.GroupModel;
@@ -33,20 +34,25 @@ public class GroupController{
     GroupService groupService;
 
     @RequestMapping(value = "/send", method = RequestMethod.POST)
-    public Object send(@RequestBody ImGroupMessage imGroupMessage) throws Exception {
+    public Object send(@RequestBody ImMessageDto imMessageDto) throws Exception {
         GroupMessage groupMessage = new GroupMessage();
-        ImTxtMessage imTxtMessage = (ImTxtMessage) imGroupMessage.getContent();
-        String objectName = imGroupMessage.getObjectName();
+        String objectName = imMessageDto.getObjectName();
         if("DY:NoticeMsg".equals(objectName)){
-            NoticeMessage noticeMessage = new NoticeMessage(imTxtMessage.getContent(),imTxtMessage.getExtra());
+            NoticeMessage noticeMessage = new NoticeMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
             groupMessage.setContent(noticeMessage);
+        }else if("RC:ImgMsg".equals(objectName)){
+            ImgMessage imgMessage = new ImgMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra(),imMessageDto.getFileUrl());
+            groupMessage.setContent(imgMessage);
+        }else if("RC:FileMsg".equals(objectName)){
+            FileMessage imgMessage = new FileMessage(imMessageDto.getFileName(),imMessageDto.getFileSize(),imMessageDto.getFileUrl(),imMessageDto.getExtra());
+            groupMessage.setContent(imgMessage);
         }else {
-            TxtMessage txtMessage = new TxtMessage(imTxtMessage.getContent(),imTxtMessage.getExtra());
+            TxtMessage txtMessage = new TxtMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
             groupMessage.setContent(txtMessage);
         }
-        groupMessage.setTargetId(imGroupMessage.getTargetId());
-        groupMessage.setSenderId(imGroupMessage.getSenderId());
-        groupMessage.setObjectName(imGroupMessage.getObjectName());
+        groupMessage.setTargetId(imMessageDto.getTargetIds());
+        groupMessage.setSenderId(imMessageDto.getSenderId());
+        groupMessage.setObjectName(imMessageDto.getObjectName());
         groupMessage.setIsIncludeSender(1);
         return messageService.groupSend(groupMessage);
     }

+ 2 - 2
mec-im/src/main/java/com/ym/controller/PrivateController.java

@@ -26,8 +26,8 @@ public class PrivateController {
     @RequestMapping(value = "/send", method = RequestMethod.POST)
     public Object send(@RequestBody ImPrivateMessage imPrivateMessage) throws Exception {
         PrivateMessage privateMessage = new PrivateMessage();
-        ImTxtMessage content = (ImTxtMessage)imPrivateMessage.getContent();
-        TxtMessage txtMessage = new TxtMessage(content.getContent(),content.getExtra());
+        ImTxtMessage content = imPrivateMessage.getContent();
+        TxtMessage txtMessage = new TxtMessage(content.getMessageContent(),content.getExtra());
         privateMessage.setContent(txtMessage);
         privateMessage.setTargetId(imPrivateMessage.getTargetId());
         privateMessage.setSenderId(imPrivateMessage.getSenderId());

+ 2 - 2
mec-im/src/main/java/com/ym/controller/SystemController.java

@@ -30,8 +30,8 @@ public class SystemController {
     @RequestMapping(value = "/send", method = RequestMethod.POST)
     public Object send(@RequestBody ImSystemMessage imSystemMessage) throws Exception {
         SystemMessage systemMessage = new SystemMessage();
-        ImTxtMessage content = (ImTxtMessage)imSystemMessage.getContent();
-        TxtMessage txtMessage = new TxtMessage(content.getContent(),content.getExtra());
+        ImTxtMessage content = imSystemMessage.getContent();
+        TxtMessage txtMessage = new TxtMessage(content.getMessageContent(),content.getExtra());
         systemMessage.setContent(txtMessage);
         systemMessage.setSenderId(imSystemMessage.getSenderId());
         systemMessage.setObjectName(imSystemMessage.getObjectName());

+ 1 - 1
mec-student/src/main/java/com/ym/mec/student/controller/DegreeController.java

@@ -94,7 +94,7 @@ public class DegreeController extends BaseController {
             teacherDao.updateUser(user);
         }
         degreeRegistration.setOrganId(user.getOrganId());
-        if(Objects.isNull(degreeRegistration.getOrganId())){
+        if(Objects.isNull(degreeRegistration.getOrganId()) || degreeRegistration.getOrganId() == 4){
             return failed("该分部暂未开放此活动");
         }
         HttpResponseResult pay = degreeRegistrationService.pay(degreeRegistration);

+ 6 - 0
mec-student/src/main/java/com/ym/mec/student/controller/MemberRankController.java

@@ -63,6 +63,12 @@ public class MemberRankController extends BaseController {
         return memberRankSettingService.buy(memberPayParamDto);
     }
 
+    @ApiOperation(value = "购买会员")
+    @PostMapping("/buy1")
+    public Object buy1(@RequestBody MemberPayParamDto memberPayParamDto) throws Exception {
+        return memberRankSettingService.buy1(memberPayParamDto);
+    }
+
     /**
      * 齐齐哈尔购买团练宝-默认激活
      * <p> 购买规则

+ 26 - 31
mec-web/src/main/java/com/ym/mec/web/controller/ImGroupController.java

@@ -1,11 +1,27 @@
 package com.ym.mec.web.controller;
 
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.dto.ImGroupMemberDto;
+import com.ym.mec.biz.dal.dto.ImUserFriendDto;
+import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.entity.ImSendGroupMessage;
+import com.ym.mec.biz.dal.page.ImGroupNoticeQueryInfo;
 import com.ym.mec.biz.service.ImGroupMemberService;
+import com.ym.mec.biz.service.ImGroupNoticeService;
+import com.ym.mec.biz.service.ImGroupService;
+import com.ym.mec.biz.service.ImUserFriendService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
 import com.yonge.log.model.AuditLogAnnotation;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.Arrays;
 import java.util.Date;
@@ -13,25 +29,6 @@ import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.GetMapping;
-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.RestController;
-
-import com.ym.mec.auth.api.client.SysUserFeignService;
-import com.ym.mec.auth.api.entity.SysUser;
-import com.ym.mec.biz.dal.dto.ImUserFriendDto;
-import com.ym.mec.biz.dal.entity.ImGroup;
-import com.ym.mec.biz.dal.page.ImGroupNoticeQueryInfo;
-import com.ym.mec.biz.service.ImGroupNoticeService;
-import com.ym.mec.biz.service.ImGroupService;
-import com.ym.mec.biz.service.ImUserFriendService;
-import com.ym.mec.common.controller.BaseController;
-
 @RequestMapping("imGroup")
 @Api(tags = "IM群服务")
 @RestController
@@ -54,7 +51,7 @@ public class ImGroupController extends BaseController {
 
 	@ApiOperation("查询群列表")
 	@GetMapping(value = "/queryGroupList")
-	public Object queryGroupList(String search) {
+	public HttpResponseResult<List<ImGroup>> queryGroupList(String search) {
 		SysUser sysUser = sysUserFeignService.queryUserInfo();
 		if (Objects.isNull(sysUser)) {
 			return failed(HttpStatus.FORBIDDEN, "请登录");
@@ -65,7 +62,7 @@ public class ImGroupController extends BaseController {
 
 	@ApiOperation("查询群详情")
 	@GetMapping(value = "/queryGroupDetail")
-	public Object queryGroupDetail(String imGroupId) {
+	public HttpResponseResult<ImGroup> queryGroupDetail(String imGroupId) {
 		if (imGroupId.contains("S") || imGroupId.contains("I")){
 			imGroupId = imGroupId.substring(1);
 		}
@@ -74,41 +71,39 @@ public class ImGroupController extends BaseController {
 
 	@ApiOperation("修改群信息")
 	@PostMapping(value = "/updateImGroup")
-	public Object updateImGroup(@RequestBody ImGroup imGroup) {
+	public HttpResponseResult<Integer> updateImGroup(@RequestBody ImGroup imGroup) {
 		imGroup.setUpdateTime(new Date());
 		return succeed(imGroupService.update(imGroup));
 	}
 
 	@ApiOperation("修改群成员信息")
 	@PostMapping(value = "/updateNickName")
-	public Object updateNickName(Integer userId,String nickName) {
+	public HttpResponseResult updateNickName(Integer userId,String nickName) {
 		imGroupService.updateNickName1(userId,nickName);
 		return succeed();
 	}
 
 	@ApiOperation("查询群成员列表")
 	@GetMapping(value = "/queryGroupMemberList")
-	public Object queryGroupMemberList(Long imGroupId) {
-
+	public HttpResponseResult<List<ImGroupMemberDto>> queryGroupMemberList(Long imGroupId) {
 		return succeed(imGroupService.queryMemberById(imGroupId));
 	}
 
 	@ApiOperation("查询群学生列表")
 	@GetMapping(value = "/queryGroupStudentList")
-	public Object queryGroupStudentList(Long imGroupId) {
-
+	public HttpResponseResult<List<ImGroupMemberDto>> queryGroupStudentList(Long imGroupId) {
 		return succeed(imGroupService.queryMemberById(imGroupId).stream().filter(e -> StringUtils.isBlank(e.getRoleType())).collect(Collectors.toList()));
 	}
 
 	@ApiOperation("查询群成员详情")
 	@GetMapping(value = "/queryGroupMemberDetail")
-	public Object queryGroupMemberDetail(Long imGroupId, Integer userId) {
+	public HttpResponseResult<ImGroupMemberDto> queryGroupMemberDetail(Long imGroupId, Integer userId) {
 		return succeed(imGroupService.queryMember(imGroupId, userId));
 	}
 
 	@ApiOperation("查询好友详情")
 	@GetMapping(value = "/queryFriendDetail")
-	public Object queryFriendDetail(Integer userId) {
+	public HttpResponseResult<ImUserFriendDto> queryFriendDetail(Integer userId) {
 		SysUser sysUser = sysUserFeignService.queryUserInfo();
 		if (Objects.isNull(sysUser)) {
 			return failed(HttpStatus.FORBIDDEN, "请登录");
@@ -132,7 +127,7 @@ public class ImGroupController extends BaseController {
 
 	@ApiOperation("查询好友列表")
 	@GetMapping(value = "/queryFriendList")
-	public Object queryFriendList(String search) {
+	public HttpResponseResult<List<ImUserFriendDto>> queryFriendList(String search) {
 		SysUser sysUser = sysUserFeignService.queryUserInfo();
 		if (Objects.isNull(sysUser)) {
 			return failed(HttpStatus.FORBIDDEN, "请登录");
@@ -143,7 +138,7 @@ public class ImGroupController extends BaseController {
 
 	@ApiOperation("查询好友中的学生列表")
 	@GetMapping(value = "/queryFriendStudentList")
-	public Object queryFriendStudentList(String search) {
+	public HttpResponseResult<List<ImUserFriendDto>> queryFriendStudentList(String search) {
 		SysUser sysUser = sysUserFeignService.queryUserInfo();
 		if (Objects.isNull(sysUser)) {
 			return failed(HttpStatus.FORBIDDEN, "请登录");

+ 5 - 4
mec-web/src/main/java/com/ym/mec/web/controller/ImLiveBroadcastRoomController.java

@@ -2,8 +2,8 @@ package com.ym.mec.web.controller;
 
 
 import com.ym.mec.biz.dal.dto.ImLiveBroadcastRoomDto;
+import com.ym.mec.biz.dal.vo.BaseRoomUserVo;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
-import com.ym.mec.biz.dal.vo.RoomUserInfoVo;
 import com.ym.mec.biz.service.ImLiveBroadcastRoomService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.entity.HttpResponseResult;
@@ -40,6 +40,7 @@ public class ImLiveBroadcastRoomController extends BaseController {
             @ApiImplicitParam(name = "liveState", dataType = "Integer", value = "直播状态 0未开始 1开始 2结束"),
             @ApiImplicitParam(name = "startTime", dataType = "String", value = "开始时间"),
             @ApiImplicitParam(name = "endTime", dataType = "String", value = "结束时间"),
+            @ApiImplicitParam(name = "popularize", dataType = "String", value = "结束时间"),
             @ApiImplicitParam(name = "page", dataType = "Integer", value = "页数"),
             @ApiImplicitParam(name = "rows", dataType = "Integer", value = "每页数量"),
     })
@@ -116,7 +117,7 @@ public class ImLiveBroadcastRoomController extends BaseController {
     }
 
     @ApiOperation("推广直播间-每个机构只能有一个直播间在首页推广")
-    @PostMapping("/opsPopularize")
+    @GetMapping("/opsPopularize")
     @PreAuthorize("@pcs.hasPermissions('imLiveBroadcastRoom/opsPopularize')")
     public HttpResponseResult<Object> opsPopularize(@ApiParam(value = "房间id", required = true) Integer id,
                                                     @ApiParam(value = "是否在首页推广 0否 1是", required = true) Integer popularize) {
@@ -186,8 +187,8 @@ public class ImLiveBroadcastRoomController extends BaseController {
 
     @ApiOperation("获取房间人员")
     @GetMapping("/queryRoomUserInfo")
-    public HttpResponseResult<List<RoomUserInfoVo>> queryRoomUserInfo(@ApiParam(value = "房间uid", required = true) String roomUid) {
-        return succeed(imLiveBroadcastRoomService.queryRoomUserInfo(roomUid));
+    public HttpResponseResult<List<BaseRoomUserVo>> queryRoomUserInfo(@ApiParam(value = "房间uid", required = true) String roomUid) {
+        return succeed(imLiveBroadcastRoomService.queryRoomLimitOnlineUserInfo(roomUid));
     }
 
 }

+ 36 - 0
mec-web/src/main/java/com/ym/mec/web/controller/ImSendGroupMessageController.java

@@ -0,0 +1,36 @@
+package com.ym.mec.web.controller;
+
+import com.ym.mec.biz.dal.entity.ImSendGroupMessage;
+import com.ym.mec.biz.service.ImSendGroupMessageService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+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.RestController;
+
+@Api(tags = "群消息定时发送")
+@RequestMapping("imSendGroupMessage")
+@RestController
+public class ImSendGroupMessageController extends BaseController {
+
+    @Autowired
+    private ImSendGroupMessageService imSendGroupMessageService;
+
+    @ApiOperation("发送群聊消息")
+    @PostMapping(value = "/send")
+    public HttpResponseResult send(@RequestBody ImSendGroupMessage imSendGroupMessage) throws Exception {
+        imSendGroupMessageService.sendGroupMessage(imSendGroupMessage);
+        return succeed();
+    }
+
+    @ApiOperation("修改未发送的群消息")
+    @PostMapping(value = "/update")
+    public HttpResponseResult update(@RequestBody ImSendGroupMessage imSendGroupMessage) throws Exception {
+        imSendGroupMessageService.updateGroupMessage(imSendGroupMessage);
+        return succeed();
+    }
+}

+ 0 - 1
mec-web/src/main/java/com/ym/mec/web/controller/StudentManageController.java

@@ -406,7 +406,6 @@ public class StudentManageController extends BaseController {
 
     @ApiOperation(value = "云教练学员数据预览")
     @GetMapping("/getCloudStudyStudentOverView")
-    @PreAuthorize("@pcs.hasPermissions('studentManage/getCloudStudyStudentOverView')")
     public HttpResponseResult<Object> getCloudStudyStudentOverView(String organIds) throws Exception {
         List<Integer> organIdsList;
         if(StringUtils.isNotBlank(organIds)){

+ 19 - 21
mec-web/src/main/java/com/ym/mec/web/controller/TaskController.java

@@ -1,25 +1,5 @@
 package com.ym.mec.web.controller;
 
-import com.ym.mec.biz.service.*;
-import io.swagger.annotations.ApiOperation;
-
-import java.io.File;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ym.mec.biz.dal.dao.MusicGroupSchoolTermCourseDetailDao;
@@ -27,12 +7,26 @@ import com.ym.mec.biz.dal.entity.MusicGroupSchoolTermCourseDetail;
 import com.ym.mec.biz.dal.entity.TenantInfo;
 import com.ym.mec.biz.dal.enums.IndexDataType;
 import com.ym.mec.biz.event.source.CourseEventSource;
+import com.ym.mec.biz.service.*;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.redis.service.RedisCache;
 import com.ym.mec.common.tenant.TenantContextHolder;
 import com.ym.mec.im.ImFeignService;
 import com.ym.mec.util.date.DateUtil;
 import com.yonge.log.service.HistoryMessageService;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.File;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 @RequestMapping("task")
 @RestController
@@ -122,6 +116,8 @@ public class TaskController extends BaseController {
     private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
 	@Autowired
 	private StudentStatisticsService studentStatisticsService;
+	@Autowired
+	private ImSendGroupMessageService imSendGroupMessageService;
 
 	@GetMapping(value = "/syncImHistoryMessageTask")
 	// 同步即时通讯聊天记录
@@ -233,11 +229,13 @@ public class TaskController extends BaseController {
 
 	@GetMapping("/updateCourseScheduleToOverStatus")
 	// 更新课程状态至已结束
-	public void updateCourseScheduleToOverStatus() {
+	public void updateCourseScheduleToOverStatus() throws Exception {
 		List<Long> courseIds = courseScheduleService.updateCourseScheduleToOverStatus();
 		courseEventSource.courseStatusChange(courseIds);
 		courseIds = courseScheduleService.updateCourseScheduleToUnderway();
 		courseEventSource.courseStatusChange(courseIds);
+		//发送定时群消息
+		imSendGroupMessageService.sendTimedMessages();
 		//更新乐团课统计信息
 		courseScheduleStatisticsService.courseScheduleStatistics();
 	}

+ 1 - 0
mec-web/src/main/java/com/ym/mec/web/controller/UploadFileController.java

@@ -44,6 +44,7 @@ public class UploadFileController extends BaseController {
 		try {
 			if (file != null && StringUtils.isNotBlank(file.getOriginalFilename())) {
 				UploadReturnBean bean = uploadFileService.uploadFile(file.getInputStream(), UploadUtil.getExtension(file.getOriginalFilename()));
+				bean.setSize(file.getSize());
 				bean.setName(file.getOriginalFilename());
 				if (bean.isStatus()) {
 					return succeed(bean);