Browse Source

Merge remote-tracking branch 'origin/dev_v1.3.5_20230106' into dev_mall_20221201

liujunchi 2 năm trước cách đây
mục cha
commit
3568f29ea5
100 tập tin đã thay đổi với 3165 bổ sung307 xóa
  1. 6 1
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java
  2. 8 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java
  3. 10 0
      cooleshow-auth/auth-api/src/main/java/com/yonge/cooleshow/auth/api/entity/LoginEntity.java
  4. 16 0
      cooleshow-auth/auth-server/pom.xml
  5. 11 10
      cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/core/filter/PhoneLoginAuthenticationFilter.java
  6. 37 12
      cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/core/provider/PhoneAuthenticationProvider.java
  7. 5 0
      cooleshow-common/pom.xml
  8. 1 1
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/RewardTypeEnum.java
  9. 2 2
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java
  10. 22 0
      cooleshow-task/src/main/java/com/yonge/cooleshow/task/jobs/BatchSendingTask.java
  11. 175 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/CustomerServiceBatchSendingController.java
  12. 91 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/CustomerServiceReceiveController.java
  13. 15 16
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicAlbumController.java
  14. 35 4
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicSheetController.java
  15. 3 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/UserAccountRecordController.java
  16. 33 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/AdminClient.java
  17. 1 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/OpenUserAccountController.java
  18. 1 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/UserOrderClient.java
  19. 106 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/CustomerServiceBatchSendingVo.java
  20. 59 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/CustomerServiceReceiveVo.java
  21. 7 2
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/IMNotifyMessageVO.java
  22. 26 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/task/TaskController.java
  23. 14 0
      cooleshow-user/user-biz/pom.xml
  24. 3 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/PlatformCashAccountRecordDao.java
  25. 10 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/SubjectDao.java
  26. 22 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/MusicImgDto.java
  27. 54 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/MusicSheetRenderDto.java
  28. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/OrderReq.java
  29. 22 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/TeacherMusicSheetAuditReq.java
  30. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/MusicSheetSearch.java
  31. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/UserAccountRecordSearch.java
  32. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityReward.java
  33. 95 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CustomerServiceBatchSending.java
  34. 44 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CustomerServiceReceive.java
  35. 88 14
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicSheet.java
  36. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PlatformCashAccountRecord.java
  37. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/Student.java
  38. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrder.java
  39. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrderDetail.java
  40. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/AccountBizTypeEnum.java
  41. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/GoodTypeEnum.java
  42. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/OrderTypeEnum.java
  43. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/coupon/CouponCategoryEnum.java
  44. 28 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImReceiveType.java
  45. 30 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImSendStatus.java
  46. 28 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImSendType.java
  47. 36 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CustomerServiceBatchSendingMapper.java
  48. 25 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CustomerServiceReceiveMapper.java
  49. 11 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/SysUserMapper.java
  50. 61 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CustomerServiceBatchSendingService.java
  51. 43 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CustomerServiceReceiveService.java
  52. 4 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicSheetService.java
  53. 14 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/PlatformCashAccountRecordService.java
  54. 12 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/StudentService.java
  55. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityRewardServiceImpl.java
  56. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseGroupServiceImpl.java
  57. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java
  58. 609 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceBatchSendingServiceImpl.java
  59. 94 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceReceiveServiceImpl.java
  60. 29 44
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java
  61. 111 24
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MusicSheetServiceImpl.java
  62. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PianoRoomBuyRecordServiceImpl.java
  63. 20 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PlatformCashAccountRecordServiceImpl.java
  64. 132 10
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/StudentServiceImpl.java
  65. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserAccountRecordServiceImpl.java
  66. 3 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserAccountServiceImpl.java
  67. 16 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserBindingTeacherServiceImpl.java
  68. 5 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderRefundServiceImpl.java
  69. 63 57
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java
  70. 8 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/VideoLessonPurchaseRecordServiceImpl.java
  71. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/UserOrderRefundVo.java
  72. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/activity/UserRewardWrapper.java
  73. 77 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/StudentWrapper.java
  74. 22 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerService.java
  75. 206 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerServiceBatchSendingWrapper.java
  76. 83 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerServiceReceiveWrapper.java
  77. 74 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CustomerServiceBatchSendingMapper.xml
  78. 28 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CustomerServiceReceiveMapper.xml
  79. 2 2
      cooleshow-user/user-biz/src/main/resources/config/mybatis/MusicAlbumMapper.xml
  80. 16 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/MusicSheetMapper.xml
  81. 3 3
      cooleshow-user/user-biz/src/main/resources/config/mybatis/PlatformCashAccountRecordMapper.xml
  82. 1 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/StudentMapper.xml
  83. 6 2
      cooleshow-user/user-biz/src/main/resources/config/mybatis/SubjectMapper.xml
  84. 20 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/SysUserMapper.xml
  85. 1 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/TeacherMapper.xml
  86. 38 6
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/MusicSheetController.java
  87. 1 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/StudentController.java
  88. 1 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/SubjectController.java
  89. 26 21
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/open/OpenClient.java
  90. 1 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/io/request/ActivityVo.java
  91. 35 6
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/MusicSheetController.java
  92. 1 1
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/SubjectController.java
  93. 3 3
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherController.java
  94. 16 4
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/open/OpenShareController.java
  95. 1 1
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/io/request/ActivityVo.java
  96. 1 1
      cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/StudentController.java
  97. 1 1
      cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/TeacherController.java
  98. 15 5
      cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/open/OpenMusicSheetController.java
  99. 1 1
      cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/open/OpenSubjectController.java
  100. 1 1
      cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/open/SubjectController.java

+ 6 - 1
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java

@@ -20,7 +20,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 
 import java.math.BigDecimal;
 import java.util.List;
-import java.util.Map;
 
 /**
  * Description
@@ -144,4 +143,10 @@ public interface AdminFeignService {
      */
     @GetMapping("/task/virtualNumber")
     HttpResponseResult<Boolean> virtualNumber();
+
+    /**
+     * 群发消息
+     */
+    @GetMapping("/task/batchSending")
+    HttpResponseResult<Boolean> batchSending();
 }

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

@@ -123,4 +123,12 @@ public class AdminFeignServiceFallback implements AdminFeignService {
     public HttpResponseResult<Boolean> virtualNumber() {
         return null;
     }
+
+    /**
+     * 群发消息
+     */
+    @Override
+    public HttpResponseResult<Boolean> batchSending() {
+        return null;
+    }
 }

+ 10 - 0
cooleshow-auth/auth-api/src/main/java/com/yonge/cooleshow/auth/api/entity/LoginEntity.java

@@ -18,6 +18,8 @@ public class LoginEntity {
     private String deviceNum;
     //二维码code
     private String qrCode;
+    //关联帐号授权码
+    private String authToken;
     
     public Boolean getIsSurportRegister() {
 		return isSurportRegister;
@@ -82,4 +84,12 @@ public class LoginEntity {
     public void setQrCode(String qrCode) {
         this.qrCode = qrCode;
     }
+
+    public String getAuthToken() {
+        return authToken;
+    }
+
+    public void setAuthToken(String authToken) {
+        this.authToken = authToken;
+    }
 }

+ 16 - 0
cooleshow-auth/auth-server/pom.xml

@@ -17,6 +17,22 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
     <dependencies>
+
+        <dependency>
+            <groupId>com.microsvc.toolkit.config</groupId>
+            <artifactId>microsvc-config-jwt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-jwt</artifactId>
+            <version>1.0.9.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.79</version>
+        </dependency>
+
         <dependency>
             <groupId>com.yonge.toolset</groupId>
             <artifactId>toolset-mybatis</artifactId>

+ 11 - 10
cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/core/filter/PhoneLoginAuthenticationFilter.java

@@ -1,12 +1,8 @@
 package com.yonge.cooleshow.auth.core.filter;
 
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import com.yonge.cooleshow.auth.api.entity.LoginEntity;
+import com.yonge.cooleshow.auth.config.token.PhoneAuthenticationToken;
+import com.yonge.cooleshow.common.security.SecurityConstants;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.security.authentication.AbstractAuthenticationToken;
 import org.springframework.security.authentication.AuthenticationServiceException;
@@ -15,9 +11,11 @@ import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 
-import com.yonge.cooleshow.auth.api.entity.LoginEntity;
-import com.yonge.cooleshow.auth.config.token.PhoneAuthenticationToken;
-import com.yonge.cooleshow.common.security.SecurityConstants;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 
 public class PhoneLoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
 
@@ -27,6 +25,7 @@ public class PhoneLoginAuthenticationFilter extends AbstractAuthenticationProces
 	private static final String IS_SURPORT_REGISTER = "isSurportRegister";
 	private static final String LOGIN_USER_TYPE = "loginUserType";
 	private static final String QR_CODE = "qrCode";
+	private static final String AUTH_TOKEN = "token";
 
 	private static final String DEVICE_NUM = "deviceNum";
 
@@ -51,6 +50,7 @@ public class PhoneLoginAuthenticationFilter extends AbstractAuthenticationProces
 		boolean isRegister = StringUtils.equals("true", request.getParameter(IS_SURPORT_REGISTER));
 		String loginUserType = obtainParameter(request, LOGIN_USER_TYPE);
 		String qrCode = obtainParameter(request, QR_CODE);
+		String authToken = obtainParameter(request, AUTH_TOKEN);
 
 		String clientId = request.getParameter(clientIdParameter).toUpperCase();
 
@@ -70,6 +70,7 @@ public class PhoneLoginAuthenticationFilter extends AbstractAuthenticationProces
 		loginEntity.setLoginUserType(loginUserType);
 		loginEntity.setDeviceNum(deviceNum);
 		loginEntity.setQrCode(qrCode);
+		loginEntity.setAuthToken(authToken);
 
 		authRequest = new PhoneAuthenticationToken(SecurityConstants.PHONE_PRINCIPAL_PREFIX + principal, loginEntity);
 

+ 37 - 12
cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/core/provider/PhoneAuthenticationProvider.java

@@ -1,8 +1,15 @@
 package com.yonge.cooleshow.auth.core.provider;
 
-import java.util.Date;
-import java.util.Objects;
-
+import com.microsvc.toolkit.config.jwt.utils.RsaKeyHelper;
+import com.yonge.cooleshow.auth.api.dto.SysUserInfo;
+import com.yonge.cooleshow.auth.api.entity.LoginEntity;
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.auth.config.token.PhoneAuthenticationToken;
+import com.yonge.cooleshow.auth.service.SysUserDeviceService;
+import com.yonge.cooleshow.auth.service.SysUserService;
+import com.yonge.cooleshow.common.service.IdGeneratorService;
+import com.yonge.toolset.base.exception.BizException;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.InternalAuthenticationServiceException;
@@ -12,16 +19,15 @@ import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.jwt.Jwt;
+import org.springframework.security.jwt.JwtHelper;
+import org.springframework.security.jwt.crypto.sign.RsaVerifier;
 import org.springframework.transaction.annotation.Transactional;
 
-import com.yonge.cooleshow.auth.api.dto.SysUserInfo;
-import com.yonge.cooleshow.auth.api.entity.LoginEntity;
-import com.yonge.cooleshow.auth.api.entity.SysUser;
-import com.yonge.cooleshow.auth.config.token.PhoneAuthenticationToken;
-import com.yonge.cooleshow.auth.service.SysUserDeviceService;
-import com.yonge.cooleshow.auth.service.SysUserService;
-import com.yonge.cooleshow.common.service.IdGeneratorService;
-
+import java.security.interfaces.RSAPublicKey;
+import java.util.Date;
+import java.util.Objects;
+@Slf4j
 public class PhoneAuthenticationProvider extends AbstractAuthenticationProvider {
 
     private UserDetailsService userDetailsService;
@@ -49,13 +55,32 @@ public class PhoneAuthenticationProvider extends AbstractAuthenticationProvider
 
         String smsCode = loginEntity.getSmsCode();
         String phone = loginEntity.getPhone();
+        // 二维码登录
         String qrCode = loginEntity.getQrCode();
-        if (StringUtils.isNotEmpty(qrCode) && StringUtils.isEmpty(smsCode)) {
+        // 授权Token登录
+        String authToken = loginEntity.getAuthToken();
+        if (StringUtils.isNotEmpty(qrCode)) {
             // 二维码验证
             boolean b = sysUserService.verifyQrCode(phone, qrCode);
             if (!b) {
                 throw new BadCredentialsException("二维码校验失败");
             }
+        } else if (StringUtils.isNotEmpty(authToken)) {
+            // 授权authToken登录
+            try {
+                RSAPublicKey rsaPublicKey = RsaKeyHelper.getRSAPublicKey("jmedu", "dayaedu", "jmedu.jks", "dayaedu");
+                Jwt jwt = JwtHelper.decodeAndVerify(authToken, new RsaVerifier(rsaPublicKey));
+
+                //获取jwt原始内容
+                String claims = jwt.getClaims();
+                if (StringUtils.isEmpty(claims)) {
+                    throw new BizException("三方授权校验失败");
+                }
+                log.info("retrieveUser claims={}", claims);
+            } catch (Exception e) {
+                log.error("retrieveUser authToken={}", authToken, e);
+            }
+
         } else {
             // 验证码验证
             boolean b = smsCodeService.verifyValidCode(phone, smsCode, "SMS_VERIFY_CODE_LOGIN");

+ 5 - 0
cooleshow-common/pom.xml

@@ -49,6 +49,11 @@
 			<groupId>org.springframework.cloud</groupId>
 			<artifactId>spring-cloud-starter-oauth2</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework.security.oauth</groupId>
+			<artifactId>spring-security-oauth2</artifactId>
+			<version>2.3.3.RELEASE</version>
+		</dependency>
 
 		<dependency>
 			<groupId>com.baomidou</groupId>

+ 1 - 1
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/RewardTypeEnum.java

@@ -13,7 +13,7 @@ public enum RewardTypeEnum implements BaseEnum<String, RewardTypeEnum> {
 
     ACTUAL("实物"),
     VIP("小酷AI会员"),
-    PIAMO_ROOM("琴房时长"),
+    PIANO_ROOM("琴房时长"),
     COUPON("优惠券"),
     ;
 

+ 2 - 2
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java

@@ -377,7 +377,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
 
         List<MallOrderItemDto> list = new ArrayList<>();
         for (OmsOrderItem omsOrderItem : orderItemList) {
-            if (omsOrderItem.getReturnStatus() != -1) {
+            if (!omsOrderItem.getReturnStatus().equals( -1)) {
                 continue;
             }
             MallOrderItemDto teacherShareDto = new MallOrderItemDto();
@@ -398,7 +398,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             result = adminFeignService.mallRecordState(list);
         }
         if (result.getStatus()) {
-            LOG.debug("分润记录写入成功,json: {}",JSON.toJSONString(list));
+            LOG.info("分润记录写入成功,json: {}",JSON.toJSONString(list));
         } else {
             LOG.error("分润记录写入失败,json: {}",JSON.toJSONString(list));
         }

+ 22 - 0
cooleshow-task/src/main/java/com/yonge/cooleshow/task/jobs/BatchSendingTask.java

@@ -0,0 +1,22 @@
+package com.yonge.cooleshow.task.jobs;
+
+import com.yonge.cooleshow.api.feign.AdminFeignService;
+import com.yonge.cooleshow.task.core.BaseTask;
+import com.yonge.cooleshow.task.core.TaskException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 消息定时群发
+ */
+@Service
+public class BatchSendingTask extends BaseTask {
+
+    @Autowired
+    private AdminFeignService adminFeignService;
+
+    @Override
+    public void execute() throws TaskException {
+        Object o = adminFeignService.batchSending();
+    }
+}

+ 175 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/CustomerServiceBatchSendingController.java

@@ -0,0 +1,175 @@
+package com.yonge.cooleshow.admin.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.admin.io.request.im.CustomerServiceBatchSendingVo;
+import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.enums.im.EImReceiveType;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendStatus;
+import com.yonge.cooleshow.biz.dal.service.CustomerServiceBatchSendingService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceBatchSendingWrapper;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.page.PageInfo;
+import com.yonge.toolset.mybatis.support.PageUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Objects;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("/batchSending")
+@Api(tags = "客服群发")
+public class CustomerServiceBatchSendingController extends BaseController {
+
+    @Autowired
+    private CustomerServiceBatchSendingService customerServiceBatchSendingService;
+	@Autowired
+	private SysUserFeignService sysUserFeignService;
+
+	/**
+	 * 查询单条
+	 * @param id 详情ID
+	 * @return R<CustomerServiceBatchSendingVo.CustomerServiceBatchSending>
+	 */
+	@ApiOperation(value = "详情", notes = "客服群发-根据详情ID查询单条, 传入id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/detail/{id}")
+    public HttpResponseResult<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> detail(@PathVariable("id") Long id) {
+
+		CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending wrapper = customerServiceBatchSendingService.detail(id);
+        
+        return HttpResponseResult.succeed(wrapper);
+	}
+    
+    /**
+	 * 查询分页
+	 * @param query CustomerServiceBatchSendingVo.CustomerServiceBatchSendingQuery
+	 * @return R<PageInfo<CustomerServiceBatchSendingVo.CustomerServiceBatchSending>>
+	 */
+    @ApiOperation(value = "查询分页", notes = "客服群发- 传入 CustomerServiceBatchSendingVo.CustomerServiceBatchSendingQuery") 
+    @PostMapping("/page")
+    public HttpResponseResult<PageInfo<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending>> page(@RequestBody CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery query) {
+    
+        // 查询数据
+        IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> pages = customerServiceBatchSendingService.selectPage(PageUtil.getPage(query), query);
+
+        return HttpResponseResult.succeed(PageUtil.pageInfo(pages));
+	}
+    
+    /**
+	 * 新增
+	 * @param info CustomerServiceBatchSendingVo.CustomerServiceBatchSending
+	 * @return R<Boolean>
+	 */
+    @ApiOperation(value = "新增", notes = "客服群发- 传入 CustomerServiceBatchSendingVo.CustomerServiceBatchSending")
+	@PostMapping("/save")
+	public HttpResponseResult<Boolean> add(@RequestBody CustomerServiceBatchSendingVo.CustomerServiceBatchSending info) {
+
+		// 获取当前用户ID
+		SysUser user = sysUserFeignService.queryUserInfo();
+		if (user == null || null == user.getId()) {
+			return failed(HttpStatus.FORBIDDEN, "请登录");
+		}
+		info.setCreateBy(user.getId());
+
+		if (EImReceiveType.PORTION == info.getReceiveType()
+				&& CollectionUtils.isEmpty(info.getReceives())) {
+			throw new BizException("接收用户不能为空");
+		}
+		// 设置默认参数
+		info.setSendStatus(EImSendStatus.WAIT);
+
+        // 新增数据
+        customerServiceBatchSendingService.add(JSON.parseObject(info.jsonString(),
+				CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending.class));
+        
+        return HttpResponseResult.succeed();
+	}
+    
+    /**
+	 * 修改
+	 * @param info CustomerServiceBatchSendingVo.CustomerServiceBatchSending
+	 * @return R<Boolean>
+	 */
+    @ApiOperation(value = "修改", notes = "客服群发- 传入 CustomerServiceBatchSendingVo.CustomerServiceBatchSending")
+	@PostMapping("/update")
+	public HttpResponseResult<Boolean> update(@Validated @RequestBody CustomerServiceBatchSendingVo.CustomerServiceBatchSending info) {
+
+		if (Objects.isNull(info.getId())) {
+			throw new BizException("请求参数异常");
+		}
+
+        // 更新数据
+        customerServiceBatchSendingService.update(JSON.parseObject(info.jsonString(),
+				CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending.class));
+        
+        return HttpResponseResult.succeed();
+	}
+
+ 	/**
+	 * 删除
+	 * @param id 详情ID
+	 * @return R<Boolean>
+	 */
+	@ApiOperation(value = "删除", notes = "客服群发- 传入id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+	@PostMapping("/remove")
+	public HttpResponseResult<Boolean> remove(@RequestParam Long id) {
+    
+		return HttpResponseResult.succeed(customerServiceBatchSendingService.removeById(id));
+	}
+
+	@ApiOperation(value = "更新消息状态", notes = "客服群发- 传入id")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "id", value = "主键Id", dataType = "long"),
+			@ApiImplicitParam(name = "sendStatus", value = "发送状态", dataType = "String")
+	})
+	@PostMapping("/status/{id}")
+	public HttpResponseResult<Boolean> status(@PathVariable("id") Long id, EImSendStatus sendStatus) {
+
+		if (Objects.isNull(sendStatus)) {
+			throw new BizException("发送状态不能为空");
+		}
+
+		// 更新群发消息状态
+		customerServiceBatchSendingService.status(id, sendStatus);
+
+		return HttpResponseResult.succeed(true);
+	}
+
+	@ApiOperation(value = "立即发送", notes = "客服群发- 传入id")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "id", value = "主键Id", dataType = "long")
+	})
+	@PostMapping("/send/{id}")
+	public HttpResponseResult<Boolean> send(@PathVariable("id") Long id) {
+
+		// 更新群发消息状态
+		customerServiceBatchSendingService.sendMessage(id);
+
+		return HttpResponseResult.succeed(true);
+	}
+}

+ 91 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/CustomerServiceReceiveController.java

@@ -0,0 +1,91 @@
+package com.yonge.cooleshow.admin.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.admin.io.request.im.CustomerServiceReceiveVo;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceReceive;
+import com.yonge.cooleshow.biz.dal.service.CustomerServiceReceiveService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.page.PageInfo;
+import com.yonge.toolset.mybatis.support.PageUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Objects;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("/batchReceive")
+@Api(tags = "客服群发接收")
+public class CustomerServiceReceiveController {
+
+    @Autowired
+    private CustomerServiceReceiveService customerServiceReceiveService;
+
+    
+    /**
+	 * 查询分页
+	 * @param query CustomerServiceReceiveVo.CustomerServiceReceiveQuery
+	 * @return R<PageInfo<CustomerServiceReceiveVo.CustomerServiceReceive>>
+	 */
+    @ApiOperation(value = "查询分页", notes = "客服群发接收- 传入 CustomerServiceReceiveVo.CustomerServiceReceiveQuery") 
+    @PostMapping("/page")
+    public HttpResponseResult<PageInfo<CustomerServiceReceiveWrapper.CustomerServiceReceive>> page(@RequestBody CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery query) {
+    
+        // 查询数据
+        IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive> pages = customerServiceReceiveService.selectPage(PageUtil.getPage(query), query);
+
+        return HttpResponseResult.succeed(PageUtil.pageInfo(pages));
+	}
+    
+    /**
+	 * 新增
+	 * @param info CustomerServiceReceiveVo.CustomerServiceReceive
+	 * @return R<Boolean>
+	 */
+    @ApiOperation(value = "新增", notes = "客服群发接收- 传入 CustomerServiceReceiveVo.CustomerServiceReceive")
+	@PostMapping("/save")
+	public HttpResponseResult<Boolean> add(@Validated @RequestBody List<CustomerServiceReceiveVo.CustomerServiceReceive> info) {
+
+		if (CollectionUtils.isEmpty(info)
+				|| info.stream().anyMatch(x -> Objects.isNull(x.getBatchSendingId()))) {
+			throw new BizException("无效的请求参数");
+		}
+
+		List<CustomerServiceReceive> receives = JSON.parseArray(JSON.toJSONString(info), CustomerServiceReceive.class);
+		// 新增数据
+        customerServiceReceiveService.saveBatch(receives);
+        
+        return HttpResponseResult.succeed();
+	}
+    
+ 	/**
+	 * 删除
+	 * @param id 详情ID
+	 * @return R<Boolean>
+	 */
+	@ApiOperation(value = "删除", notes = "客服群发接收- 传入id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+	@PostMapping("/remove")
+	public HttpResponseResult<Boolean> remove(@RequestParam Long id) {
+    
+		return HttpResponseResult.succeed(customerServiceReceiveService.removeById(id));
+	}
+}

+ 15 - 16
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicAlbumController.java

@@ -3,36 +3,35 @@ package com.yonge.cooleshow.admin.controller;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dto.AdjustModel;
 import com.yonge.cooleshow.biz.dal.dto.MusicAlbumSheetDto;
 import com.yonge.cooleshow.biz.dal.dto.MusicAlbumSheetSortDto;
-import com.yonge.cooleshow.biz.dal.dto.AdjustModel;
 import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumDetailSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumSearch;
-import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicAlbumSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicSheetOrderSearch;
 import com.yonge.cooleshow.biz.dal.entity.MusicAlbum;
-import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
-import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
-import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
-import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
-import com.yonge.cooleshow.biz.dal.vo.StudentMusicAlbumOrderVo;
-import com.yonge.cooleshow.biz.dal.vo.StudentMusicSheetOrderVo;
-import com.yonge.cooleshow.common.enums.YesOrNoEnum;
-import com.yonge.toolset.base.exception.BizException;
-import com.yonge.toolset.base.page.QueryInfo;
-import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.cooleshow.biz.dal.vo.AlbumDetailVo;
 import com.yonge.cooleshow.biz.dal.vo.MusicAlbumVo;
+import com.yonge.cooleshow.biz.dal.vo.StudentMusicAlbumOrderVo;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.base.page.PageInfo;
 import com.yonge.toolset.base.util.StringUtil;
-import io.swagger.annotations.*;
+import com.yonge.toolset.mybatis.support.PageUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
 import java.util.Date;
@@ -99,10 +98,10 @@ public class MusicAlbumController extends BaseController {
         if (musicAlbum.getId()==null){
             return failed("缺少ID");
         }
-        MusicAlbum service = musicAlbumService.getById(musicAlbum.getId());
+        /*MusicAlbum service = musicAlbumService.getById(musicAlbum.getId());
         if (YesOrNoEnum.YES.getCode().equals(service.getAlbumStatus().getCode())) {
             return failed("启用状态不许修改");
-        }
+        }*/
 
         String[] split = musicAlbum.getAlbumTag().split(",");
         if (split.length >3) {

+ 35 - 4
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicSheetController.java

@@ -1,7 +1,5 @@
 package com.yonge.cooleshow.admin.controller;
 
-import com.yonge.cooleshow.biz.dal.dto.AdjustModel;
-import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -26,8 +24,10 @@ import org.springframework.web.multipart.MultipartFile;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dto.AdjustModel;
 import com.yonge.cooleshow.biz.dal.dto.MusicSheetDto;
 import com.yonge.cooleshow.biz.dal.dto.MusicSheetExport;
+import com.yonge.cooleshow.biz.dal.dto.MusicSheetRenderDto;
 import com.yonge.cooleshow.biz.dal.dto.ReasonDto;
 import com.yonge.cooleshow.biz.dal.dto.req.TeacherMusicSheetAuditReq;
 import com.yonge.cooleshow.biz.dal.dto.search.MusicSheetSearch;
@@ -38,6 +38,7 @@ import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
 import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
 import com.yonge.cooleshow.biz.dal.service.MusicTagService;
@@ -167,10 +168,10 @@ public class MusicSheetController extends BaseController {
         if (musicSheet.getId()==null){
             return failed("缺少ID");
         }
-        MusicSheet service = musicSheetService.getById(musicSheet.getId());
+        /*MusicSheet service = musicSheetService.getById(musicSheet.getId());
         if (YesOrNoEnum.YES.getCode().equals(service.getState().getCode())) {
             return failed("启用状态不许修改");
-        }
+        }*/
 
         if (musicSheet.getNotation() == null) {
             musicSheet.setNotation(YesOrNoEnum.NO);
@@ -190,6 +191,36 @@ public class MusicSheetController extends BaseController {
         }
     }
 
+    @ApiOperation(value = "修改", httpMethod="POST", consumes="application/json", produces="application/json")
+    @PostMapping(value="/updateRenderFile", consumes="application/json", produces="application/json")
+    @PreAuthorize("@pcs.hasPermissions('music/sheet/updateRenderFile')")
+    public HttpResponseResult<Object> updateRenderFile(@Valid @RequestBody MusicSheetRenderDto musicSheetRenderDto) {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null  || sysUser.getId() == null) {
+            return failed("用户信息获取失败");
+        }
+        if (musicSheetRenderDto.getMusicSheetId()==null){
+            return failed("缺少ID");
+        }
+        MusicSheet musicSheet = musicSheetService.getById(musicSheetRenderDto.getMusicSheetId());
+        
+        if(musicSheet == null){
+        	return failed("参数异常");
+        }
+        musicSheet.setMusicFirstSvg(musicSheetRenderDto.getMusicFirstSvg());
+        musicSheet.setMusicJianSvg(musicSheetRenderDto.getMusicJianSvg());
+        musicSheet.setMusicJSON(musicSheetRenderDto.getMusicJSON());
+        musicSheet.setMusicSvg(musicSheetRenderDto.getMusicSvg());
+
+        musicSheet.setUpdateBy(sysUser.getId());
+        musicSheet.setUpdateTime(new Date());
+        if ( musicSheetService.updateById(musicSheet)){
+            return succeed("修改成功");
+        } else {
+            return failed("修改失败");
+        }
+    }
+
     @ApiOperation(value = "分页查询", httpMethod="POST", consumes="application/json", produces="application/json")
     @PostMapping(value="/list", consumes="application/json", produces="application/json")
     @PreAuthorize("@pcs.hasPermissions('music/sheet/list')")

+ 3 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/UserAccountRecordController.java

@@ -57,6 +57,9 @@ public class UserAccountRecordController extends BaseController {
     @ApiOperation(value = "查询分页", notes = "传入userAccountRecordSearch")
     @PreAuthorize("@pcs.hasPermissions('userAccountRecord/page')")
     public HttpResponseResult<PageInfo<UserAccountRecordVo>> page(@RequestBody UserAccountRecordSearch query) {
+        if (query.getInOrOut() == null) {
+            query.setInOrOut(InOrOutEnum.IN);
+        }
         IPage<UserAccountRecordVo> pages = userAccountRecordService.selectPage(PageUtil.getPage(query), query);
         return succeed(PageUtil.pageInfo(pages));
     }

+ 33 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/AdminClient.java

@@ -1,5 +1,6 @@
 package com.yonge.cooleshow.admin.controller.open;
 
+import com.microsvc.toolkit.config.jwt.utils.RsaKeyHelper;
 import com.yonge.cooleshow.admin.io.request.coupon.CouponOrderVO;
 import com.yonge.cooleshow.api.feign.dto.CouponInfoApi;
 import com.yonge.cooleshow.api.feign.dto.EmployeeApi;
@@ -17,24 +18,32 @@ import com.yonge.cooleshow.biz.dal.service.EmployeeService;
 import com.yonge.cooleshow.biz.dal.service.StudentService;
 import com.yonge.cooleshow.biz.dal.service.TeacherService;
 import com.yonge.cooleshow.biz.dal.service.UserFirstTimeService;
+import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.coupon.CouponOrderWrapper;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.UserFirstTimeTypeEnum;
+import com.yonge.toolset.base.exception.BizException;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.jwt.Jwt;
+import org.springframework.security.jwt.JwtHelper;
+import org.springframework.security.jwt.crypto.sign.RsaVerifier;
 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.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.math.BigDecimal;
+import java.security.interfaces.RSAPublicKey;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -88,6 +97,30 @@ public class AdminClient extends BaseController {
         return succeed(studentApi);
     }
 
+    @ApiOperation(value = "学生帐号关联Id", notes = "CouponOrderVO.PageRequest")
+    @PostMapping("/unionStudent")
+    public HttpResponseResult<StudentWrapper.UnionStudentResp> unionStudent(@RequestBody StudentWrapper.UnionStudent info) {
+
+        if (StringUtils.isAnyBlank(info.getToken(), info.getMobile())) {
+            throw new BizException("请求参数错误");
+        }
+
+        // 校验三方帐号关联请求合法性
+        RSAPublicKey rsaPublicKey = RsaKeyHelper.getRSAPublicKey("jmedu", "dayaedu", "jmedu.jks", "dayaedu");
+        Jwt jwt = JwtHelper.decodeAndVerify(info.getToken(), new RsaVerifier(rsaPublicKey));
+
+        //获取jwt原始内容
+        String claims = jwt.getClaims();
+        if (StringUtils.isEmpty(claims)) {
+            throw new BizException("三方授权校验失败");
+        }
+
+        // 学生帐号关联
+        StudentWrapper.UnionStudentResp studentResp = studentService.unionStudent(info);
+
+        return succeed(studentResp);
+    }
+
     @GetMapping("/getEmployee")
     public HttpResponseResult<EmployeeApi> getEmployee(@RequestParam("userId") Long userId) {
         Employee employee = employeeService.get(userId);

+ 1 - 1
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/OpenUserAccountController.java

@@ -57,7 +57,7 @@ public class OpenUserAccountController extends BaseController {
     @ApiOperation(value = "新增曲谱渲染图")
     @PostMapping(value="/music/sheet/img")
     public HttpResponseResult<Boolean> img(@RequestBody @Valid MusicImgDto musicImgDto) {
-        return succeed(musicSheetService.updateMusicImg(musicImgDto.getMusicImg(),musicImgDto.getMusicSheetId()));
+        return succeed(musicSheetService.updateMusicImg(musicImgDto, musicImgDto.getMusicSheetId()));
     }
 
 }

+ 1 - 1
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/UserOrderClient.java

@@ -120,7 +120,7 @@ public class UserOrderClient extends BaseController {
             } catch (BizException e) {
                 log.error("回调业务异常,data is {}, msg is {}", JSONObject.toJSONString(data), e.getMessage());
             } catch (Exception e) {
-                log.error("回调业务异常,data is {}", JSONObject.toJSONString(data));
+                log.error("回调业务异常,data is {} , msg is {}", JSONObject.toJSONString(data),e.getMessage());
                 e.printStackTrace();
             }
         }

+ 106 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/CustomerServiceBatchSendingVo.java

@@ -0,0 +1,106 @@
+package com.yonge.cooleshow.admin.io.request.im;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.biz.dal.enums.im.EImReceiveType;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendStatus;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendType;
+import com.yonge.toolset.base.page.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 客服群发
+ * 2022-12-09 10:49:10
+ */
+@ApiModel(value = "CustomerServiceBatchSendingVo对象", description = "客服群发查询视图对象")
+public class CustomerServiceBatchSendingVo {
+
+    @ApiModel(" CustomerServiceBatchSendingQuery-客服群发")
+    public static class CustomerServiceBatchSendingQuery extends QueryInfo {
+    
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceBatchSendingQuery from(String json) {
+            return JSON.parseObject(json, CustomerServiceBatchSendingQuery.class);
+        }
+    }
+    
+    @Data
+    @ApiModel(" CustomerServiceBatchSending-客服群发")
+    public static class CustomerServiceBatchSending {
+    	
+                
+		@ApiModelProperty("主键ID") 
+        private Long id;
+                
+		@ApiModelProperty("目标群体")
+        private String targetGroup;
+                
+		@ApiModelProperty("发送声部")
+        private String sendSubject;
+
+        @ApiModelProperty("发送人数")
+        private Integer sendNumber;
+
+		@ApiModelProperty("接收人数")
+        private Integer receiveNumber;
+                
+		@ApiModelProperty("目标人群")
+        private EImReceiveType receiveType;
+                
+		@ApiModelProperty("发送方式")
+        private EImSendType sendType;
+                
+		@ApiModelProperty("发送状态")
+        private EImSendStatus sendStatus;
+                
+		@ApiModelProperty("发送时间")
+        private Date sendTime;
+
+        @ApiModelProperty("消息标题")
+        private String condition;
+
+		@ApiModelProperty("消息标题")
+        private String title;
+                
+		@ApiModelProperty("文本消息")
+        private String textMessage;
+                
+		@ApiModelProperty("图片消息")
+        private String imgMessage;
+                
+		@ApiModelProperty("图片地址")
+        private String imgUrl;
+                
+		@ApiModelProperty("创建用户")
+        private Long createBy;
+                
+		@ApiModelProperty("创建时间")
+        private Date createTime;
+
+        @ApiModelProperty("客服人员")
+        private String sender;
+        @ApiModelProperty("客服联系方式")
+        private String mobile;
+
+        @ApiModelProperty("目标人群")
+        private List<CustomerServiceReceiveVo.CustomerServiceReceive> receives;
+                
+                
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceBatchSending from(String json) {
+            return JSON.parseObject(json, CustomerServiceBatchSending.class);
+        }
+    }
+    
+}

+ 59 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/CustomerServiceReceiveVo.java

@@ -0,0 +1,59 @@
+package com.yonge.cooleshow.admin.io.request.im;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.toolset.base.page.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 客服群发接收
+ * 2022-12-09 10:49:10
+ */
+@ApiModel(value = "CustomerServiceReceiveVo对象", description = "客服群发接收查询视图对象")
+public class CustomerServiceReceiveVo {
+
+    @ApiModel(" CustomerServiceReceiveQuery-客服群发接收")
+    public static class CustomerServiceReceiveQuery extends QueryInfo {
+    
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceReceiveQuery from(String json) {
+            return JSON.parseObject(json, CustomerServiceReceiveQuery.class);
+        }
+    }
+    
+    @Data
+    @ApiModel(" CustomerServiceReceive-客服群发接收")
+    public static class CustomerServiceReceive {
+    	
+                
+		@ApiModelProperty("主键ID") 
+        private Long id;
+
+        @ApiModelProperty("群发消息ID")
+        private Long batchSendingId;
+                
+		@ApiModelProperty("用户ID") 
+        private Long userId;
+                
+		@ApiModelProperty("用户身份")
+        private String clientType;
+                
+		@ApiModelProperty("创建时间")
+        private Date createTime;
+                
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceReceive from(String json) {
+            return JSON.parseObject(json, CustomerServiceReceive.class);
+        }
+    }
+    
+}

+ 7 - 2
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/IMNotifyMessageVO.java

@@ -1,16 +1,15 @@
 package com.yonge.cooleshow.admin.io.request.im;
 
 import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import java.io.Serializable;
 import java.util.List;
-import java.util.Optional;
 
 /**
  * 系统IM通知信息
@@ -39,6 +38,12 @@ public class IMNotifyMessageVO implements Serializable {
     @ApiModelProperty(value = "图片文件地址")
     private String imgUrl;
 
+    @ApiModelProperty("用户身份")
+    private ClientEnum clientType;
+
+    @ApiModelProperty("声部ID")
+    private String subjectId;
+
     public String jsonString() {
 
         return JSON.toJSONString(this);

+ 26 - 1
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/task/TaskController.java

@@ -1,6 +1,17 @@
 package com.yonge.cooleshow.admin.task;
 
-import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.service.ActivityPlanEvaluationService;
+import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
+import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
+import com.yonge.cooleshow.biz.dal.service.CustomerServiceBatchSendingService;
+import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
+import com.yonge.cooleshow.biz.dal.service.PlatformCashAccountRecordService;
+import com.yonge.cooleshow.biz.dal.service.TeacherStyleVideoService;
+import com.yonge.cooleshow.biz.dal.service.UserAccountRecordService;
+import com.yonge.cooleshow.biz.dal.service.UserBindingTeacherService;
+import com.yonge.cooleshow.biz.dal.service.UserOrderService;
+import com.yonge.cooleshow.biz.dal.service.VideoLessonGroupService;
 import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
@@ -57,6 +68,8 @@ public class TaskController extends BaseController {
 
     @Autowired
     private VideoLessonGroupService videoLessonGroupService;
+    @Autowired
+    private CustomerServiceBatchSendingService customerServiceBatchSendingService;
 
     /***
      * 轮询用户订单
@@ -158,4 +171,16 @@ public class TaskController extends BaseController {
         return HttpResponseResult.succeed();
     }
 
+    /**
+     * 群发消息
+     */
+    @GetMapping("/batchSending")
+    public HttpResponseResult<Object> batchSending() {
+
+        // 群发消息定时
+        customerServiceBatchSendingService.scheduleSendMessage();
+
+        return HttpResponseResult.succeed();
+    }
+
 }

+ 14 - 0
cooleshow-user/user-biz/pom.xml

@@ -23,6 +23,20 @@
             <artifactId>cooleshow-common</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.microsvc.toolkit.config</groupId>
+            <artifactId>microsvc-config-jwt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-jwt</artifactId>
+            <version>1.0.9.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.79</version>
+        </dependency>
 
         <dependency>
             <groupId>com.spring4all</groupId>

+ 3 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/PlatformCashAccountRecordDao.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.biz.dal.dto.search.PlatformCashAccountRecordSearch;
 import com.yonge.cooleshow.biz.dal.entity.PlatformCashAccountRecord;
+import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
 import com.yonge.cooleshow.biz.dal.vo.PlatformCashAccountRecordSummaryVo;
 
 import io.swagger.models.auth.In;
@@ -33,7 +34,8 @@ public interface PlatformCashAccountRecordDao extends BaseMapper<PlatformCashAcc
 
     List<PlatformCashAccountRecord> queryByBizTypeAndPaymentDays(@Param("bizType")String bizType, @Param("paymentDays")int paymentDays);
 
-    Integer cancelRecord(@Param("orderNo")String orderNo,@Param("bizType") String bizType, @Param("bizId") Long bizId);
+    Integer cancelRecord(@Param("orderNo") String orderNo, @Param("bizType") String bizType, @Param(
+            "bizId") Long bizId, @Param("type") InOrOutEnum type);
 
     Integer mallRecordedRecord(@Param("orderNo")String orderNo,@Param("bizType") String bizType, @Param("bizId") Long bizId);
 

+ 10 - 4
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/SubjectDao.java

@@ -1,11 +1,10 @@
 package com.yonge.cooleshow.biz.dal.dao;
 
-import java.util.List;
-
-import org.apache.ibatis.annotations.Param;
-
 import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.toolset.mybatis.dal.BaseDAO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 public interface SubjectDao extends BaseDAO<Long, Subject> {
     /***
@@ -55,4 +54,11 @@ public interface SubjectDao extends BaseDAO<Long, Subject> {
     Subject queryByName(@Param("name") String name);
 
     List<Subject> subjectSelect(@Param("type") String type);
+
+    /**
+     * 声部模糊匹配
+     * @param subjectName 声部匹配
+     * @return Subject
+     */
+    Subject getSubjectMatchByName(@Param("name") String subjectName);
 }

+ 22 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/MusicImgDto.java

@@ -23,6 +23,12 @@ public class MusicImgDto {
     @ApiModelProperty("曲目id")
     private Long musicSheetId;
 
+    @ApiModelProperty("首调")
+    private String firstTone;
+
+    @ApiModelProperty("固定调")
+    private String fixedTone;
+
     public String getMusicImg() {
         return musicImg;
     }
@@ -38,4 +44,20 @@ public class MusicImgDto {
     public void setMusicSheetId(Long musicSheetId) {
         this.musicSheetId = musicSheetId;
     }
+
+    public String getFirstTone() {
+        return firstTone;
+    }
+
+    public void setFirstTone(String firstTone) {
+        this.firstTone = firstTone;
+    }
+
+    public String getFixedTone() {
+        return fixedTone;
+    }
+
+    public void setFixedTone(String fixedTone) {
+        this.fixedTone = fixedTone;
+    }
 }

+ 54 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/MusicSheetRenderDto.java

@@ -0,0 +1,54 @@
+package com.yonge.cooleshow.biz.dal.dto;
+
+public class MusicSheetRenderDto {
+
+	private Long musicSheetId;
+	
+	private String musicJSON;
+	
+	private String musicSvg;
+	
+	private String musicJianSvg;
+	
+	private String musicFirstSvg;
+
+	public Long getMusicSheetId() {
+		return musicSheetId;
+	}
+
+	public void setMusicSheetId(Long musicSheetId) {
+		this.musicSheetId = musicSheetId;
+	}
+
+	public String getMusicJSON() {
+		return musicJSON;
+	}
+
+	public void setMusicJSON(String musicJSON) {
+		this.musicJSON = musicJSON;
+	}
+
+	public String getMusicSvg() {
+		return musicSvg;
+	}
+
+	public void setMusicSvg(String musicSvg) {
+		this.musicSvg = musicSvg;
+	}
+
+	public String getMusicJianSvg() {
+		return musicJianSvg;
+	}
+
+	public void setMusicJianSvg(String musicJianSvg) {
+		this.musicJianSvg = musicJianSvg;
+	}
+
+	public String getMusicFirstSvg() {
+		return musicFirstSvg;
+	}
+
+	public void setMusicFirstSvg(String musicFirstSvg) {
+		this.musicFirstSvg = musicFirstSvg;
+	}
+}

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/OrderReq.java

@@ -33,7 +33,7 @@ public class OrderReq {
     @ApiModelProperty(value = "订单名称 ", required = true)
     private String orderName;
     @NotNull(message = "订单类型不能为空")
-    @ApiModelProperty(value = "订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名 ) 老师端(VIP、开通会员 PINAO_ROOM、琴房时长 ACTI_REGIST 活动报名)", required = true)
+    @ApiModelProperty(value = "订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名 ) 老师端(VIP、开通会员 PIANO_ROOM、琴房时长 ACTI_REGIST 活动报名)", required = true)
     private OrderTypeEnum orderType;
     @ApiModelProperty(value = "订单描述信息 ")
     private String orderDesc;
@@ -68,7 +68,7 @@ public class OrderReq {
         @ApiModelProperty(value = "订单详情号", hidden = true)
         private String subOrderNo;
         @NotNull(message = "商品类型不能为空")
-        @ApiModelProperty(value = "商品类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端( PINAO_ROOM、琴房时长 ACTI_REGIST 活动报名)", required = true)
+        @ApiModelProperty(value = "商品类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端( PIANO_ROOM、琴房时长 ACTI_REGIST 活动报名)", required = true)
         private GoodTypeEnum goodType;
         @ApiModelProperty("商品名称 ")
         private String goodName;

+ 22 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/TeacherMusicSheetAuditReq.java

@@ -26,6 +26,12 @@ public class TeacherMusicSheetAuditReq {
     @ApiModelProperty(value = "曲谱渲染图",required = true)
     private String musicImg;
 
+    @ApiModelProperty("首调")
+    private String firstTone;
+
+    @ApiModelProperty("固定调")
+    private String fixedTone;
+
     @ApiModelProperty(value = "审批状态(PASS:通过,UNPASS:不通过)",required = true)
     @NotNull(message = "审批状态不为空 ")
     private AuthStatusEnum authStatus;
@@ -142,4 +148,20 @@ public class TeacherMusicSheetAuditReq {
     public void setAudioFileUrl(String audioFileUrl) {
         this.audioFileUrl = audioFileUrl;
     }
+
+    public String getFirstTone() {
+        return firstTone;
+    }
+
+    public void setFirstTone(String firstTone) {
+        this.firstTone = firstTone;
+    }
+
+    public String getFixedTone() {
+        return fixedTone;
+    }
+
+    public void setFixedTone(String fixedTone) {
+        this.fixedTone = fixedTone;
+    }
 }

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

@@ -15,6 +15,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
@@ -84,6 +85,9 @@ public class MusicSheetSearch  extends QueryInfo{
     @ApiModelProperty("TOP:推荐曲目 NEW:最新曲目 HOT:最热曲目")
     private MusicSortType musicSortType;
 
+    @ApiModelProperty("数据恢复")
+    private String dataRecovery;
+
     public MusicSortType getMusicSortType() {
         return musicSortType;
     }
@@ -247,4 +251,12 @@ public class MusicSheetSearch  extends QueryInfo{
     public void setActivityId(Long activityId) {
         this.activityId = activityId;
     }
+
+    public String getDataRecovery() {
+        return Optional.ofNullable(dataRecovery).filter(StringUtils::isNotBlank).orElse(null);
+    }
+
+    public void setDataRecovery(String dataRecovery) {
+        this.dataRecovery = dataRecovery;
+    }
 }

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/UserAccountRecordSearch.java

@@ -27,7 +27,7 @@ public class UserAccountRecordSearch extends QueryInfo{
 	private String orderNo;
 
 	@ApiModelProperty("收支类型:IN、收入 OUT、支出 ")
-	private InOrOutEnum inOrOut;
+	private InOrOutEnum inOrOut ;
 
 	@ApiModelProperty(value = "入账状态 WAIT 待入账 FROZEN 冻结入账 RECORDED 已入账 CANCEL 退费 ")
 	private PostStatusEnum postStatus;

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityReward.java

@@ -41,7 +41,7 @@ public class ActivityReward implements Serializable {
     @TableField(value = "reward_name_")
     @NotBlank(message = "奖品名称不能为空")
     private String rewardName;
-    @ApiModelProperty("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIAMO_ROOM 琴房时长 COUPON(优惠券)")
+    @ApiModelProperty("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIANO_ROOM 琴房时长 COUPON(优惠券)")
     @TableField(value = "reward_type_")
     @NotNull(message = "奖品类型不能为空")
     private RewardTypeEnum rewardType;

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

@@ -0,0 +1,95 @@
+package com.yonge.cooleshow.biz.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.yonge.cooleshow.biz.dal.enums.im.EImReceiveType;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendStatus;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 客服群发
+ * 2022-12-09 10:49:10
+ */
+@Data
+@ApiModel(" CustomerServiceBatchSending-客服群发")
+@TableName("customer_service_batch_sending")
+public class CustomerServiceBatchSending implements Serializable {
+
+    @ApiModelProperty("主键ID") 
+    @TableId(value = "id_", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("目标群体") 
+	@TableField(value = "target_group_")
+    private String targetGroup;
+
+    @ApiModelProperty("发送声部") 
+	@TableField(value = "send_subject_")
+    private String sendSubject;
+
+    @ApiModelProperty("发送人数")
+    @TableField(value = "send_number_")
+    private Integer sendNumber;
+
+    @ApiModelProperty("接收人数") 
+	@TableField(value = "receive_number_")
+    private Integer receiveNumber;
+
+    @ApiModelProperty("目标人群") 
+	@TableField(value = "receive_type_")
+    private EImReceiveType receiveType;
+
+    @ApiModelProperty("发送方式") 
+	@TableField(value = "send_type_")
+    private EImSendType sendType;
+
+    @ApiModelProperty("发送状态") 
+	@TableField(value = "send_status_")
+    private EImSendStatus sendStatus;
+
+    @ApiModelProperty("发送时间") 
+	@TableField(value = "send_time_")
+    private Date sendTime;
+
+    @ApiModelProperty("发送条件")
+    @TableField(value = "condition_")
+    private String condition;
+
+    @ApiModelProperty("消息标题") 
+	@TableField(value = "title_")
+    private String title;
+
+    @ApiModelProperty("文本消息") 
+	@TableField(value = "text_message_")
+    private String textMessage;
+
+    @ApiModelProperty("图片消息") 
+	@TableField(value = "img_message_")
+    private String imgMessage;
+
+    @ApiModelProperty("图片地址") 
+	@TableField(value = "img_url_")
+    private String imgUrl;
+
+    @ApiModelProperty("客户ID")
+    @TableField(value = "sender_id_")
+    private Long senderId;
+
+    @ApiModelProperty("创建用户") 
+	@TableField(value = "create_by_")
+    private Long createBy;
+
+    @ApiModelProperty("创建时间") 
+	@TableField(value = "create_time_")
+    private Date createTime;
+
+}

+ 44 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CustomerServiceReceive.java

@@ -0,0 +1,44 @@
+package com.yonge.cooleshow.biz.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 客服群发接收
+ * 2022-12-09 10:49:10
+ */
+@Data
+@ApiModel(" CustomerServiceReceive-客服群发接收")
+@TableName("customer_service_receive")
+public class CustomerServiceReceive implements Serializable {
+
+    @ApiModelProperty("主键ID") 
+    @TableId(value = "id_", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("群发消息ID")
+    @TableField(value = "batch_sending_id_")
+    private Long batchSendingId;
+
+    @ApiModelProperty("用户ID") 
+	@TableField(value = "user_id_")
+    private Long userId;
+
+    @ApiModelProperty("用户身份") 
+	@TableField(value = "client_type_")
+    private String clientType;
+
+    @ApiModelProperty("创建时间") 
+	@TableField(value = "create_time_")
+    private Date createTime;
+
+}

+ 88 - 14
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicSheet.java

@@ -1,18 +1,5 @@
 package com.yonge.cooleshow.biz.dal.entity;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.Objects;
-import java.util.Optional;
-
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -22,8 +9,18 @@ import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang3.StringUtils;
 
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.Objects;
+
 /**
  * 曲谱表
  * @author yzp
@@ -224,7 +221,26 @@ public class MusicSheet implements Serializable {
 	@TableField("ext_config_json_")
 	@ApiModelProperty("曲目配置信息")
 	private String extConfigJson;
-
+	
+	@TableField("music_json_")
+	private String musicJSON;
+	
+	@TableField("music_svg_")
+	private String musicSvg;
+	
+	@TableField("music_jian_svg_")
+	private String musicJianSvg;
+	
+	@TableField("music_first_svg_")
+	private String musicFirstSvg;
+
+	@TableField("first_tone_")
+	@ApiModelProperty("首调")
+	private String firstTone;
+
+	@TableField("fixed_tone_")
+	@ApiModelProperty("固定调")
+	private String fixedTone;
 
 	@TableField("del_flag_")
 	@ApiModelProperty(value = "假删除标识 0:未删除 1:已删除")
@@ -586,6 +602,22 @@ public class MusicSheet implements Serializable {
 		this.paymentType = paymentType;
 	}
 
+	public String getFirstTone() {
+		return firstTone;
+	}
+
+	public void setFirstTone(String firstTone) {
+		this.firstTone = firstTone;
+	}
+
+	public String getFixedTone() {
+		return fixedTone;
+	}
+
+	public void setFixedTone(String fixedTone) {
+		this.fixedTone = fixedTone;
+	}
+
 	public MusicSheet notation(YesOrNoEnum notation) {
 		this.notation = notation;
 		return this;
@@ -620,4 +652,46 @@ public class MusicSheet implements Serializable {
 		this.audioFileUrl = audioFileUrl;
 		return this;
 	}
+
+	public String getMusicJSON() {
+		return musicJSON;
+	}
+
+	public void setMusicJSON(String musicJSON) {
+		this.musicJSON = musicJSON;
+	}
+
+	public String getMusicSvg() {
+		return musicSvg;
+	}
+
+	public void setMusicSvg(String musicSvg) {
+		this.musicSvg = musicSvg;
+	}
+
+	public String getMusicJianSvg() {
+		return musicJianSvg;
+	}
+
+	public void setMusicJianSvg(String musicJianSvg) {
+		this.musicJianSvg = musicJianSvg;
+	}
+
+	public String getMusicFirstSvg() {
+		return musicFirstSvg;
+	}
+
+	public void setMusicFirstSvg(String musicFirstSvg) {
+		this.musicFirstSvg = musicFirstSvg;
+	}
+
+	public MusicSheet firstTone(String firstTone) {
+		this.firstTone = firstTone;
+		return this;
+	}
+
+	public MusicSheet fixedTone(String fixedTone) {
+		this.fixedTone = fixedTone;
+		return this;
+	}
 }

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PlatformCashAccountRecord.java

@@ -44,11 +44,11 @@ public class PlatformCashAccountRecord implements Serializable {
     private PostStatusEnum postStatus;
 
     @TableField("biz_type_")
-    @ApiModelProperty(value = "业务类型:PRACTICE、陪练课 LIVE、直播课 VIDEO、视频课 MUSIC、乐谱 VIP、会员充值 MALL、商品购买 PIAON_ROOM、琴房充值 ACTI_REGIST、活动报名 LIVE_SHARE、直播课分润 VIDEO_SHARE、视频课分润  MUSIC_SHARE、乐谱分润  VIP_SHARE、会员分润  MALL_SHARE、商品分润")
+    @ApiModelProperty(value = "业务类型:PRACTICE、陪练课 LIVE、直播课 VIDEO、视频课 MUSIC、乐谱 VIP、会员充值 MALL、商品购买 PIANO_ROOM、琴房充值 ACTI_REGIST、活动报名 LIVE_SHARE、直播课分润 VIDEO_SHARE、视频课分润  MUSIC_SHARE、乐谱分润  VIP_SHARE、会员分润  MALL_SHARE、商品分润")
     private AccountBizTypeEnum bizType;
 
     @TableField("biz_id_")
-    @ApiModelProperty(value = "业务id(PRACTICE,LIVE,LIVE_SHARE为课程组id | VIDEO,VIDEO_SHARE为视频组id |MUSIC,MUSIC_SHARE为曲谱id | VIP,VIP_SHARE,PIAON_ROOM为会员琴房价格表id | MALL,MALL_SHARE为商品id | ACTI_REGIST为活动id )")
+    @ApiModelProperty(value = "业务id(PRACTICE,LIVE,LIVE_SHARE为课程组id | VIDEO,VIDEO_SHARE为视频组id |MUSIC,MUSIC_SHARE为曲谱id | VIP,VIP_SHARE,PIANO_ROOM为会员琴房价格表id | MALL,MALL_SHARE为商品id | ACTI_REGIST为活动id )")
     private Long bizId;
 
     @TableField("memo_")

+ 12 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/Student.java

@@ -75,6 +75,10 @@ public class Student implements Serializable {
     @TableField(value = "evaluate_time_")
     private Long evaluateTime;
 
+    @ApiModelProperty("帐号关联Id ")
+    @TableField(value = "union_id_")
+    private Long unionId;
+
 	@TableField(value = "create_time_")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@@ -179,4 +183,12 @@ public class Student implements Serializable {
     public void setEvaluateTime(Long evaluateTime) {
         this.evaluateTime = evaluateTime;
     }
+
+    public Long getUnionId() {
+        return unionId;
+    }
+
+    public void setUnionId(Long unionId) {
+        this.unionId = unionId;
+    }
 }

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrder.java

@@ -51,7 +51,7 @@ public class UserOrder implements Serializable {
     @ApiModelProperty("下单应用:STUDENT 学生端 TEACHER 老师端")
     @TableField(value = "order_client_")
     private ClientEnum orderClient;
-    @ApiModelProperty("订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端(VIP、开通会员 PINAO_ROOM、琴房时长)")
+    @ApiModelProperty("订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端(VIP、开通会员 PIANO_ROOM、琴房时长)")
     @TableField(value = "order_type_")
     private OrderTypeEnum orderType;
     @ApiModelProperty("订单描述信息 ")

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrderDetail.java

@@ -32,7 +32,7 @@ public class UserOrderDetail implements Serializable {
     @ApiModelProperty("卖家id ")
     @TableField(value = "merch_id_")
     private Long merchId;
-    @ApiModelProperty("订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端(VIP、开通会员 PINAO_ROOM、琴房时长)")
+    @ApiModelProperty("订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端(VIP、开通会员 PIANO_ROOM、琴房时长)")
     @TableField(value = "good_type_")
     private GoodTypeEnum goodType;
     @ApiModelProperty("业务id ")

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/AccountBizTypeEnum.java

@@ -17,7 +17,7 @@ public enum AccountBizTypeEnum implements BaseEnum<String, AccountBizTypeEnum> {
     MUSIC("乐谱"),
     VIP("会员充值"),
     MALL("商品购买"),
-    PIAON_ROOM("琴房充值"),
+    PIANO_ROOM("琴房充值"),
     ACTI_REGIST("活动报名"),
     WITHDRAWAL("结算"),
     ALBUM("专辑"),

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/GoodTypeEnum.java

@@ -16,7 +16,7 @@ public enum GoodTypeEnum implements BaseEnum<String, GoodTypeEnum> {
     VIDEO("视频课购买"),
     MUSIC("单曲点播"),
     ALBUM("专辑购买"),
-    PINAO_ROOM("琴房时长"),
+    PIANO_ROOM("琴房时长"),
     ACTI_REGIST("活动报名")
     ;
 

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/OrderTypeEnum.java

@@ -15,7 +15,7 @@ public enum OrderTypeEnum implements BaseEnum<String, OrderTypeEnum> {
     LIVE("直播课购买"),
     VIDEO("视频课购买"),
     MUSIC("单曲点播"),
-    PINAO_ROOM("琴房时长"),
+    PIANO_ROOM("琴房时长"),
     ACTI_REGIST("活动报名"),
     ALBUM("专辑购买"),
     ;

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/coupon/CouponCategoryEnum.java

@@ -16,7 +16,7 @@ public enum CouponCategoryEnum implements BaseEnum<String, CouponCategoryEnum> {
 
     UNIVERSAL("全场通用", "UNIVERSAL"),
     VIP("小酷Ai", "VIP"),
-    PIANO("云酷琴房", "PINAO_ROOM"),
+    PIANO("云酷琴房", "PIANO_ROOM"),
     MALL("商场购物券", "MALL"),
     MUSIC("单曲点播券", "MUSIC"),
     ALBUM("专辑优惠券", "ALBUM"),

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

@@ -0,0 +1,28 @@
+package com.yonge.cooleshow.biz.dal.enums.im;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.toolset.base.enums.BaseEnum;
+import lombok.Getter;
+
+/**
+ * IM群发接收方式
+ * Created by Eric.Shang on 2022/12/9.
+ */
+@Getter
+public enum EImReceiveType implements BaseEnum<String, EImReceiveType> {
+
+    ALL("全部"),
+    PORTION("一部分"),
+    ;
+
+    @EnumValue
+    private final String code;
+
+    private final String msg;
+
+    EImReceiveType(String msg) {
+        this.msg = msg;
+
+        this.code = this.name();
+    }
+}

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

@@ -0,0 +1,30 @@
+package com.yonge.cooleshow.biz.dal.enums.im;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.toolset.base.enums.BaseEnum;
+import lombok.Getter;
+
+/**
+ * IM群发消息状态
+ * Created by Eric.Shang on 2022/12/9.
+ */
+@Getter
+public enum EImSendStatus implements BaseEnum<String, EImSendStatus> {
+
+    WAIT("待发送"),
+    SEND("已发送"),
+    DISABLE("已停用"),
+    EXPIRE("已失效"),
+    ;
+
+    @EnumValue
+    private final String code;
+
+    private final String msg;
+
+    EImSendStatus(String msg) {
+        this.msg = msg;
+
+        this.code = this.name();
+    }
+}

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

@@ -0,0 +1,28 @@
+package com.yonge.cooleshow.biz.dal.enums.im;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.toolset.base.enums.BaseEnum;
+import lombok.Getter;
+
+/**
+ * IM群发方式
+ * Created by Eric.Shang on 2022/12/9.
+ */
+@Getter
+public enum EImSendType implements BaseEnum<String, EImSendType> {
+
+    IMMEDIATELY("即时发送"),
+    SCHEDULED("定时发送"),
+    ;
+
+    @EnumValue
+    private final String code;
+
+    private final String msg;
+
+    EImSendType(String msg) {
+        this.msg = msg;
+
+        this.code = this.name();
+    }
+}

+ 36 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CustomerServiceBatchSendingMapper.java

@@ -0,0 +1,36 @@
+package com.yonge.cooleshow.biz.dal.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceBatchSending;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceBatchSendingWrapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 客服群发
+ * 2022-12-09 10:49:10
+ */
+public interface CustomerServiceBatchSendingMapper extends BaseMapper<CustomerServiceBatchSending> {
+
+	/**
+	 * 分页查询
+	 * @param page IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending>
+	 * @param param CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery
+	 * @return List<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending>
+	 */
+	List<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> selectPage(@Param("page") IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> page,
+																					@Param("param") CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery param);
+
+	/**
+	 * 客服消息接收者
+	 * @param message 客服消息
+	 * @return List<CustomerService.MessageReceives>
+	 */
+	List<CustomerService.MessageReceives> selectMessageReceives(@Param("page") IPage<CustomerService.MessageReceives> page,
+																@Param("param") CustomerService.NotifyMessage message);
+
+	
+}

+ 25 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CustomerServiceReceiveMapper.java

@@ -0,0 +1,25 @@
+package com.yonge.cooleshow.biz.dal.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceReceive;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 客服群发接收
+ * 2022-12-09 10:49:10
+ */
+public interface CustomerServiceReceiveMapper extends BaseMapper<CustomerServiceReceive> {
+
+	/**
+	 * 分页查询
+	 * @param page IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive>
+	 * @param param CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery
+	 * @return List<CustomerServiceReceiveWrapper.CustomerServiceReceive>
+	 */
+	List<CustomerServiceReceiveWrapper.CustomerServiceReceive> selectPage(@Param("page") IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive> page, @Param("param") CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery param);
+	
+}

+ 11 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/SysUserMapper.java

@@ -1,11 +1,12 @@
 package com.yonge.cooleshow.biz.dal.mapper;
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.auth.api.dto.RealnameAuthReq;
 import com.yonge.cooleshow.biz.dal.entity.SysUser;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.vo.CouponIssueUserVo;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Repository;
 
@@ -30,8 +31,8 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
      * @param keyword 查询条件
      * @return
      */
-    List<CouponIssueUserVo> queryCouponIssueUser(@Param("iPage") IPage<CouponIssueUserVo> iPage, @Param(
-            "client") ClientEnum client, @Param("keyword") String keyword);
+    List<CouponIssueUserVo> queryCouponIssueUser(@Param("iPage") IPage<CouponIssueUserVo> iPage,
+                                                 @Param("client") ClientEnum client, @Param("keyword") String keyword);
 
 
     /***
@@ -42,4 +43,11 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
      * @return: java.lang.Integer
      */
     Integer updateUserCard(@Param("param") RealnameAuthReq param);
+
+    /**
+     * 客服消息接收者
+     * @param message 客服消息
+     * @return List<CustomerService.MessageReceives>
+     */
+    List<CustomerService.MessageReceives> selectMessageReceives(@Param("param") CustomerService.NotifyMessage message);
 }

+ 61 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CustomerServiceBatchSendingService.java

@@ -0,0 +1,61 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceBatchSending;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendStatus;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceBatchSendingWrapper;
+
+/**
+ * 客服群发
+ * 2022-12-09 10:49:10
+ */
+public interface CustomerServiceBatchSendingService extends IService<CustomerServiceBatchSending>  {
+
+	/**
+     * 查询详情
+     * @param id 详情ID
+     * @return CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending
+     */
+    CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending detail(Long id);
+
+    /**
+     * 分页查询
+     * @param page IPage<CustomerServiceBatchSending>
+     * @param query CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery
+     * @return IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending>
+     */
+    IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> selectPage(IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> page, CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery query);
+	
+    /**
+     * 添加
+     * @param customerServiceBatchSending CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending
+     * @return Boolean
+     */
+     Boolean add(CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending customerServiceBatchSending);   
+
+    /**
+     * 更新
+     * @param customerServiceBatchSending CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending
+     * @return Boolean
+     */
+     Boolean update(CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending customerServiceBatchSending);
+
+    /**
+     * 更新消息状态
+     * @param id 消息Id
+     * @param sendStatus EImSendStatus
+     */
+    void status(Long id, EImSendStatus sendStatus);
+
+    /**
+     * 发送消息
+     * @param id 群发消息ID
+     */
+    void sendMessage(Long id);
+
+    /**
+     * 定时发送消息
+     */
+    void scheduleSendMessage();
+}

+ 43 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CustomerServiceReceiveService.java

@@ -0,0 +1,43 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceReceive;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper;
+
+/**
+ * 客服群发接收
+ * 2022-12-09 10:49:10
+ */
+public interface CustomerServiceReceiveService extends IService<CustomerServiceReceive>  {
+
+	/**
+     * 查询详情
+     * @param id 详情ID
+     * @return CustomerServiceReceive
+     */
+	CustomerServiceReceive detail(Long id);
+
+    /**
+     * 分页查询
+     * @param page IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive>
+     * @param query CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery
+     * @return IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive>
+     */
+    IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive> selectPage(IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive> page, CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery query);
+	
+    /**
+     * 添加
+     * @param customerServiceReceive CustomerServiceReceiveWrapper.CustomerServiceReceive
+     * @return Boolean
+     */
+     Boolean add(CustomerServiceReceiveWrapper.CustomerServiceReceive customerServiceReceive);   
+
+    /**
+     * 更新
+     * @param customerServiceReceive CustomerServiceReceiveWrapper.CustomerServiceReceive
+     * @return Boolean
+     */
+     Boolean update(CustomerServiceReceiveWrapper.CustomerServiceReceive customerServiceReceive);
+     
+}

+ 4 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicSheetService.java

@@ -1,10 +1,9 @@
 package com.yonge.cooleshow.biz.dal.service;
 
-import java.util.List;
-
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dto.MusicImgDto;
 import com.yonge.cooleshow.biz.dal.dto.MusicSheetDto;
 import com.yonge.cooleshow.biz.dal.dto.MusicSheetExport;
 import com.yonge.cooleshow.biz.dal.dto.ReasonDto;
@@ -35,6 +34,8 @@ import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.utils.easyexcel.ExcelDataReaderProperty;
 
+import java.util.List;
+
 /**
  * MusicSheetService服务类
  * @author yzp
@@ -332,7 +333,7 @@ public interface MusicSheetService extends IService<MusicSheet> {
      * @param musicSheetId
      * @return
      */
-    Boolean updateMusicImg(String musicImg, Long musicSheetId);
+    Boolean updateMusicImg(MusicImgDto musicImgDto, Long musicSheetId);
 
     /**
      *

+ 14 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/PlatformCashAccountRecordService.java

@@ -6,7 +6,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dao.PlatformCashAccountRecordDao;
 import com.yonge.cooleshow.biz.dal.dto.search.PlatformCashAccountRecordSearch;
 import com.yonge.cooleshow.biz.dal.entity.PlatformCashAccountRecord;
+import com.yonge.cooleshow.biz.dal.enums.AccountBizTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
 import com.yonge.cooleshow.biz.dal.vo.PlatformCashAccountRecordSummaryVo;
 
 import java.util.List;
@@ -39,7 +41,7 @@ public interface PlatformCashAccountRecordService extends IService<PlatformCashA
      * @param bizType
      * @param bizId
      */
-    void cancelRecord(String orderNo, String bizType, Long bizId);
+    void cancelRecord(String orderNo, String bizType, Long bizId,InOrOutEnum type);
 
     /**
      * 设置商城预收-> 实收
@@ -49,5 +51,16 @@ public interface PlatformCashAccountRecordService extends IService<PlatformCashA
      * @param goodType
      */
     void mallRecordedRecord(Long productSkuId, String orderSn, String goodType);
+
+
+    /**
+     * 更新入账状态成功
+     *
+     * @param orderNo 订单号
+     * @param bizType 订单类型
+     * @param bizId 业务id
+     * @param type 收入 / 支出
+     */
+    void recordedRecord(String orderNo, AccountBizTypeEnum bizType, Long bizId, InOrOutEnum type);
 }
 

+ 12 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/StudentService.java

@@ -7,7 +7,11 @@ import com.yonge.cooleshow.biz.dal.dto.search.QueryMyFollowSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
 import com.yonge.cooleshow.biz.dal.entity.Student;
 import com.yonge.cooleshow.biz.dal.entity.Subject;
-import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.vo.MyFollow;
+import com.yonge.cooleshow.biz.dal.vo.StudentHomeVo;
+import com.yonge.cooleshow.biz.dal.vo.StudentVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
+import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 
 import java.util.List;
@@ -93,4 +97,11 @@ public interface StudentService extends IService<Student> {
      * @return
      */
     HttpResponseResult<Map<String, TeacherVo>> bindTeacher(String phone, Long userId, Boolean isUpdate);
+
+    /**
+     * 学生帐号关联
+     * @param info StudentWrapper.UnionStudent
+     * @return StudentWrapper.UnionStudentResp
+     */
+    StudentWrapper.UnionStudentResp unionStudent(StudentWrapper.UnionStudent info);
 }

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

@@ -150,7 +150,7 @@ public class ActivityRewardServiceImpl extends ServiceImpl<ActivityRewardDao, Ac
         if (RewardTypeEnum.ACTUAL.equals(activityReward.getRewardType())) {
             activityReward.setNum(1);
             activityReward.setUnit(UnitEnum.PCS);
-        } else if (RewardTypeEnum.PIAMO_ROOM.equals(activityReward.getRewardType())) {
+        } else if (RewardTypeEnum.PIANO_ROOM.equals(activityReward.getRewardType())) {
             activityReward.setUnit(UnitEnum.MINUTE);
         }
 
@@ -306,7 +306,7 @@ public class ActivityRewardServiceImpl extends ServiceImpl<ActivityRewardDao, Ac
         if (activityReward == null) {
             throw new BizException("奖品不存在");
         }
-        if (activityReward.getRewardType().equals(RewardTypeEnum.PIAMO_ROOM)) {
+        if (activityReward.getRewardType().equals(RewardTypeEnum.PIANO_ROOM)) {
             // 琴房课时
             PianoRoomChangeRecord pianoRoomChangeRecord = new PianoRoomChangeRecord();
             pianoRoomChangeRecord.setUserId(userId);

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

@@ -106,6 +106,9 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
     @Autowired
     private CouponInfoService couponInfoService;
 
+    @Autowired
+    private PlatformCashAccountRecordService platformCashAccountRecordService;
+
     @Override
     public CourseGroupDao getDao() {
         return this.baseMapper;
@@ -878,13 +881,21 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 
         //老师待入账
         List<UserAccountRecordDto> userAccountRecordDtos = new ArrayList<>();
+        List<PlatformCashAccountRecord> platformCashAccountRecords = new ArrayList<>();
         for (CourseScheduleTeacherSalary salary : teacherSalaryList) {
             UserAccountRecordDto dto = new UserAccountRecordDto(orderParam.getMerchId(), PostStatusEnum.WAIT, salary.getActualSalary(),
                     InOrOutEnum.IN, AccountBizTypeEnum.LIVE, salary.getCourseScheduleId(), orderParam.getGoodName(), orderParam.getOrderNo(), orderParam.getUserId(), accountPeriodTime);
             userAccountRecordDtos.add(dto);
+
+            // 支出给老师金额
+            PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(orderParam.getUserId(), salary.getActualSalary(),
+                                                                      InOrOutEnum.OUT, PostStatusEnum.WAIT, AccountBizTypeEnum.LIVE, salary.getCourseScheduleId(),
+                                                                        orderParam.getOrderNo(), accountPeriodTime);
+            platformCashAccountRecords.add(platformCashAccountRecord);
         }
         if (CollectionUtils.isNotEmpty(userAccountRecordDtos)) {
             userAccountService.accountRecord(userAccountRecordDtos);
+            platformCashAccountRecordService.saveBatch(platformCashAccountRecords);
         }
     }
 

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

@@ -123,6 +123,9 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
     private UserAccountRecordService userAccountRecordService;
     @Autowired
     private UserOrderService userOrderService;
+
+    @Autowired
+    private PlatformCashAccountRecordService platformCashAccountRecordService;
     
     @Autowired
     private StudentService studentService;
@@ -1203,14 +1206,22 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
 
         //老师待入账
         List<UserAccountRecordDto> userAccountRecordDtos = new ArrayList<>();
+        List<PlatformCashAccountRecord> platformCashAccountRecords = new ArrayList<>();
         for (CourseScheduleTeacherSalary salary : teacherSalaryList) {
             UserAccountRecordDto dto = new UserAccountRecordDto(orderParam.getMerchId(), PostStatusEnum.WAIT, salary.getActualSalary(),
                     InOrOutEnum.IN, AccountBizTypeEnum.PRACTICE, salary.getCourseScheduleId(), orderParam.getGoodName(), orderParam.getOrderNo(), orderParam.getUserId(), accountPeriodTime);
             userAccountRecordDtos.add(dto);
+
+            // 插入平台账户 支出
+            PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(orderParam.getUserId(), salary.getActualSalary(),
+                                                        InOrOutEnum.OUT, PostStatusEnum.WAIT, AccountBizTypeEnum.PRACTICE, salary.getCourseScheduleId(),
+                                                                                                orderParam.getOrderNo(), accountPeriodTime);
+            platformCashAccountRecords.add(platformCashAccountRecord);
         }
 
         if (CollectionUtils.isNotEmpty(userAccountRecordDtos)) {
             userAccountService.accountRecord(userAccountRecordDtos);
+            platformCashAccountRecordService.saveBatch(platformCashAccountRecords);
         }
     }
 
@@ -1880,6 +1891,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
                 UserAccountRecordVo record = userAccountRecordService.detail(dto.getOrderNo(), dto.getBizType(), dto.getBizId());
                 if (null != record) {
                     userAccountService.accountChange(record, PostStatusEnum.RECORDED);
+                    platformCashAccountRecordService.recordedRecord(dto.getOrderNo(), dto.getBizType(), dto.getBizId(),InOrOutEnum.OUT);
                 }
             }
             Set<Long> bizIds = list.stream().map(UserAccountRecordDto::getBizId).collect(Collectors.toSet());

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

@@ -0,0 +1,609 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
+import com.yonge.cooleshow.auth.config.CustomerServiceConfig;
+import com.yonge.cooleshow.biz.dal.config.RongCloudConfig;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceBatchSending;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceReceive;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
+import com.yonge.cooleshow.biz.dal.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.entity.Teacher;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.MK;
+import com.yonge.cooleshow.biz.dal.enums.im.EImReceiveType;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendStatus;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendType;
+import com.yonge.cooleshow.biz.dal.mapper.CustomerServiceBatchSendingMapper;
+import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
+import com.yonge.cooleshow.biz.dal.service.CustomerServiceBatchSendingService;
+import com.yonge.cooleshow.biz.dal.service.CustomerServiceReceiveService;
+import com.yonge.cooleshow.biz.dal.service.SubjectService;
+import com.yonge.cooleshow.biz.dal.service.TeacherService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceBatchSendingWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper;
+import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.util.ImUtil;
+import com.yonge.toolset.base.util.ThreadPool;
+import com.yonge.toolset.mybatis.support.PageUtil;
+import com.yonge.toolset.payment.util.DistributedLock;
+import io.rong.messages.BaseMessage;
+import io.rong.messages.ImgMessage;
+import io.rong.messages.TxtMessage;
+import io.rong.models.message.PrivateMessage;
+import io.rong.models.message.PushExt;
+import io.rong.models.response.ResponseResult;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Random;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * 客服群发
+ * 2022-12-09 10:49:10
+ */
+@Slf4j
+@Service
+public class CustomerServiceBatchSendingServiceImpl extends ServiceImpl<CustomerServiceBatchSendingMapper, CustomerServiceBatchSending> implements CustomerServiceBatchSendingService {
+
+    @Autowired
+    private CustomerServiceReceiveService customerServiceReceiveService;
+    @Autowired
+    private SubjectService subjectService;
+    @Autowired
+    private CustomerServiceConfig customerServiceConfig;
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    @Autowired
+    private RedissonClient redissonClient;
+    @Autowired
+    private TeacherService teacherService;
+
+	/**
+     * 查询详情
+     * @param id 详情ID
+     * @return CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending
+     */
+	@Override
+    public CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending detail(Long id) {
+
+        CustomerServiceBatchSending sending = baseMapper.selectById(id);
+        if (Objects.isNull(sending)) {
+            throw new BizException("无效的请求ID");
+        }
+
+        CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending record = CustomerServiceBatchSendingWrapper
+                .CustomerServiceBatchSending.from(JSON.toJSONString(sending));
+
+        // 填充声部,目标群体
+        List<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> records = Lists.newArrayList(record);
+
+        // 返回消息封闭
+        getBatchSendingPaddingData(records);
+
+        // 部分推送,查询用户信息
+        if (EImReceiveType.PORTION == sending.getReceiveType()) {
+
+            CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery receiveQuery = CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery
+                    .builder().batchSendingId(sending.getId()).build();
+            IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive> page = customerServiceReceiveService.selectPage(PageUtil.getPage(1, 9999), receiveQuery);
+
+            record.setReceives(page.getRecords());
+        }
+
+        return record;
+    }
+    
+    /**
+     * 分页查询
+     * @param page IPage<CustomerServiceBatchSending>
+     * @param query CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery
+     * @return IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending>
+     */
+    @Override
+    public IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> selectPage(IPage<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> page,
+                                                                                            CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery query){
+
+        // 群发消息记录
+        List<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> sendings = baseMapper.selectPage(page, query);
+
+        if (CollectionUtils.isNotEmpty(sendings)) {
+
+            // 返回消息封闭
+            getBatchSendingPaddingData(sendings);
+        }
+
+        return page.setRecords(sendings);
+    }
+
+    /**
+     * 群发消息返回封装
+     * @param sendings List<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending>
+     */
+    private void getBatchSendingPaddingData(List<CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending> sendings) {
+
+        // 声部信息
+        List<Long> subjectIds = sendings.stream()
+                .flatMap(x -> Arrays.stream(x.getSendSubject().split(",")))
+                .map(Long::parseLong).distinct().collect(Collectors.toList());
+
+        Map<Long, String> subjectNameMap = subjectService.findBySubjectByIdList(subjectIds).stream()
+                .collect(Collectors.toMap(Subject::getId, Subject::getName, (o, n) -> n));
+
+        // 创建用户
+        List<Long> userIds = sendings.stream()
+                .flatMap(x -> Lists.newArrayList(x.getCreateBy(), x.getSenderId()).stream())
+                .filter(Objects::nonNull).distinct().collect(Collectors.toList());
+
+        List<SysUser> sysUsers = sysUserMapper.selectBatchIds(userIds);
+
+        Map<Long, String> usernameMap = sysUsers.stream()
+                .collect(Collectors.toMap(SysUser::getId, SysUser::getUsername, (o, n) -> n));
+
+        Map<Long, SysUser> senderMap = sysUsers.stream()
+                .collect(Collectors.toMap(SysUser::getId, Function.identity(), (o, n) -> n));
+
+        // 发送群体,发送声部
+        SysUser sysUser;
+        for (CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending item : sendings) {
+
+            // 创建用户
+            item.sender("").mobile("")
+                    .setCreateUser(usernameMap.getOrDefault(item.getCreateBy(), ""));
+
+            if (senderMap.containsKey(item.getSenderId())) {
+                sysUser = senderMap.get(item.getSenderId());
+
+                item.sender(sysUser.getUsername()).mobile(sysUser.getPhone());
+            }
+
+            List<Long> collect = Arrays.stream(Optional.ofNullable(item.getSendSubject()).orElse("").split(","))
+                    .map(Long::parseLong).distinct().collect(Collectors.toList());
+
+            // 发送声部
+            String subjectName = subjectNameMap.entrySet().stream()
+                    .filter(x -> collect.contains(x.getKey()))
+                    .map(Map.Entry::getValue).collect(Collectors.joining(","));
+            item.setSubjectName(subjectName);
+
+            // 发送群体
+            List<String> clientTypes = Arrays.stream(Optional.ofNullable(item.getTargetGroup()).orElse("").split(","))
+                    .collect(Collectors.toList());
+
+            String targetGroup = Arrays.stream(ClientEnum.values())
+                    .filter(x -> clientTypes.contains(x.getCode())).map(ClientEnum::getMsg)
+                    .collect(Collectors.joining(","));
+            item.setTargetGroupName(targetGroup);
+        }
+    }
+
+    /**
+     * 添加
+     * @param info CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending
+     * @return Boolean
+     */
+    @Transactional
+    @Override
+    public Boolean add(CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending info) {
+
+        // 发送客服ID
+        String customerService = info.getMobile();
+        if (StringUtils.isBlank(customerService)) {
+            customerService = customerServiceConfig.getCustomerService();
+        }
+        if (StringUtils.isNotEmpty(customerService)) {
+
+            List<String> collect = Arrays.stream(customerService.split(",")).collect(Collectors.toList());
+
+            Random rand = new Random();
+            String mobile = collect.get(rand.nextInt(collect.size()));
+
+            // 查询发送客服ID
+            SysUser senderUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery()
+                    .eq(SysUser::getPhone, mobile));
+            if (Objects.isNull(senderUser)) {
+                throw new BizException("未匹配到客服人员");
+            }
+            info.setSenderId(senderUser.getId());
+
+            Teacher teacher = teacherService.getOne(Wrappers.<Teacher>lambdaQuery()
+                    .eq(Teacher::getUserId, info.getSenderId()));
+            if (Objects.isNull(teacher)) {
+                throw new BizException("当前帐号未注册老师帐号");
+            }
+        }
+
+        // 推送消息
+        CustomerServiceBatchSending sending = JSON.parseObject(info.jsonString(), CustomerServiceBatchSending.class);
+
+        // 保存推送群发消息
+        save(sending);
+
+        // 部分推送用户
+       if (CollectionUtils.isNotEmpty(info.getReceives())) {
+           for (CustomerServiceReceiveWrapper.CustomerServiceReceive item : info.getReceives()) {
+               item.setBatchSendingId(sending.getId());
+           }
+           customerServiceReceiveService.saveBatch(JSON.parseArray(JSON.toJSONString(info.getReceives()),
+                   CustomerServiceReceive.class));
+       }
+
+        // 更新群发消息人数
+        updateBatchSendingSendNumber(sending);
+
+       // 发送推送消息
+        if (EImSendType.IMMEDIATELY == info.getSendType()) {
+            asyncBatchSendingMessage(sending);
+        }
+
+        return true;
+    }
+
+    /**
+     * 更新群发消息人数
+     * @param info CustomerServiceBatchSending
+     */
+    private void updateBatchSendingSendNumber(CustomerServiceBatchSending info) {
+
+        // 发送条件,接收人数
+        CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery query = CustomerServiceBatchSendingWrapper.CustomerServiceBatchSendingQuery
+                .builder()
+                .sendSubject(info.getSendSubject())
+                .targetGroup(info.getTargetGroup())
+                .build();
+        info.setCondition(query.jsonString()); // 发送条件
+
+        // 更新发送人数,接收人数
+        if (EImReceiveType.ALL == info.getReceiveType()) {
+
+            info.setSendNumber(0);
+            List<Integer> receiveNums = Lists.newCopyOnWriteArrayList();
+            // 条件匹配的老师、学生数量
+            query.getClientTypes().parallelStream().forEach(item -> {
+
+                CustomerService.NotifyMessage receiveQuery = CustomerService.NotifyMessage.builder()
+                        .clientType(ClientEnum.valueOf(item))
+                        .subjectIds(Arrays.stream(info.getSendSubject().split(",")).collect(Collectors.toList()))
+                        .build();
+
+                Page<CustomerService.MessageReceives> page = PageUtil.getPage(1, 10);
+                // 统计当前匹配用户数量
+                getBaseMapper().selectMessageReceives(page, receiveQuery);
+
+                receiveNums.add((int) page.getTotal());
+            });
+            info.setSendNumber(receiveNums.stream().mapToInt(Integer::intValue).sum());
+        } else {
+            // 选择的老师、学生数量
+            int sendNumber = customerServiceReceiveService.count(Wrappers.<CustomerServiceReceive>lambdaQuery()
+                    .eq(CustomerServiceReceive::getBatchSendingId, info.getId()));
+            info.setSendNumber(sendNumber);
+        }
+
+        // 更新群发消息人数
+        lambdaUpdate()
+                .eq(CustomerServiceBatchSending::getId, info.getId())
+                .set(CustomerServiceBatchSending::getSendNumber, info.getSendNumber())
+                .set(CustomerServiceBatchSending::getCondition, info.getCondition())
+                .update();
+    }
+
+    /**
+     * 更新
+     * @param info CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending
+     * @return Boolean
+     */
+    @Transactional
+    @Override
+    public Boolean update(CustomerServiceBatchSendingWrapper.CustomerServiceBatchSending info){
+
+        CustomerServiceBatchSending sending = JSON.parseObject(info.jsonString(),
+                CustomerServiceBatchSending.class);
+        // 更新群发消息
+        this.updateById(sending);
+
+        if (CollectionUtils.isNotEmpty(info.getReceives())) {
+
+            // 先清除数据,后重新插入
+            customerServiceReceiveService.remove(Wrappers.<CustomerServiceReceive>lambdaQuery()
+                    .eq(CustomerServiceReceive::getBatchSendingId, sending.getId()));
+
+            for (CustomerServiceReceiveWrapper.CustomerServiceReceive item : info.getReceives()) {
+                item.setBatchSendingId(sending.getId());
+            }
+            customerServiceReceiveService.saveBatch(JSON.parseArray(JSON.toJSONString(info.getReceives()),
+                    CustomerServiceReceive.class));
+        }
+
+        sending = getById(info.getId());
+        // 更新群发消息人数
+        updateBatchSendingSendNumber(sending);
+
+        // 发送推送消息
+        if (EImSendType.IMMEDIATELY == sending.getSendType()) {
+            sendMessage(info.getId());
+        }
+
+        return true;
+    }
+
+    /**
+     * 更新消息状态
+     *
+     * @param id         消息Id
+     * @param sendStatus EImSendStatus
+     */
+    @Override
+    public void status(Long id, EImSendStatus sendStatus) {
+
+        CustomerServiceBatchSending record = getById(id);
+        if (Objects.isNull(record)) {
+            throw new BizException("无效的请求Id");
+        }
+
+        // 校验消息发送状态
+        if (EImSendStatus.SEND == record.getSendStatus()) {
+            throw new BizException("当前消息已发送");
+        }
+
+        // 当前群发消息状态一致
+        if (record.getSendStatus() == sendStatus) {
+            throw new BizException("群发消息状态一致");
+        }
+
+        // 更新群发消息状态
+        lambdaUpdate()
+                .eq(CustomerServiceBatchSending::getId, id)
+                .set(CustomerServiceBatchSending::getSendStatus, sendStatus)
+                .update();
+    }
+
+    /**
+     * 发送消息
+     *
+     * @param id 群发消息ID
+     */
+    @Override
+    public void sendMessage(Long id) {
+
+        CustomerServiceBatchSending info = getById(id);
+        if (Objects.isNull(info)) {
+            throw new BizException("无效的群发消息ID");
+        }
+
+        // 发送消息
+        asyncBatchSendingMessage(info);
+
+    }
+
+    /**
+     * 异步发送消息
+     * @param info CustomerServiceBatchSending
+     */
+    private void asyncBatchSendingMessage(CustomerServiceBatchSending info) {
+        String lockName = MessageFormat.format("batchSending:{0}", String.valueOf(info.getId()));
+        // 消息状态判定,且不能重复发送
+        DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
+
+            List<BaseMessage> messages = getReceiveMessage(info);
+
+            // 异步发送消息且同步更新已发送人数,稍后可在页面刷新查看已发送用户数
+            ThreadPool.getExecutor().submit(() -> {
+                // 接收消息用户数
+                List<Integer> receiveNums = Lists.newCopyOnWriteArrayList();
+                // 分页数限制
+                int limit = 500;
+
+                try {
+
+                    if (EImReceiveType.ALL == info.getReceiveType()) {
+
+                        // 推送消息给匹配用户
+                        List<String> targetGroupes = Arrays.stream(info.getTargetGroup().split(",")).collect(Collectors.toList());
+
+                        targetGroupes.parallelStream().forEach(clientType -> {
+
+                            CustomerService.NotifyMessage receiveQuery = CustomerService.NotifyMessage.builder()
+                                    .clientType(ClientEnum.valueOf(clientType))
+                                    .subjectIds(Arrays.stream(info.getSendSubject().split(",")).collect(Collectors.toList()))
+                                    .build();
+
+                            Page<CustomerService.MessageReceives> page = PageUtil.getPage(1, 10);
+                            // 统计当前匹配用户数量
+                            getBaseMapper().selectMessageReceives(page, receiveQuery);
+
+                            // 计算总页数
+                            int pages = (int) (page.getTotal() - 1) / limit + 1;
+
+                            List<Integer> collect = IntStream.iterate(1, i -> i + 1).limit(pages).boxed().collect(Collectors.toList());
+
+                            for (Integer pageNum : collect) {
+
+                                List<String> receiveUserIds = getBaseMapper().selectMessageReceives(PageUtil.getPage(pageNum, limit), receiveQuery).stream()
+                                        .map(x -> String.valueOf(x.getUserId()))
+                                        .collect(Collectors.toList());
+
+                                if (ClientEnum.STUDENT.match(clientType)) {
+                                    receiveUserIds = receiveUserIds.stream()
+                                            .map(x -> MessageFormat.format("{0}:STUDENT", x))
+                                            .collect(Collectors.toList());
+                                }
+
+                                batchSendCustomerServiceMessage(info, messages, receiveNums, receiveUserIds);
+                            }
+                        });
+
+                    } else {
+
+                        // 查询条件
+                        CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery receiveQuery = CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery
+                                .builder().batchSendingId(info.getId()).build();
+
+                        Page<CustomerServiceReceiveWrapper.CustomerServiceReceive> page = PageUtil.getPage(1, 10);
+                        // 推送消息给指定用户
+                        customerServiceReceiveService.selectPage(page, receiveQuery);
+
+                        // 计算总页数
+                        int pages = (int) (page.getTotal() - 1) / limit + 1;
+
+                        List<Integer> collect = IntStream.iterate(1, i -> i + 1).limit(pages).boxed().collect(Collectors.toList());
+
+                        for (Integer pageNum : collect) {
+
+                            List<String> receiveUserIds = customerServiceReceiveService.selectPage(PageUtil.getPage(pageNum, limit), receiveQuery).getRecords().stream()
+                                    .map(x -> {
+                                        if (ClientEnum.STUDENT.match(x.getClientType())) {
+                                            return MessageFormat.format("{0}:STUDENT", String.valueOf(x.getUserId()));
+                                        }
+                                        return String.valueOf(x.getUserId());
+                                    })
+                                    .collect(Collectors.toList());
+
+                            batchSendCustomerServiceMessage(info, messages, receiveNums, receiveUserIds);
+                        }
+                    }
+
+                    // 更新消息状态为已发送
+                    lambdaUpdate()
+                            .eq(CustomerServiceBatchSending::getId, info.getId())
+                            .set(CustomerServiceBatchSending::getSendStatus, EImSendStatus.SEND)
+                            .set(CustomerServiceBatchSending::getReceiveNumber, receiveNums.stream().mapToInt(Integer::intValue).sum())
+                            .set(CustomerServiceBatchSending::getSendTime, DateTime.now().toDate())
+                            .update();
+
+                } catch (Exception e) {
+                    log.error("sendMessage id={}", info.getId(), e);
+                }
+
+            });
+
+        });
+    }
+
+    /**
+     * 批量发送客服消息
+     * @param info CustomerServiceBatchSending
+     * @param messages 推送消息类型
+     * @param receiveNums 接收消息用户数
+     * @param receiveUserIds 接收消息用户Id
+     */
+    private static void batchSendCustomerServiceMessage(CustomerServiceBatchSending info, List<BaseMessage> messages,
+                                                        List<Integer> receiveNums, List<String> receiveUserIds) {
+        // 拓展消息
+        PushExt pushExt = PushExt.build(info.getTitle(), 1,
+                new PushExt.HW("channelId", "NORMAL"), new PushExt.VIVO("1"),
+                new PushExt.APNs("", ""),
+                new PushExt.OPPO(""));
+
+        String senderId = String.valueOf(info.getSenderId());
+        PrivateMessage privateMessage;
+        ResponseResult privateResult;
+        for (List<String> item : Lists.partition(receiveUserIds, 100)) {
+
+            try {
+
+                for (BaseMessage message : messages) {
+
+                    // 发送用户IM通知消息
+                    privateMessage = new PrivateMessage()
+                            .setSenderId(senderId)
+                            .setTargetId(item.toArray(new String[0]))
+                            .setObjectName(message.getType())
+                            .setContent(message)
+                            .setPushExt(pushExt)
+                            .setIsIncludeSender(0);
+
+                    privateResult = RongCloudConfig.rongCloud.message.msgPrivate.send(privateMessage);
+                    log.info("batchSendCustomerServiceMessage senderId={}, ret={}", senderId, privateResult.getCode());
+                }
+
+                receiveNums.add(item.size());
+            } catch (Exception e) {
+                log.error("batchSendCustomerServiceMessage senderId={}", senderId, e);
+            }
+
+        }
+    }
+
+    /**
+     * 推送消息类型
+     * @param info CustomerServiceBatchSending
+     * @return List<BaseMessage>
+     */
+    private static List<BaseMessage> getReceiveMessage(CustomerServiceBatchSending info) {
+        List<BaseMessage> messages = Lists.newArrayList();
+
+        if (StringUtils.isNotEmpty(info.getImgMessage())) {
+
+            //String suffix = info.getImgMessage().substring(info.getImgMessage().lastIndexOf("."));
+
+            // 发送图片消息
+            ImgMessage imgMessage = new ImgMessage(ImUtil.imageToBase64(info.getImgMessage(), "png"), "", info.getImgMessage());
+
+            messages.add(imgMessage);
+        }
+
+        if (StringUtils.isNotEmpty(info.getTextMessage())) {
+
+            // 发送文本消息
+            TxtMessage txtMessage = new TxtMessage(info.getTextMessage(), "");
+
+            messages.add(txtMessage);
+        }
+        return messages;
+    }
+
+
+    /**
+     * 定时发送消息
+     */
+    @Override
+    public void scheduleSendMessage() {
+
+        DistributedLock.of(redissonClient).runIfLockCanGet("scheduleSendMessage:LOCK", () -> {
+
+            // 定时发送时间
+            // 开始时间
+            Date startTime = DateTime.now().minusMinutes(2).toDate();
+            // 结束时间
+            Date endTime = DateTime.now().toDate();
+
+            List<CustomerServiceBatchSending> batchSendings = lambdaQuery()
+                    .between(CustomerServiceBatchSending::getSendTime, startTime, endTime)
+                    .eq(CustomerServiceBatchSending::getSendType, EImSendType.SCHEDULED)
+                    .eq(CustomerServiceBatchSending::getSendStatus, EImSendStatus.WAIT)
+                    .list();
+
+            if (CollectionUtils.isNotEmpty(batchSendings)) {
+                log.info("scheduleSendMessage time={}, size={}", DateTime.now().toString(MK.TIME_PATTERN), batchSendings.size());
+
+                for (List<CustomerServiceBatchSending> item : Lists.partition(batchSendings, 10)) {
+
+                    item.parallelStream().forEach(x -> sendMessage(x.getId()));
+                }
+
+            }
+        });
+    }
+}

+ 94 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceReceiveServiceImpl.java

@@ -0,0 +1,94 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yonge.cooleshow.biz.dal.entity.CustomerServiceReceive;
+import com.yonge.cooleshow.biz.dal.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.mapper.CustomerServiceReceiveMapper;
+import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
+import com.yonge.cooleshow.biz.dal.service.CustomerServiceReceiveService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 客服群发接收
+ * 2022-12-09 10:49:10
+ */
+@Slf4j
+@Service
+public class CustomerServiceReceiveServiceImpl extends ServiceImpl<CustomerServiceReceiveMapper, CustomerServiceReceive> implements CustomerServiceReceiveService {
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+	/**
+     * 查询详情
+     * @param id 详情ID
+     * @return CustomerServiceReceive
+     */
+	@Override
+    public CustomerServiceReceive detail(Long id) {
+        
+        return baseMapper.selectById(id);
+    }
+    
+    /**
+     * 分页查询
+     * @param page IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive>
+     * @param query CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery
+     * @return IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive>
+     */
+    @Override
+    public IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive> selectPage(IPage<CustomerServiceReceiveWrapper.CustomerServiceReceive> page,
+                                                                                  CustomerServiceReceiveWrapper.CustomerServiceReceiveQuery query){
+
+        List<CustomerServiceReceiveWrapper.CustomerServiceReceive> receives = baseMapper.selectPage(page, query);
+
+        if (CollectionUtils.isNotEmpty(receives)) {
+
+            List<Long> userIds = receives.stream()
+                    .map(CustomerServiceReceiveWrapper.CustomerServiceReceive::getUserId).distinct().collect(Collectors.toList());
+
+            Map<Long, String> usernameMap = sysUserMapper.selectBatchIds(userIds).stream()
+                    .collect(Collectors.toMap(SysUser::getId, x -> Optional.ofNullable(x.getUsername()).orElse(""), (o, n) -> n));
+
+            for (CustomerServiceReceiveWrapper.CustomerServiceReceive item : receives) {
+
+                item.setUserName(usernameMap.getOrDefault(item.getUserId(), ""));
+            }
+        }
+
+        return page.setRecords(receives);
+    }
+	
+    /**
+     * 添加
+     * @param customerServiceReceive CustomerServiceReceiveWrapper.CustomerServiceReceive
+     * @return Boolean
+     */
+    @Override
+    public Boolean add(CustomerServiceReceiveWrapper.CustomerServiceReceive customerServiceReceive) {    	
+        
+        return this.save(JSON.parseObject(customerServiceReceive.jsonString(), CustomerServiceReceive.class));
+    }
+
+    /**
+     * 更新
+     * @param customerServiceReceive CustomerServiceReceiveWrapper.CustomerServiceReceive
+     * @return Boolean
+     */
+    @Override
+    public Boolean update(CustomerServiceReceiveWrapper.CustomerServiceReceive customerServiceReceive){
+
+        return this.updateById(JSON.parseObject(customerServiceReceive.jsonString(), CustomerServiceReceive.class));       
+    }
+}

+ 29 - 44
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java

@@ -21,6 +21,7 @@ import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.ImUserWrapper;
 import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.util.ImUtil;
 import io.rong.messages.BaseMessage;
 import io.rong.messages.ImgMessage;
 import io.rong.messages.TxtMessage;
@@ -28,8 +29,6 @@ import io.rong.models.message.PrivateMessage;
 import io.rong.models.message.PushExt;
 import io.rong.models.response.ResponseResult;
 import lombok.extern.slf4j.Slf4j;
-import net.coobird.thumbnailator.Thumbnails;
-import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -37,11 +36,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.URL;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -269,17 +263,37 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
             throw new BizException("无效的客服联系方式");
         }
 
-        LambdaQueryWrapper<com.yonge.cooleshow.biz.dal.entity.SysUser> wrapper = Wrappers.<com.yonge.cooleshow.biz.dal.entity.SysUser>lambdaQuery()
-                .select(com.yonge.cooleshow.biz.dal.entity.SysUser::getId,
-                        com.yonge.cooleshow.biz.dal.entity.SysUser::getUsername)
-                .in(com.yonge.cooleshow.biz.dal.entity.SysUser::getPhone, info.getReceives());
+        List<String> receiveUserIds;
+        if (Objects.nonNull(info.getClientType())) {
 
-        wrapper.last("LIMIT 1000");
-        // 接收者信息
-        List<com.yonge.cooleshow.biz.dal.entity.SysUser> sysUsers = sysUserMapper.selectList(wrapper);
+            receiveUserIds = sysUserMapper.selectMessageReceives(info).stream()
+                    .map(x -> String.valueOf(x.getUserId()))
+                    .collect(Collectors.toList());
+            if (ClientEnum.STUDENT == info.getClientType()) {
+                receiveUserIds = receiveUserIds.stream()
+                        .map(x -> MessageFormat.format("{0}:STUDENT", x))
+                        .collect(Collectors.toList());
+            }
+        } else {
+
+            LambdaQueryWrapper<com.yonge.cooleshow.biz.dal.entity.SysUser> wrapper = Wrappers.<com.yonge.cooleshow.biz.dal.entity.SysUser>lambdaQuery()
+                    .select(com.yonge.cooleshow.biz.dal.entity.SysUser::getId,
+                            com.yonge.cooleshow.biz.dal.entity.SysUser::getUsername)
+                    .in(com.yonge.cooleshow.biz.dal.entity.SysUser::getPhone, info.getReceives());
+
+            wrapper.last("LIMIT 1500");
+            // 接收者信息
+            List<com.yonge.cooleshow.biz.dal.entity.SysUser> sysUsers = sysUserMapper.selectList(wrapper);
+
+            // 分批次发送用户消息
+            receiveUserIds = sysUsers.stream()
+                    .map(com.yonge.cooleshow.biz.dal.entity.SysUser::getId)
+                    .map(String::valueOf)
+                    .collect(Collectors.toList());
+        }
 
         // 发送图片消息
-        ImgMessage imgMessage = new ImgMessage(imageToBase64(info.getImgMessage(), "png"), "", info.getImgUrl());
+        ImgMessage imgMessage = new ImgMessage(ImUtil.imageToBase64(info.getImgMessage(), "png"), "", info.getImgUrl());
 
         // 发送文本消息
         TxtMessage txtMessage = new TxtMessage(info.getTxtMessage(), "");
@@ -292,12 +306,6 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
                 new PushExt.APNs("", ""),
                 new PushExt.OPPO(""));
 
-        // 分批次发送用户消息
-        List<String> receiveUserIds = sysUsers.stream()
-                .map(com.yonge.cooleshow.biz.dal.entity.SysUser::getId)
-                .map(String::valueOf)
-                .collect(Collectors.toList());
-
         String senderId = String.valueOf(senderUser.getId());
         PrivateMessage privateMessage;
         ResponseResult privateResult;
@@ -328,30 +336,7 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
 
     }
 
-    public static String imageToBase64(String imgMessage, String suffix) {
-
-        Base64 encoder = new Base64();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try {
-            URL url = new URL(imgMessage);
-            BufferedImage bufferedImage = Thumbnails.of(url).scale(0.1f).outputQuality(0.25f).asBufferedImage();
-            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-            ImageIO.write(bufferedImage, suffix, outputStream);
-
-            byte[] bytes = outputStream.toByteArray();
-            outputStream.close();
-            int length = bytes.length;
-            //文件大小不能超过393216 Bytes
-            if (length > 393216) {
-                throw new BizException("文件过大请调整 像素 或 文件大小");
-            }
 
-            ImageIO.write(bufferedImage, suffix, baos);
-        } catch (IOException e) {
-            log.error("imageToBase64", e);
-        }
-        return new String(encoder.encode((baos.toByteArray())));
-    }
 
     /**
      * 用户IM好友列表

+ 111 - 24
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MusicSheetServiceImpl.java

@@ -3,41 +3,106 @@ package com.yonge.cooleshow.biz.dal.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dao.MusicAlbumDao;
-import com.yonge.cooleshow.biz.dal.dto.*;
-import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
-import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
-import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
-import com.yonge.cooleshow.common.enums.ActivityShareEnum;
-import com.yonge.cooleshow.common.enums.PostStatusEnum;
 import com.yonge.cooleshow.biz.dal.dao.MusicSheetDao;
+import com.yonge.cooleshow.biz.dal.dto.MusicImgDto;
+import com.yonge.cooleshow.biz.dal.dto.MusicSheetDto;
+import com.yonge.cooleshow.biz.dal.dto.MusicSheetExport;
+import com.yonge.cooleshow.biz.dal.dto.MusicSheetPayDto;
+import com.yonge.cooleshow.biz.dal.dto.ReasonDto;
+import com.yonge.cooleshow.biz.dal.dto.UserAccountRecordDto;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
 import com.yonge.cooleshow.biz.dal.dto.req.TeacherMusicSheetAuditReq;
-import com.yonge.cooleshow.biz.dal.dto.search.*;
-import com.yonge.cooleshow.biz.dal.entity.*;
-import com.yonge.cooleshow.biz.dal.enums.*;
-import com.yonge.cooleshow.biz.dal.service.*;
-import com.yonge.cooleshow.common.enums.YesOrNoEnum;
-import com.yonge.toolset.mybatis.support.PageUtil;
-import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumDetailSearch;
+import com.yonge.cooleshow.biz.dal.dto.search.MusicSheetSearch;
+import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicSheetOrderSearch;
+import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicSheetSearch;
+import com.yonge.cooleshow.biz.dal.dto.search.TeacherMusicSheetAuditSearch;
+import com.yonge.cooleshow.biz.dal.dto.search.TeacherMusicSheetSearch;
+import com.yonge.cooleshow.biz.dal.entity.AlbumMusicRelate;
+import com.yonge.cooleshow.biz.dal.entity.CourseCourseware;
+import com.yonge.cooleshow.biz.dal.entity.MusicAlbum;
+import com.yonge.cooleshow.biz.dal.entity.MusicFavorite;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheetAccompaniment;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheetAuthRecord;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheetPurchaseRecord;
+import com.yonge.cooleshow.biz.dal.entity.MusicTag;
+import com.yonge.cooleshow.biz.dal.entity.PlatformCashAccountRecord;
+import com.yonge.cooleshow.biz.dal.entity.StudentStar;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
+import com.yonge.cooleshow.biz.dal.entity.TeacherTotal;
+import com.yonge.cooleshow.biz.dal.enums.AccountBizTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.AudioTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
+import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
+import com.yonge.cooleshow.biz.dal.enums.MessageTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.TeacherTagEnum;
+import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
+import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
+import com.yonge.cooleshow.biz.dal.service.AlbumMusicRelateService;
+import com.yonge.cooleshow.biz.dal.service.CourseCoursewareService;
+import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
+import com.yonge.cooleshow.biz.dal.service.MusicFavoriteService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetAccompanimentService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetAuthRecordService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetPracticeRecordService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetPurchaseRecordService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
+import com.yonge.cooleshow.biz.dal.service.MusicTagService;
+import com.yonge.cooleshow.biz.dal.service.PlatformCashAccountRecordService;
+import com.yonge.cooleshow.biz.dal.service.StudentService;
+import com.yonge.cooleshow.biz.dal.service.StudentStarService;
+import com.yonge.cooleshow.biz.dal.service.SubjectService;
+import com.yonge.cooleshow.biz.dal.service.SysConfigService;
+import com.yonge.cooleshow.biz.dal.service.SysMessageService;
+import com.yonge.cooleshow.biz.dal.service.TeacherService;
+import com.yonge.cooleshow.biz.dal.service.TeacherTotalService;
+import com.yonge.cooleshow.biz.dal.service.UserAccountService;
+import com.yonge.cooleshow.biz.dal.service.UserOrderService;
+import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
+import com.yonge.cooleshow.biz.dal.vo.ActivityPlanVo;
+import com.yonge.cooleshow.biz.dal.vo.HomeMusicSheetVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicSheetDetailVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicSheetShareVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicSheetWebsiteDetailVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicTagVo;
+import com.yonge.cooleshow.biz.dal.vo.ShareProfitVo;
+import com.yonge.cooleshow.biz.dal.vo.StudentMusicSheetOrderVo;
+import com.yonge.cooleshow.biz.dal.vo.StudentTotalVo;
+import com.yonge.cooleshow.biz.dal.vo.StudentVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherAuditMusicSheetVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherMusicSheetListVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherMusicSheetVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherTotalVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
+import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
 import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.ActivityShareEnum;
+import com.yonge.cooleshow.common.enums.PostStatusEnum;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.base.string.MessageFormatter;
 import com.yonge.toolset.base.util.StringUtil;
+import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
 import com.yonge.toolset.utils.easyexcel.ErrMsg;
 import com.yonge.toolset.utils.easyexcel.ExcelDataReaderProperty;
 import com.yonge.toolset.utils.easyexcel.ExcelException;
-
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang3.RandomUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
@@ -46,11 +111,20 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.MessageFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -123,6 +197,9 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
     private CourseCoursewareService courseCoursewareService;
 
     @Autowired
+    private PlatformCashAccountRecordService platformCashAccountRecordService;
+
+    @Autowired
     private StudentStarService studentStarService;
     @Autowired
     private UserOrderService userOrderService;
@@ -142,7 +219,7 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         //保存主表
         musicSheet.setUpdateBy(userId);
         musicSheet.setUpdateTime(new Date());
-        musicSheet.setState(YesOrNoEnum.NO);
+        //musicSheet.setState(YesOrNoEnum.NO);
         this.saveOrUpdate(musicSheet);
 
         if (musicSheet.getAuditStatus() == null || AuthStatusEnum.DOING.getCode().equals(musicSheet.getAuditStatus().getCode())) {
@@ -201,7 +278,7 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         if (musicSheet == null) {
             throw new BizException("未找到曲目信息");
         }
-        if (YesOrNoEnum.NO.getCode().equals(musicSheet.getState().getCode())) {
+        if (YesOrNoEnum.NO.getCode().equals(Optional.ofNullable(musicSheet.getState()).orElse(YesOrNoEnum.NO).getCode())) {
             musicSheet.setState(YesOrNoEnum.YES);
         } else {
             musicSheet.setState(YesOrNoEnum.NO);
@@ -345,7 +422,7 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
             // 先判断是否购买过
             MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
                     studentId, detail.getId(), userType, PurchaseRecordTypeEnum.MUSIC);
-            if (musicSheetPurchaseRecord != null) {
+            if (musicSheetPurchaseRecord != null && OrderStatusEnum.PAID.getCode().equals(musicSheetPurchaseRecord.getOrderStatus().getCode())) {
                 detail.setPlay(YesOrNoEnum.YES);
             } else
             // 会员 判断是否为会员, 会员可播放
@@ -633,6 +710,8 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
                     .showFingering(param.getShowFingering())
                     //.hasBeat(param.getHasBeat())
                     .mp3Type(param.getMp3Type())
+                    .firstTone(Optional.ofNullable(param.getFirstTone()).orElse(musicSheet.getFirstTone()))
+                    .fixedTone(Optional.ofNullable(param.getFixedTone()).orElse(musicSheet.getFixedTone()))
                     //.audioType(param.getAudioType())
                     //.audioFileUrl(param.getAudioFileUrl())
                     .setState(YesOrNoEnum.YES);
@@ -796,7 +875,7 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
             BeanUtils.copyProperties(musicSheetDto, musicSheet);
             musicSheet.setUpdateTime(new Date());
             musicSheet.setUpdateBy(userId);
-            musicSheet.setState(YesOrNoEnum.NO);
+            //musicSheet.setState(YesOrNoEnum.NO);
             this.saveOrUpdate(musicSheet);
             if (musicSheet.getAuditStatus() == null || AuthStatusEnum.DOING.getCode().equals(musicSheet.getAuditStatus().getCode())) {
                 musicSheetAuthRecordService.setAuditDoing(musicSheet.getId(),originalMusicSheetId,lastMusicSheetId);
@@ -1070,6 +1149,12 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         userAccountService.accountRecord(
                 new UserAccountRecordDto(userOrderDetailVo.getMerchId(), PostStatusEnum.WAIT, transAmount, InOrOutEnum.IN,
                         AccountBizTypeEnum.MUSIC, musicSheetId, userOrderDetailVo.getGoodName(), userOrderDetailVo.getOrderNo(), userOrderDetailVo.getUserId(), accountPeriodTime));
+
+        // 插入平台账户 支出
+        PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(userOrderDetailVo.getUserId(), transAmount,
+                                                                                            InOrOutEnum.OUT, PostStatusEnum.WAIT, AccountBizTypeEnum.MUSIC, musicSheetId,
+                                                                                            userOrderDetailVo.getOrderNo(), accountPeriodTime);
+        platformCashAccountRecordService.save(platformCashAccountRecord);
     }
 
     @Override
@@ -1458,9 +1543,11 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
     }
 
     @Override
-    public Boolean updateMusicImg(String musicImg, Long musicSheetId) {
+    public Boolean updateMusicImg(MusicImgDto musicImgDto, Long musicSheetId) {
         MusicSheet musicSheet = new MusicSheet();
-        musicSheet.setMusicImg(musicImg);
+        musicSheet.setMusicImg(musicImgDto.getMusicImg());
+        musicSheet.setFirstTone(musicImgDto.getFirstTone());
+        musicSheet.setFixedTone(musicImgDto.getFixedTone());
         musicSheet.setId(musicSheetId);
         this.updateById(musicSheet);
 

+ 15 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PianoRoomBuyRecordServiceImpl.java

@@ -4,11 +4,13 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomChangeRecord;
 import com.yonge.cooleshow.biz.dal.entity.PianoRoomTime;
 import com.yonge.cooleshow.biz.dal.entity.PlatformCashAccountRecord;
 import com.yonge.cooleshow.biz.dal.entity.UserOrder;
 import com.yonge.cooleshow.biz.dal.enums.AccountBizTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
+import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.vo.*;
 import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
@@ -44,6 +46,9 @@ public class PianoRoomBuyRecordServiceImpl extends ServiceImpl<PianoRoomBuyRecor
     @Autowired
     private RedissonClient redissonClient;
 
+    @Autowired
+    private PianoRoomChangeRecordService pianoRoomChangeRecordService;
+
     @Override
     public PianoRoomBuyRecordVo detail(Long id) {
         return baseMapper.detail(id);
@@ -83,6 +88,16 @@ public class PianoRoomBuyRecordServiceImpl extends ServiceImpl<PianoRoomBuyRecor
         //保存琴房购买记录
         save(new PianoRoomBuyRecord(teacherVo.getUserId(), detail.getId(), orderDetailVo.getOrderNo(),
                 orderDetailVo.getSubOrderNo(), detail.getTimes()));
+        // 保存琴房变动记录
+        PianoRoomChangeRecord pianoRoomChangeRecord = new PianoRoomChangeRecord();
+        pianoRoomChangeRecord.setInOrOut(InOrOutEnum.IN);
+        pianoRoomChangeRecord.setCreateTime(new Date());
+        pianoRoomChangeRecord.setSourceType(SourceTypeEnum.ORDER);
+        pianoRoomChangeRecord.setTimes(detail.getTimes());
+        pianoRoomChangeRecord.setCreateBy(orderDetailVo.getUserId());
+        pianoRoomChangeRecord.setBizId(detail.getId().toString());
+        pianoRoomChangeRecord.setUserId(orderDetailVo.getUserId());
+        pianoRoomChangeRecordService.save(pianoRoomChangeRecord);
 
         //入琴房账户
         DistributedLock.of(redissonClient)

+ 20 - 5
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PlatformCashAccountRecordServiceImpl.java

@@ -1,10 +1,13 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
 
+import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
 import com.yonge.cooleshow.biz.dal.service.UserAccountRecordService;
+import com.yonge.cooleshow.common.enums.PostStatusEnum;
 import com.yonge.toolset.base.util.StringUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -64,8 +67,6 @@ public class PlatformCashAccountRecordServiceImpl extends ServiceImpl<PlatformCa
     public boolean updateWaitRecord() {
         //平台账户修改
         List<String> paramNames = new ArrayList<>();
-        paramNames.add(AccountBizTypeEnum.PRACTICE.getCode());
-        paramNames.add(AccountBizTypeEnum.LIVE.getCode());
         paramNames.add(AccountBizTypeEnum.LIVE_SHARE.getCode());
         paramNames.add(AccountBizTypeEnum.VIDEO.getCode());
         paramNames.add(AccountBizTypeEnum.VIDEO_SHARE.getCode());
@@ -89,12 +90,14 @@ public class PlatformCashAccountRecordServiceImpl extends ServiceImpl<PlatformCa
     }
 
     @Override
-    public void cancelRecord(String orderNo, String bizType, Long bizId) {
+    public void cancelRecord(String orderNo, String bizType, Long bizId,InOrOutEnum type) {
         if(StringUtil.isEmpty(orderNo) || StringUtil.isEmpty(bizType) || null == bizId){
             return;
         }
-        baseMapper.cancelRecord(orderNo, bizType, bizId);
-        baseMapper.cancelRecord(orderNo, bizType + "_SHARE", bizId);
+        baseMapper.cancelRecord(orderNo, bizType, bizId,type);
+        if (type.equals(InOrOutEnum.IN)) {
+            baseMapper.cancelRecord(orderNo, bizType + "_SHARE", bizId, InOrOutEnum.OUT);
+        }
     }
 
     @Override
@@ -102,5 +105,17 @@ public class PlatformCashAccountRecordServiceImpl extends ServiceImpl<PlatformCa
 
         baseMapper.mallRecordedRecord(orderSn, goodType, productSkuId);
     }
+
+    @Override
+    public void recordedRecord(String orderNo, AccountBizTypeEnum bizType, Long bizId, InOrOutEnum type) {
+        this.lambdaUpdate()
+                .eq(PlatformCashAccountRecord::getOrderNo,orderNo)
+                .eq(PlatformCashAccountRecord::getBizType,bizType)
+                .eq(PlatformCashAccountRecord::getBizId,bizId)
+                .eq(PlatformCashAccountRecord::getInOrOut,type)
+                .set(PlatformCashAccountRecord::getPostStatus, PostStatusEnum.RECORDED)
+                .set(PlatformCashAccountRecord::getUpdateTime,new Date())
+                .update();
+    }
 }
 

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

@@ -5,20 +5,28 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dao.StudentDao;
+import com.yonge.cooleshow.biz.dal.dao.SubjectDao;
 import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
 import com.yonge.cooleshow.biz.dal.dao.UserBindingTeacherDao;
 import com.yonge.cooleshow.biz.dal.dto.search.QueryMyFollowSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
+import com.yonge.cooleshow.biz.dal.entity.Student;
 import com.yonge.cooleshow.biz.dal.entity.StudentTotal;
 import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
 import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
-import com.yonge.cooleshow.biz.dal.service.TeacherService;
-import com.yonge.cooleshow.common.enums.CacheNameEnum;
+import com.yonge.cooleshow.biz.dal.service.StudentService;
 import com.yonge.cooleshow.biz.dal.service.StudentTotalService;
-import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.vo.MyFollow;
+import com.yonge.cooleshow.biz.dal.vo.StudentHomeVo;
+import com.yonge.cooleshow.biz.dal.vo.StudentVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
+import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.CacheNameEnum;
 import com.yonge.cooleshow.common.enums.UserLockFlag;
 import com.yonge.toolset.base.util.StringUtil;
 import com.yonge.toolset.utils.date.DateUtil;
@@ -28,13 +36,17 @@ import org.redisson.api.RedissonClient;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.yonge.cooleshow.biz.dal.entity.Student;
-import com.yonge.cooleshow.biz.dal.dao.StudentDao;
-import com.yonge.cooleshow.biz.dal.service.StudentService;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.text.MessageFormat;
-import java.util.*;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 
@@ -48,10 +60,12 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> impleme
     private ImUserFriendService imUserFriendService;
     @Resource
     private UserBindingTeacherDao userBindingTeacherDao;
-    @Autowired
-    private StudentService studentService;
     @Resource
     private TeacherDao teacherDao;
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    @Autowired
+    private SubjectDao subjectDao;
 
     @Override
     public StudentVo detail(Long userId) {
@@ -165,7 +179,7 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> impleme
         }
         resMap.put("old", old);
 
-        StudentVo studentVo = studentService.detailByPhone(phone);
+        StudentVo studentVo = detailByPhone(phone);
 
         if (null == studentVo) {
             return HttpResponseResult.failed("未找到用户信息");
@@ -202,4 +216,112 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> impleme
         return HttpResponseResult.succeed(resMap);
     }
 
+    /**
+     * 学生帐号关联
+     *
+     * @param info StudentWrapper.UnionStudent
+     * @return StudentWrapper.UnionStudentResp
+     */
+    @Transactional
+    @Override
+    public StudentWrapper.UnionStudentResp unionStudent(StudentWrapper.UnionStudent info) {
+
+        // 帐号关联响应数据
+        StudentWrapper.UnionStudentResp studentResp = StudentWrapper.UnionStudentResp
+                .builder()
+                .unionId(info.getUnionId())
+                .mobile(info.getMobile())
+                .updateFlag(false)
+                .build();
+
+        // 手机号查询用户信息
+        StudentVo studentVo = detailByPhone(info.getMobile());
+        if (Objects.isNull(studentVo)) {
+
+            com.yonge.cooleshow.biz.dal.entity.SysUser sysUser = sysUserMapper.selectOne(Wrappers.<com.yonge.cooleshow.biz.dal.entity.SysUser>lambdaQuery()
+                    .eq(com.yonge.cooleshow.biz.dal.entity.SysUser::getPhone, info.getMobile()));
+
+            if (Objects.isNull(sysUser)) {
+
+                // 自动注册创建用户
+                com.yonge.cooleshow.biz.dal.entity.SysUser user = new com.yonge.cooleshow.biz.dal.entity.SysUser();
+                user.setUsername(info.getUsername());
+                user.setPhone(info.getMobile());
+                user.setLockFlag(0);
+                user.setGender(info.getGender());
+                sysUserMapper.insert(user);
+
+                String subjectId = null;
+                // 学生声部
+                Subject subject = subjectDao.getSubjectMatchByName(info.getSubjectName());
+                if (Objects.nonNull(subject)) {
+                    subjectId = String.valueOf(subject.getId());
+                }
+
+                // 添加学生帐号
+                Student student = new Student();
+                student.setUserId(user.getId());
+                student.setSubjectId(subjectId);
+                student.setUnionId(info.getUnionId());
+                save(student);
+
+                // 更新标识
+                studentResp.setUpdateFlag(true);
+            } else {
+
+                com.yonge.cooleshow.biz.dal.entity.SysUser updateEntity = new com.yonge.cooleshow.biz.dal.entity.SysUser();
+                updateEntity.setId(sysUser.getId());
+                updateEntity.setDelFlag(0); // 激活帐号
+                // 激活帐号
+                sysUserMapper.updateById(updateEntity);
+
+                studentResp.username(sysUser.getUsername()).userId(sysUser.getId());
+
+                Student student = lambdaQuery().eq(Student::getUserId, sysUser.getId()).one();
+
+                // 更新学生关联帐号
+                updateStudentUnionStatus(info, studentResp, student);
+
+            }
+
+        } else {
+
+            studentResp.username(studentVo.getUsername()).userId(studentVo.getUserId());
+
+            Student student = lambdaQuery().eq(Student::getUserId, studentVo.getUserId()).one();
+
+            // 更新学生关联帐号
+            updateStudentUnionStatus(info, studentResp, student);
+        }
+
+        return studentResp;
+    }
+
+    /**
+     * 更新学生关联帐号
+     * @param info StudentWrapper.UnionStudent
+     * @param studentResp StudentWrapper.UnionStudentResp
+     * @param student Student
+     */
+    private void updateStudentUnionStatus(StudentWrapper.UnionStudent info,
+                                          StudentWrapper.UnionStudentResp studentResp, Student student) {
+
+        if (Objects.nonNull(student)) {
+
+            if (Objects.isNull(student.getUnionId())) {
+
+                // 更新学生关联Id
+                lambdaUpdate()
+                        .eq(Student::getUserId, student.getUserId())
+                        .set(Student::getUnionId, info.getUnionId())
+                        .update();
+            } else {
+                studentResp.setUnionId(student.getUnionId());
+            }
+
+            // 更新标识
+            studentResp.setUpdateFlag(true);
+        }
+    }
+
 }

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

@@ -91,7 +91,7 @@ public class UserAccountRecordServiceImpl extends ServiceImpl<UserAccountRecordD
 
     @Override
     public void updateWaitRecord() {
-        //平台账户修改
+        //老师账户修改
         List<String> paramNames = new ArrayList<>();
         paramNames.add(AccountBizTypeEnum.ACTI_REGIST_SHARE.getCode());
         paramNames.add(AccountBizTypeEnum.LIVE_SHARE.getCode());
@@ -150,7 +150,7 @@ public class UserAccountRecordServiceImpl extends ServiceImpl<UserAccountRecordD
     @Override
     public List<UserAccountRecord> selectRecordByOrderDetail(UserOrderDetailVo userOrderDetailVo) {
         List<UserAccountRecord> records = new ArrayList<>();
-        //订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ) 老师端(VIP、开通会员 PINAO_ROOM、琴房时长)
+        //订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ) 老师端(VIP、开通会员 PIANO_ROOM、琴房时长)
         //获取业务id
         List<Long> bizIds = new ArrayList<>();
         if (GoodTypeEnum.VIP.equals(userOrderDetailVo.getGoodType())){

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

@@ -391,6 +391,7 @@ public class UserAccountServiceImpl extends ServiceImpl<UserAccountDao, UserAcco
                             .subtract(total.getLiveRate())
                             .subtract(total.getVideoRate())
                             .subtract(total.getMusicRate())
+                            .subtract(total.getMusicShareRate())
                             .subtract(total.getLiveShareRate())
                             .subtract(total.getVideoShareRate())
                             .subtract(total.getAlbumShareRate())
@@ -453,7 +454,7 @@ public class UserAccountServiceImpl extends ServiceImpl<UserAccountDao, UserAcco
             platformCashAccountRecordService.mallRecordedRecord(shareDto.getProductSkuId(), shareDto.getOrderSn(), AccountBizTypeEnum.MALL.getCode());
 
         } else if (shareDto.getStatus().equals(PostStatusEnum.CANCEL)) {
-            platformCashAccountRecordService.cancelRecord(shareDto.getOrderSn(), AccountBizTypeEnum.MALL.getCode(), shareDto.getProductSkuId());
+            platformCashAccountRecordService.cancelRecord(shareDto.getOrderSn(), AccountBizTypeEnum.MALL.getCode(), shareDto.getProductSkuId(),InOrOutEnum.IN);
         }
 
         // 修改老师分润
@@ -499,7 +500,7 @@ public class UserAccountServiceImpl extends ServiceImpl<UserAccountDao, UserAcco
         }
         //平台收入
         PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(shareDto.getUserId(), expectPrice,
-                InOrOutEnum.IN, PostStatusEnum.WAIT, AccountBizTypeEnum.MALL, shareDto.getProductSkuId(), shareDto.getOrderSn(), new Date());
+                InOrOutEnum.IN, PostStatusEnum.RECORDED, AccountBizTypeEnum.MALL, shareDto.getProductSkuId(), shareDto.getOrderSn(), new Date());
 
         platformCashAccountRecordService.save(platformCashAccountRecord);
 

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

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import com.yonge.cooleshow.biz.dal.dao.CourseScheduleDao;
 import com.yonge.cooleshow.biz.dal.dao.StudentDao;
 import com.yonge.cooleshow.biz.dal.dao.SubjectDao;
@@ -13,13 +14,16 @@ import com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher;
 import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
 import com.yonge.cooleshow.biz.dal.enums.StudentCourseEnum;
 import com.yonge.cooleshow.biz.dal.queryInfo.TeacherBindingUserQueryInfo;
-import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.service.StudentAttendanceService;
+import com.yonge.cooleshow.biz.dal.service.SysConfigService;
+import com.yonge.cooleshow.biz.dal.service.UserBindingTeacherService;
 import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingCourseWrapper;
 import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingTeacherWrapper;
 import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.base.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
 import org.joda.time.DateTime;
 import org.joda.time.Period;
 import org.joda.time.PeriodType;
@@ -29,7 +33,11 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -110,8 +118,12 @@ public class UserBindingTeacherServiceImpl extends ServiceImpl<UserBindingTeache
                 subjectIdList.add(aLong);
             }
         }
-        List<Subject> subjectList = subjectDao.findBySubjectIds(subjectIdList);
+        List<Subject> subjectList = Lists.newArrayList();
+        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(subjectIdList)) {
+            subjectList.addAll(subjectDao.findBySubjectIds(subjectIdList));
+        }
         Map<Long, String> userIdSubjectMap = students.stream()
+                .filter(x -> StringUtils.isNotBlank(x.getSubjectId()))
                       .collect(Collectors.toMap(Student::getUserId,student -> subjectList.stream()
                                  .filter(subject -> student.getSubjectId().equals(subject.getId().toString())).findFirst().get().getName(), (o, n) -> n));
 
@@ -123,7 +135,7 @@ public class UserBindingTeacherServiceImpl extends ServiceImpl<UserBindingTeache
 
         for (UserBindingTeacherWrapper record : records) {
             record.setIsVip(userIdVipMap.get(record.getUserId()));
-            record.setSubjectName(userIdSubjectMap.get(record.getUserId()));
+            record.setSubjectName(userIdSubjectMap.getOrDefault(record.getUserId(), ""));
 
             List<UserBindingTeacherWrapper.CourseNum> courseNums = userIdCourseStatusMap.get(record.getUserId());
 

+ 5 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderRefundServiceImpl.java

@@ -14,6 +14,7 @@ import com.yonge.cooleshow.biz.dal.dto.search.UserOrderRefundSearch;
 import com.yonge.cooleshow.biz.dal.entity.*;
 import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
 import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
 import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
@@ -637,10 +638,13 @@ public class UserOrderRefundServiceImpl extends ServiceImpl<UserOrderRefundDao,
             if (PostStatusEnum.WAIT.equals(userAccountRecord.getPostStatus())
                     || PostStatusEnum.FROZEN.equals(userAccountRecord.getPostStatus())) {
                 userAccountService.accountChange(userAccountRecord, PostStatusEnum.CANCEL);
+                platformCashAccountRecordService.cancelRecord(userAccountRecord.getOrderNo(), userAccountRecord.getBizType().getCode(), userAccountRecord.getBizId(),
+                                                              InOrOutEnum.OUT);
             }
         }
         //处理平台入账
-        platformCashAccountRecordService.cancelRecord(vo.getOrderNo(),vo.getGoodType().getCode(),vo.getBizId());
+        platformCashAccountRecordService.cancelRecord(vo.getOrderNo(), vo.getGoodType().getCode(), vo.getBizId(),
+                                                      InOrOutEnum.IN);
     }
 
     /**

+ 63 - 57
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java

@@ -163,7 +163,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         // 专辑购买
         orderCreate.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetCheck);
         //琴房时长
-        orderCreate.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderCreate);
+        orderCreate.put(GoodTypeEnum.PIANO_ROOM, pianoRoomBuyRecordService::orderCreate);
         //活动报名
         orderCreate.put(GoodTypeEnum.ACTI_REGIST, activityPlanService::orderCreate);
 
@@ -187,7 +187,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         // 专辑购买
         orderSuccess.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetSuccess);
         //琴房时长
-        orderSuccess.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderSuccess);
+        orderSuccess.put(GoodTypeEnum.PIANO_ROOM, pianoRoomBuyRecordService::orderSuccess);
         //活动报名
         orderSuccess.put(GoodTypeEnum.ACTI_REGIST, activityPlanService::orderSuccess);
 
@@ -503,7 +503,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
     }
 
     @Transactional(rollbackFor = Exception.class)
-    void pollingCancelOrder(String orderNo) {
+    public void pollingCancelOrder(String orderNo) {
         closeOrSuccessOrder(orderNo, "订单超时");
     }
 
@@ -529,7 +529,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
             Payment queryPaymentData = res.getData();
 
             //支付成功
-            if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(queryPaymentData.getStatus())
+            if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(queryPaymentData.getStatus().getCode())
                     && (OrderStatusEnum.WAIT_PAY.equals(detail.getStatus()) || OrderStatusEnum.PAYING.equals(detail.getStatus()))) {
                 //订单已经完成,则完成订单
                 orderSuccess(detail);
@@ -538,15 +538,19 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
                 userOrderPayment.setStatus(TradeStatusEnum.succeeded);
                 userOrderPayment.setUpdateTime(new Date());
                 userOrderPayment.setArrivalTime(new Date());
-                userOrderPayment.setBackPayAmt(
-                        new BigDecimal(queryPaymentData.getPayAmt()));
+                if (queryPaymentData.getPayAmt() != null) {
+                    userOrderPayment.setBackPayAmt(new BigDecimal(queryPaymentData.getPayAmt()));
+                }
 
                 ExecutePaymentCallBack executePaymentCallBack = queryPaymentData.getExecutePaymentCallBack();
                 if (null != executePaymentCallBack) {
                     userOrderPayment.setArrivalTime(executePaymentCallBack.getTradeTime());
-                    userOrderPayment.setBackPayAmt(
-                            new BigDecimal(executePaymentCallBack.getPayAmt()));
-                    userOrderPayment.setFeeAmt(new BigDecimal(executePaymentCallBack.getFeeAmt()));
+                    if (executePaymentCallBack.getPayAmt() != null) {
+                        userOrderPayment.setBackPayAmt(
+                                new BigDecimal(executePaymentCallBack.getPayAmt()));
+                        userOrderPayment.setFeeAmt(new BigDecimal(executePaymentCallBack.getFeeAmt()));
+                    }
+
                 }
                 orderPaymentService.updateById(userOrderPayment);
             } else {
@@ -597,7 +601,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         Payment queryPaymentData = res.getData();
 
         //支付成功
-        if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(queryPaymentData.getStatus())
+        if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(queryPaymentData.getStatus().getCode())
                 && (OrderStatusEnum.WAIT_PAY.equals(detail.getStatus()) || OrderStatusEnum.PAYING.equals(detail.getStatus()))) {
             //订单已经完成,则完成订单
             orderSuccess(detail, null);
@@ -606,15 +610,18 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
             userOrderPayment.setStatus(TradeStatusEnum.succeeded);
             userOrderPayment.setUpdateTime(new Date());
             userOrderPayment.setArrivalTime(new Date());
-            userOrderPayment.setBackPayAmt(
-                    new BigDecimal(queryPaymentData.getPayAmt()));
+            if (queryPaymentData.getPayAmt() != null) {
+                userOrderPayment.setBackPayAmt(new BigDecimal(queryPaymentData.getPayAmt()));
+            }
 
             ExecutePaymentCallBack executePaymentCallBack = queryPaymentData.getExecutePaymentCallBack();
             if (null != executePaymentCallBack) {
                 userOrderPayment.setArrivalTime(executePaymentCallBack.getTradeTime());
-                userOrderPayment.setBackPayAmt(
-                        new BigDecimal(executePaymentCallBack.getPayAmt()));
-                userOrderPayment.setFeeAmt(new BigDecimal(executePaymentCallBack.getFeeAmt()));
+
+                if (executePaymentCallBack.getPayAmt() != null) {
+                    userOrderPayment.setBackPayAmt(new BigDecimal(executePaymentCallBack.getPayAmt()));
+                    userOrderPayment.setFeeAmt(new BigDecimal(executePaymentCallBack.getFeeAmt()));
+                }
             }
             orderPaymentService.updateById(userOrderPayment);
             return false;
@@ -773,7 +780,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
             configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_LIVE);
         } else if (GoodTypeEnum.MUSIC.equals(goodTypeEnum)) {
             configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_MUSIC);
-        } else if (GoodTypeEnum.PINAO_ROOM.equals(goodTypeEnum)) {
+        } else if (GoodTypeEnum.PIANO_ROOM.equals(goodTypeEnum)) {
             configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_PIANO_ROOM);
         } else if (GoodTypeEnum.ACTI_REGIST.equals(goodTypeEnum)) {
             configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_ACTI_REGIST);
@@ -897,13 +904,14 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
             orderDetailVo.setActivityId(detail.getActivityId());
             orderDetailVo.setRewardId(detail.getRewardId());
             orderDetailVo.setOrderType(detail.getOrderType());
+
+            //记录平台收入和用户分润收入(未记录卖家收益,卖家收益业务逻辑处理)
+            savePlatformAccountRecord(orderDetailVo);
             //调用业务
             Consumer<UserOrderDetailVo> userOrderVoConsumer = orderSuccess.get(orderDetailVo.getGoodType());
             if (!Objects.isNull(userOrderVoConsumer)) {
                 userOrderVoConsumer.accept(orderDetailVo);
             }
-            //记录平台收入和用户分润收入(未记录卖家收益,卖家收益业务逻辑处理)
-            savePlatformAccountRecord(orderDetailVo);
             //清除商家统计缓存
             Long merchId = orderDetailVo.getMerchId();
             if (merchId != null && merchId != 0) {
@@ -960,48 +968,46 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         }
         BigDecimal platformFee = expectPrice.multiply(platformFeeRate).setScale(2, RoundingMode.HALF_UP);
         platformFee = platformFee.subtract(orderDetailVo.getCouponAmount());
-
-        if (platformFee.compareTo(BigDecimal.ZERO) > 0) {
-            PlatformCashAccountRecord platformCashAccountRecord;
-            if (GoodTypeEnum.PINAO_ROOM.equals(orderDetailVo.getGoodType())) {
-                platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getUserId(), platformFee,
-                        InOrOutEnum.IN, PostStatusEnum.RECORDED, AccountBizTypeEnum.PIAON_ROOM, orderDetailVo.getBizId(),
-                        orderDetailVo.getOrderNo(), accountPeriodTime);
-            } else {
-                AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(orderDetailVo.getGoodType().getCode());
-                platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getUserId(), platformFee,
-                        InOrOutEnum.IN, PostStatusEnum.WAIT, bizTypeEnum, orderDetailVo.getBizId(),
-                        orderDetailVo.getOrderNo(), accountPeriodTime);
-            }
-            platformCashAccountRecordService.save(platformCashAccountRecord);
-
-            //卖家不能分润自己 买家和分润人相同,不分润
-            if (null != orderDetailVo.getRecomUserId() && orderDetailVo.getRecomUserId() != 0
-                    && !orderDetailVo.getRecomUserId().equals(orderDetailVo.getMerchId())
-                    && !orderDetailVo.getUserId().equals(orderDetailVo.getRecomUserId())) {
-                //获取分润收益费率
-                BigDecimal shareFeeRate = getShareFreeByGoodType(orderDetailVo.getGoodType()
-                        , orderDetailVo.getBizId());
-                //入老师账户
-                BigDecimal shareFee = platformFee.multiply(shareFeeRate).setScale(2, RoundingMode.HALF_UP);
-                if (shareFee.compareTo(BigDecimal.ZERO) > 0) {
-                    AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(orderDetailVo.getGoodType().getCode() + "_SHARE");
-                    if (null != bizTypeEnum) {
-                        //插入分润老师账户变更记录-分润老师预收
-                        HttpResponseResult<UserAccountRecord> recomRecordRes = userAccountService.accountRecord(
-                                new UserAccountRecordDto(orderDetailVo.getRecomUserId(), PostStatusEnum.WAIT, shareFee, InOrOutEnum.IN,
-                                        bizTypeEnum, orderDetailVo.getBizId(), bizTypeEnum.getMsg(), orderDetailVo.getOrderNo(), orderDetailVo.getUserId(), accountPeriodTime));
-                        if (recomRecordRes.getStatus()) {
-                            //插入平台预支
-                            platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getRecomUserId(), shareFee,
-                                    InOrOutEnum.OUT, PostStatusEnum.WAIT, bizTypeEnum, orderDetailVo.getBizId(), orderDetailVo.getOrderNo(), accountPeriodTime);
-                            platformCashAccountRecordService.save(platformCashAccountRecord);
-                        }
+        PlatformCashAccountRecord platformCashAccountRecord;
+        if (GoodTypeEnum.PIANO_ROOM.equals(orderDetailVo.getGoodType())) {
+            platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getUserId(), orderDetailVo.getActualPrice(),
+                                                                      InOrOutEnum.IN, PostStatusEnum.RECORDED, AccountBizTypeEnum.PIANO_ROOM, orderDetailVo.getBizId(),
+                                                                      orderDetailVo.getOrderNo(), new Date());
+        } else {
+            AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(orderDetailVo.getGoodType().getCode());
+            platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getUserId(), orderDetailVo.getActualPrice(),
+                                                                      InOrOutEnum.IN, PostStatusEnum.RECORDED, bizTypeEnum, orderDetailVo.getBizId(),
+                                                                      orderDetailVo.getOrderNo(), new Date());
+        }
+        platformCashAccountRecordService.save(platformCashAccountRecord);
+
+
+        //卖家不能分润自己 买家和分润人相同,不分润
+        if (null != orderDetailVo.getRecomUserId() && orderDetailVo.getRecomUserId() != 0
+                && !orderDetailVo.getRecomUserId().equals(orderDetailVo.getMerchId())
+                && !orderDetailVo.getUserId().equals(orderDetailVo.getRecomUserId())) {
+            //获取分润收益费率
+            BigDecimal shareFeeRate = getShareFreeByGoodType(orderDetailVo.getGoodType()
+                    , orderDetailVo.getBizId());
+            //入老师账户
+            BigDecimal shareFee = platformFee.multiply(shareFeeRate).setScale(2, RoundingMode.HALF_UP);
+            if (shareFee.compareTo(BigDecimal.ZERO) > 0) {
+                AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(orderDetailVo.getGoodType().getCode() + "_SHARE");
+                if (null != bizTypeEnum) {
+                    //插入分润老师账户变更记录-分润老师预收
+                    HttpResponseResult<UserAccountRecord> recomRecordRes = userAccountService.accountRecord(
+                            new UserAccountRecordDto(orderDetailVo.getRecomUserId(), PostStatusEnum.WAIT, shareFee, InOrOutEnum.IN,
+                                    bizTypeEnum, orderDetailVo.getBizId(), bizTypeEnum.getMsg(), orderDetailVo.getOrderNo(), orderDetailVo.getUserId(), accountPeriodTime));
+                    if (recomRecordRes.getStatus()) {
+                        //插入平台预支
+                        platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getRecomUserId(), shareFee,
+                                InOrOutEnum.OUT, PostStatusEnum.WAIT, bizTypeEnum, orderDetailVo.getBizId(), orderDetailVo.getOrderNo(), accountPeriodTime);
+                        platformCashAccountRecordService.save(platformCashAccountRecord);
                     }
                 }
             }
-
         }
+
     }
 
     /**
@@ -1083,7 +1089,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
      */
     private BigDecimal getPlatformFreeByGoodType(GoodTypeEnum goodType) {
         //会员|琴房时长,平台全额收益
-        if (GoodTypeEnum.VIP.equals(goodType) || GoodTypeEnum.PINAO_ROOM.equals(goodType)
+        if (GoodTypeEnum.VIP.equals(goodType) || GoodTypeEnum.PIANO_ROOM.equals(goodType)
                 || GoodTypeEnum.ACTI_REGIST.equals(goodType)) {
             return BigDecimal.ONE;
         }

+ 8 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/VideoLessonPurchaseRecordServiceImpl.java

@@ -74,6 +74,8 @@ public class VideoLessonPurchaseRecordServiceImpl extends ServiceImpl<VideoLesso
     @Autowired
     private MusicSheetPurchaseRecordService musicSheetPurchaseRecordService;
 
+    @Autowired
+    private PlatformCashAccountRecordService platformCashAccountRecordService;
     public VideoLessonPurchaseRecordDao getDao() {
         return videoLessonPurchaseRecordDao;
     }
@@ -240,6 +242,12 @@ public class VideoLessonPurchaseRecordServiceImpl extends ServiceImpl<VideoLesso
         userAccountService.accountRecord(
                 new UserAccountRecordDto(userOrderDetailVo.getMerchId(), PostStatusEnum.WAIT, transAmount, InOrOutEnum.IN,
                         AccountBizTypeEnum.VIDEO, lessonGroup.getId(), lessonGroup.getLessonName(), userOrderDetailVo.getOrderNo(), userOrderDetailVo.getUserId(), accountPeriodTime));
+
+        // 插入平台账户 支出
+        PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(userOrderDetailVo.getUserId(), transAmount,
+                                                                                            InOrOutEnum.OUT, PostStatusEnum.WAIT, AccountBizTypeEnum.VIDEO, lessonGroup.getId(),
+                                                                                            userOrderDetailVo.getOrderNo(), accountPeriodTime);
+        platformCashAccountRecordService.save(platformCashAccountRecord);
     }
 
     /**

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/UserOrderRefundVo.java

@@ -18,7 +18,7 @@ public class UserOrderRefundVo extends UserOrderRefund{
     @TableField(value = "order_name_")
     private String orderName;
 
-    @ApiModelProperty("订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端(VIP、开通会员 PINAO_ROOM、琴房时长)")
+    @ApiModelProperty("订单类型: 学生端( VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名) 老师端(VIP、开通会员 PIANO_ROOM、琴房时长)")
     @TableField(value = "order_type_")
     private OrderTypeEnum orderType;
 

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/activity/UserRewardWrapper.java

@@ -21,7 +21,7 @@ public class UserRewardWrapper {
     // ("奖品名称 ")
     private String rewardName;
 
-     // ("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIAMO_ROOM 琴房时长 COUPON(优惠券)")
+     // ("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIANO_ROOM 琴房时长 COUPON(优惠券)")
     private RewardTypeEnum rewardType;
 
     // ("奖品描述 ")

+ 77 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/StudentWrapper.java

@@ -0,0 +1,77 @@
+package com.yonge.cooleshow.biz.dal.wrapper;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 学生封装类
+ * Created by Eric.Shang on 2023/1/6.
+ */
+public class StudentWrapper {
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("学生帐号关联")
+    public static class UnionStudent implements Serializable {
+
+        @ApiModelProperty("帐号关联Id")
+        private Long unionId;
+
+        @ApiModelProperty("授权Token")
+        private String token;
+
+        @ApiModelProperty("联系方式")
+        private String mobile;
+
+        @ApiModelProperty("声部名称")
+        private String subjectName;
+
+        @ApiModelProperty("用户名")
+        private String username;
+
+        @ApiModelProperty("性别(0,女  1,男)")
+        private Integer gender;
+
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("帐号关联响应")
+    public static class UnionStudentResp implements Serializable {
+
+        @ApiModelProperty("帐号关联Id")
+        private Long unionId;
+
+        @ApiModelProperty("联系方式")
+        private String mobile;
+
+        @ApiModelProperty("用户Id")
+        private Long userId;
+
+        @ApiModelProperty("用户名")
+        private String username;
+
+        @ApiModelProperty("更新标识")
+        private Boolean updateFlag;
+
+        public UnionStudentResp userId(Long userId) {
+            this.userId = userId;
+            return this;
+        }
+
+        public UnionStudentResp username(String username) {
+            this.username = username;
+            return this;
+        }
+    }
+}

+ 22 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerService.java

@@ -1,10 +1,12 @@
 package com.yonge.cooleshow.biz.dal.wrapper.im;
 
 import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
 
 import java.io.Serializable;
 import java.util.List;
@@ -25,6 +27,9 @@ public class CustomerService {
     public static class NotifyMessage implements Serializable {
 
         private List<String> receives;
+        private ClientEnum clientType;
+        private String subjectId;
+        private List<String> subjectIds;
 
         private String title;
         private String txtMessage;
@@ -35,5 +40,22 @@ public class CustomerService {
 
             return JSON.parseObject(recv, NotifyMessage.class);
         }
+
+        public List<String> getReceives() {
+            if (CollectionUtils.isEmpty(receives)) {
+                return null;
+            }
+            return receives;
+        }
+    }
+
+    /**
+     * 消息接收者
+     */
+    @Data
+    public static class MessageReceives implements Serializable {
+
+        private Long userId;
+        private String nickname;
     }
 }

+ 206 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerServiceBatchSendingWrapper.java

@@ -0,0 +1,206 @@
+package com.yonge.cooleshow.biz.dal.wrapper.im;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.biz.dal.enums.im.EImReceiveType;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendStatus;
+import com.yonge.cooleshow.biz.dal.enums.im.EImSendType;
+import com.yonge.toolset.base.page.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 客服群发
+ * 2022-12-09 10:49:10
+ */
+@ApiModel(value = "CustomerServiceBatchSendingWrapper对象", description = "客服群发查询对象")
+public class CustomerServiceBatchSendingWrapper {
+
+    @Data
+	@Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" CustomerServiceBatchSendingQuery-客服群发")
+    public static class CustomerServiceBatchSendingQuery extends QueryInfo {
+    
+        @ApiModelProperty("关键字匹配")
+		private String keyword;
+
+        @ApiModelProperty("发送声部")
+        private String sendSubject;
+
+        @ApiModelProperty("发送群体")
+        private String targetGroup;
+
+        @ApiModelProperty("发送方式")
+        private EImSendType sendType;
+
+        @ApiModelProperty("创建开始时间")
+        private Date startTime;
+
+        @ApiModelProperty("创建结束时间")
+        private Date endTime;
+
+        @ApiModelProperty("发送开始时间")
+        private Date sendStartTime;
+
+        @ApiModelProperty("发送结束时间")
+        private Date sendEndTime;
+
+        @ApiModelProperty("发送状态")
+        private EImSendStatus sendStatus;
+
+        @ApiModelProperty("发送用户ID")
+        private Long sendId;
+
+        @ApiModelProperty(value = "声部", hidden = true)
+        private List<String> subjectIds;
+
+        @ApiModelProperty(value = "用户身份", hidden = true)
+        private List<String> clientTypes;
+        
+        public String getKeyword() {
+            return Optional.ofNullable(keyword).filter(StringUtils::isNotBlank).orElse(null);
+        }
+
+        public List<String> getSubjectIds() {
+            if (StringUtils.isNotBlank(getSendSubject())) {
+                return Arrays.stream(getSendSubject().split(",")).collect(Collectors.toList());
+            }
+            return subjectIds;
+        }
+
+        public List<String> getClientTypes() {
+            if (StringUtils.isNotBlank(getTargetGroup())) {
+                return Arrays.stream(getTargetGroup().split(",")).collect(Collectors.toList());
+            }
+            return clientTypes;
+        }
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceBatchSendingQuery from(String json) {
+            return JSON.parseObject(json, CustomerServiceBatchSendingQuery.class);
+        }
+    }  
+
+    @Data
+	@ApiModel(" CustomerServiceBatchSending-客服群发")
+    public static class CustomerServiceBatchSending {
+
+        @ApiModelProperty("主键ID")
+        private Long id;
+
+        @ApiModelProperty("目标群体")
+        private String targetGroup;
+
+        @ApiModelProperty("发送声部")
+        private String sendSubject;
+
+        @ApiModelProperty("发送人数")
+        private Integer sendNumber;
+
+        @ApiModelProperty("接收人数")
+        private Integer receiveNumber;
+
+        @ApiModelProperty("目标人群")
+        private EImReceiveType receiveType;
+
+        @ApiModelProperty("发送方式")
+        private EImSendType sendType;
+
+        @ApiModelProperty("发送状态")
+        private EImSendStatus sendStatus;
+
+        @ApiModelProperty("发送时间")
+        private Date sendTime;
+
+        @ApiModelProperty("消息标题")
+        private String condition;
+
+        @ApiModelProperty("消息标题")
+        private String title;
+
+        @ApiModelProperty("文本消息")
+        private String textMessage;
+
+        @ApiModelProperty("图片消息")
+        private String imgMessage;
+
+        @ApiModelProperty("图片地址")
+        private String imgUrl;
+
+        @ApiModelProperty("客户ID")
+        private Long senderId;
+
+        @ApiModelProperty("创建用户")
+        private Long createBy;
+
+        @ApiModelProperty("创建时间")
+        private Date createTime;
+
+        @ApiModelProperty("创建用户")
+        private String createUser;
+
+        @ApiModelProperty("目标人群")
+        private List<CustomerServiceReceiveWrapper.CustomerServiceReceive> receives;
+
+        @ApiModelProperty("声部名称")
+        private String subjectName;
+
+        @ApiModelProperty("目标群体名称")
+        private String targetGroupName;
+
+        @ApiModelProperty("客服人员")
+        private String sender;
+        @ApiModelProperty("客服联系方式")
+        private String mobile;
+        
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceBatchSending from(String json) {
+            return JSON.parseObject(json, CustomerServiceBatchSending.class);
+        }
+
+
+        public CustomerServiceBatchSending targetGroup(String targetGroup) {
+            this.targetGroup = targetGroup;
+            return this;
+        }
+
+        public CustomerServiceBatchSending sendSubject(String sendSubject) {
+            this.sendSubject = sendSubject;
+            return this;
+        }
+
+        public CustomerServiceBatchSending createUser(String createUser) {
+            this.createUser = createUser;
+            return this;
+        }
+
+        public CustomerServiceBatchSending sender(String sender) {
+            this.sender = sender;
+            return this;
+        }
+
+        public CustomerServiceBatchSending mobile(String mobile) {
+            this.mobile = mobile;
+            return this;
+        }
+    }
+
+}

+ 83 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerServiceReceiveWrapper.java

@@ -0,0 +1,83 @@
+package com.yonge.cooleshow.biz.dal.wrapper.im;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.toolset.base.page.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Date;
+import java.util.Optional;
+
+/**
+ * 客服群发接收
+ * 2022-12-09 10:49:10
+ */
+@ApiModel(value = "CustomerServiceReceiveWrapper对象", description = "客服群发接收查询对象")
+public class CustomerServiceReceiveWrapper {
+
+    @Data
+	@Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" CustomerServiceReceiveQuery-客服群发接收")
+    public static class CustomerServiceReceiveQuery extends QueryInfo {
+    
+        @ApiModelProperty("关键字匹配")
+		private String keyword;
+
+        @ApiModelProperty("群发消息ID")
+        private Long batchSendingId;
+        
+        public String getKeyword() {
+            return Optional.ofNullable(keyword).filter(StringUtils::isNotBlank).orElse(null);
+        }
+        
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceReceiveQuery from(String json) {
+            return JSON.parseObject(json, CustomerServiceReceiveQuery.class);
+        }
+    }  
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+	@ApiModel(" CustomerServiceReceive-客服群发接收")
+    public static class CustomerServiceReceive {
+
+        @ApiModelProperty("主键ID")
+        private Long id;
+
+        @ApiModelProperty("群发消息ID")
+        private Long batchSendingId;
+
+        @ApiModelProperty("用户ID")
+        private Long userId;
+
+        @ApiModelProperty("用户身份")
+        private String clientType;
+
+        @ApiModelProperty("创建时间")
+        private Date createTime;
+
+        @ApiModelProperty("用户名称")
+        private String userName;
+        
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static CustomerServiceReceive from(String json) {
+            return JSON.parseObject(json, CustomerServiceReceive.class);
+        }
+	}
+
+}

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

@@ -0,0 +1,74 @@
+<?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.yonge.cooleshow.biz.dal.mapper.CustomerServiceBatchSendingMapper">
+
+	 
+    
+    <!-- 表字段 -->
+    <sql id="baseColumns">
+         t.id_ AS id
+        , t.target_group_ AS targetGroup
+        , t.send_subject_ AS sendSubject
+        , t.send_number_ AS sendNumber
+        , t.receive_number_ AS receiveNumber
+        , t.receive_type_ AS receiveType
+        , t.send_type_ AS sendType
+        , t.send_status_ AS sendStatus
+        , t.send_time_ AS sendTime
+        , t.condition_ AS `condition`
+        , t.title_ AS title
+        , t.text_message_ AS textMessage
+        , t.img_message_ AS imgMessage
+        , t.img_url_ AS imgUrl
+        , t.sender_id_ AS senderId
+        , t.create_by_ AS createBy
+        , t.create_time_ AS createTime
+    </sql>
+    
+    <select id="selectPage" resultType="com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceBatchSendingWrapper$CustomerServiceBatchSending">
+		SELECT         
+        	<include refid="baseColumns" />
+		FROM customer_service_batch_sending t
+		<where>
+            <if test="param.keyword != null">
+                AND t.id_ = #{param.keyword}
+            </if>
+		    <if test="param.sendSubject != null">
+                AND FIND_IN_SET(#{param.sendSubject}, t.send_subject_)
+            </if>
+		    <if test="param.targetGroup != null">
+                AND FIND_IN_SET(#{param.targetGroup}, t.target_group_)
+            </if>
+		    <if test="param.sendType != null">
+                AND t.send_type_ = #{param.sendType}
+            </if>
+		    <if test="param.sendStatus != null">
+                AND t.send_status_ = #{param.sendStatus}
+            </if>
+            <if test="param.startTime != null and param.endTime != null">
+                AND (#{param.startTime} &lt;= t.create_time_ AND t.create_time_ &lt;= #{param.endTime})
+            </if>
+		    <if test="param.sendStartTime != null and param.sendEndTime != null">
+                AND (#{param.sendStartTime} &lt;= t.send_time_ AND t.send_time_ &lt;= #{param.sendEndTime})
+            </if>
+        </where>
+        ORDER BY t.id_ DESC
+	</select>
+
+    <!--客服消息接收者-->
+    <select id="selectMessageReceives"
+            resultType="com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService$MessageReceives">
+        SELECT t1.id_ AS userId, t1.username_ FROM sys_user t1
+        <if test="param.clientType != null">
+            <if test="param.clientType.code == 'TEACHER'"> LEFT JOIN teacher t2 ON (t1.id_ = t2.user_id_)</if>
+            <if test="param.clientType.code == 'STUDENT'"> LEFT JOIN student t2 ON (t1.id_ = t2.user_id_)</if>
+        </if>
+        <where>
+            <if test="param.subjectIds != null">
+                AND (<foreach collection="param.subjectIds" separator="OR" item="item"> FIND_IN_SET(#{item}, t2.subject_id_) </foreach>)
+            </if>
+        </where>
+    </select>
+    <!--客服消息接收者-->
+
+</mapper>

+ 28 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/CustomerServiceReceiveMapper.xml

@@ -0,0 +1,28 @@
+<?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.yonge.cooleshow.biz.dal.mapper.CustomerServiceReceiveMapper">
+
+	 
+    
+    <!-- 表字段 -->
+    <sql id="baseColumns">
+         t.id_ AS id
+        , t.batch_sending_id_ AS batchSendingId
+        , t.user_id_ AS userId
+        , t.client_type_ AS clientType
+        , t.create_time_ AS createTime
+    </sql>
+    
+    <select id="selectPage" resultType="com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper$CustomerServiceReceive">
+		SELECT         
+        	<include refid="baseColumns" />
+		FROM customer_service_receive t
+		<where>
+            <if test="param.batchSendingId != null">
+                AND t.batch_sending_id_ = #{param.batchSendingId}
+            </if>
+        </where>
+        ORDER BY t.id_ DESC
+	</select>
+    
+</mapper>

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

@@ -171,8 +171,8 @@
     <select id="selectFavoriteNumAndMusicNum" resultType="com.yonge.cooleshow.biz.dal.vo.MusicAlbumVo">
         select
         t.id_ as id,
-        t1.num as musicSheetCount
-        ,t2.num as albumFavoriteCount
+        ifnull(t1.num,0) as musicSheetCount
+        ,ifnull(t2.num,0) as albumFavoriteCount
         from music_album t
         left join (select count(1) as num,amr.album_id_
             from album_music_relate amr

+ 16 - 1
cooleshow-user/user-biz/src/main/resources/config/mybatis/MusicSheetMapper.xml

@@ -35,6 +35,8 @@
         <result column="accompaniment_type_" jdbcType="VARCHAR" property="accompanimentType"/>
         <result column="title_img_" jdbcType="VARCHAR" property="titleImg"/>
         <result column="music_img_" jdbcType="VARCHAR" property="musicImg"/>
+        <result column="first_tone_" jdbcType="VARCHAR" property="firstTone"/>
+        <result column="fixed_tone_" jdbcType="VARCHAR" property="fixedTone"/>
     </resultMap>
 
     <sql id="Base_Column_List">
@@ -75,10 +77,16 @@
         t.submit_audit_time_ as submitAuditTime,
         t.accompaniment_type_ as accompanimentType,
         t.remark_ as remark,
+        t.first_tone_ as firstTone,
+        t.fixed_tone_ as fixedTone,
         t.title_img_ as titleImg,
         t.reason_ as reason,
         t.music_img_ as musicImg,
-        t.notation_ as notation
+        t.notation_ as notation,
+        t.music_json_ as musicJSON,
+        t.music_svg_ as musicSvg,
+        t.music_jian_svg_ as musicJianSvg,
+        t.music_first_svg_ as musicFirstSvg
     </sql>
 
     <select id="selectPage" resultType="com.yonge.cooleshow.biz.dal.vo.MusicSheetVo">
@@ -97,6 +105,9 @@
             <if test="param.auditVersion != null ">
                 and #{param.auditVersion} = t.audit_version_
             </if>
+            <if test="param.dataRecovery != null">
+                AND (t.music_svg_ = '' OR t.music_svg_ IS NULL OR t.music_first_svg_ = '' OR t.music_first_svg_ IS NULL OR t.music_jian_svg_ = '' OR t.music_jian_svg_ IS NULL)
+            </if>
         </where>
         order by
         <if test="param.myself == null or param.myself == false ">
@@ -303,6 +314,10 @@
         <result column="auditName" jdbcType="VARCHAR" property="auditName"/>
         <result column="auditReason" jdbcType="VARCHAR" property="auditReason"/>
         <result column="aiDefaultFrequency" jdbcType="VARCHAR" property="aiDefaultFrequency"/>
+        <result column="musicJSON" jdbcType="VARCHAR" property="musicJSON"/>
+        <result column="musicSvg" jdbcType="VARCHAR" property="musicSvg"/>
+        <result column="musicJianSvg" jdbcType="VARCHAR" property="musicJianSvg"/>
+        <result column="musicFirstSvg" jdbcType="VARCHAR" property="musicFirstSvg"/>
         <collection property="background" ofType="com.yonge.cooleshow.biz.dal.entity.MusicSheetAccompaniment">
             <id column="accompanimentId" jdbcType="BIGINT" property="id"/>
             <result column="accompanimentMusicSheetId" jdbcType="BIGINT" property="musicSheetId"/>

+ 3 - 3
cooleshow-user/user-biz/src/main/resources/config/mybatis/PlatformCashAccountRecordMapper.xml

@@ -161,12 +161,12 @@
 
     <update id="cancelRecord">
 		update platform_cash_account_record set post_status_ = 'CANCEL'
-		where post_status_ = 'WAIT' and order_no_ = #{orderNo} and biz_id_ = #{bizId}
-		and biz_type_ = #{bizType}
+		where  order_no_ = #{orderNo} and biz_id_ = #{bizId}
+		and biz_type_ = #{bizType} and in_or_out_ = #{type}
 	</update>
 
     <update id="mallRecordedRecord">
 		update platform_cash_account_record set post_status_ = 'RECORDED'
-		where post_status_ = 'WAIT' and order_no_ = #{orderNo} and biz_id_ = #{bizId}
+		where order_no_ = #{orderNo} and biz_id_ = #{bizId}
 	</update>
 </mapper>

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

@@ -180,7 +180,7 @@
                             GROUP BY a.lesson_subject_
                         )
                     </if>
-                    <if test="type == null or type =='PINAO_ROOM'">
+                    <if test="type == null or type =='PIANO_ROOM'">
                         union all
                         (
                             select

+ 6 - 2
cooleshow-user/user-biz/src/main/resources/config/mybatis/SubjectMapper.xml

@@ -49,7 +49,7 @@
                     where a.audit_status_ = 'PASS' and a.shelves_flag_ = 1
                     GROUP BY a.lesson_subject_)
                 </if>
-                <if test="type == null or type =='PINAO_ROOM'">
+                <if test="type == null or type =='PIANO_ROOM'">
                     union all
                     (select a.subject_id_ as subject_id_ from course_group a
                     where a.type_ = 'PIANO_ROOM_CLASS' and a.status_ in ('ING','COMPLETE','APPLY')
@@ -200,6 +200,10 @@
         where  t.id_ = #{id}
     </select>
 
-
+    <!--声部模糊匹配-->
+    <select id="getSubjectMatchByName" resultType="com.yonge.cooleshow.biz.dal.entity.Subject">
+        SELECT * FROM subject WHERE del_flag_ = 0 and name_ LIKE CONCAT('%', #{name}, '%') LIMIT 1
+    </select>
+    <!--声部模糊匹配-->
 
 </mapper>

+ 20 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/SysUserMapper.xml

@@ -85,4 +85,24 @@
         update_time_ = now()
         WHERE del_flag_ = 0 and id_ = #{param.userId}
     </update>
+
+    <!--客服消息接收者-->
+    <select id="selectMessageReceives"
+            resultType="com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService$MessageReceives">
+        SELECT t1.id_ AS userId, t1.username_ FROM sys_user t1
+        <if test="param.clientType != null">
+            <if test="param.clientType.code == 'TEACHER'"> LEFT JOIN teacher t2 ON (t1.id_ = t2.user_id_)</if>
+            <if test="param.clientType.code == 'STUDENT'"> LEFT JOIN student t2 ON (t1.id_ = t2.user_id_)</if>
+        </if>
+        <where>
+            <if test="param.receives != null">
+                AND t1.phone_ IN (<foreach collection="param.receives" separator="," item="item">#{item}</foreach>)
+            </if>
+            <if test="param.subjectId != null">
+                AND FIND_IN_SET(#{param.subjectId}, t2.subject_id_)
+            </if>
+        </where>
+        LIMIT 1500
+    </select>
+    <!--客服消息接收者-->
 </mapper>

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

@@ -242,7 +242,7 @@
                         union all
                         (select lesson_subject_ as subject_id_ from video_lesson_group where teacher_id_ = #{userId} GROUP BY lesson_subject_)
                     </if>
-                    <if test="type == null or type =='PINAO_ROOM'">
+                    <if test="type == null or type =='PIANO_ROOM'">
                         union all
                         (select subject_id_ as subject_id_ from course_group where type_ = 'PIANO_ROOM_CLASS' and teacher_id_ = #{userId} GROUP BY subject_id_)
                     </if>

+ 38 - 6
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/MusicSheetController.java

@@ -1,14 +1,15 @@
 package com.yonge.cooleshow.student.controller;
 
-import com.yonge.cooleshow.biz.dal.dto.AppMusicSheetVo;
-import com.yonge.cooleshow.biz.dal.enums.MusicSortType;
-import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Optional;
+
 import javax.validation.Valid;
 
 import org.apache.commons.lang3.StringUtils;
@@ -25,13 +26,18 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.dto.RealnameAuthReq;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dto.AppMusicSheetVo;
+import com.yonge.cooleshow.biz.dal.dto.MusicSheetRenderDto;
 import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.MusicSheetRelatedQueryInfo;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicSheetSearch;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
 import com.yonge.cooleshow.biz.dal.entity.Student;
 import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.MusicSortType;
 import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.AppVersionInfoService;
 import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
 import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
@@ -50,9 +56,6 @@ import com.yonge.toolset.base.util.StringUtil;
 import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.toolset.utils.idcard.IdcardInfoExtractor;
 
-import java.util.ArrayList;
-import java.util.Optional;
-
 /**
  * 曲谱表 web 控制层
  * @author yzp
@@ -132,6 +135,35 @@ public class MusicSheetController extends BaseController {
         return succeed(PageUtil.pageInfo(musicSheetVoIPage));
     }
 
+    @ApiOperation(value = "修改", httpMethod="POST", consumes="application/json", produces="application/json")
+    @PostMapping(value="/updateRenderFile", consumes="application/json", produces="application/json")
+    public HttpResponseResult<Object> updateRenderFile(@Valid @RequestBody MusicSheetRenderDto musicSheetRenderDto) {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null  || sysUser.getId() == null) {
+            return failed("用户信息获取失败");
+        }
+        if (musicSheetRenderDto.getMusicSheetId()==null){
+            return failed("缺少ID");
+        }
+        MusicSheet musicSheet = musicSheetService.getById(musicSheetRenderDto.getMusicSheetId());
+        
+        if(musicSheet == null){
+        	return failed("参数异常");
+        }
+        musicSheet.setMusicFirstSvg(musicSheetRenderDto.getMusicFirstSvg());
+        musicSheet.setMusicJianSvg(musicSheetRenderDto.getMusicJianSvg());
+        musicSheet.setMusicJSON(musicSheetRenderDto.getMusicJSON());
+        musicSheet.setMusicSvg(musicSheetRenderDto.getMusicSvg());
+
+        musicSheet.setUpdateBy(sysUser.getId());
+        musicSheet.setUpdateTime(new Date());
+        if ( musicSheetService.updateById(musicSheet)){
+            return succeed("修改成功");
+        } else {
+            return failed("修改失败");
+        }
+    }
+
     @ApiOperation(value = "乐谱(专辑和曲目同时查询)分页查询", httpMethod="POST", consumes="application/json", produces="application/json")
     @PostMapping(value="/albumAndSheetList", consumes="application/json", produces="application/json")
     public HttpResponseResult<AlbumAndSheetVo> albumAndSheetList(@RequestBody StudentMusicSheetSearch query) {

+ 1 - 1
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/StudentController.java

@@ -102,7 +102,7 @@ public class StudentController extends BaseController {
     @ApiOperation(value = "获取声部搜索下拉框")
     @PostMapping("/querySubjectItem")
     public HttpResponseResult<List<Subject>> querySubjectItem(
-            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type) {
+            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {
             return failed(HttpStatus.FORBIDDEN, "请登录");

+ 1 - 1
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/SubjectController.java

@@ -43,7 +43,7 @@ public class SubjectController extends BaseController {
     @ApiOperation(value = "获取声部")
     @GetMapping("/subjectSelect")
     public HttpResponseResult<List<Subject>> subjectSelect(
-            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type) {
+            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type) {
     	
     	String userExtSubjectIds = null;
         

+ 26 - 21
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/open/OpenClient.java

@@ -1,26 +1,37 @@
 package com.yonge.cooleshow.student.controller.open;
 
+import com.ksyun.ks3.dto.PostObjectFormFields;
+import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dto.MusicImgDto;
 import com.yonge.cooleshow.biz.dal.dto.search.MemberPriceSettingsSearch;
 import com.yonge.cooleshow.biz.dal.entity.SysConfig;
-import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
+import com.yonge.cooleshow.biz.dal.service.AppVersionInfoService;
+import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
+import com.yonge.cooleshow.biz.dal.service.MemberPriceSettingsService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
+import com.yonge.cooleshow.biz.dal.service.StudentService;
+import com.yonge.cooleshow.biz.dal.service.SysConfigService;
+import com.yonge.cooleshow.biz.dal.service.TeacherService;
+import com.yonge.cooleshow.biz.dal.service.UploadFileService;
 import com.yonge.cooleshow.biz.dal.vo.CheckVo;
 import com.yonge.cooleshow.biz.dal.vo.MemberPriceVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicActivityVo;
+import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
 import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.cooleshow.student.io.request.LiveRoomVO;
+import com.yonge.toolset.base.util.StringUtil;
+import com.yonge.toolset.thirdparty.entity.UploadSign;
+import com.yonge.toolset.utils.string.ValueUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-import javax.validation.Valid;
-
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -31,17 +42,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import com.ksyun.ks3.dto.PostObjectFormFields;
-import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
-import com.yonge.cooleshow.auth.api.entity.SysUser;
-import com.yonge.cooleshow.biz.dal.dto.MusicImgDto;
-import com.yonge.cooleshow.biz.dal.vo.MusicActivityVo;
-import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
-import com.yonge.cooleshow.common.controller.BaseController;
-import com.yonge.cooleshow.common.entity.HttpResponseResult;
-import com.yonge.toolset.base.util.StringUtil;
-import com.yonge.toolset.thirdparty.entity.UploadSign;
-import com.yonge.toolset.utils.string.ValueUtil;
+import javax.validation.Valid;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
 
 @RestController
@@ -119,7 +124,7 @@ public class OpenClient extends BaseController {
     @ApiOperation(value = "新增曲谱渲染图")
     @PostMapping(value="/music/sheet/img")
     public HttpResponseResult<Boolean> img(@RequestBody @Valid MusicImgDto musicImgDto) {
-        return succeed(musicSheetService.updateMusicImg(musicImgDto.getMusicImg(),musicImgDto.getMusicSheetId()));
+        return succeed(musicSheetService.updateMusicImg(musicImgDto, musicImgDto.getMusicSheetId()));
     }
 
 

+ 1 - 1
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/io/request/ActivityVo.java

@@ -74,7 +74,7 @@ public class ActivityVo {
         @ApiModelProperty("奖品名称 ")
         private String rewardName;
 
-        @ApiModelProperty("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIAMO_ROOM 琴房时长 COUPON(优惠券)")
+        @ApiModelProperty("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIANO_ROOM 琴房时长 COUPON(优惠券)")
         private RewardTypeEnum rewardType;
 
         @ApiModelProperty("奖品描述 ")

+ 35 - 6
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/MusicSheetController.java

@@ -1,11 +1,5 @@
 package com.yonge.cooleshow.teacher.controller;
 
-import com.yonge.cooleshow.biz.dal.dto.AppMusicSheetVo;
-import com.yonge.cooleshow.biz.dal.entity.Student;
-import com.yonge.cooleshow.biz.dal.enums.MusicSortType;
-import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
-import com.yonge.cooleshow.common.enums.EStatus;
-import com.yonge.toolset.base.page.QueryInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -29,7 +23,9 @@ import org.springframework.web.bind.annotation.RestController;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dto.AppMusicSheetVo;
 import com.yonge.cooleshow.biz.dal.dto.MusicSheetDto;
+import com.yonge.cooleshow.biz.dal.dto.MusicSheetRenderDto;
 import com.yonge.cooleshow.biz.dal.dto.search.MusicSheetRelatedQueryInfo;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicSheetSearch;
 import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
@@ -37,7 +33,9 @@ import com.yonge.cooleshow.biz.dal.entity.Teacher;
 import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.MusicSortType;
 import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.AppVersionInfoService;
 import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
 import com.yonge.cooleshow.biz.dal.service.TeacherService;
@@ -46,8 +44,10 @@ import com.yonge.cooleshow.biz.dal.vo.MusicSheetShareVo;
 import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.EStatus;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.page.PageInfo;
+import com.yonge.toolset.base.page.QueryInfo;
 import com.yonge.toolset.base.util.StringUtil;
 import com.yonge.toolset.mybatis.support.PageUtil;
 
@@ -96,6 +96,35 @@ public class MusicSheetController extends BaseController {
         return succeed(detail);
     }
 
+    @ApiOperation(value = "修改", httpMethod="POST", consumes="application/json", produces="application/json")
+    @PostMapping(value="/updateRenderFile", consumes="application/json", produces="application/json")
+    public HttpResponseResult<Object> updateRenderFile(@Valid @RequestBody MusicSheetRenderDto musicSheetRenderDto) {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null  || sysUser.getId() == null) {
+            return failed("用户信息获取失败");
+        }
+        if (musicSheetRenderDto.getMusicSheetId()==null){
+            return failed("缺少ID");
+        }
+        MusicSheet musicSheet = musicSheetService.getById(musicSheetRenderDto.getMusicSheetId());
+        
+        if(musicSheet == null){
+        	return failed("参数异常");
+        }
+        musicSheet.setMusicFirstSvg(musicSheetRenderDto.getMusicFirstSvg());
+        musicSheet.setMusicJianSvg(musicSheetRenderDto.getMusicJianSvg());
+        musicSheet.setMusicJSON(musicSheetRenderDto.getMusicJSON());
+        musicSheet.setMusicSvg(musicSheetRenderDto.getMusicSvg());
+
+        musicSheet.setUpdateBy(sysUser.getId());
+        musicSheet.setUpdateTime(new Date());
+        if ( musicSheetService.updateById(musicSheet)){
+            return succeed("修改成功");
+        } else {
+            return failed("修改失败");
+        }
+    }
+
 	@ApiOperation(value = "新增", httpMethod="POST", consumes="application/json", produces="application/json")
     @PostMapping(value="/create", consumes="application/json", produces="application/json")
     public HttpResponseResult<Object> create(@Valid @RequestBody MusicSheetDto musicSheetDto) {

+ 1 - 1
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/SubjectController.java

@@ -42,7 +42,7 @@ public class SubjectController extends BaseController {
 	@ApiOperation(value = "获取声部")
 	@GetMapping("/subjectSelect")
     public HttpResponseResult<List<Subject>> subjectSelect(
-			@ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type){
+			@ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type){
 		
 		String userExtSubjectIds = null;
         

+ 3 - 3
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherController.java

@@ -96,7 +96,7 @@ public class TeacherController extends BaseController {
     @ApiOperation(value = "获取声部搜索下拉框")
     @PostMapping("/querySubjectItem")
     public HttpResponseResult<List<Subject>> querySubjectItem(
-            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type) {
+            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {
             return failed(HttpStatus.FORBIDDEN, "请登录");
@@ -147,13 +147,13 @@ public class TeacherController extends BaseController {
      */
     @PostMapping("/defaultSubject")
     @ApiOperation(value = "设置老师默认查询声部")
-    public HttpResponseResult defaultSubject(@RequestParam Long subjectId) {
+    public HttpResponseResult defaultSubject(@RequestParam(required = false) Long subjectId) {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         if (sysUser == null  || sysUser.getId() == null) {
             return failed("用户信息获取失败");
         }
         if (subjectId == null) {
-            return failed("声部id不能为空");
+            return succeed();
         }
         Teacher teacher = new Teacher();
         teacher.setUserId(sysUser.getId());

+ 16 - 4
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/open/OpenShareController.java

@@ -7,20 +7,32 @@ import com.yonge.cooleshow.biz.dal.dto.MusicImgDto;
 import com.yonge.cooleshow.biz.dal.dto.search.ShareProfitParam;
 import com.yonge.cooleshow.biz.dal.entity.SysConfig;
 import com.yonge.cooleshow.biz.dal.entity.Teacher;
-import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
+import com.yonge.cooleshow.biz.dal.service.AppVersionInfoService;
+import com.yonge.cooleshow.biz.dal.service.CourseGroupService;
+import com.yonge.cooleshow.biz.dal.service.MemberPriceSettingsService;
+import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
+import com.yonge.cooleshow.biz.dal.service.SysConfigService;
+import com.yonge.cooleshow.biz.dal.service.TeacherService;
+import com.yonge.cooleshow.biz.dal.service.VideoLessonGroupService;
 import com.yonge.cooleshow.biz.dal.vo.CheckVo;
 import com.yonge.cooleshow.biz.dal.vo.MusicActivityVo;
 import com.yonge.cooleshow.biz.dal.vo.ShareProfitVo;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
-import com.yonge.cooleshow.common.enums.ActivityShareEnum;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
@@ -65,7 +77,7 @@ public class OpenShareController extends BaseController {
     @ApiOperation(value = "新增曲谱渲染图")
     @PostMapping(value="/music/sheet/img")
     public HttpResponseResult<Boolean> img(@RequestBody @Valid MusicImgDto musicImgDto) {
-        return succeed(musicSheetService.updateMusicImg(musicImgDto.getMusicImg(),musicImgDto.getMusicSheetId()));
+        return succeed(musicSheetService.updateMusicImg(musicImgDto, musicImgDto.getMusicSheetId()));
     }
 
     /**

+ 1 - 1
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/io/request/ActivityVo.java

@@ -73,7 +73,7 @@ public class ActivityVo {
         @ApiModelProperty("奖品名称 ")
         private String rewardName;
 
-        @ApiModelProperty("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIAMO_ROOM 琴房时长 COUPON(优惠券)")
+        @ApiModelProperty("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIANO_ROOM 琴房时长 COUPON(优惠券)")
         private RewardTypeEnum rewardType;
 
         @ApiModelProperty("奖品描述 ")

+ 1 - 1
cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/StudentController.java

@@ -74,7 +74,7 @@ public class StudentController extends BaseController {
     @ApiOperation(value = "获取声部搜索下拉框")
     @PostMapping("/querySubjectItem")
     public HttpResponseResult<List<Subject>> querySubjectItem(
-            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type) {
+            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {
             return failed(HttpStatus.FORBIDDEN, "请登录");

+ 1 - 1
cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/TeacherController.java

@@ -83,7 +83,7 @@ public class TeacherController extends BaseController {
     @ApiOperation(value = "获取声部搜索下拉框")
     @PostMapping("/querySubjectItem")
     public HttpResponseResult<List<Subject>> querySubjectItem(
-            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type) {
+            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {
             return failed(HttpStatus.FORBIDDEN, "请登录");

+ 15 - 5
cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/open/OpenMusicSheetController.java

@@ -13,18 +13,28 @@ import com.yonge.cooleshow.biz.dal.enums.HotSearchEnum;
 import com.yonge.cooleshow.biz.dal.service.HotSearchService;
 import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
 import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
-import com.yonge.cooleshow.common.enums.YesOrNoEnum;
-import com.yonge.toolset.mybatis.support.PageUtil;
-import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.vo.AlbumAndSheetVo;
+import com.yonge.cooleshow.biz.dal.vo.HotSearchVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicAlbumVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
+import com.yonge.cooleshow.biz.dal.vo.MusicSheetWebsiteDetailVo;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.page.PageInfo;
+import com.yonge.toolset.mybatis.support.PageUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
 import java.util.List;
@@ -145,7 +155,7 @@ public class OpenMusicSheetController extends BaseController {
     @ApiOperation(value = "新增曲谱渲染图")
     @PostMapping(value="/img")
     public HttpResponseResult<Boolean> img(@RequestBody @Valid MusicImgDto musicImgDto) {
-        return succeed(musicSheetService.updateMusicImg(musicImgDto.getMusicImg(),musicImgDto.getMusicSheetId()));
+        return succeed(musicSheetService.updateMusicImg(musicImgDto, musicImgDto.getMusicSheetId()));
     }
 
 }

+ 1 - 1
cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/open/OpenSubjectController.java

@@ -36,7 +36,7 @@ public class OpenSubjectController extends BaseController {
     @ApiOperation(value = "获取声部")
     @GetMapping("/subjectSelect")
     public HttpResponseResult<List<Subject>> subjectSelect(
-            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type) {
+            @ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type) {
         List<Subject> subjectSelect = subjectService.subjectSelect(type, null);
         return succeed(subjectSelect);
     }

+ 1 - 1
cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/open/SubjectController.java

@@ -51,7 +51,7 @@ public class SubjectController extends BaseController {
 	@ApiOperation(value = "获取声部")
 	@GetMapping("/subjectSelect")
     public HttpResponseResult<List<Subject>> subjectSelect(
-			@ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PINAO_ROOM 琴房 MUSIC 曲目 ") String type, @ApiParam(value = "客户端 TEACHER/STUDENT") String clientId){
+			@ApiParam(value = "类型 PRACTICE 陪练课 LIVE 直播课 VIDEO 视频课 PIANO_ROOM 琴房 MUSIC 曲目 ") String type, @ApiParam(value = "客户端 TEACHER/STUDENT") String clientId){
 
 		String userExtSubjectIds = null;
         

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác