浏览代码

Merge branch 'dev_v1.3.5_20220929' into dev_v1.3.5_20220927

Eric 2 年之前
父节点
当前提交
f41d143e0c
共有 100 个文件被更改,包括 4273 次插入238 次删除
  1. 1 1
      audio-analysis/src/main/java/com/yonge/audio/AudioAnalysisServerApplication.java
  2. 11 0
      cooleshow-auth/auth-api/src/main/java/com/yonge/cooleshow/auth/api/dto/RealnameAuthReq.java
  3. 2 1
      cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/web/controller/UserController.java
  4. 1 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/CacheNameEnum.java
  5. 2 1
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/ContractTemplateTypeEnum.java
  6. 32 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/ActivityEvaluationController.java
  7. 2 2
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicAlbumController.java
  8. 90 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/TeacherController.java
  9. 1 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/coupon/CouponIssueController.java
  10. 21 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/ImUserFriendController.java
  11. 326 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/TeacherBindingUserVo.java
  12. 52 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/IMNotifyMessageVO.java
  13. 142 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/teacher/TeacherVO.java
  14. 15 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/task/TaskController.java
  15. 6 0
      cooleshow-user/user-biz/pom.xml
  16. 9 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ActivityEvaluationDao.java
  17. 22 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ActivityPlanDao.java
  18. 18 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ActivityUserRewardDao.java
  19. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java
  20. 10 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/MusicAlbumDao.java
  21. 8 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/MusicSheetDao.java
  22. 13 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/TeacherDao.java
  23. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserBindingTeacherDao.java
  24. 48 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ActivityEvaluationDto.java
  25. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/OrderReq.java
  26. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/ActivityRegistrationSearch.java
  27. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/MusicAlbumDetailSearch.java
  28. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/MusicAlbumSearch.java
  29. 88 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/StudentMusicAlbumSearch.java
  30. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityEvaluation.java
  31. 24 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityEvaluationRecord.java
  32. 25 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityPlan.java
  33. 13 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityUserReward.java
  34. 24 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicAlbum.java
  35. 13 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicSheetPurchaseRecord.java
  36. 10 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/ChargeTypeEnum.java
  37. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/GoodTypeEnum.java
  38. 2 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/OrderTypeEnum.java
  39. 34 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/activity/ActivityRankingMethodEnum.java
  40. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/activity/ActivityRankingRuleEnum.java
  41. 41 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/album/PurchaseRecordTypeEnum.java
  42. 29 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CourseScheduleMapper.java
  43. 19 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/StudentMapper.java
  44. 13 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/SubjectMapper.java
  45. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/SysUserMapper.java
  46. 102 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/TeacherBindingUserQueryInfo.java
  47. 40 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/TeacherQueryInfo.java
  48. 52 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/UserRewardQueryInfo.java
  49. 2 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ActivityEvaluationRecordService.java
  50. 8 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ActivityEvaluationService.java
  51. 12 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ActivityRewardService.java
  52. 23 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ActivityUserRewardService.java
  53. 6 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CouponIssueService.java
  54. 8 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImUserFriendService.java
  55. 4 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicAlbumService.java
  56. 2 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicSheetPurchaseRecordService.java
  57. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/SysUserService.java
  58. 24 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/TeacherService.java
  59. 18 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserBindingTeacherService.java
  60. 203 19
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityEvaluationRecordServiceImpl.java
  61. 100 10
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityEvaluationServiceImpl.java
  62. 93 28
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityPlanEvaluationServiceImpl.java
  63. 183 34
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityPlanServiceImpl.java
  64. 59 11
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityRegistrationServiceImpl.java
  65. 47 39
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityRewardServiceImpl.java
  66. 34 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityUserRewardServiceImpl.java
  67. 16 20
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CouponIssueServiceImp.java
  68. 122 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java
  69. 121 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MusicAlbumServiceImpl.java
  70. 7 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MusicSheetPurchaseRecordServiceImpl.java
  71. 118 24
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MusicSheetServiceImpl.java
  72. 66 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SysUserServiceImpl.java
  73. 118 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherServiceImpl.java
  74. 165 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserBindingTeacherServiceImpl.java
  75. 13 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java
  76. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityEvaluationVo.java
  77. 70 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityMusicVo.java
  78. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityRankingVo.java
  79. 38 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityRegistrationVo.java
  80. 56 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/AlbumDetailVo.java
  81. 79 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/MusicActivityVo.java
  82. 10 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/MusicSheetVo.java
  83. 67 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/MyFens.java
  84. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherHomeVo.java
  85. 107 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherVo.java
  86. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/UserOrderDetailVo.java
  87. 87 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/activity/UserRewardWrapper.java
  88. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/res/OrderCreateRes.java
  89. 125 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/userBindingTeacher/UserBindingCourseWrapper.java
  90. 179 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/userBindingTeacher/UserBindingTeacherWrapper.java
  91. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/StatGroupWrapper.java
  92. 39 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerService.java
  93. 77 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/teacher/TeacherWrapper.java
  94. 30 11
      cooleshow-user/user-biz/src/main/resources/config/mybatis/ActivityEvaluationMapper.xml
  95. 48 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/ActivityPlanMapper.xml
  96. 3 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/ActivityRegistrationMapper.xml
  97. 45 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/ActivityUserRewardMapper.xml
  98. 39 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml
  99. 53 7
      cooleshow-user/user-biz/src/main/resources/config/mybatis/MusicAlbumMapper.xml
  100. 22 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/MusicSheetMapper.xml

+ 1 - 1
audio-analysis/src/main/java/com/yonge/audio/AudioAnalysisServerApplication.java

@@ -24,7 +24,7 @@ import com.yonge.audio.config.LocalFastJsonHttpMessageConverter;
 @SpringBootApplication
 @EnableDiscoveryClient
 @EnableFeignClients("com.yonge.cooleshow")
-@MapperScan(basePackages = {"com.yonge.cooleshow.biz.dal.dao", "com.yonge.toolset.payment.core.dao"})
+@MapperScan(basePackages = {"com.yonge.cooleshow.biz.dal.dao", "com.yonge.cooleshow.biz.dal.mapper", "com.yonge.toolset.payment.core.dao"})
 @ComponentScan(basePackages = {
         "com.yonge.netty", "com.yonge.cooleshow", "com.yonge.toolset"
 })

+ 11 - 0
cooleshow-auth/auth-api/src/main/java/com/yonge/cooleshow/auth/api/dto/RealnameAuthReq.java

@@ -29,12 +29,23 @@ public class RealnameAuthReq implements Serializable {
     @ApiModelProperty(value = "是否修改用户信息", required = true)
     private Boolean save;
 
+    @ApiModelProperty("是否签署协议")
+    private Boolean contract = false;
+
     private Long userId;
     // 性别(1,男 0,女)
     private int gender;
     // 出生日期
     private Date birthday;
 
+    public Boolean getContract() {
+        return contract;
+    }
+
+    public void setContract(Boolean contract) {
+        this.contract = contract;
+    }
+
     public Long getUserId() {
         return userId;
     }

+ 2 - 1
cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/web/controller/UserController.java

@@ -535,7 +535,8 @@ public class UserController extends BaseController {
     }
 
 
-    @PostMapping("/realNameAuth")
+    // 实名认证改到对应的服务中
+    // @PostMapping("/realNameAuth")
     @ApiOperation(value = "实名认证", notes = "传入realNameAuthDto")
     @ResponseBody
     public HttpResponseResult<IdcardInfoExtractor> realNameAuth(@Valid @RequestBody RealnameAuthReq realNameAuthDto) {

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

@@ -30,6 +30,7 @@ public enum CacheNameEnum implements BaseEnum<String, CacheNameEnum> {
     LOCK_ACTIVITY_REWARD_STOCK("锁活动奖品变更"),
     LOCK_ACTIVITY_STOCK("锁活动变更"),
     LOCK_STANDARD_GIFT_CRON("达标活动定时任务锁"),
+    LOCK_EVALUATION_CRON("评测活动定时任务锁"),
     ;
     /***
      * 缓存描述

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

@@ -5,7 +5,8 @@ import com.yonge.toolset.base.enums.BaseEnum;
 
 public enum ContractTemplateTypeEnum implements BaseEnum<String, ContractTemplateTypeEnum> {
     BUY_ORDER(ContractTemplateSourceEnum.PLATFORM, "平台购买商品"),
-    WITHDRAW(ContractTemplateSourceEnum.LINGXINPAY, "用户结算");
+    WITHDRAW(ContractTemplateSourceEnum.LINGXINPAY, "用户结算"),
+    REGISTER(ContractTemplateSourceEnum.PLATFORM, "注册协议");
 
     @EnumValue
     private String code;

+ 32 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/ActivityEvaluationController.java

@@ -23,6 +23,8 @@ 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.joda.time.DateTime;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -36,6 +38,7 @@ import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 
 @RestController
 @RequestMapping("/activityEvaluation")
@@ -80,6 +83,35 @@ public class ActivityEvaluationController extends BaseController {
     	return status(activityEvaluationService.addBatch(param,user));
 	}
 
+	@ApiOperation(value = "批量更新曲目信息")
+	@PostMapping("/batchUpdate")
+	public HttpResponseResult<Boolean> batchUpdateEvaluationInfo(@Valid @RequestBody ActivityEvaluationDto info) {
+
+		SysUser user = sysUserFeignService.queryUserInfo();
+		if (user == null || null == user.getId()) {
+			return failed(HttpStatus.FORBIDDEN, "请登录");
+		}
+
+		if (CollectionUtils.isEmpty(info.getEvaluationInfos())) {
+			return failed("评测曲目信息为空");
+		}
+
+		for (ActivityEvaluationDto.EvaluationInfo item : info.getEvaluationInfos()) {
+
+			if (Objects.isNull(item.getId())
+					|| Objects.isNull(item.getEvaluationDifficulty())) {
+				return failed("无效的请求参数");
+			}
+
+			item.updateBy(user.getId()).updateTime(DateTime.now().toDate());
+		}
+
+		// 批量更新曲目信息
+		int ret = activityEvaluationService.batchUpdateEvaluationInfo(user, info);
+
+		return status(ret > 0);
+	}
+
  	/**
 	 * 删除
 	 */

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

@@ -127,7 +127,7 @@ public class MusicAlbumController extends BaseController {
     public HttpResponseResult<AlbumDetailVo> detail(@Valid @RequestBody MusicAlbumDetailSearch query) {
 
         query.setType(2);
-        AlbumDetailVo albumDetailVo = musicAlbumService.detail(PageUtil.getPage(query),query);
+        AlbumDetailVo albumDetailVo = musicAlbumService.detail(PageUtil.getPage(query), query, null, null);
         return succeed(albumDetailVo);
     }
 
@@ -142,7 +142,7 @@ public class MusicAlbumController extends BaseController {
 
         query.setType(1);
         query.setState(YesOrNoEnum.YES);
-        AlbumDetailVo albumDetailVo = musicAlbumService.detail(PageUtil.getPage(query),query);
+        AlbumDetailVo albumDetailVo = musicAlbumService.detail(PageUtil.getPage(query), query, null, null);
         return succeed(albumDetailVo);
     }
 

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

@@ -1,5 +1,17 @@
 package com.yonge.cooleshow.admin.controller;
 
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.admin.io.request.TeacherBindingUserVo;
+import com.yonge.cooleshow.admin.io.request.coupon.CouponIssueVo;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherBindingUserQueryInfo;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherQueryInfo;
+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.admin.io.request.teacher.TeacherVO;
+import com.yonge.cooleshow.biz.dal.vo.MyFens;
+import com.yonge.cooleshow.biz.dal.wrapper.teacher.TeacherWrapper;
+import com.yonge.toolset.base.page.QueryInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -9,6 +21,8 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import javax.servlet.http.HttpServletResponse;
@@ -17,6 +31,7 @@ import javax.validation.Valid;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -54,6 +69,8 @@ import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.toolset.utils.date.DateUtil;
 import com.yonge.toolset.utils.excel.POIUtil;
 
+import static com.yonge.cooleshow.common.entity.HttpResponseResult.succeed;
+
 @RestController
 @RequestMapping("/teacher")
 @Api(value = "教师表", tags = "教师表")
@@ -71,6 +88,9 @@ public class TeacherController extends BaseController {
     @Autowired
     private VipCardRecordService vipCardRecordService;
 
+    @Autowired
+    private UserBindingTeacherService userBindingTeacherService;
+
     /**
      * 查询单条
      */
@@ -81,7 +101,9 @@ public class TeacherController extends BaseController {
     })
     @PreAuthorize("@pcs.hasPermissions('teacher/detail')")
     public HttpResponseResult<TeacherVo> detail(@PathVariable("id") Long userId) {
-        TeacherVo detail = teacherService.detail(userId);
+        //TeacherVo detail = teacherService.detail(userId);
+
+        TeacherVo detail = teacherService.findTeacherDetailInfo(userId);
         if (null != detail && !CollectionUtils.isEmpty(detail.getStyleVideo())) {
             List<TeacherStyleVideo> styleVideo = detail.getStyleVideo();
             List<TeacherStyleVideo> collect = styleVideo.stream().filter(o -> AuthStatusEnum.PASS.equals(o.getAuthStatus())).collect(Collectors.toList());
@@ -244,4 +266,71 @@ public class TeacherController extends BaseController {
         teacherService.updateStyleVideo(teacherDto.getUserId(), teacherDto.getStyleVideo(), teacherDto.getMessage());
         return succeed();
     }
+
+
+    @ApiOperation(value = "老师琴房课绑定学员列表")
+    @PostMapping("/bindingUserList")
+    // @PreAuthorize("@pcs.hasPermissions('teacher/bindingUserList')")
+    public HttpResponseResult<PageInfo<TeacherBindingUserVo.BindingUserList>> bindingUserList(@RequestBody  @Valid  TeacherBindingUserVo.BindingUserQuery query) {
+        IPage<UserBindingTeacherWrapper> wrapperIPage = userBindingTeacherService.selectBindingUserPage(PageUtil.getPage(query),
+                                                        TeacherBindingUserQueryInfo.BindingUserQuery.from(query.jsonString()));
+        // 数据转换
+        List<TeacherBindingUserVo.BindingUserList> pageInfos = JSON.parseArray(JSON.toJSONString(wrapperIPage.getRecords()),
+                                                                               TeacherBindingUserVo.BindingUserList.class);
+
+        return succeed(PageUtil.getPageInfo(wrapperIPage,pageInfos));
+    }
+
+
+    @ApiOperation(value = "查看课表")
+    @PostMapping("/selectBindingUserCourse")
+    // @PreAuthorize("@pcs.hasPermissions('teacher/selectBindingUserCourse')")
+    public HttpResponseResult<PageInfo<TeacherBindingUserVo.BindingStudentCourseList>> selectBindingUserCourse(@RequestBody @Valid TeacherBindingUserVo.BindingStudentCourseQuery query) {
+        IPage<UserBindingCourseWrapper> wrapperIPage = userBindingTeacherService.selectBindingUserCoursePage(PageUtil.getPage(query),
+                                                                                                             TeacherBindingUserQueryInfo.BindingStudentCourseQuery.from(query.jsonString()));
+        // 数据转换
+        List<TeacherBindingUserVo.BindingStudentCourseList> pageInfos = JSON.parseArray(JSON.toJSONString(wrapperIPage.getRecords()),
+                                                                                        TeacherBindingUserVo.BindingStudentCourseList.class);
+
+        return succeed(PageUtil.getPageInfo(wrapperIPage, pageInfos));
+    }
+    /**
+     * 查询老师统计指标
+     * @param userId 老师ID
+     * @return HttpResponseResult<TeacherVO.TeacherStat>
+     */
+    @ApiOperation(value = "老师统计指标", notes = "传入id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", paramType = "path", dataType = "long", required = true),
+    })
+    @GetMapping("/stat/{id}")
+    public HttpResponseResult<TeacherVO.TeacherStat> teacherStatInfo(@PathVariable("id") Long userId) {
+
+        // 老师统计指标
+        TeacherWrapper.TeacherStatInfo statInfo = teacherService.findTeacherStatInfoById(userId);
+
+        return succeed(TeacherVO.TeacherStat.from(statInfo.jsonString()));
+    }
+
+    /**
+     * 老师粉丝信息查询
+     * @param query TeacherVO.TeacherFansQuery
+     * @return HttpResponseResult<PageInfo<MyFens>>
+     */
+    @ApiOperation(value = "我的粉丝")
+    @PostMapping(value = "/myFans")
+    public HttpResponseResult<PageInfo<TeacherVO.TeacherFans>> queryMyFans(@RequestBody TeacherVO.TeacherFansQuery query) {
+
+        if (Optional.ofNullable(query.getTeacherId()).orElse(0L) <= 0) {
+            return failed("无效的请求参数");
+        }
+
+        IPage<MyFens> pages = teacherService.queryMyFans(PageUtil.getPage(query), TeacherQueryInfo.FansQuery.from(query.jsonString()));
+
+        // 数据转换
+        List<TeacherVO.TeacherFans> responses = JSON.parseArray(JSON.toJSONString(pages.getRecords()),
+                TeacherVO.TeacherFans.class);
+
+        return succeed(PageUtil.getPageInfo(pages, responses));
+    }
 }

+ 1 - 1
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/coupon/CouponIssueController.java

@@ -96,7 +96,7 @@ public class CouponIssueController {
         if (sysUser == null  || sysUser.getId() == null) {
             return failed("用户信息获取失败");
         }
-        couponIssueService.issueCoupon(param.getCouponId(), param.getUserParam(), sysUser.getId(), param.getRemark(), true, true,
+        couponIssueService.issueCoupon(param.getCouponId(), param.getUserParam(), sysUser.getId(), param.getRemark(),
                                        SendTypeEnum.PLATFORM, new Date());
 
         return succeed();

+ 21 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/ImUserFriendController.java

@@ -1,7 +1,9 @@
 package com.yonge.cooleshow.admin.controller.open;
 
+import com.yonge.cooleshow.admin.io.request.im.IMNotifyMessageVO;
 import com.yonge.cooleshow.admin.io.request.im.UserFriendInfoVO;
 import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import io.swagger.annotations.Api;
@@ -44,5 +46,24 @@ public class ImUserFriendController extends BaseController {
 
         return succeed(ret > 0);
     }
+
+    /**
+     * 发送系统客服消息
+     * @param info IMNotifyMessageVO
+     * @return HttpResponseResult<Boolean>
+     */
+    @PostMapping(value = "/message")
+    public HttpResponseResult<Boolean> sendSysCustomerServiceMessage(@RequestBody IMNotifyMessageVO info) {
+
+        if (info.invalidRequestParam()) {
+            return failed("无效的请求参数");
+        }
+
+        // 发送客服通知消息
+        imUserFriendService.sendCustomerServiceNotifyMessage(info.getSender(),
+                CustomerService.NotifyMessage.from(info.jsonString()));
+
+        return succeed();
+    }
 }
 

+ 326 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/TeacherBindingUserVo.java

@@ -0,0 +1,326 @@
+package com.yonge.cooleshow.admin.io.request;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import com.yonge.toolset.base.page.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-10-08
+ */
+public class TeacherBindingUserVo {
+
+    @ApiModel("BindingUserQuery-老师绑定的学生列表查询")
+    public static class BindingUserQuery extends QueryInfo {
+
+        @ApiModelProperty(value = "老师id",required = true)
+        @NotNull(message = "老师id不能为空")
+        private Long teacherId;
+
+        @ApiModelProperty("查询条件 昵称、编号、手机号")
+        private String search;
+
+        @ApiModelProperty("绑定开始时间")
+        private Date startTime;
+
+        @ApiModelProperty("绑定结束时间")
+        private Date endTime;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public Long getTeacherId() {
+            return teacherId;
+        }
+
+        public void setTeacherId(Long teacherId) {
+            this.teacherId = teacherId;
+        }
+
+        @Override
+        public String getSearch() {
+            return search;
+        }
+
+        @Override
+        public void setSearch(String search) {
+            this.search = search;
+        }
+
+        public Date getStartTime() {
+            return startTime;
+        }
+
+        public void setStartTime(Date startTime) {
+            this.startTime = startTime;
+        }
+
+        public Date getEndTime() {
+            return endTime;
+        }
+
+        public void setEndTime(Date endTime) {
+            this.endTime = endTime;
+        }
+    }
+
+
+    @ApiModel("BindingUserList-老师绑定的学生列表")
+    public static class BindingUserList  {
+
+        @ApiModelProperty("学生编号")
+        private Long userId;
+
+        @ApiModelProperty("昵称")
+        private String username;
+
+
+        @ApiModelProperty(value = "性别0女1男")
+        private Integer gender;
+
+        @ApiModelProperty(value = "年龄")
+        private Integer age;
+
+
+        // 声部
+        @ApiModelProperty(value = "声部")
+        private String subjectName;
+
+        @ApiModelProperty(value = "手机号")
+        private String phone;
+
+        @ApiModelProperty(value = "是否会员 0否 1是")
+        private YesOrNoEnum isVip;
+
+
+        @ApiModelProperty("课程数")
+        private Long courseNum;
+
+        @ApiModelProperty("已结束课时数")
+        private Integer endCourseNum;
+
+        @ApiModelProperty("未开始课程数")
+        private Integer noStartCourseNum;
+
+        @ApiModelProperty("绑定时间")
+        private Date bindingTime;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public String getSubjectName() {
+            return subjectName;
+        }
+
+        public void setSubjectName(String subjectName) {
+            this.subjectName = subjectName;
+        }
+
+        public Long getUserId() {
+            return userId;
+        }
+
+        public void setUserId(Long userId) {
+            this.userId = userId;
+        }
+
+        public String getUsername() {
+            return username;
+        }
+
+        public void setUsername(String username) {
+            this.username = username;
+        }
+
+        public Integer getGender() {
+            return gender;
+        }
+
+        public void setGender(Integer gender) {
+            this.gender = gender;
+        }
+
+        public Integer getAge() {
+            return age;
+        }
+
+        public void setAge(Integer age) {
+            this.age = age;
+        }
+
+        public String getPhone() {
+            return phone;
+        }
+
+        public void setPhone(String phone) {
+            this.phone = phone;
+        }
+
+        public YesOrNoEnum getIsVip() {
+            return isVip;
+        }
+
+        public void setIsVip(YesOrNoEnum isVip) {
+            this.isVip = isVip;
+        }
+
+        public Long getCourseNum() {
+            return courseNum;
+        }
+
+        public void setCourseNum(Long courseNum) {
+            this.courseNum = courseNum;
+        }
+
+        public Integer getEndCourseNum() {
+            return endCourseNum;
+        }
+
+        public void setEndCourseNum(Integer endCourseNum) {
+            this.endCourseNum = endCourseNum;
+        }
+
+        public Integer getNoStartCourseNum() {
+            return noStartCourseNum;
+        }
+
+        public void setNoStartCourseNum(Integer noStartCourseNum) {
+            this.noStartCourseNum = noStartCourseNum;
+        }
+
+        public Date getBindingTime() {
+            return bindingTime;
+        }
+
+        public void setBindingTime(Date bindingTime) {
+            this.bindingTime = bindingTime;
+        }
+    }
+
+    @ApiModel("BindingStudentCourseQuery-绑定学生课程列表查询")
+    public static class BindingStudentCourseQuery extends QueryInfo{
+
+        @ApiModelProperty(value = "老师id",required = true)
+        @NotNull(message = "老师id不能为空")
+        private Long teacherId;
+
+        @NotNull(message = "学员id不能为空")
+        @ApiModelProperty(value = "学员id",required = true)
+        private Long studentId;
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+        public Long getTeacherId() {
+            return teacherId;
+        }
+
+        public void setTeacherId(Long teacherId) {
+            this.teacherId = teacherId;
+        }
+
+        public Long getStudentId() {
+            return studentId;
+        }
+
+        public void setStudentId(Long studentId) {
+            this.studentId = studentId;
+        }
+    }
+
+
+
+    @ApiModel("BindingStudentCourseList-绑定学生课程列表")
+    public static class BindingStudentCourseList{
+
+        @ApiModelProperty("课程编号")
+        private Long courseId;
+
+        @ApiModelProperty("课程声部")
+        private String subjectName;
+
+        @ApiModelProperty("学员考勤 TRUANT:旷课 ATTENDCLASS:到课 NOTSTART:未开始")
+        private String status;
+
+        @ApiModelProperty(value = "课程状态 NOT_START未开始 ING进行中 COMPLETE已完成 CANCEL已取消  CourseScheduleEnum")
+        private String courseStatus;
+
+        @ApiModelProperty("上课时间")
+        private Date classDate;
+
+        // 课程开始时间
+        @ApiModelProperty("课程开始时间")
+        private Date startTime;
+
+        //课程结束时间
+        @ApiModelProperty("课程结束时间")
+        private Date endTime;
+
+        public Date getStartTime() {
+            return startTime;
+        }
+
+        public void setStartTime(Date startTime) {
+            this.startTime = startTime;
+        }
+
+        public Date getEndTime() {
+            return endTime;
+        }
+
+        public void setEndTime(Date endTime) {
+            this.endTime = endTime;
+        }
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+        public Long getCourseId() {
+            return courseId;
+        }
+
+        public void setCourseId(Long courseId) {
+            this.courseId = courseId;
+        }
+
+        public String getSubjectName() {
+            return subjectName;
+        }
+
+        public void setSubjectName(String subjectName) {
+            this.subjectName = subjectName;
+        }
+
+        public String getStatus() {
+            return status;
+        }
+
+        public void setStatus(String status) {
+            this.status = status;
+        }
+
+        public String getCourseStatus() {
+            return courseStatus;
+        }
+
+        public void setCourseStatus(String courseStatus) {
+            this.courseStatus = courseStatus;
+        }
+
+        public Date getClassDate() {
+            return classDate;
+        }
+
+        public void setClassDate(Date classDate) {
+            this.classDate = classDate;
+        }
+    }
+}

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

@@ -0,0 +1,52 @@
+package com.yonge.cooleshow.admin.io.request.im;
+
+import com.alibaba.fastjson.JSON;
+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通知信息
+ * Created by Eric.Shang on 2022/9/20.
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class IMNotifyMessageVO implements Serializable {
+
+    @ApiModelProperty(value = "发送者ID")
+    private String sender;
+
+    @ApiModelProperty(value = "接收ID")
+    private List<String> receives;
+
+    @ApiModelProperty(value = "通知标题")
+    private String title;
+
+    @ApiModelProperty(value = "文件通知消息")
+    private String txtMessage;
+
+    @ApiModelProperty(value = "图片通知消息")
+    private String imgMessage;
+
+    @ApiModelProperty(value = "图片文件地址")
+    private String imgUrl;
+
+    public String jsonString() {
+
+        return JSON.toJSONString(this);
+    }
+
+    public boolean invalidRequestParam() {
+
+        return StringUtils.isEmpty(getSender())
+                || StringUtils.isAllBlank(getTxtMessage(), getImgMessage());
+    }
+}

+ 142 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/teacher/TeacherVO.java

@@ -0,0 +1,142 @@
+package com.yonge.cooleshow.admin.io.request.teacher;
+
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.yonge.cooleshow.biz.dal.enums.GenderEnum;
+import com.yonge.cooleshow.biz.dal.enums.MK;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import com.yonge.toolset.base.page.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 老师端统计信息
+ * Created by Eric.Shang on 2022/10/8.
+ */
+public class TeacherVO {
+
+    /**
+     * 老师统计指标信息
+     */
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("老师统计响应信息")
+    public static class TeacherStat implements Serializable {
+
+        @ApiModelProperty("星级")
+        private Integer starGrade;
+        @ApiModelProperty("粉丝数")
+        private Integer fansNum;
+        @ApiModelProperty("已上课时")
+        private Integer expTime;
+        @ApiModelProperty("未上课时")
+        private Integer unExpTime;
+        @ApiModelProperty("专辑数 ")
+        private Integer musicAlbumNum;
+        @ApiModelProperty("曲谱数 ")
+        private Integer musicSheetNum;
+        @ApiModelProperty("学生数")
+        private Integer studentNums;
+
+        public static TeacherStat from(String recv) {
+
+            return JSON.parseObject(recv, TeacherStat.class);
+        }
+    }
+
+    /**
+     * 老师粉丝数
+     */
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class TeacherFansQuery extends QueryInfo {
+
+        @ApiModelProperty("搜索条件:昵称/编号/手机号")
+        private String search;
+
+        @ApiModelProperty("老师ID")
+        private Long teacherId;
+
+        @ApiModelProperty("开始时间")
+        @JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
+        private Date startTime;
+
+        @ApiModelProperty("结束时间")
+        @JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
+        private Date endTime;
+
+        private String nickname;
+        private Long userId;
+        private String phone;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public void setSearch(String search) {
+            if (StringUtils.isNotEmpty(search)) {
+
+                if (search.matches(MK.EXP_INT)) {
+
+                    if (search.matches(MK.EXP_MOBILE_NUMBER)) {
+
+                        setPhone(search);
+                    } else {
+                        setUserId(Long.parseLong(search));
+                    }
+
+                } else {
+                    // 昵称
+                    setNickname(search);
+                }
+            }
+            this.search = search;
+        }
+    }
+
+    /**
+     * 老师粉丝
+     */
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class TeacherFans implements Serializable {
+
+        @ApiModelProperty("用户编号")
+        private String userId;
+        @ApiModelProperty("昵称")
+        private String userName;
+        @ApiModelProperty(value = "真实姓名")
+        private String realName;
+        @ApiModelProperty("头像地址")
+        private String avatar;
+        @ApiModelProperty("声部")
+        private String subjectName;
+        @ApiModelProperty(value = "性别 0女 1男")
+        private GenderEnum gender;
+        @ApiModelProperty(value = "是否会员 0否 1是")
+        private YesOrNoEnum isVip;
+
+        @ApiModelProperty("手机号")
+        private String phone;
+
+        @ApiModelProperty("关注时间")
+        @JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
+        private Date starTime;
+
+        @ApiModelProperty("出生日期")
+        private Date birthdate;
+
+        @ApiModelProperty("出生日期")
+        private Integer age;
+    }
+}

+ 15 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/task/TaskController.java

@@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import springfox.documentation.annotations.ApiIgnore;
 
@@ -39,6 +40,8 @@ public class TaskController extends BaseController {
     private PlatformCashAccountRecordService platformCashAccountRecordService;
     @Autowired
     private ActivityPlanService activityPlanService;
+    @Autowired
+    private ActivityPlanEvaluationService activityPlanEvaluationService;
 
     @Value("${app.blacklist:}")
     private String blacklistFilePath;
@@ -111,4 +114,16 @@ public class TaskController extends BaseController {
         activityPlanService.activityIng();
         return HttpResponseResult.succeed();
     }
+
+    /**
+     * 活动测试
+     * @param activityId 活动ID
+     * @return HttpResponseResult<Object>
+     */
+    @GetMapping("/test")
+    public HttpResponseResult<Object> test(@RequestParam("activityId") Long activityId) {
+
+        activityPlanEvaluationService.successActivity(activityId);
+        return HttpResponseResult.succeed();
+    }
 }

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

@@ -43,6 +43,12 @@
             <version>${rongcloud.im.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.11</version>
+        </dependency>
+
         <!-- redisson -->
         <dependency>
             <groupId>org.redisson</groupId>

+ 9 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ActivityEvaluationDao.java

@@ -9,6 +9,7 @@ import com.yonge.cooleshow.biz.dal.dto.search.MusicSheetSearch;
 import com.yonge.cooleshow.biz.dal.vo.ActivityMusicVo;
 import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
 import com.yonge.cooleshow.biz.dal.vo.activity.ActivityTeacherWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import org.apache.ibatis.annotations.Param;
 import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluation;
 import com.yonge.cooleshow.biz.dal.vo.ActivityEvaluationVo;
@@ -85,4 +86,12 @@ public interface ActivityEvaluationDao extends BaseMapper<ActivityEvaluation> {
 	 * @return List<ActivityTeacherWrapper>
 	 */
 	List<ActivityTeacherWrapper> selectActivityTeacherByTimePageInfo(@Param("page") IPage<ActivityTeacherWrapper> page, @Param("record") ActivityTeacherQuery query);
+
+	/**
+	 * 评测活动声部曲目最高分
+	 * @param activityId 活动ID
+	 * @param userId 用户ID
+	 * @return List<StatGroupWrapper>
+	 */
+    List<StatGroupWrapper> selectSubjectMusicHighestScoreStat(@Param("activityId") Long activityId, @Param("userId") Long userId);
 }

+ 22 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ActivityPlanDao.java

@@ -4,6 +4,8 @@ import java.util.List;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluationRecord;
+import com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo;
 import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import org.apache.ibatis.annotations.Param;
 import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
@@ -82,4 +84,24 @@ public interface ActivityPlanDao extends BaseMapper<ActivityPlan> {
 	 * @return List<StatGroupWrapper>
 	 */
 	List<StatGroupWrapper> selectActivityWinnerStatInfo(@Param("activityIds") List<Long> activityIds);
+
+	/**
+	 * 活动总分用户排名
+	 * @param activityId 活动ID
+	 * @param subjectId 声部ID
+	 * @return List<ActivityRankingVo>
+	 */
+    List<ActivityRankingVo> selectActivityHighestScoreRankingInfo(@Param("activityId") Long activityId, @Param("subjectId") Long subjectId,
+																  @Param("rankingScore") Double rankingScore, @Param("limit") Integer limit);
+
+	/**
+	 * 总分用户排名信息
+	 * @param activityPlanId 活动ID
+	 * @param subjectId 声部ID
+	 * @param rankingScore 分数
+	 * @param userId 用户ID
+	 * @return ActivityRankingVo
+	 */
+	ActivityRankingVo selectActivityHighestScoreUserRanking(@Param("activityId") Long activityPlanId, @Param("subjectId") Long subjectId,
+															@Param("rankingScore") Double rankingScore, @Param("userId") Long userId);
 }

+ 18 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/ActivityUserRewardDao.java

@@ -1,10 +1,13 @@
 package com.yonge.cooleshow.biz.dal.dao;
 
+import java.util.Date;
 import java.util.List;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.biz.dal.queryInfo.UserRewardQueryInfo;
 import com.yonge.cooleshow.biz.dal.vo.UserRewardVo;
+import com.yonge.cooleshow.biz.dal.vo.activity.UserRewardWrapper;
 import org.apache.ibatis.annotations.Param;
 import com.yonge.cooleshow.biz.dal.entity.ActivityUserReward;
 import com.yonge.cooleshow.biz.dal.vo.ActivityUserRewardVo;
@@ -35,4 +38,19 @@ public interface ActivityUserRewardDao extends BaseMapper<ActivityUserReward>{
 	 * @return List<UserRewardVo>
 	 */
 	List<UserRewardVo> selectActivityShareTeacher(@Param("activityId") Long activityId, @Param("userIds") List<Long> userIds);
+
+	/**
+	 * 查询领取的奖品数
+	 */
+	int selectReceiveRewardCount(@Param("query") UserRewardQueryInfo query);
+
+	/**
+	 * 修改领奖状态
+	 */
+	int receiveReward(@Param("userId") Long userId, @Param("receiveRewardId") Long receiveRewardId, @Param(
+			"receiveTime") Date receiveTime);
+
+
+	IPage<UserRewardWrapper> selectReceiveRewardList(@Param("page") IPage<UserRewardWrapper> page, @Param(
+			"query") UserRewardQueryInfo query);
 }

+ 15 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java

@@ -10,7 +10,10 @@ import com.yonge.cooleshow.biz.dal.dto.search.HomeworkSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.MyCourseSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.PracticeTeacherSearch;
 import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherBindingUserQueryInfo;
 import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingCourseWrapper;
+import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingTeacherWrapper;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import org.apache.ibatis.annotations.Param;
 
@@ -235,4 +238,16 @@ public interface CourseScheduleDao extends BaseMapper<CourseSchedule> {
 
     //查询待结算课程
     List<UserAccountRecordDto> selectWaitCourse(String day);
+
+    /**
+     * 查询课程数
+     */
+    List<UserBindingTeacherWrapper.CourseNum> selectStudentPianoCourse(@Param("teacherId") Long teacherId, @Param(
+            "studentIdList") List<Long> studentIdList);
+
+    /**
+     * 查询琴房课
+     */
+    IPage<UserBindingCourseWrapper> selectBindingUserCoursePage(@Param(
+            "page") IPage<UserBindingCourseWrapper> page, @Param("query") TeacherBindingUserQueryInfo.BindingStudentCourseQuery query);
 }

+ 10 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/MusicAlbumDao.java

@@ -5,8 +5,10 @@ import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicAlbumSearch;
 import com.yonge.cooleshow.biz.dal.entity.MusicAlbum;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.vo.MusicAlbumVo;
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -64,4 +66,12 @@ public interface MusicAlbumDao extends BaseMapper<MusicAlbum> {
      * @return page
      */
     List<MusicAlbumVo> selectStudentPage(@Param("page") IPage<MusicAlbumVo> page, @Param("query") MusicAlbumSearch query, @Param("clientType") ClientEnum clientType);
+
+    /**
+     * 专辑单曲付费类型统计
+     * @param albumId 专辑ID
+     * @param paymentType 付费方式
+     * @return List<StatGroupWrapper>
+     */
+    List<StatGroupWrapper> selectAlbumMusicSheetStatInfo(@Param("albumId") Long albumId, @Param("paymentType") ChargeTypeEnum paymentType);
 }

+ 8 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/MusicSheetDao.java

@@ -6,6 +6,7 @@ import com.yonge.cooleshow.biz.dal.dto.search.*;
 import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -162,4 +163,11 @@ public interface MusicSheetDao extends BaseMapper<MusicSheet> {
      */
     List<MusicSheetDetailVo> auditDetailList(@Param("originalMusicSheetId") Long originalMusicSheetId, @Param(
             "authMusicSheetId") Long authMusicSheetId);
+
+    /**
+     * 单曲数量统计
+     * @param musicIds 单曲ID
+     * @return List<StatGroupWrapper>
+     */
+    List<StatGroupWrapper> selectMusicAlbumStatInfo(@Param("musicIds") List<Long> musicIds);
 }

+ 13 - 4
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/TeacherDao.java

@@ -9,10 +9,12 @@ import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.dto.search.TeacherSearch;
 import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.cooleshow.biz.dal.entity.Teacher;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherQueryInfo;
 import com.yonge.cooleshow.biz.dal.vo.HotTeacherVo;
 import com.yonge.cooleshow.biz.dal.vo.MyFens;
 import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
 
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import org.apache.ibatis.annotations.Param;
 
 public interface TeacherDao extends BaseMapper<Teacher> {
@@ -87,15 +89,22 @@ public interface TeacherDao extends BaseMapper<Teacher> {
 
     /**
      * 查询我的粉丝
-     * @param page
-     * @param teacherId
-     * @return
+     * @param page IPage<MyFens>
+     * @param query TeacherQueryInfo.FansQuery
+     * @return List<MyFens>
      */
-    List<MyFens> queryMyFans(@Param("page") IPage<MyFens> page, @Param("teacherId") Long teacherId);
+    List<MyFens> queryMyFans(@Param("page") IPage<MyFens> page, @Param("record") TeacherQueryInfo.FansQuery query);
     
     /**
      * 查询热门老师
      * @return
      */
     List<HotTeacherVo> queryHotTeacherList(Long subjectId);
+
+    /**
+     * 老师学生人数统计
+     * @param teacherIds 老师ID
+     * @return List<StatGroupWrapper>
+     */
+    List<StatGroupWrapper> selectTeacherStudentNumberStatInfo(@Param("teacherIds") List<Long> teacherIds);
 }

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

@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherBindingUserQueryInfo;
 import com.yonge.cooleshow.biz.dal.vo.CourseStudentVo;
 import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
+import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingTeacherWrapper;
 import io.swagger.models.auth.In;
 import org.apache.ibatis.annotations.Param;
 
@@ -25,4 +27,14 @@ public interface UserBindingTeacherDao extends BaseMapper<UserBindingTeacher> {
 
     //查询超过days天数没有排课的绑定学院
     List<UserBindingTeacher> queryUnbindList(@Param("days") Integer days);
+
+    /**
+     * 查询绑定的学员信息
+     *
+     * @param page
+     * @param query
+     * @return
+     */
+    IPage<UserBindingTeacherWrapper> selectBindingUserPage(@Param("page") IPage<UserBindingTeacherWrapper> page,
+                                                           @Param("query") TeacherBindingUserQueryInfo.BindingUserQuery query);
 }

+ 48 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ActivityEvaluationDto.java

@@ -1,10 +1,17 @@
 package com.yonge.cooleshow.biz.dal.dto;
 
 import com.yonge.cooleshow.common.entity.BaseEntity;
+import com.yonge.cooleshow.common.enums.HardLevelEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
 
 /**
  * @Author: liweifan
@@ -17,12 +24,16 @@ public class ActivityEvaluationDto extends BaseEntity {
 	@ApiModelProperty("活动id ")
 	@NotNull(message = "活动id不能为空")
 	private Long activityId;
+
 	@ApiModelProperty("曲目id 多个用,分割 ")
 	//@NotBlank(message = "曲子id不能为空")
 	private String musicSheetIds; // 评测活动曲目ID
 	@ApiModelProperty("活动老师id 多个用,分割 ")
 	private String teacherIds; // 分享活动老师ID
 
+	@ApiModelProperty("评测曲目信息 ")
+	private List<EvaluationInfo> evaluationInfos;
+
 	public String getTeacherIds() {
 		return teacherIds;
 	}
@@ -47,4 +58,41 @@ public class ActivityEvaluationDto extends BaseEntity {
 	public void setMusicSheetIds(String musicSheetIds) {
 		this.musicSheetIds = musicSheetIds;
 	}
+
+	public List<EvaluationInfo> getEvaluationInfos() {
+		return evaluationInfos;
+	}
+
+	public void setEvaluationInfos(List<EvaluationInfo> evaluationInfos) {
+		this.evaluationInfos = evaluationInfos;
+	}
+
+	/**
+	 * 评测活动内容
+	 */
+	@Data
+	@NoArgsConstructor
+	@AllArgsConstructor
+	public static class EvaluationInfo implements Serializable {
+
+		@ApiModelProperty("主键 ")
+		private Long id;
+
+		@ApiModelProperty("评测难度 BEGINNER 入门级 ADVANCED 进阶级 PERFORMER 大师级 ")
+		private HardLevelEnum evaluationDifficulty;
+
+		private Date updateTime;
+		private Long updateBy;
+
+
+		public EvaluationInfo updateTime(Date updateTime) {
+			this.updateTime = updateTime;
+			return this;
+		}
+
+		public EvaluationInfo updateBy(Long updateBy) {
+			this.updateBy = updateBy;
+			return this;
+		}
+	}
 }

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

@@ -83,6 +83,9 @@ public class OrderReq {
         @ApiModelProperty(value = "活动id")
         private Long activityId;
 
+        // 透传订单类型
+        private OrderTypeEnum orderType;
+
         public BigDecimal getActualPrice() {
             return actualPrice;
         }
@@ -170,6 +173,14 @@ public class OrderReq {
         public void setRecomUserId(Long recomUserId) {
             this.recomUserId = recomUserId;
         }
+
+        public OrderTypeEnum getOrderType() {
+            return orderType;
+        }
+
+        public void setOrderType(OrderTypeEnum orderType) {
+            this.orderType = orderType;
+        }
     }
 
     public Long getRewardId() {

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

@@ -34,6 +34,9 @@ public class ActivityRegistrationSearch extends QueryInfo {
     @ApiModelProperty(value = "是否获奖 0 否 1 是")
     private YesOrNoEnum rewardFlag;
 
+    @ApiModelProperty(value = "声部ID集合")
+    private List<Long> subjectIds;
+
     public ActivityTypeEnum getActivityType() {
         return activityType;
     }
@@ -65,4 +68,12 @@ public class ActivityRegistrationSearch extends QueryInfo {
     public void setRewardFlag(YesOrNoEnum rewardFlag) {
         this.rewardFlag = rewardFlag;
     }
+
+    public List<Long> getSubjectIds() {
+        return subjectIds;
+    }
+
+    public void setSubjectIds(List<Long> subjectIds) {
+        this.subjectIds = subjectIds;
+    }
 }

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

@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
 import javax.validation.constraints.NotNull;
+import java.util.List;
 import java.util.Optional;
 
 /**
@@ -38,6 +39,8 @@ public class MusicAlbumDetailSearch extends MusicSheetSearch {
     @ApiModelProperty(value = "艺术家")
     private String composer;  //音乐家
 
+    private List<String> paymentTypes;
+
     public Integer getRelatedNum() {
         return relatedNum;
     }
@@ -87,4 +90,12 @@ public class MusicAlbumDetailSearch extends MusicSheetSearch {
     public void setDelFlag(Boolean delFlag) {
         this.delFlag = delFlag;
     }
+
+    public List<String> getPaymentTypes() {
+        return paymentTypes;
+    }
+
+    public void setPaymentTypes(List<String> paymentTypes) {
+        this.paymentTypes = paymentTypes;
+    }
 }

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

@@ -53,6 +53,9 @@ public class MusicAlbumSearch extends QueryInfo{
     @ApiModelProperty("声部id,多个逗号隔开")
     private String subjectIds;
 
+    @ApiModelProperty("曲目ID")
+    private Long musicId;
+
     @ApiModelProperty(hidden = true)
     private List<Long> subjectIdList;
 
@@ -157,4 +160,12 @@ public class MusicAlbumSearch extends QueryInfo{
 	public void setClientId(String clientId) {
 		this.clientId = clientId;
 	}
+
+    public Long getMusicId() {
+        return musicId;
+    }
+
+    public void setMusicId(Long musicId) {
+        this.musicId = musicId;
+    }
 }

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

@@ -1,5 +1,8 @@
 package com.yonge.cooleshow.biz.dal.dto.search;
 
+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 io.swagger.annotations.ApiModelProperty;
 
 /**
@@ -14,6 +17,20 @@ public class StudentMusicAlbumSearch extends MusicAlbumSearch{
     @ApiModelProperty(value = "登录学生id",hidden = true)
     private Long studentId;
 
+    @ApiModelProperty(value = "收藏专辑标识", hidden = true)
+    private Boolean albumFavorite;
+
+    @ApiModelProperty("已购买专辑 ")
+    private Boolean albumPurchased;
+
+    @ApiModelProperty(value = "订单状态(WAIT_PAY:待支付;PAYING:支付中,PAID:已付款)", hidden = true)
+    private OrderStatusEnum orderStatus;  //订单状态(1:已完成;0:取消)
+
+    @ApiModelProperty(value = "购买类型 ", hidden = true)
+    private PurchaseRecordTypeEnum purchaseType;
+
+    @ApiModelProperty(value = "用户类型 TEACHER:老师,STUDENT:学生", hidden = true)
+    private ClientEnum clientType;
 
     public Long getStudentId() {
         return studentId;
@@ -22,4 +39,75 @@ public class StudentMusicAlbumSearch extends MusicAlbumSearch{
     public void setStudentId(Long studentId) {
         this.studentId = studentId;
     }
+
+    public Boolean getAlbumFavorite() {
+        return albumFavorite;
+    }
+
+    public void setAlbumFavorite(Boolean albumFavorite) {
+        this.albumFavorite = albumFavorite;
+    }
+
+    public Boolean getAlbumPurchased() {
+        return albumPurchased;
+    }
+
+    public void setAlbumPurchased(Boolean albumPurchased) {
+        this.albumPurchased = albumPurchased;
+    }
+
+    public OrderStatusEnum getOrderStatus() {
+        return orderStatus;
+    }
+
+    public void setOrderStatus(OrderStatusEnum orderStatus) {
+        this.orderStatus = orderStatus;
+    }
+
+    public PurchaseRecordTypeEnum getPurchaseType() {
+        return purchaseType;
+    }
+
+    public void setPurchaseType(PurchaseRecordTypeEnum purchaseType) {
+        this.purchaseType = purchaseType;
+    }
+
+    public ClientEnum getClientType() {
+        return clientType;
+    }
+
+    public void setClientType(ClientEnum clientType) {
+        this.clientType = clientType;
+    }
+
+
+    public StudentMusicAlbumSearch studentId(Long studentId) {
+        this.studentId = studentId;
+        return this;
+    }
+
+    public StudentMusicAlbumSearch albumFavorite(Boolean albumFavorite) {
+        this.albumFavorite = albumFavorite;
+        return this;
+    }
+
+    public StudentMusicAlbumSearch albumPurchased(Boolean albumPurchased) {
+        this.albumPurchased = albumPurchased;
+        return this;
+    }
+
+    public StudentMusicAlbumSearch orderStatus(OrderStatusEnum orderStatus) {
+        this.orderStatus = orderStatus;
+        return this;
+    }
+
+    public StudentMusicAlbumSearch purchaseType(PurchaseRecordTypeEnum purchaseType) {
+        this.purchaseType = purchaseType;
+        return this;
+    }
+
+    public StudentMusicAlbumSearch clientType(ClientEnum clientType) {
+        this.clientType = clientType;
+        return this;
+    }
 }

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

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.yonge.cooleshow.common.enums.ActivityResourceEnum;
+import com.yonge.cooleshow.common.enums.HardLevelEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -30,6 +31,10 @@ public class ActivityEvaluation implements Serializable {
     @TableField(value = "music_sheet_id_")
     private Long musicSheetId;
 
+    @ApiModelProperty("评测难度 BEGINNER 入门级 ADVANCED 进阶级 PERFORMER 大师级 ")
+    @TableField(value = "evaluation_difficulty_")
+    private HardLevelEnum evaluationDifficulty;
+
     @ApiModelProperty("资源类型 ")
     @TableField(value = "resource_type_")
     private ActivityResourceEnum resourceType;
@@ -91,4 +96,11 @@ public class ActivityEvaluation implements Serializable {
         this.createBy = createBy;
     }
 
+    public HardLevelEnum getEvaluationDifficulty() {
+        return evaluationDifficulty;
+    }
+
+    public void setEvaluationDifficulty(HardLevelEnum evaluationDifficulty) {
+        this.evaluationDifficulty = evaluationDifficulty;
+    }
 }

+ 24 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityEvaluationRecord.java

@@ -4,6 +4,7 @@ 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.activity.ActivityRankingMethodEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -43,6 +44,14 @@ public class ActivityEvaluationRecord implements Serializable {
     @ApiModelProperty("次数")
     @TableField(value = "times_")
     private int times;
+
+    @ApiModelProperty("评份方式")
+    @TableField(value = "ranking_method_")
+    private ActivityRankingMethodEnum rankingMethod;
+
+    @ApiModelProperty("活动报名时间 ")
+    @TableField(value = "registration_time_")
+    private Long registrationTime;
     
     @ApiModelProperty("创建时间 ")
     @TableField(value = "create_time_")
@@ -114,4 +123,19 @@ public class ActivityEvaluationRecord implements Serializable {
         this.createTime = createTime;
     }
 
+    public ActivityRankingMethodEnum getRankingMethod() {
+        return rankingMethod;
+    }
+
+    public void setRankingMethod(ActivityRankingMethodEnum rankingMethod) {
+        this.rankingMethod = rankingMethod;
+    }
+
+    public Long getRegistrationTime() {
+        return registrationTime;
+    }
+
+    public void setRegistrationTime(Long registrationTime) {
+        this.registrationTime = registrationTime;
+    }
 }

+ 25 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityPlan.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
 import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingRuleEnum;
 import com.yonge.cooleshow.common.enums.ActivityTypeEnum;
 import com.yonge.cooleshow.common.enums.RegistrationMethodEnum;
@@ -118,6 +119,14 @@ public class ActivityPlan implements Serializable {
     @TableField(value = "ranking_rule_")
     private ActivityRankingRuleEnum rankingRule;
 
+    @ApiModelProperty("活动形式: MUSIC_RANKING(单曲排名) TOTAL_SCORE(总分排名) ")
+    @TableField(value = "ranking_method_")
+    private ActivityRankingMethodEnum rankingMethod;
+
+    @ApiModelProperty("获奖分数 ")
+    @TableField(value = "ranking_score_")
+    private Double rankingScore;
+
     public Long getId() {
         return id;
     }
@@ -317,4 +326,20 @@ public class ActivityPlan implements Serializable {
     public void setRankingRule(ActivityRankingRuleEnum rankingRule) {
         this.rankingRule = rankingRule;
     }
+
+    public ActivityRankingMethodEnum getRankingMethod() {
+        return rankingMethod;
+    }
+
+    public void setRankingMethod(ActivityRankingMethodEnum rankingMethod) {
+        this.rankingMethod = rankingMethod;
+    }
+
+    public Double getRankingScore() {
+        return rankingScore;
+    }
+
+    public void setRankingScore(Double rankingScore) {
+        this.rankingScore = rankingScore;
+    }
 }

+ 13 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/ActivityUserReward.java

@@ -56,6 +56,11 @@ public class ActivityUserReward implements Serializable {
     @TableField(value = "winning_time_")
     private Date winningTime;
 
+
+    @ApiModelProperty("领奖时间 ")
+    @TableField(value = "receive_time_")
+    private Date receiveTime;
+
     @ApiModelProperty("奖品单位 同奖品表")
     @TableField(value = "unit_")
     private String unit;
@@ -69,6 +74,14 @@ public class ActivityUserReward implements Serializable {
     @TableField(value = "ranking_rule_")
     private ActivityRankingRuleEnum rankingRule;
 
+    public Date getReceiveTime() {
+        return receiveTime;
+    }
+
+    public void setReceiveTime(Date receiveTime) {
+        this.receiveTime = receiveTime;
+    }
+
     public Integer getRanking() {
         return ranking;
     }

+ 24 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicAlbum.java

@@ -90,6 +90,14 @@ public class MusicAlbum extends BaseEntity {
 	@ApiModelProperty("假删除标识 0:未删除 1:已删除")
 	private Boolean delFlag;
 
+	@TableField("album_price_")
+	@ApiModelProperty("专辑价格 ")
+	private Double albumPrice;
+
+	@TableField("payment_type_")
+	@ApiModelProperty("专辑价格 ")
+	private String paymentType;
+
 	public String getSubjectId() {
 		return subjectId;
 	}
@@ -236,4 +244,20 @@ public class MusicAlbum extends BaseEntity {
 	public void setAuditVersion(YesOrNoEnum auditVersion) {
 		this.auditVersion = auditVersion;
 	}
+
+	public Double getAlbumPrice() {
+		return albumPrice;
+	}
+
+	public void setAlbumPrice(Double albumPrice) {
+		this.albumPrice = albumPrice;
+	}
+
+	public String getPaymentType() {
+		return paymentType;
+	}
+
+	public void setPaymentType(String paymentType) {
+		this.paymentType = paymentType;
+	}
 }

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

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.biz.dal.entity;
 
 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.common.entity.BaseEntity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
@@ -67,6 +68,10 @@ public class MusicSheetPurchaseRecord extends BaseEntity {
     @ApiModelProperty(value = "订单状态(WAIT_PAY:待支付;PAYING:支付中,PAID:已付款)")
     private OrderStatusEnum orderStatus;  //订单状态(1:已完成;0:取消)
 
+	@TableField("purchase_type_")
+	@ApiModelProperty("购买类型 ")
+	private PurchaseRecordTypeEnum purchaseType;
+
 	public ClientEnum getClientType() {
 		return clientType;
 	}
@@ -163,8 +168,15 @@ public class MusicSheetPurchaseRecord extends BaseEntity {
 	    return this.orderStatus;
 	}
 
+	public PurchaseRecordTypeEnum getPurchaseType() {
+		return purchaseType;
+	}
+
+	public void setPurchaseType(PurchaseRecordTypeEnum purchaseType) {
+		this.purchaseType = purchaseType;
+	}
 
-    @Override
+	@Override
     public String toString() {
         return ToStringBuilder.reflectionToString(this);
     }

+ 10 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/ChargeTypeEnum.java

@@ -30,4 +30,14 @@ public enum ChargeTypeEnum implements BaseEnum<String, ChargeTypeEnum> {
     public String getCode() {
         return this.code;
     }
+
+    /**
+     * 收费类型匹配
+     * @param type 收费类型
+     * @return boolean
+     */
+    public boolean match(String type) {
+
+        return getCode().equals(type);
+    }
 }

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

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

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

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

+ 34 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/activity/ActivityRankingMethodEnum.java

@@ -0,0 +1,34 @@
+package com.yonge.cooleshow.biz.dal.enums.activity;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.toolset.base.enums.BaseEnum;
+
+/**
+ * 活动获奖排名方式
+ *
+ * @Author: Eric
+ * @Data: 2022/3/16 10:19
+ */
+public enum ActivityRankingMethodEnum implements BaseEnum<String, ActivityRankingMethodEnum> {
+
+    MUSIC_RANKING("单曲排名"),
+    TOTAL_SCORE("总分排名"),
+    ;
+    @EnumValue
+    private String code;
+    private String name;
+
+    ActivityRankingMethodEnum(String name) {
+        this.code = this.name();
+        this.name = name;
+    }
+
+    @Override
+    public String getCode() {
+        return this.code;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

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

@@ -13,6 +13,7 @@ public enum ActivityRankingRuleEnum implements BaseEnum<String, ActivityRankingR
 
     EVALUATIONS_NUMBER("评测次数"),
     EVALUATIONS_TIME("评测时间"),
+    TOTAL_SCORE("评测总分"),
     ;
     @EnumValue
     private String code;

+ 41 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/album/PurchaseRecordTypeEnum.java

@@ -0,0 +1,41 @@
+package com.yonge.cooleshow.biz.dal.enums.album;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.toolset.base.enums.BaseEnum;
+
+/**
+ * 单曲、专辑付费购买类型
+ */
+public enum PurchaseRecordTypeEnum implements BaseEnum<String, PurchaseRecordTypeEnum> {
+
+    MUSIC("单曲"),
+    ALBUM("专辑"),
+    ;
+    @EnumValue
+    private String code;
+    private String msg;
+
+    PurchaseRecordTypeEnum(String msg) {
+        this.code = this.name();
+        this.msg = msg;
+    }
+
+    public String getMsg() {
+        return this.msg;
+    }
+
+    @Override
+    public String getCode() {
+        return this.code;
+    }
+
+    /**
+     * 收费类型匹配
+     * @param type 收费类型
+     * @return boolean
+     */
+    public boolean match(String type) {
+
+        return getCode().equals(type);
+    }
+}

+ 29 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CourseScheduleMapper.java

@@ -0,0 +1,29 @@
+package com.yonge.cooleshow.biz.dal.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
+import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingTeacherWrapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 用户表 Mapper 接口
+ * </p>
+ *
+ * @author Eric
+ * @since 2022-09-02
+ */
+@Repository
+public interface CourseScheduleMapper extends BaseMapper<CourseSchedule> {
+
+
+    /**
+     * 查询课程数
+     */
+    List<UserBindingTeacherWrapper.CourseNum> selectStudentPianoCourse(@Param("teacherId") Long teacherId, @Param(
+            "studentIdList") List<Long> studentIdList);
+}

+ 19 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/StudentMapper.java

@@ -0,0 +1,19 @@
+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.Student;
+import com.yonge.cooleshow.biz.dal.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.vo.CouponIssueUserVo;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+
+@Repository
+public interface StudentMapper extends BaseMapper<Student> {
+
+
+}

+ 13 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/SubjectMapper.java

@@ -0,0 +1,13 @@
+package com.yonge.cooleshow.biz.dal.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yonge.cooleshow.biz.dal.entity.Student;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
+import org.springframework.stereotype.Repository;
+
+
+@Repository
+public interface SubjectMapper extends BaseMapper<Subject> {
+
+
+}

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

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.biz.dal.mapper;
 
 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;
@@ -31,4 +32,14 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
      */
     List<CouponIssueUserVo> queryCouponIssueUser(@Param("iPage") IPage<CouponIssueUserVo> iPage, @Param(
             "client") ClientEnum client, @Param("keyword") String keyword);
+
+
+    /***
+     * 修改用户实名信息
+     * @author liweifan
+     * @param: teacherApplyDetailDto
+     * @updateTime 2022/3/18 15:57
+     * @return: java.lang.Integer
+     */
+    Integer updateUserCard(@Param("param") RealnameAuthReq param);
 }

+ 102 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/TeacherBindingUserQueryInfo.java

@@ -0,0 +1,102 @@
+package com.yonge.cooleshow.biz.dal.queryInfo;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-10-08
+ */
+public class TeacherBindingUserQueryInfo {
+
+    // 老师绑定的学生列表查询
+    public static class BindingUserQuery{
+
+        // 老师id
+        private Long teacherId;
+
+        // 查询条件 昵称、编号、手机号
+        private String search;
+
+        // 绑定开始时间
+        private Date startTime;
+
+        // 绑定结束时间
+        private Date endTime;
+
+
+        public static BindingUserQuery from(String recv) {
+
+            return JSON.parseObject(recv, BindingUserQuery.class);
+        }
+
+        public Long getTeacherId() {
+            return teacherId;
+        }
+
+        public void setTeacherId(Long teacherId) {
+            this.teacherId = teacherId;
+        }
+
+        public String getSearch() {
+            return search;
+        }
+
+        public void setSearch(String search) {
+            this.search = search;
+        }
+
+        public Date getStartTime() {
+            return startTime;
+        }
+
+        public void setStartTime(Date startTime) {
+            this.startTime = startTime;
+        }
+
+        public Date getEndTime() {
+            return endTime;
+        }
+
+        public void setEndTime(Date endTime) {
+            this.endTime = endTime;
+        }
+    }
+    // 绑定学生课程列表查询
+    public static class BindingStudentCourseQuery{
+
+        // 老师id
+        private Long teacherId;
+
+        // 学员id
+        private Long studentId;
+
+
+        public static BindingStudentCourseQuery from(String recv) {
+
+            return JSON.parseObject(recv, BindingStudentCourseQuery.class);
+        }
+
+        public Long getTeacherId() {
+            return teacherId;
+        }
+
+        public void setTeacherId(Long teacherId) {
+            this.teacherId = teacherId;
+        }
+
+        public Long getStudentId() {
+            return studentId;
+        }
+
+        public void setStudentId(Long studentId) {
+            this.studentId = studentId;
+        }
+    }
+
+
+
+}

+ 40 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/TeacherQueryInfo.java

@@ -0,0 +1,40 @@
+package com.yonge.cooleshow.biz.dal.queryInfo;
+
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Created by Eric.Shang on 2022/10/9.
+ */
+public class TeacherQueryInfo {
+
+    /**
+     * 老师粉丝数查询条件
+     */
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class FansQuery implements Serializable {
+
+        private Long teacherId;
+        private Date startTime;
+        private Date endTime;
+        // 昵称
+        private String nickname;
+        // 编号/手机号
+        private Long userId;
+        private String phone;
+
+        public static FansQuery from(String recv) {
+
+            return JSON.parseObject(recv, FansQuery.class);
+        }
+    }
+}

+ 52 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/queryInfo/UserRewardQueryInfo.java

@@ -0,0 +1,52 @@
+package com.yonge.cooleshow.biz.dal.queryInfo;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+
+/**
+ * Description 用户领奖查询
+ *
+ * @author liujunchi
+ * @date 2022-10-08
+ */
+public class UserRewardQueryInfo {
+
+    // 用户id
+    private Long userId;
+
+    // 客户端类型
+    private ClientEnum client;
+
+
+    // 是否领取
+    private YesOrNoEnum receive;
+    public static UserRewardQueryInfo from(String recv) {
+
+        return JSON.parseObject(recv, UserRewardQueryInfo.class);
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public ClientEnum getClient() {
+        return client;
+    }
+
+    public void setClient(ClientEnum client) {
+        this.client = client;
+    }
+
+    public YesOrNoEnum getReceive() {
+        return receive;
+    }
+
+    public void setReceive(YesOrNoEnum receive) {
+        this.receive = receive;
+    }
+}

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ActivityEvaluationRecordService.java

@@ -87,4 +87,6 @@ public interface ActivityEvaluationRecordService extends IService<ActivityEvalua
 	 * @return List<ActivityEvaluationRecord>
 	 */
 	List<ActivityEvaluationRecord> queryActivityUserHighestRankingInfo(Long activityId, List<Long> userIds);
+
+
 }

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

@@ -77,4 +77,12 @@ public interface ActivityEvaluationService extends IService<ActivityEvaluation>
 	 * @return IPage<ActivityTeacherWrapper>
 	 */
 	IPage<ActivityTeacherWrapper> activityTeacherByTimePageInfo(IPage<ActivityTeacherWrapper> page, ActivityTeacherQuery query);
+
+	/**
+	 * 批量更新评测曲目信息
+	 * @param user SysUser
+	 * @param info ActivityEvaluationDto
+	 * @return int
+	 */
+    int batchUpdateEvaluationInfo(SysUser user, ActivityEvaluationDto info);
 }

+ 12 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ActivityRewardService.java

@@ -83,7 +83,7 @@ public interface ActivityRewardService extends IService<ActivityReward>  {
 	IPage<ActivityRewardChangeStockVo> selectChangeStockPage(IPage<ActivityRewardChangeStockVo> page, ActivityRewardChangeStockSearch query);
 
 	/**
-	 * 发放获奖奖品
+	 * 发放获奖奖品 记录
 	 * @param userId 用户id
 	 * @param activityId 活动id
 	 * @param activityRewardIds 活动关联奖品ID
@@ -92,5 +92,15 @@ public interface ActivityRewardService extends IService<ActivityReward>  {
 	 */
 	List<Long> sendReward(Long userId, Long activityId, List<Long> activityRewardIds, Date date);
 
-	Boolean userRewarded(Long userId, Long activityId);
+	/**
+	 * 领取奖品
+	 *
+	 * @param userId 用户id
+	 * @param date 领取时间
+	 * @param activityPlanId 活动id
+	 * @param activityRewardId 奖品id
+	 */
+    void receiveReward(Long userId, Date date, Long activityPlanId, Long activityRewardId);
+
+    Boolean userRewarded(Long userId, Long activityId);
 }

+ 23 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ActivityUserRewardService.java

@@ -2,10 +2,13 @@ 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.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.queryInfo.UserRewardQueryInfo;
 import com.yonge.cooleshow.biz.dal.vo.ActivityUserRewardVo;
 import com.yonge.cooleshow.biz.dal.dto.search.ActivityUserRewardSearch;
 import com.yonge.cooleshow.biz.dal.entity.ActivityUserReward;
 import com.yonge.cooleshow.biz.dal.vo.UserRewardVo;
+import com.yonge.cooleshow.biz.dal.vo.activity.UserRewardWrapper;
 
 /**
  * 活动用户获奖表 服务类
@@ -36,4 +39,24 @@ public interface ActivityUserRewardService extends IService<ActivityUserReward>
 	 * @param userId 用户id
 	 */
     void saveRewardRecord(Long activityId, Long rewardId, Long userId);
+
+	/**
+	 * 检查是否存在未领取的奖品
+	 *
+	 * @param userId 用户id
+	 * @param client 客户端
+	 * @return
+	 */
+    Boolean checkReceiveReward(Long userId, ClientEnum client);
+
+	/**
+	 * 领奖
+	 *
+	 */
+	Boolean receiveReward(Long userId, Long receiveRewardId);
+
+	/**
+	 * 发放奖品记录
+	 */
+	IPage<UserRewardWrapper> receiveRewardList(IPage<UserRewardWrapper> page, UserRewardQueryInfo query);
 }

+ 6 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CouponIssueService.java

@@ -51,7 +51,12 @@ public interface CouponIssueService extends IService<CouponIssue> {
      * @param date
      * @return
      */
-    Boolean issueCoupon(Long couponId, List<UserParam> userParam, Long issuer, String reason, Boolean sendMessage, Boolean throwE, SendTypeEnum issueWay, Date date);
+    void issueCoupon(Long couponId, List<UserParam> userParam, Long issuer, String reason,SendTypeEnum issueWay, Date date);
+
+    /**
+     * 保存发放优惠券记录,不发推送
+     */
+    void saveIssueCoupon(Long couponId, List<UserParam> userParam, Long issuer, String reason, SendTypeEnum issueWay, Date date);
 
     /**
      * 查询能发放优惠券的用户列表

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

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.biz.dal.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dao.ImUserFriendDao;
 import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 
 import java.util.List;
 import java.util.Set;
@@ -43,5 +44,12 @@ public interface ImUserFriendService extends IService<ImUserFriend> {
      * @return Integer
      */
     Integer registerUserBindCustomerService(Long userId, List<Long> friendIds);
+
+    /**
+     * 发送系统客服消息
+     * @param sender 发送者
+     * @param info CustomerService.NotifyMessage
+     */
+    void sendCustomerServiceNotifyMessage(String sender, CustomerService.NotifyMessage info);
 }
 

+ 4 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicAlbumService.java

@@ -2,6 +2,7 @@ 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.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dto.MusicAlbumSheetDto;
 import com.yonge.cooleshow.biz.dal.dto.MusicAlbumSheetSortDto;
 import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumDetailSearch;
@@ -46,9 +47,11 @@ public interface MusicAlbumService extends IService<MusicAlbum> {
      *
      * @param page 分页信息
      * @param query 查询条件
+     * @param sysUser
+     * @param student
      * @return AlbumDetailVo
      */
-    AlbumDetailVo detail(IPage<MusicSheetVo> page, MusicAlbumDetailSearch query);
+    AlbumDetailVo detail(IPage<MusicSheetVo> page, MusicAlbumDetailSearch query, SysUser sysUser, ClientEnum client);
 
     /**
      * 删除专辑详情关联曲目

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

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.biz.dal.service;
 import com.yonge.cooleshow.biz.dal.entity.MusicSheetPurchaseRecord;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
 
 /**
  * MusicSheetPurchaseRecordService服务类
@@ -19,5 +20,5 @@ public interface MusicSheetPurchaseRecordService extends IService<MusicSheetPurc
      * @param musicSheetId 曲目id
      * @return boolean
      */
-    MusicSheetPurchaseRecord checkPurchase(Long userId, Long musicSheetId, ClientEnum clientType);
+    MusicSheetPurchaseRecord checkPurchase(Long userId, Long musicSheetId, ClientEnum clientType, PurchaseRecordTypeEnum purchaseType);
 }

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

@@ -1,6 +1,9 @@
 package com.yonge.cooleshow.biz.dal.service;
 
+import com.yonge.cooleshow.auth.api.dto.RealnameAuthReq;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.toolset.utils.idcard.IdcardInfoExtractor;
 
 public interface SysUserService{
 
@@ -9,4 +12,13 @@ public interface SysUserService{
     SysUser getUser();
 
     SysUser findUserById(Long userId);
+
+    /**
+     * 实名 + 注册协议
+     *
+     *  @param realNameAuthDto
+     * @param sysUser
+     * @param client
+     */
+    IdcardInfoExtractor updateUserCard(RealnameAuthReq realNameAuthDto, SysUser sysUser, ClientEnum client);
 }

+ 24 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/TeacherService.java

@@ -9,7 +9,9 @@ import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.cooleshow.biz.dal.entity.Teacher;
 import com.yonge.cooleshow.biz.dal.entity.TeacherStyleVideo;
 import com.yonge.cooleshow.biz.dal.enums.TeacherTagEnum;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherQueryInfo;
 import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.wrapper.teacher.TeacherWrapper;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 
 import java.util.List;
@@ -138,6 +140,14 @@ public interface TeacherService extends IService<Teacher> {
     IPage<MyFens> queryMyFans(IPage<MyFens> page, Long teacherId);
 
     /**
+     * 老师粉丝查询
+     * @param page IPage<MyFens>
+     * @param query TeacherQueryInfo.FansQuery
+     * @return IPage<MyFens>
+     */
+    IPage<MyFens> queryMyFans(IPage<MyFens> page, TeacherQueryInfo.FansQuery query);
+
+    /**
      * 设置老师标签
      *
      * @param userId 老师id
@@ -151,4 +161,18 @@ public interface TeacherService extends IService<Teacher> {
      * @return
      */
     List<HotTeacherVo> queryHotTeacherList(Long userId);
+
+    /**
+     * 老师详情信息
+     * @param teacherId 用户ID
+     * @return TeacherVo
+     */
+    TeacherVo findTeacherDetailInfo(Long teacherId);
+
+    /**
+     * 老师统计指标信息
+     * @param userId 用户ID
+     * @return TeacherWrapper.TeacherStatInfo
+     */
+    TeacherWrapper.TeacherStatInfo findTeacherStatInfoById(Long userId);
 }

+ 18 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserBindingTeacherService.java

@@ -1,7 +1,11 @@
 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.UserBindingTeacher;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherBindingUserQueryInfo;
+import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingCourseWrapper;
+import com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingTeacherWrapper;
 
 /**
  * @Author: cy
@@ -12,5 +16,19 @@ public interface UserBindingTeacherService extends IService<UserBindingTeacher>
      * 超过天数无琴房课的解除绑定关系
      */
     void unbindTask();
+
+    /**
+     * 查询老师绑定学生数据
+     *
+     * @param page
+     * @param query
+     * @return
+     */
+    IPage<UserBindingTeacherWrapper> selectBindingUserPage(IPage<UserBindingTeacherWrapper> page, TeacherBindingUserQueryInfo.BindingUserQuery query);
+
+    /**
+     * 查询老师绑定的学生课程信息
+     */
+    IPage<UserBindingCourseWrapper> selectBindingUserCoursePage(IPage<UserBindingCourseWrapper> page, TeacherBindingUserQueryInfo.BindingStudentCourseQuery query);
 }
 

+ 203 - 19
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityEvaluationRecordServiceImpl.java

@@ -1,43 +1,63 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
-
-import com.google.common.collect.Lists;
-import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
-import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingRuleEnum;
-import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
-import org.apache.commons.collections.CollectionUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import com.yonge.cooleshow.biz.dal.dao.ActivityEvaluationRecordDao;
+import com.yonge.cooleshow.biz.dal.dao.ActivityPlanDao;
+import com.yonge.cooleshow.biz.dal.dao.StudentDao;
 import com.yonge.cooleshow.biz.dal.dto.search.ActivityEvaluationRecordSearch;
 import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluation;
 import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluationRecord;
+import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
+import com.yonge.cooleshow.biz.dal.entity.Student;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
+import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationService;
+import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
+import com.yonge.cooleshow.biz.dal.service.SubjectService;
 import com.yonge.cooleshow.biz.dal.vo.ActivityEvaluationRecordVo;
 import com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo;
 import com.yonge.cooleshow.common.enums.ActivityResourceEnum;
 import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.util.ThreadPool;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.joda.time.DateTime;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
 
+@Slf4j
 @Service
 public class ActivityEvaluationRecordServiceImpl extends ServiceImpl<ActivityEvaluationRecordDao, ActivityEvaluationRecord> implements ActivityEvaluationRecordService {
-    private final static Logger log = LoggerFactory.getLogger(ActivityEvaluationRecordServiceImpl.class);
 
     @Autowired
     private ActivityEvaluationService activityEvaluationService;
-
+    @Autowired
+    private ActivityEvaluationRecordService activityEvaluationRecordService;
     @Autowired
     private ActivityPlanService activityPlanService;
+    @Autowired
+    private MusicSheetService musicSheetService;
+    @Autowired
+    private ActivityPlanDao activityPlanMapper;
+    @Autowired
+    private StudentDao studentMapper;
+    @Autowired
+    private SubjectService subjectService;
 
 	@Override
     public ActivityEvaluationRecordVo detail(Long id) {
@@ -63,10 +83,13 @@ public class ActivityEvaluationRecordServiceImpl extends ServiceImpl<ActivityEva
         if (activityEvaluation == null) {
             throw new BizException("未找到评测项目");
         }
+
+        // 记录曲目评测试分数
         ActivityEvaluationRecord activityEvaluationRecord = new ActivityEvaluationRecord();
         activityEvaluationRecord.setActivityId(activityEvaluation.getActivityId());
         activityEvaluationRecord.setUserId(userId);
         activityEvaluationRecord.setEvaluationId(evaluationId);
+        activityEvaluationRecord.setResourceId(activityEvaluation.getMusicSheetId());
         activityEvaluationRecord.setCreateTime(new Date());
         activityEvaluationRecord.setScore(score == null ? 0:score.doubleValue());
         
@@ -77,6 +100,99 @@ public class ActivityEvaluationRecordServiceImpl extends ServiceImpl<ActivityEva
         	activityEvaluationRecord.setTimes(lastestRecord.getTimes() + 1);
         }
         save(activityEvaluationRecord);
+
+        // 活动信息
+        ActivityPlan activity = activityPlanService.getById(activityEvaluation.getActivityId());
+        if (ActivityRankingMethodEnum.TOTAL_SCORE == activity.getRankingMethod()) {
+
+            // 若为总分评测,计算声部分数
+            ThreadPool.getExecutor().submit(() -> {
+
+                List<ActivityEvaluationRecord> records = activityEvaluationRecordService.list(Wrappers.<ActivityEvaluationRecord>lambdaQuery()
+                        .eq(ActivityEvaluationRecord::getActivityId, activityEvaluation.getActivityId())
+                        .eq(ActivityEvaluationRecord::getUserId, userId));
+
+                // 用户当前声部所有评测数据,获取单曲最高进行加和计算为声部最高分
+                Map<Long, Double> highestScoreMap = records.stream()
+                        .filter(x -> Optional.ofNullable(x.getScore()).orElse(0D) > 0)
+                        .filter(x -> Optional.ofNullable(x.getEvaluationId()).orElse(0L) > 0)
+                        .collect(Collectors.groupingBy(ActivityEvaluationRecord::getEvaluationId,
+                                Collectors.mapping(ActivityEvaluationRecord::getScore, Collectors.toSet())))
+                        .entrySet().stream()
+                        .collect(Collectors.toMap(Map.Entry::getKey,
+                                x -> x.getValue().stream().mapToDouble(Double::doubleValue).max().orElse(0D), (o, n) -> n));
+
+                // 最高分
+                double sumScore = highestScoreMap.values().stream().mapToDouble(Double::doubleValue).sum();
+
+                // 获取最高分的时间为每个单曲最高分的记录时间
+                Map<Long, Long> highestScoreTimeMap = records.stream()
+                        .filter(x -> Optional.ofNullable(x.getScore()).orElse(0D) > 0)
+                        .filter(x -> Optional.ofNullable(x.getEvaluationId()).orElse(0L) > 0)
+                        .filter(x -> highestScoreMap.getOrDefault(x.getEvaluationId(), -1D).doubleValue() == x.getScore())
+                        .collect(Collectors.groupingBy(ActivityEvaluationRecord::getEvaluationId, Collectors.mapping(x -> x.getCreateTime().getTime(), Collectors.toSet())))
+                        .entrySet().stream()
+                        .collect(Collectors.toMap(Map.Entry::getKey,
+                                x -> x.getValue().stream().mapToLong(Long::longValue).max().orElse(0L), (o, n) -> n));
+
+                // 最高分时间
+                long highScoreTime = highestScoreTimeMap.values().stream().mapToLong(Long::longValue).max().orElse(DateTime.now().getMillis());
+
+                // 若分总相同,最高分时间相同,则根据用户活动报名时间进行排序
+                Date registrationTime = records.stream()
+                        .filter(x -> Objects.isNull(x.getScore()))
+                        .min(Comparator.comparing(ActivityEvaluationRecord::getId))
+                        .map(ActivityEvaluationRecord::getCreateTime).orElse(DateTime.now().toDate());
+
+                // 查询用户声部评分记录
+                ActivityEvaluationRecord evaluationRecord = activityEvaluationRecordService.getOne(Wrappers.<ActivityEvaluationRecord>lambdaQuery()
+                        .eq(ActivityEvaluationRecord::getActivityId, activity.getId())
+                        .eq(ActivityEvaluationRecord::getUserId, userId)
+                        .eq(ActivityEvaluationRecord::getRankingMethod, activity.getRankingMethod())
+                );
+
+                if (Objects.isNull(evaluationRecord)) {
+
+                    MusicSheet musicSheet = musicSheetService.getById(activityEvaluation.getMusicSheetId());
+
+                    long subjectId = 0;
+                    if (Objects.nonNull(musicSheet)) {
+                        subjectId = Long.parseLong(musicSheet.getMusicSubject().split(",")[0]);
+                    }
+                    // 添加用户声部总分记录
+                    ActivityEvaluationRecord record = new ActivityEvaluationRecord();
+
+                    record.setActivityId(activityEvaluation.getActivityId());
+                    record.setUserId(userId);
+                    record.setEvaluationId(0L);
+                    // 声部ID
+                    record.setResourceId(subjectId);
+                    record.setRegistrationTime(registrationTime.getTime());
+                    record.setRankingMethod(activity.getRankingMethod());
+                    record.setTimes(0);
+                    // 最高分时间
+                    record.setCreateTime(new DateTime(highScoreTime).toDate());
+                    record.setScore(sumScore);
+
+                    save(record);
+                }
+
+                // 更新最高分记录
+                if (Objects.nonNull(evaluationRecord)
+                        && evaluationRecord.getScore() < sumScore) {
+
+                    ActivityEvaluationRecord record = new ActivityEvaluationRecord();
+
+                    record.setId(evaluationRecord.getId());
+                    record.setScore(sumScore);
+                    record.setCreateTime(new DateTime(highScoreTime).toDate());
+
+                    updateById(record);
+                }
+
+            });
+        }
+
     }
 
 
@@ -105,7 +221,41 @@ public class ActivityEvaluationRecordServiceImpl extends ServiceImpl<ActivityEva
         if (activityPlan == null) {
             throw new BizException("活动已结束");
         }
-		return baseMapper.queryRankingList(activityPlanId, activityEvaluationId, limit,activityPlan.getRankingRule());
+
+        List<ActivityRankingVo> activityRankings;
+        // 活动排名
+        if (ActivityRankingMethodEnum.TOTAL_SCORE == activityPlan.getRankingMethod()) {
+
+            // 总分排名, 根据声部ID进行查询
+            activityRankings = activityPlanMapper.selectActivityHighestScoreRankingInfo(activityPlanId, activityEvaluationId,
+                    1D, limit);
+
+            List<Long> userIds = activityRankings.stream()
+                    .map(ActivityRankingVo::getUserId).distinct().collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(userIds)) {
+
+                Map<Long, Long> userSubjectMap = studentMapper.selectList(Wrappers.<Student>lambdaQuery().in(Student::getUserId, userIds)).stream()
+                        .filter(x -> Objects.nonNull(x.getSubjectId()))
+                        .collect(Collectors.toMap(Student::getUserId, x -> Long.parseLong(Optional.ofNullable(x.getSubjectId()).orElse("0").split(",")[0]), (o, n) -> n));
+
+
+                Map<Long, String> subjectNameMap = subjectService.findBySubjectByIdList(Lists.newArrayList(userSubjectMap.values())).stream()
+                        .collect(Collectors.toMap(Subject::getId, Subject::getName, (o, n) -> n));
+
+                for (ActivityRankingVo item : activityRankings) {
+
+                    item.setUserSubject(subjectNameMap.getOrDefault(userSubjectMap.get(item.getUserId()), ""));
+                }
+            }
+
+        } else {
+
+            // 单曲排名
+            activityRankings = baseMapper.queryRankingList(activityPlanId, activityEvaluationId, limit, activityPlan.getRankingRule());
+        }
+
+        return activityRankings;
 	}
 
 	@Override
@@ -114,7 +264,41 @@ public class ActivityEvaluationRecordServiceImpl extends ServiceImpl<ActivityEva
         if (activityPlan == null) {
             throw new BizException("活动已结束");
         }
-        return baseMapper.queryUserRanking(activityPlanId, activityEvaluationId, userId,activityPlan.getRankingRule());
+
+        // 用户排名信息
+        ActivityRankingVo userRanking;
+
+        if (ActivityRankingMethodEnum.TOTAL_SCORE == activityPlan.getRankingMethod()) {
+
+            // 总分排名
+            userRanking = activityPlanMapper.selectActivityHighestScoreUserRanking(activityPlanId, activityEvaluationId,
+                    1D, userId);
+
+            // 学生声部信息
+            Student student = studentMapper.selectOne(Wrappers.<Student>lambdaQuery().eq(Student::getUserId, userId));
+
+            String userSubject = "";
+            if (Objects.nonNull(student) && Objects.nonNull(student.getSubjectId())) {
+                long subjectId = Long.parseLong(student.getSubjectId().split(",")[0]);
+
+                Subject subject = subjectService.get(subjectId);
+
+                // 学生声部信息
+                userSubject = Optional.ofNullable(subject).map(Subject::getName).orElse("");
+            }
+
+            if (Objects.nonNull(userRanking)) {
+
+                userRanking.setUserSubject(userSubject);
+            }
+
+        } else {
+
+            // 单曲排名
+            userRanking = baseMapper.queryUserRanking(activityPlanId, activityEvaluationId, userId, activityPlan.getRankingRule());
+        }
+
+        return userRanking;
 	}
 
     /**

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

@@ -1,5 +1,6 @@
 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.service.impl.ServiceImpl;
@@ -15,6 +16,7 @@ import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluation;
 import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
 import com.yonge.cooleshow.biz.dal.entity.ActivityPlanReward;
 import com.yonge.cooleshow.biz.dal.entity.Subject;
+import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationService;
 import com.yonge.cooleshow.biz.dal.service.ActivityPlanRewardService;
@@ -26,9 +28,11 @@ import com.yonge.cooleshow.biz.dal.vo.ActivityMusicVo;
 import com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo;
 import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
 import com.yonge.cooleshow.biz.dal.vo.activity.ActivityTeacherWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import com.yonge.cooleshow.common.enums.ActivityResourceEnum;
 import com.yonge.cooleshow.common.enums.ActivityTypeEnum;
 import com.yonge.cooleshow.common.enums.EStatus;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.exception.BizException;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -68,7 +72,28 @@ public class ActivityEvaluationServiceImpl extends ServiceImpl<ActivityEvaluatio
 
     @Override
     public IPage<ActivityEvaluationVo> selectPage(IPage<ActivityEvaluationVo> page, ActivityEvaluationSearch query) {
-        return page.setRecords(baseMapper.selectPage(page, query));
+
+        ActivityPlan activity = activityPlanService.getById(query.getActivityId());
+        if (Objects.isNull(activity)) {
+            throw new BizException("无效的活动ID");
+        }
+
+        List<ActivityEvaluationVo> evaluationInfos = baseMapper.selectPage(page, query);
+        // 排序方式
+        if (ActivityTypeEnum.EVALUATION == activity.getActivityType()
+                && ActivityRankingMethodEnum.TOTAL_SCORE == activity.getRankingMethod()) {
+
+            // 按声部聚合数据返回
+            evaluationInfos = evaluationInfos.stream()
+                    .collect(Collectors.groupingBy(x -> Long.parseLong(x.getSubjectId().split(",")[0])))
+                    .entrySet().stream()
+                    .sorted(Map.Entry.comparingByKey())
+                    .flatMap(x -> x.getValue().stream())
+                    .collect(Collectors.toList());
+
+        }
+
+        return page.setRecords(evaluationInfos);
     }
 
     @Override
@@ -146,8 +171,9 @@ public class ActivityEvaluationServiceImpl extends ServiceImpl<ActivityEvaluatio
         activityContentIds.removeAll(oldMusicSheetIds);
 
         if ((oldMusicSheetIds.size() + activityContentIds.size()) > 10
+                && activity.getRankingMethod() == ActivityRankingMethodEnum.MUSIC_RANKING
                 && activityType == ActivityTypeEnum.EVALUATION) {
-
+            // 评测活动、曲目排名需要限制曲目数量
             throw new BizException("添加的曲目不能多余10首");
         }
         if (CollectionUtils.isNotEmpty(activityContentIds)) {
@@ -179,17 +205,59 @@ public class ActivityEvaluationServiceImpl extends ServiceImpl<ActivityEvaluatio
 
     @Override
     public List<ActivityMusicVo> getActivityMusic(Long activityPlanId, Long userId) {
+
+        // 活动曲目信息
         List<ActivityMusicVo> result = baseMapper.selectActivityMusic(activityPlanId, userId);
-        for (ActivityMusicVo activityMusicVo : result) {
-        	List<ActivityRankingVo> rankingList =  activityEvaluationRecordService.queryRankingList(activityPlanId, activityMusicVo.getEvaluationId(), 1);
-            if (rankingList != null && rankingList.size() > 0) {
-                activityMusicVo.setUserSubject(rankingList.get(0).getUserSubject());
-                activityMusicVo.setScore(rankingList.get(0).getScore());
-                activityMusicVo.setUserAvatar(rankingList.get(0).getUserAvatar());
-                activityMusicVo.setUsername(rankingList.get(0).getUsername());
-                activityMusicVo.setUserId(rankingList.get(0).getUserId());
+
+        // 活动信息
+        ActivityPlan activity = activityPlanService.getById(activityPlanId);
+        if (Objects.isNull(activity)) {
+            throw new BizException("无效的活动ID");
+        }
+
+        // 评测活动
+        if (ActivityTypeEnum.EVALUATION == activity.getActivityType()) {
+
+
+            // 单曲排名,计算每一个曲目的最高分
+            if (ActivityRankingMethodEnum.MUSIC_RANKING == activity.getRankingMethod()) {
+
+                result.parallelStream().forEach(item -> {
+
+                    List<ActivityRankingVo> rankingList =  activityEvaluationRecordService.queryRankingList(activityPlanId, item.getEvaluationId(), 1);
+                    if (rankingList != null && rankingList.size() > 0) {
+                        item.setUserSubject(rankingList.get(0).getUserSubject());
+                        item.setScore(rankingList.get(0).getScore());
+                        item.setUserAvatar(rankingList.get(0).getUserAvatar());
+                        item.setUsername(rankingList.get(0).getUsername());
+                        item.setUserId(rankingList.get(0).getUserId());
+                    }
+
+                });
+
+            }
+
+            // 总分排名
+            if (ActivityRankingMethodEnum.TOTAL_SCORE == activity.getRankingMethod()) {
+
+                Map<Long, Double> collect = Maps.newHashMap();
+                if (result.stream().anyMatch(x -> x.getJoin() == YesOrNoEnum.YES
+                        && Objects.nonNull(userId))) {
+
+                    collect = getBaseMapper().selectSubjectMusicHighestScoreStat(activity.getId(), userId).stream()
+                            .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getNumber, (o, n) -> n));
+                }
+
+                for (ActivityMusicVo item : result) {
+
+                    item.setScore(collect.getOrDefault(item.getEvaluationId(), 0D));
+                }
+
+
             }
+
         }
+
         return result;
     }
 
@@ -266,4 +334,26 @@ public class ActivityEvaluationServiceImpl extends ServiceImpl<ActivityEvaluatio
         return page.setRecords(wrappers);
     }
 
+    /**
+     * 批量更新评测曲目信息
+     *
+     * @param user SysUser
+     * @param info ActivityEvaluationDto
+     * @return int
+     */
+    @Transactional
+    @Override
+    public int batchUpdateEvaluationInfo(SysUser user, ActivityEvaluationDto info) {
+
+        List<ActivityEvaluationDto.EvaluationInfo> evaluationInfos = info.getEvaluationInfos();
+
+        List<ActivityEvaluation> evaluations = JSON.parseArray(JSON.toJSONString(evaluationInfos),
+                ActivityEvaluation.class);
+
+        // 批量更新
+        activityEvaluationService.updateBatchById(evaluations, 30);
+
+        return evaluationInfos.size();
+    }
+
 }

+ 93 - 28
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ActivityPlanEvaluationServiceImpl.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yonge.cooleshow.biz.dal.dao.ActivityPlanDao;
 import com.yonge.cooleshow.biz.dal.dto.ActivityPlanDto;
 import com.yonge.cooleshow.biz.dal.dto.ActivityPlanRewardDto;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderPayReq;
@@ -10,6 +11,7 @@ import com.yonge.cooleshow.biz.dal.entity.ActivityPlanReward;
 import com.yonge.cooleshow.biz.dal.entity.ActivityUserReward;
 import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
 import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.vo.ActivityPlanVo;
 import com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo;
@@ -52,6 +54,8 @@ public class ActivityPlanEvaluationServiceImpl extends ServiceImpl<ActivityPlanE
 
     @Autowired
     private ActivityEvaluationService activityEvaluationService;
+    @Autowired
+    private ActivityPlanDao activityPlanMapper;
 
     @Override
     public boolean createOrUpdate(ActivityPlanDto activityPlan) {
@@ -86,7 +90,7 @@ public class ActivityPlanEvaluationServiceImpl extends ServiceImpl<ActivityPlanE
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
+    //@Transactional(rollbackFor = Exception.class)
     public void successActivity(Long activityId) {
         //关闭未付款订单
         closeActivity(activityId);
@@ -110,53 +114,114 @@ public class ActivityPlanEvaluationServiceImpl extends ServiceImpl<ActivityPlanE
         } catch (ParseException e) {
             e.printStackTrace();
         }
-        for (ActivityEvaluation activityEvaluation : activityEvaluationList) {
+        // 总分排名发奖流程
+        if (ActivityRankingMethodEnum.TOTAL_SCORE == detail.getRankingMethod()) {
 
-            List<ActivityRankingVo> activityRankingVos = activityEvaluationRecordService.queryRankingList(activityId,
-                                                              activityEvaluation.getId(),detail.getRanking());
-            for (int i = 0; i < activityRankingVos.size(); i++) {
+            // 查询活动获奖用户信息
+            List<ActivityRankingVo> rankingInfos = activityPlanMapper.selectActivityHighestScoreRankingInfo(detail.getId(), null,
+                    detail.getRankingScore(), 9999);
 
-                ActivityRankingVo activityRankingVo = activityRankingVos.get(i);
+            if (CollectionUtils.isEmpty(detail.getActivityRewardList())) {
+                // 活动未关联奖品,忽略后续流程
+                return;
+            }
 
-                List<ActivityPlanRewardDto> activityPlanRewardDtos = rewardMap.get(i + 1 + "");
-                if (CollectionUtils.isEmpty(activityPlanRewardDtos)) {
-                    continue;
-                }
+            // 活动关联奖品ID
+            List<Long> activityRewardIds = detail.getActivityRewardList().stream()
+                    .map(ActivityPlanReward::getId).collect(Collectors.toList());
 
-                // 活动关联奖品ID
-                List<Long> activityRewardIds = activityPlanRewardDtos.stream()
-                                   .map(ActivityPlanReward::getId).collect(Collectors.toList());
+            int ranking = 0;
+            for (ActivityRankingVo rankingInfo : rankingInfos) {
 
-                //给用户发放奖品 传入用户id和活动id
-                List<Long> collect = activityRewardService.sendReward(activityRankingVo.getUserId(), activityId, activityRewardIds, date);
+                // 推送发奖消息给用户
+                List<Long> collect = activityRewardService.sendReward(rankingInfo.getUserId(), activityId, activityRewardIds, date);
 
-                // 保存奖品发放记录
-                for (ActivityPlanRewardDto item : activityPlanRewardDtos) {
+                // 活动奖品信息
+                for (ActivityPlanRewardDto reward : detail.getActivityRewardList()) {
 
                     ActivityUserReward activityUserReward = new ActivityUserReward();
                     activityUserReward.setActivityId(activityId);
-                    activityUserReward.setBizId(activityEvaluation.getId());
-                    activityUserReward.setUserId(activityRankingVo.getUserId());
+                    activityUserReward.setBizId(rankingInfo.getResourceId());
+                    activityUserReward.setUserId(rankingInfo.getUserId());
                     activityUserReward.setRankingRule(detail.getRankingRule());
-                    activityUserReward.setRanking(i+1);
-                    activityUserReward.setGrantFlag(0);
-                    activityUserReward.setWinningTime(activityRankingVo.getJoinDate());
+                    activityUserReward.setRanking(ranking++);
+                    // 奖品发送状态
+                    activityUserReward.setGrantFlag(collect.contains(reward.getId()) ? 1 : 0);
+                    // 获取最高分时间
+                    activityUserReward.setWinningTime(rankingInfo.getJoinDate());
                     activityUserReward.setCreateTime(date);
                     activityUserReward.setUpdateTime(date);
-                    activityUserReward.setRewardId(item.getRewardId());
+                    activityUserReward.setRewardId(reward.getRewardId());
 
-                    // 奖品发送状态
-                    if (collect.contains(item.getId())) {
-                        activityUserReward.setGrantFlag(1);
-                    }
+                    // 添加发放记录
                     activityUserRewardList.add(activityUserReward);
                 }
 
+                // 若奖品数量超过1000,提交数据刷新缓存
+                if (activityUserRewardList.size() > 1000) {
+
+                    // 提交奖品发放记录
+                    activityUserRewardService.saveBatch(activityUserRewardList);
+
+                    // 清除缓存数据
+                    activityUserRewardList.clear();
+                }
+            }
+
+        } else {
+
+            // 曲目排名发奖流程
+            for (ActivityEvaluation activityEvaluation : activityEvaluationList) {
+
+                List<ActivityRankingVo> activityRankingVos = activityEvaluationRecordService.queryRankingList(activityId,
+                        activityEvaluation.getId(),detail.getRanking());
+                for (int i = 0; i < activityRankingVos.size(); i++) {
+
+                    ActivityRankingVo activityRankingVo = activityRankingVos.get(i);
+
+                    List<ActivityPlanRewardDto> activityPlanRewardDtos = rewardMap.get(i + 1 + "");
+                    if (CollectionUtils.isEmpty(activityPlanRewardDtos)) {
+                        continue;
+                    }
+
+                    // 活动关联奖品ID
+                    List<Long> activityRewardIds = activityPlanRewardDtos.stream()
+                            .map(ActivityPlanReward::getId).collect(Collectors.toList());
+
+                    //给用户发放奖品 传入用户id和活动id
+                    List<Long> collect = activityRewardService.sendReward(activityRankingVo.getUserId(), activityId, activityRewardIds, date);
+
+                    // 保存奖品发放记录
+                    for (ActivityPlanRewardDto item : activityPlanRewardDtos) {
+
+                        ActivityUserReward activityUserReward = new ActivityUserReward();
+                        activityUserReward.setActivityId(activityId);
+                        activityUserReward.setBizId(activityEvaluation.getId());
+                        activityUserReward.setUserId(activityRankingVo.getUserId());
+                        activityUserReward.setRankingRule(detail.getRankingRule());
+                        activityUserReward.setRanking(i+1);
+                        activityUserReward.setGrantFlag(0);
+                        activityUserReward.setWinningTime(activityRankingVo.getJoinDate());
+                        activityUserReward.setCreateTime(date);
+                        activityUserReward.setUpdateTime(date);
+                        activityUserReward.setRewardId(item.getRewardId());
+
+                        // 奖品发送状态
+                        if (collect.contains(item.getId())) {
+                            activityUserReward.setGrantFlag(1);
+                        }
+                        activityUserRewardList.add(activityUserReward);
+                    }
+
+                }
             }
+
         }
-        if (!CollectionUtils.isEmpty(activityUserRewardList)) {
+
+        if (CollectionUtils.isNotEmpty(activityUserRewardList)) {
             activityUserRewardService.saveBatch(activityUserRewardList);
         }
+
         //发完奖后将库存归还
         // activityPlanRewardService.recoveryReward(activityId);
     }

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

@@ -10,6 +10,8 @@ import com.google.common.collect.Maps;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dao.ActivityPlanDao;
+import com.yonge.cooleshow.biz.dal.dao.StudentDao;
+import com.yonge.cooleshow.biz.dal.dao.SubjectDao;
 import com.yonge.cooleshow.biz.dal.dto.ActivityPlanDto;
 import com.yonge.cooleshow.biz.dal.dto.ActivityPlanPayDto;
 import com.yonge.cooleshow.biz.dal.dto.ActivityPlanRewardDto;
@@ -23,10 +25,13 @@ import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
 import com.yonge.cooleshow.biz.dal.entity.ActivityPlanReward;
 import com.yonge.cooleshow.biz.dal.entity.ActivityRegistration;
 import com.yonge.cooleshow.biz.dal.entity.ActivityReward;
+import com.yonge.cooleshow.biz.dal.entity.Student;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.EQueryOp;
 import com.yonge.cooleshow.biz.dal.enums.MK;
 import com.yonge.cooleshow.biz.dal.enums.MessageTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationService;
 import com.yonge.cooleshow.biz.dal.service.ActivityPlanEvaluationService;
@@ -35,9 +40,11 @@ import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
 import com.yonge.cooleshow.biz.dal.service.ActivityPlanStandardService;
 import com.yonge.cooleshow.biz.dal.service.ActivityRegistrationService;
 import com.yonge.cooleshow.biz.dal.service.ActivityRewardService;
+import com.yonge.cooleshow.biz.dal.service.SubjectService;
 import com.yonge.cooleshow.biz.dal.service.SysMessageService;
 import com.yonge.cooleshow.biz.dal.vo.ActivityMusicVo;
 import com.yonge.cooleshow.biz.dal.vo.ActivityPlanVo;
+import com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo;
 import com.yonge.cooleshow.biz.dal.vo.MusicActivityVo;
 import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
 import com.yonge.cooleshow.biz.dal.vo.activity.ActivityTeacherWrapper;
@@ -117,6 +124,10 @@ public class ActivityPlanServiceImpl extends ServiceImpl<ActivityPlanDao, Activi
 
     @Autowired
     private RedissonClient redissonClient;
+    @Autowired
+    private StudentDao studentMapper;
+    @Autowired
+    private SubjectService subjectService;
 
     //保存/更新拓展字段
     private static final Map<ActivityTypeEnum, Consumer<ActivityPlanDto>> saveOrUpdateExpand = new HashMap<>();
@@ -488,6 +499,11 @@ public class ActivityPlanServiceImpl extends ServiceImpl<ActivityPlanDao, Activi
     @Override
     public MusicActivityVo getActivityInfo(Long activityPlanId, SysUser user) {
         ActivityPlan activityPlan = this.getById(activityPlanId);
+
+        if (Objects.isNull(activityPlan)) {
+            throw new BizException("无效的活动ID");
+        }
+
         if (activityPlan.getActivityState() != 1) {
             activityPlan.setActivityState(0);
         }
@@ -501,9 +517,127 @@ public class ActivityPlanServiceImpl extends ServiceImpl<ActivityPlanDao, Activi
         }
 
 
-        // 活动曲目
-        List<ActivityMusicVo> activityMusicVoList = activityEvaluationService.getActivityMusic(activityPlanId, userId);
-        activityVo.setActivityMusicVoList(activityMusicVoList);
+        // 评测活动曲目信息
+        if (ActivityTypeEnum.EVALUATION == activityPlan.getActivityType()) {
+
+            // 活动曲目
+            List<ActivityMusicVo> activityMusicVoList = activityEvaluationService.getActivityMusic(activityPlanId, userId);
+            activityVo.setActivityMusicVoList(activityMusicVoList);
+
+            // 评测难度
+            String evaluationDifficulty = baseMapper.selectActivityPlanEvaluation(activityPlanId);
+            activityVo.setEvaluationDifficulty(evaluationDifficulty);
+
+            // 单曲排名
+            if (ActivityRankingMethodEnum.MUSIC_RANKING == activityPlan.getRankingMethod()) {
+
+                for (ActivityMusicVo item : activityVo.getActivityMusicVoList()) {
+
+                    if (StringUtils.isEmpty(item.getEvaluationDifficulty())) {
+
+                        item.setEvaluationDifficulty(evaluationDifficulty);
+                    }
+                }
+            }
+
+            // 计算评测活动声部最高分
+            if (ActivityRankingMethodEnum.TOTAL_SCORE == activityPlan.getRankingMethod()) {
+
+                Map<String, List<ActivityMusicVo>> collect = activityMusicVoList.stream()
+                        .collect(Collectors.groupingBy(x -> x.getSubjectId().split(",")[0]));
+
+                // 曲目难度
+                Map<Integer, String> difficultyMap = Maps.newHashMap();
+                difficultyMap.put(0, "BEGINNER");
+                difficultyMap.put(1, "ADVANCED");
+                difficultyMap.put(2, "PERFORMER");
+                // FIXME:临时增加声部曲目难度字段
+                for (Map.Entry<String, List<ActivityMusicVo>> entry : collect.entrySet()) {
+
+                    int index = 0;
+                    for (ActivityMusicVo item : entry.getValue()) {
+
+                        if (StringUtils.isEmpty(item.getEvaluationDifficulty())) {
+
+                            item.setEvaluationDifficulty(difficultyMap.getOrDefault(index, "PERFORMER"));
+                        }
+
+                        index += 1;
+                    }
+                }
+
+                // 计算声部评测最高分
+                Map<String, ActivityRankingVo> highestScoreMap = Maps.newConcurrentMap();
+                collect.entrySet().parallelStream().forEach(item -> {
+
+                    // 单声部计算用户总分排名用户信息
+                    List<ActivityRankingVo> records = getBaseMapper().selectActivityHighestScoreRankingInfo(activityPlanId, Long.parseLong(item.getKey()),
+                            1D, 1);
+
+                    if (CollectionUtils.isNotEmpty(records)) {
+
+                        highestScoreMap.put(item.getKey(), records.get(0));
+                    }
+                });
+
+                // 用户学生身份声部信息
+                List<Long> userIds = highestScoreMap.values().stream()
+                        .map(ActivityRankingVo::getUserId).distinct().collect(Collectors.toList());
+
+                Map<Long, Long> userSubjectMap = Maps.newHashMap();
+                Map<Long, String> subjectNameMap = Maps.newHashMap();
+                if (CollectionUtils.isNotEmpty(userIds)) {
+
+                    userSubjectMap = studentMapper.selectList(Wrappers.<Student>lambdaQuery().in(Student::getUserId, userIds)).stream()
+                            .filter(x -> Objects.nonNull(x.getSubjectId()))
+                            .collect(Collectors.toMap(Student::getUserId, x -> Long.parseLong(Optional.ofNullable(x.getSubjectId()).orElse("0").split(",")[0]), (o, n) -> n));
+
+
+                    subjectNameMap = subjectService.findBySubjectByIdList(Lists.newArrayList(userSubjectMap.values())).stream()
+                            .collect(Collectors.toMap(Subject::getId, Subject::getName, (o, n) -> n));
+                }
+
+
+                List<MusicActivityVo.SubjectInfo> subjectInfos = Lists.newArrayList();
+                ActivityMusicVo musicVo;
+                ActivityRankingVo ranking;
+                for (Map.Entry<String, List<ActivityMusicVo>> entry : collect.entrySet()) {
+
+                    if (CollectionUtils.isEmpty(entry.getValue())) {
+                        continue;
+                    }
+
+                    musicVo = entry.getValue().get(0);
+
+                    MusicActivityVo.SubjectInfo subjectInfo = MusicActivityVo.SubjectInfo.builder()
+                            .subjectId(musicVo.getSubjectId().split(",")[0])
+                            .subjectName(musicVo.getMusicSubject())
+                            .join(entry.getValue().stream().anyMatch(x -> x.getJoin() == YesOrNoEnum.YES) ? 1 : 0)
+                            .userId(0L)
+                            .username("")
+                            .userAvatar("")
+                            .userSubject("")
+                            .score(0D)
+                            .musicNums(entry.getValue().size())
+                            .build();
+                    subjectInfos.add(subjectInfo);
+
+                    // 最高分记录
+                    if (highestScoreMap.containsKey(entry.getKey())) {
+
+                        ranking = highestScoreMap.get(entry.getKey());
+
+                        subjectInfo.userId(ranking.getUserId())
+                                .username(ranking.getUsername())
+                                .userAvatar(ranking.getUserAvatar())
+                                .userSubject(subjectNameMap.getOrDefault(userSubjectMap.get(ranking.getUserId()), ""))
+                                .score(ranking.getScore());
+                    }
+                }
+
+                activityVo.setSubjectInfos(subjectInfos);
+            }
+        }
 
         // 报名状态
         activityVo.setJoin(activityRegistrationService.getRegistration(userId, activityPlanId));
@@ -512,10 +646,6 @@ public class ActivityPlanServiceImpl extends ServiceImpl<ActivityPlanDao, Activi
         List<ActivityReward> activityRewardList = activityRewardService.getActivityReward(activityPlanId);
         activityVo.setActivityRewardList(activityRewardList);
 
-        // 评测难度
-        String evaluationDifficulty = baseMapper.selectActivityPlanEvaluation(activityPlanId);
-
-        activityVo.setEvaluationDifficulty(evaluationDifficulty);
         return activityVo;
     }
 
@@ -634,34 +764,53 @@ public class ActivityPlanServiceImpl extends ServiceImpl<ActivityPlanDao, Activi
         // 方法调整为异常执行,预防HTTP接口调用返回超时响应
         ThreadPool.getExecutor().submit(() -> {
 
-            List<ActivityPlan> list = baseMapper.activityState();
-            for (ActivityPlan plan : list) {
-                DistributedLock.of(redissonClient)
-                        .runIfLockToFunction(CacheNameEnum.LOCK_ACTIVITY_STOCK.getRedisKey(plan.getId())
-                                , (id) -> {
-                                    ActivityPlan activityPlan = getById(id);
-                                    if (activityPlan.getActivityState() == 0) {
-                                        activityPlan.setActivityState(1);
-                                        baseMapper.updateById(activityPlan);
-
-                                        //开始活动
-                                        Consumer<Long> afterFunction = startActivity.get(activityPlan.getActivityType());
-                                        if (!Objects.isNull(afterFunction)) {
-                                            afterFunction.accept(activityPlan.getId());
-                                        }
-                                    } else {
-                                        activityPlan.setActivityState(0);
-                                        activityPlan.setRewardFlag(1);
-                                        baseMapper.updateById(activityPlan);
-
-                                        //完成活动
-                                        Consumer<Long> afterFunction = successActivity.get(activityPlan.getActivityType());
-                                        if (!Objects.isNull(afterFunction)) {
-                                            afterFunction.accept(activityPlan.getId());
+            RLock lock = redissonClient.getLock(CacheNameEnum.LOCK_EVALUATION_CRON.getCode());
+            try {
+                if (lock.isLocked()) {
+                    log.warn("activityState {}, lockName={}", DateTime.now().toString(MK.TIME_PATTERN), lock.getName());
+                    return;
+                }
+
+                // 增加达标活动计算同步标识,前一个请求未执行完时忽略后续执行请求
+                lock.lock();
+
+                List<ActivityPlan> list = baseMapper.activityState();
+                for (ActivityPlan plan : list) {
+                    DistributedLock.of(redissonClient)
+                            .runIfLockToFunction(CacheNameEnum.LOCK_ACTIVITY_STOCK.getRedisKey(plan.getId())
+                                    , (id) -> {
+                                        ActivityPlan activityPlan = getById(id);
+                                        if (activityPlan.getActivityState() == 0) {
+                                            activityPlan.setActivityState(1);
+                                            baseMapper.updateById(activityPlan);
+
+                                            //开始活动
+                                            Consumer<Long> afterFunction = startActivity.get(activityPlan.getActivityType());
+                                            if (!Objects.isNull(afterFunction)) {
+                                                afterFunction.accept(activityPlan.getId());
+                                            }
+                                        } else {
+                                            activityPlan.setActivityState(0);
+                                            activityPlan.setRewardFlag(1);
+                                            baseMapper.updateById(activityPlan);
+
+                                            //完成活动
+                                            Consumer<Long> afterFunction = successActivity.get(activityPlan.getActivityType());
+                                            if (!Objects.isNull(afterFunction)) {
+                                                afterFunction.accept(activityPlan.getId());
+                                            }
                                         }
-                                    }
-                                    return true;
-                                }, plan.getId(), 10l);
+                                        return true;
+                                    }, plan.getId(), 10l);
+                }
+
+            } catch (Exception e) {
+                log.error("activityState time={}", DateTime.now().toString(MK.TIME_PATTERN), e);
+            } finally {
+                // 释放锁
+                if (lock.isLocked() && lock.isHeldByCurrentThread()) {
+                    lock.unlock(); // 删除同步标识
+                }
             }
 
         });

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

@@ -1,13 +1,20 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 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.dao.ActivityRegistrationDao;
+import com.yonge.cooleshow.biz.dal.dao.SubjectDao;
 import com.yonge.cooleshow.biz.dal.dto.search.ActivityRegistrationSearch;
 import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluationRecord;
+import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
 import com.yonge.cooleshow.biz.dal.entity.ActivityRegistration;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
+import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
+import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
 import com.yonge.cooleshow.biz.dal.service.ActivityRegistrationService;
+import com.yonge.cooleshow.biz.dal.service.SubjectService;
 import com.yonge.cooleshow.biz.dal.vo.ActivityRegistrationVo;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import lombok.extern.slf4j.Slf4j;
@@ -17,6 +24,7 @@ import org.springframework.stereotype.Service;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -26,6 +34,10 @@ public class ActivityRegistrationServiceImpl extends ServiceImpl<ActivityRegistr
 
     @Autowired
     private ActivityEvaluationRecordService activityEvaluationRecordService;
+    @Autowired
+    private ActivityPlanService activityPlanService;
+    @Autowired
+    private SubjectService subjectService;
 	@Override
     public ActivityRegistrationVo detail(Long id) {
         return baseMapper.detail(id);
@@ -40,22 +52,58 @@ public class ActivityRegistrationServiceImpl extends ServiceImpl<ActivityRegistr
         List<Long> userIds = activityUserInfos.stream()
                 .map(ActivityRegistration::getUserId).distinct().collect(Collectors.toList());
 
+        ActivityPlan activity = activityPlanService.getById(query.getActivityId());
         // 查询用户活动评测获排名最高记录
-        if (CollectionUtils.isNotEmpty(userIds)) {
+        if (CollectionUtils.isNotEmpty(userIds) && Objects.nonNull(activity)) {
+
+            if (ActivityRankingMethodEnum.TOTAL_SCORE == activity.getRankingMethod()) {
+
+                // 总分排名
+                Map<Long, ActivityEvaluationRecord> collect = activityEvaluationRecordService.list(Wrappers.<ActivityEvaluationRecord>lambdaQuery()
+                        .eq(ActivityEvaluationRecord::getActivityId, activity.getId())
+                        .in(ActivityEvaluationRecord::getUserId, userIds)
+                        .eq(ActivityEvaluationRecord::getRankingMethod, activity.getRankingMethod().getCode())).stream()
+                        .collect(Collectors.toMap(ActivityEvaluationRecord::getUserId, Function.identity(), (o, n) -> n));
+
+                // 声部信息
+                List<Long> subjectIds = collect.values().stream()
+                        .map(ActivityEvaluationRecord::getResourceId)
+                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
+
+                Map<Long, String> subjectNameMap = subjectService.findBySubjectByIdList(subjectIds).stream()
+                        .collect(Collectors.toMap(Subject::getId, Subject::getName, (o, n) -> n));
+
+                ActivityEvaluationRecord record;
+                for (ActivityRegistrationVo item : activityUserInfos) {
+
+                    if (collect.containsKey(item.getUserId())) {
+
+                        record = collect.get(item.getUserId());
+                        // 重置当前时间为用户最高排名时间
+                        item.score(record.getScore())
+                                .subjectName(subjectNameMap.getOrDefault(record.getResourceId(), ""))
+                                .scoreTime(record.getCreateTime());
+
+                    }
+                }
+
+            } else {
 
-            Map<Long, ActivityEvaluationRecord> collect = activityEvaluationRecordService.queryActivityUserHighestRankingInfo(query.getActivityId(), userIds).stream()
-                    .collect(Collectors.toMap(ActivityEvaluationRecord::getUserId, Function.identity(), (o, n) -> n));
+                // 单曲排名
+                Map<Long, ActivityEvaluationRecord> collect = activityEvaluationRecordService.queryActivityUserHighestRankingInfo(query.getActivityId(), userIds).stream()
+                        .collect(Collectors.toMap(ActivityEvaluationRecord::getUserId, Function.identity(), (o, n) -> n));
 
-            ActivityEvaluationRecord record;
-            for (ActivityRegistrationVo item : activityUserInfos) {
+                ActivityEvaluationRecord record;
+                for (ActivityRegistrationVo item : activityUserInfos) {
 
-                if (collect.containsKey(item.getUserId())) {
+                    if (collect.containsKey(item.getUserId())) {
 
-                    record = collect.get(item.getUserId());
-                    // 重置当前时间为用户最高排名时间
-                    item.score(record.getScore())
-                            .times(record.getTimes())
-                            .setCreateTime(record.getCreateTime());
+                        record = collect.get(item.getUserId());
+                        // 重置当前时间为用户最高排名时间
+                        item.score(record.getScore())
+                                .times(record.getTimes())
+                                .setCreateTime(record.getCreateTime());
+                    }
                 }
             }
         }

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

@@ -19,6 +19,7 @@ import com.yonge.cooleshow.biz.dal.entity.ActivityRewardChangeStock;
 import com.yonge.cooleshow.biz.dal.entity.CouponInfo;
 import com.yonge.cooleshow.biz.dal.entity.PianoRoomChangeRecord;
 import com.yonge.cooleshow.biz.dal.enums.*;
+import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
 import com.yonge.cooleshow.biz.dal.mapper.CouponInfoMapper;
 import com.yonge.cooleshow.biz.dal.service.ActivityPlanRewardService;
 import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
@@ -39,8 +40,6 @@ import com.yonge.toolset.payment.util.DistributedLock;
 import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
-import org.redisson.RedissonMultiLock;
-import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,13 +48,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -281,38 +274,13 @@ public class ActivityRewardServiceImpl extends ServiceImpl<ActivityRewardDao, Ac
 
             // 扣减奖品库存
             int update = activityPlanRewardService.reduceStock(activityId, item.getId());
-            if (update == 0) {
+
+            // 排除总分排名用户库存限制
+            if (ActivityRankingMethodEnum.TOTAL_SCORE != activityPlan.getRankingMethod()
+                    && update == 0) {
                 continue;
             }
 
-            if (activityReward.getRewardType().equals(RewardTypeEnum.PIAMO_ROOM)) {
-                // 琴房课时
-                PianoRoomChangeRecord pianoRoomChangeRecord = new PianoRoomChangeRecord();
-                pianoRoomChangeRecord.setUserId(userId);
-                pianoRoomChangeRecord.setInOrOut(InOrOutEnum.IN);
-                pianoRoomChangeRecord.setSourceType(SourceTypeEnum.ACTIVITY);
-                pianoRoomChangeRecord.setTimes(activityReward.getNum());
-                pianoRoomChangeRecord.setBizId(activityId.toString());
-                pianoRoomChangeRecord.setCreateTime(new Date());
-                pianoRoomChangeRecord.setReason(activityPlan.getActivityName());
-                pianoRoomChangeRecordService.add(pianoRoomChangeRecord);
-            } else if (activityReward.getRewardType().equals(RewardTypeEnum.VIP)) {
-                // VIP
-                memberPriceSettingsService.activityReward(userId, activityPlan.getActivityClient(),
-                        activityReward, activityId,activityPlan.getActivityName());
-            } else if (activityReward.getRewardType().equals(RewardTypeEnum.COUPON)) {
-                // 优惠券
-                List<UserParam> list = new ArrayList<>();
-                UserParam userParam = new UserParam();
-                userParam.setUserId(userId);
-                userParam.setClientType(activityPlan.getActivityClient());
-                list.add(userParam);
-                Boolean issueCoupon = couponIssueService.issueCoupon(activityReward.getCouponId(), list, null, activityPlan.getActivityName(),
-                        false, false, SendTypeEnum.ACTIVITY,date);
-                if (!issueCoupon) {
-                    continue;
-                }
-            }
             // 获取推送奖品消息信息
             rewardNameList.add(activityReward.getRewardName());
             // 关联返回数据,更新用户奖品发送状态
@@ -329,6 +297,43 @@ public class ActivityRewardServiceImpl extends ServiceImpl<ActivityRewardDao, Ac
     }
 
     @Override
+    public void receiveReward(Long userId, Date date, Long activityPlanId, Long activityRewardId) {
+        ActivityPlan activityPlan = activityPlanService.getById(activityPlanId);
+        ActivityReward activityReward = getById(activityRewardId);
+        if (activityPlan == null) {
+            throw new BizException("活动不存在");
+        }
+        if (activityReward == null) {
+            throw new BizException("奖品不存在");
+        }
+        if (activityReward.getRewardType().equals(RewardTypeEnum.PIAMO_ROOM)) {
+            // 琴房课时
+            PianoRoomChangeRecord pianoRoomChangeRecord = new PianoRoomChangeRecord();
+            pianoRoomChangeRecord.setUserId(userId);
+            pianoRoomChangeRecord.setInOrOut(InOrOutEnum.IN);
+            pianoRoomChangeRecord.setSourceType(SourceTypeEnum.ACTIVITY);
+            pianoRoomChangeRecord.setTimes(activityReward.getNum());
+            pianoRoomChangeRecord.setBizId(activityPlan.getId().toString());
+            pianoRoomChangeRecord.setCreateTime(new Date());
+            pianoRoomChangeRecord.setReason(activityPlan.getActivityName());
+            pianoRoomChangeRecordService.add(pianoRoomChangeRecord);
+        } else if (activityReward.getRewardType().equals(RewardTypeEnum.VIP)) {
+            // VIP
+            memberPriceSettingsService.activityReward(userId, activityPlan.getActivityClient(), activityReward,
+                                                      activityPlan.getId(), activityPlan.getActivityName());
+        } else if (activityReward.getRewardType().equals(RewardTypeEnum.COUPON)) {
+            // 优惠券
+            List<UserParam> list = new ArrayList<>();
+            UserParam userParam = new UserParam();
+            userParam.setUserId(userId);
+            userParam.setClientType(activityPlan.getActivityClient());
+            list.add(userParam);
+            couponIssueService.saveIssueCoupon(activityReward.getCouponId(), list, null, activityPlan.getActivityName(),
+                                                                  SendTypeEnum.ACTIVITY, date);
+        }
+    }
+
+    @Override
     public Boolean userRewarded(Long userId, Long activityId) {
         return baseMapper.userRewarded(userId, activityId);
     }
@@ -351,8 +356,11 @@ public class ActivityRewardServiceImpl extends ServiceImpl<ActivityRewardDao, Ac
             Map<Long, String> receivers = new HashMap<>();
             receivers.put(userId, user.getPhone());
 
+
+            String url = sysMessageService.selectConfigUrl(MessageTypeEnum.ACTIVITY_WIN.getCode(),clientType.getCode()
+                                                                                        .toLowerCase(Locale.ROOT));
             sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.ACTIVITY_WIN, receivers, null,
-                    0, null, clientType.getCode(), activityName, activityRewardName);
+                    0, url, clientType.getCode(), activityName, activityRewardName);
         } catch (Exception e) {
             e.printStackTrace();
             log.error("获奖消息发送失败,{}", e.getMessage());

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

@@ -10,15 +10,19 @@ import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluationRecord;
 import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
 import com.yonge.cooleshow.biz.dal.entity.ActivityReward;
 import com.yonge.cooleshow.biz.dal.entity.ActivityUserReward;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.queryInfo.UserRewardQueryInfo;
 import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
 import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
 import com.yonge.cooleshow.biz.dal.service.ActivityRewardService;
 import com.yonge.cooleshow.biz.dal.service.ActivityUserRewardService;
 import com.yonge.cooleshow.biz.dal.vo.ActivityUserRewardVo;
 import com.yonge.cooleshow.biz.dal.vo.UserRewardVo;
+import com.yonge.cooleshow.biz.dal.vo.activity.UserRewardWrapper;
 import com.yonge.cooleshow.common.enums.ActivityTypeEnum;
 import com.yonge.cooleshow.common.enums.EStatus;
 import com.yonge.cooleshow.common.enums.RewardTypeEnum;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.exception.BizException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
@@ -155,4 +159,34 @@ public class ActivityUserRewardServiceImpl extends ServiceImpl<ActivityUserRewar
         activityUserReward.setReceiveFlag(1);
         this.save(activityUserReward);
     }
+
+    @Override
+    public Boolean checkReceiveReward(Long userId, ClientEnum client) {
+        UserRewardQueryInfo query = new UserRewardQueryInfo();
+        query.setUserId(userId);
+        query.setClient(client);
+        query.setReceive(YesOrNoEnum.NO);
+
+        return baseMapper.selectReceiveRewardCount(query) >0;
+    }
+
+    @Override
+    public Boolean receiveReward(Long userId, Long receiveRewardId) {
+        ActivityUserReward activityUserReward = getById(receiveRewardId);
+        Date receiveTime = new Date();
+        // 修改领奖状态
+        int i  = baseMapper.receiveReward(userId,receiveRewardId,receiveTime);
+        if (i == 0) {
+            return false;
+        }
+
+        activityRewardService.receiveReward(userId,receiveTime,activityUserReward.getActivityId(),activityUserReward.getRewardId());
+        return true;
+    }
+
+    @Override
+    public IPage<UserRewardWrapper> receiveRewardList(IPage<UserRewardWrapper> page, UserRewardQueryInfo query) {
+
+        return baseMapper.selectReceiveRewardList(page,query);
+    }
 }

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

@@ -26,7 +26,6 @@ import com.yonge.cooleshow.biz.dal.vo.coupon.CouponIssueWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
 import com.yonge.cooleshow.common.enums.EStatus;
 import com.yonge.toolset.base.exception.BizException;
-import com.yonge.toolset.base.string.MessageFormatter;
 import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -155,18 +154,15 @@ public class CouponIssueServiceImp extends ServiceImpl<CouponIssueMapper, Coupon
 
     @Override
     @Transactional
-    public Boolean issueCoupon(Long couponId, List<UserParam> userParam, Long issuer, String reason, Boolean sendMessage, Boolean throwE, SendTypeEnum issueWay, Date date) {
+    public void issueCoupon(Long couponId, List<UserParam> userParam, Long issuer, String reason,SendTypeEnum issueWay, Date date) {
         CouponInfo couponInfo = couponInfoService.queryCouponInfoById(couponId);
         if (couponInfo == null) {
-            if (!throwE) return false;
             throw new BizException("未找到优惠券信息");
         }
         if (couponInfo.getInventory() < userParam.size()) {
-            if (!throwE) return false;
             throw new BizException("库存不足");
         }
         if (couponInfo.getStatus() == EStatus.DISABLE.getValue()) {
-            if (!throwE) return false;
             throw new BizException("优惠券已被禁用");
         }
 
@@ -185,6 +181,21 @@ public class CouponIssueServiceImp extends ServiceImpl<CouponIssueMapper, Coupon
             }
         }
 
+        saveIssueCoupon(couponId, userParam, issuer, reason, issueWay, date);
+
+        //  优惠券扣减库存
+        int i = couponInfoService.updateStock(couponId, userParam.size(), InOrOutEnum.OUT);
+        if (i == 0) {
+            throw new BizException("库存不足");
+        }
+
+        // 发送消息
+        sendMessage(couponInfo.getName(), userParam);
+    }
+
+    @Override
+    public void saveIssueCoupon(Long couponId, List<UserParam> userParam, Long issuer, String reason, SendTypeEnum issueWay, Date date) {
+        CouponInfo couponInfo = couponInfoService.queryCouponInfoById(couponId);
         // 判断优惠券类型 设置优惠券时间
         Long startTime = null;
         Long endTime = null;
@@ -199,11 +210,9 @@ public class CouponIssueServiceImp extends ServiceImpl<CouponIssueMapper, Coupon
         List<CouponIssue> couponIssueList = new ArrayList<>();
         for (UserParam param : userParam) {
             if (param.getUserId() == null) {
-                if (!throwE) return false;
                 throw new BizException("发放用户id不能为空");
             }
             if (param.getClientType() == null) {
-                if (!throwE) return false;
                 throw new BizException("发放客户端不能为空");
             }
             CouponIssue couponIssue = new CouponIssue();
@@ -221,19 +230,6 @@ public class CouponIssueServiceImp extends ServiceImpl<CouponIssueMapper, Coupon
             couponIssueList.add(couponIssue);
         }
         this.saveBatch(couponIssueList);
-
-        //  优惠券扣减库存
-        int i = couponInfoService.updateStock(couponId, userParam.size(), InOrOutEnum.OUT);
-        if (i == 0) {
-            if (!throwE) return false;
-            throw new BizException("库存不足");
-        }
-
-        // 发送消息
-        if (sendMessage) {
-            sendMessage(couponInfo.getName(), userParam);
-        }
-        return true;
     }
 
     private void sendMessage(String couponName,List<UserParam> userParams) {

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

@@ -1,6 +1,9 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
@@ -11,12 +14,21 @@ import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
 import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
 import com.yonge.cooleshow.biz.dal.enums.MK;
+import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
 import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
+import com.yonge.toolset.base.exception.BizException;
+import io.rong.messages.BaseMessage;
+import io.rong.messages.FileMessage;
+import io.rong.messages.ImgMessage;
+import io.rong.messages.ImgTextMessage;
 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 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;
@@ -24,6 +36,11 @@ 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.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -48,6 +65,8 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
     private SysUserFeignService sysUserFeignService;
     @Autowired
     private CustomerServiceConfig customerServiceConfig;
+    @Autowired
+    private SysUserMapper sysUserMapper;
 
     @Override
     public ImUserFriendDao getDao() {
@@ -178,5 +197,108 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
         return CollectionUtils.size(friendIds);
     }
 
+    /**
+     * 发送系统客服消息
+     *
+     * @param sender 发送者
+     * @param info   CustomerService.NotifyMessage
+     */
+    @Override
+    public void sendCustomerServiceNotifyMessage(String sender, CustomerService.NotifyMessage info) {
+
+        // 发送者信息
+        com.yonge.cooleshow.biz.dal.entity.SysUser senderUser = sysUserMapper.selectOne(Wrappers.<com.yonge.cooleshow.biz.dal.entity.SysUser>lambdaQuery()
+                .eq(com.yonge.cooleshow.biz.dal.entity.SysUser::getPhone, sender));
+
+        if (Objects.isNull(senderUser)) {
+            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());
+
+        wrapper.last("LIMIT 1000");
+        // 接收者信息
+        List<com.yonge.cooleshow.biz.dal.entity.SysUser> sysUsers = sysUserMapper.selectList(wrapper);
+
+        // 发送图片消息
+        ImgMessage imgMessage = new ImgMessage(imageToBase64(info.getImgMessage(), "png"), "", info.getImgUrl());
+
+        // 发送文本消息
+        TxtMessage txtMessage = new TxtMessage(info.getTxtMessage(), "");
+
+        List<BaseMessage> messages = Lists.newArrayList(imgMessage, txtMessage);
+
+        // 拓展消息
+        PushExt pushExt = PushExt.build(info.getTitle(), 1,
+                new PushExt.HW("channelId", "NORMAL"), new PushExt.VIVO("1"),
+                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;
+        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("sendCustomerServiceNotifyMessage senderId={}, ret={}", senderId, privateResult.getCode());
+                }
+
+            } catch (Exception e) {
+                log.error("sendCustomerServiceNotifyMessage senderId={}", senderId, e);
+            }
+
+        }
+
+    }
+
+    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())));
+    }
+
+
+
 }
 

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

@@ -1,16 +1,29 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
+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.stream.Collectors;
 
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dao.AlbumMusicRelateDao;
+import com.yonge.cooleshow.biz.dal.dao.MusicSheetDao;
+import com.yonge.cooleshow.biz.dal.dao.MusicSheetPurchaseRecordDao;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheetPurchaseRecord;
+import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
+import com.yonge.cooleshow.biz.dal.service.MusicSheetPurchaseRecordService;
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
+import org.apache.commons.collections.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
@@ -62,6 +75,15 @@ public class MusicAlbumServiceImpl extends ServiceImpl<MusicAlbumDao,MusicAlbum>
 
     @Autowired
     private AlbumFavoriteService albumFavoriteService;
+    @Autowired
+    private MusicSheetPurchaseRecordDao musicSheetPurchaseRecordMapper;
+    @Autowired
+    private MusicSheetDao musicSheetMapper;
+    @Autowired
+    private AlbumMusicRelateDao albumMusicRelateMapper;
+
+    @Autowired
+    private MusicSheetPurchaseRecordService musicSheetPurchaseRecordService;
 
     public MusicAlbumDao getDao() {
         return musicAlbumDao;
@@ -88,7 +110,7 @@ public class MusicAlbumServiceImpl extends ServiceImpl<MusicAlbumDao,MusicAlbum>
     }
 
     @Override
-    public AlbumDetailVo detail(IPage<MusicSheetVo> page, MusicAlbumDetailSearch query) {
+    public AlbumDetailVo detail(IPage<MusicSheetVo> page, MusicAlbumDetailSearch query, SysUser sysUser, ClientEnum client) {
         MusicAlbumVo musicAlbum = baseMapper.selectMusicAlbumById(query.getId());
         if (musicAlbum == null) {
             throw  new BizException("未找到专辑信息");
@@ -101,16 +123,54 @@ public class MusicAlbumServiceImpl extends ServiceImpl<MusicAlbumDao,MusicAlbum>
         albumDetailVo.setAlbumCoverUrl(musicAlbum.getAlbumCoverUrl());
         albumDetailVo.setAlbumStatue(musicAlbum.getAlbumStatus());
         albumDetailVo.setAlbumFavoriteCount(musicAlbum.getAlbumFavoriteCount());
+        albumDetailVo.setAlbumPrice(musicAlbum.getAlbumPrice());
+        albumDetailVo.setPaymentType(musicAlbum.getPaymentType());
         albumDetailVo.setMusicTagNames(musicTagService.getMusicTagNames(StringUtil.toLongList(musicAlbum.getAlbumTag())));
 
+        // 新增专辑曲目查询条件
         if (query.getType() != null && query.getType() == 1) {
             query.setSubjectIds(musicAlbum.getSubjectId());
+
+            // 判断专辑收费类型;非免费类型,只能添加平台曲目
+            /*if (!ChargeTypeEnum.FREE.match(musicAlbum.getPaymentType())) {
+
+                // 曲目来源
+                query.setSourceType(SourceTypeEnum.PLATFORM);
+                // 曲目收费类型
+                if (musicAlbum.getPaymentType().contains(",")) {
+                    // 多种付费方式
+                    query.setPaymentTypes(Lists.newArrayList(musicAlbum.getPaymentType(), ChargeTypeEnum.FREE.getCode()));
+                } else {
+                    // 单一付费方式
+                    query.setChargeType(ChargeTypeEnum.valueOf(musicAlbum.getPaymentType()));
+                }
+
+            }*/
         }
 
         IPage<MusicSheetVo> musicSheetVoIPage = musicSheetService.selectAlbumDetailPage(page,query);
+
+        // 专辑曲目付费方式
+        List<String> paymentTypes = musicSheetVoIPage.getRecords().stream()
+                .flatMap(x -> Arrays.stream(x.getPaymentType().split(","))).distinct().collect(Collectors.toList());
+        albumDetailVo.setMusicPaymentTypes(paymentTypes);
+
         albumDetailVo.setMusicSheetList(PageUtil.pageInfo(musicSheetVoIPage));
 
         albumDetailVo.setMusicSheetCount((int) musicSheetVoIPage.getTotal());
+
+        if (sysUser == null) {
+            return albumDetailVo;
+        }
+
+        // 查询购买信息
+        MusicSheetPurchaseRecord purchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
+                sysUser.getId(), query.getId(), client, PurchaseRecordTypeEnum.ALBUM);
+        if (purchaseRecord != null) {
+            albumDetailVo.setOrderStatus(purchaseRecord.getOrderStatus());
+            albumDetailVo.setOrderNo(purchaseRecord.getOrderNo());
+        }
+
         return albumDetailVo;
     }
 
@@ -121,6 +181,20 @@ public class MusicAlbumServiceImpl extends ServiceImpl<MusicAlbumDao,MusicAlbum>
         if (musicAlbum == null) {
             throw  new BizException("未找到专辑信息");
         }
+
+        // 付费专辑,需要校验是否已存在购买记录
+        /*if (!ChargeTypeEnum.VIP.match(musicAlbum.getPaymentType())) {
+
+            // 统计付费专辑的购买数量
+            Integer count = musicSheetPurchaseRecordMapper.selectCount(Wrappers.<MusicSheetPurchaseRecord>lambdaQuery()
+                    .eq(MusicSheetPurchaseRecord::getMusicSheetId, albumId)
+                    .eq(MusicSheetPurchaseRecord::getPurchaseType, PurchaseRecordTypeEnum.ALBUM)
+            );
+            if (Optional.ofNullable(count).orElse(0) > 0) {
+                throw new BizException("当前专辑已有购买记录");
+            }
+        }*/
+
         List<Long> musicSheetIdList = StringUtil.toLongList(musicSheetIds);
         return albumMusicRelateService.delMusicSheet(albumId,musicSheetIdList);
     }
@@ -132,6 +206,31 @@ public class MusicAlbumServiceImpl extends ServiceImpl<MusicAlbumDao,MusicAlbum>
         if (musicAlbum == null) {
             throw  new BizException("未找到专辑信息");
         }
+
+        // 付费专辑最多只能添加两首免费曲目
+        if (!ChargeTypeEnum.FREE.match(musicAlbum.getPaymentType())) {
+
+            // 新添加曲目统计
+            long freeNum = 0;
+            List<Long> musicIds = albumMusicList.stream()
+                    .map(MusicAlbumSheetDto.AlbumMusic::getMusicSheetId).distinct().collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(musicIds)) {
+
+                freeNum = musicSheetMapper.selectBatchIds(musicIds).stream()
+                        .filter(x -> ChargeTypeEnum.FREE.match(x.getPaymentType()))
+                        .count();
+            }
+
+            // 已添加曲目统计
+            Map<Long, Integer> collect = getBaseMapper().selectAlbumMusicSheetStatInfo(albumId, ChargeTypeEnum.FREE).stream()
+                    .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
+
+            if ((collect.getOrDefault(albumId, 0) + freeNum) > 2) {
+                throw new BizException("专辑免费曲目最多2首");
+            }
+        }
+
         return albumMusicRelateService.addMusicSheet(albumId,albumMusicList,userId);
     }
 
@@ -157,6 +256,26 @@ public class MusicAlbumServiceImpl extends ServiceImpl<MusicAlbumDao,MusicAlbum>
         if (musicAlbum.getAuditVersion() == null) {
             musicAlbum.setAuditVersion(YesOrNoEnum.NO);
         }
+
+        // 非付费类型,已添加曲目或者已购买,不允许修改付费方式
+        /*MusicAlbum album = getById(musicAlbum.getId());
+        if (Objects.isNull(album)) {
+            throw new BizException("无效的专辑ID");
+        }*/
+
+        // 专辑从免费修改为付费方式,需要判断当前免费单曲数量
+        /*if (Objects.nonNull(musicAlbum.getPaymentType())
+                && ChargeTypeEnum.FREE.match(album.getPaymentType())
+                && !album.getPaymentType().equals(musicAlbum.getPaymentType())) {
+
+            Map<Long, Integer> collect = getBaseMapper().selectAlbumMusicSheetStatInfo(album.getId(), ChargeTypeEnum.FREE).stream()
+                    .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
+
+            if (collect.getOrDefault(album.getId(), 0) > 2) {
+                throw new BizException(MessageFormat.format("当前专辑免费单曲数为 {0}, 已超过免费数量", collect.get(album.getId())));
+            }
+        }*/
+
         return this.updateById(musicAlbum);
     }
 

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

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.biz.dal.dao.MusicSheetPurchaseRecordDao;
 import com.yonge.cooleshow.biz.dal.entity.MusicSheetPurchaseRecord;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.MusicSheetPurchaseRecordService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,12 +33,13 @@ public class MusicSheetPurchaseRecordServiceImpl extends ServiceImpl<MusicSheetP
     }
 
     @Override
-    public MusicSheetPurchaseRecord checkPurchase(Long userId, Long musicSheetId, ClientEnum clientType) {
+    public MusicSheetPurchaseRecord checkPurchase(Long userId, Long musicSheetId, ClientEnum clientType, PurchaseRecordTypeEnum purchaseType) {
         List<MusicSheetPurchaseRecord> list = this.lambdaQuery()
-                                                  .eq(MusicSheetPurchaseRecord::getMusicSheetId, musicSheetId)
-                                                  .eq(MusicSheetPurchaseRecord::getStudentId, userId)
-                                                  .eq(MusicSheetPurchaseRecord::getClientType, clientType)
-                                                  .list();
+                .eq(MusicSheetPurchaseRecord::getMusicSheetId, musicSheetId)
+                .eq(MusicSheetPurchaseRecord::getStudentId, userId)
+                .eq(MusicSheetPurchaseRecord::getClientType, clientType)
+                .eq(MusicSheetPurchaseRecord::getPurchaseType, purchaseType)
+                .list();
         if (CollectionUtils.isEmpty(list)) {
             return null;
         }

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

@@ -6,8 +6,11 @@ import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaU
 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;
@@ -31,13 +34,13 @@ 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
 
@@ -113,6 +116,8 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
     private StudentStarService studentStarService;
     @Autowired
     private UserOrderService userOrderService;
+    @Autowired
+    private MusicAlbumDao musicAlbumMapper;
 
     public MusicSheetDao getDao() {
         return musicSheetDao;
@@ -285,7 +290,7 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         if (ChargeTypeEnum.CHARGE.getCode().equals(detail.getChargeType().getCode())) {
             // 学生须判断是否能播放曲目
             MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
-                    studentId, detail.getId(), userType);
+                    studentId, detail.getId(), userType, PurchaseRecordTypeEnum.MUSIC);
             if (musicSheetPurchaseRecord != null) {
                 detail.setOrderStatus(musicSheetPurchaseRecord.getOrderStatus());
                 detail.setOrderNo(musicSheetPurchaseRecord.getOrderNo());
@@ -296,7 +301,7 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         } else if (ChargeTypeEnum.VIP.getCode().equals(detail.getChargeType().getCode())) {
             // 先判断是否购买过
             MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
-                    studentId, detail.getId(), userType);
+                    studentId, detail.getId(), userType, PurchaseRecordTypeEnum.MUSIC);
             if (musicSheetPurchaseRecord != null) {
                 detail.setPlay(YesOrNoEnum.YES);
             } else
@@ -313,11 +318,58 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
                 }
             }
         }
+
+        if (detail.getPlay().equals(YesOrNoEnum.YES)) {
+            return;
+        }
+
+        // 判断专辑购买
+
+        // 1 查询曲目所在的专辑
+        List<AlbumMusicRelate> albumMusicRelateList = albumMusicRelateService.lambdaQuery()
+                                                             .eq(AlbumMusicRelate::getMusicSheetId, detail.getId())
+                                                             .list();
+        if (CollectionUtils.isEmpty(albumMusicRelateList)) {
+            return;
+        }
+        List<Long> albumIdList = albumMusicRelateList.stream()
+                                                 .map(AlbumMusicRelate::getAlbumId)
+                                                 .collect(Collectors.toList());
+
+        // 2 检查是否购买过专辑
+        Integer count = musicSheetPurchaseRecordService.lambdaQuery()
+                                                       .eq(MusicSheetPurchaseRecord::getClientType, userType)
+                                                       .eq(MusicSheetPurchaseRecord::getOrderStatus,
+                                                           OrderStatusEnum.PAID)
+                                                       .in(MusicSheetPurchaseRecord::getMusicSheetId, albumIdList)
+                                                       .eq(MusicSheetPurchaseRecord::getPurchaseType,
+                                                           PurchaseRecordTypeEnum.ALBUM)
+                                                       .eq(MusicSheetPurchaseRecord::getStudentId, studentId)
+                                                       .count();
+        if (count >0) {
+            detail.setPlay(YesOrNoEnum.YES);
+        }
+
     }
 
     @Override
     public IPage<MusicSheetVo> selectStudentPage(IPage<MusicSheetVo> page, StudentMusicSheetSearch query, ClientEnum clientType) {
     	List<MusicSheetVo> records = baseMapper.selectStudentMusicPage(page, query, clientType);
+
+        if (CollectionUtils.isNotEmpty(records)) {
+
+            // 统计单曲归属专辑数
+            List<Long> musicIds = records.stream()
+                    .map(MusicSheet::getId).distinct().collect(Collectors.toList());
+
+            Map<Long, Integer> collect = getBaseMapper().selectMusicAlbumStatInfo(musicIds).stream()
+                    .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
+
+            for (MusicSheetVo item : records) {
+
+                item.setAlbumNums(collect.getOrDefault(item.getId(), 0));
+            }
+        }
     	
     	/*if(query.getMyself() != null && query.getMyself() == false){//首页
         	if(records == null || records.size() == 0){
@@ -627,24 +679,53 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         MusicSheetPayDto musicSheetPayDto = JSON.parseObject(
                 JSON.toJSONString(orderReqInfo.getBizContent()), MusicSheetPayDto.class);
 
-        MusicSheet musicSheet = this.getById(musicSheetPayDto.getMusicSheetId());
         OrderCreateRes orderCreateRes = new OrderCreateRes();
-        if (musicSheet == null) {
-            throw new BizException("不存在曲目信息");
-        }
+        orderCreateRes.setGoodType(orderCreateRes.getGoodType());
+        orderCreateRes.setGoodNum(1);
+        orderCreateRes.setOrderType(orderReqInfo.getOrderType());
+
+        switch (orderReqInfo.getGoodType()) {
+            case MUSIC: // 单曲
+                {
+                    MusicSheet musicSheet = this.getById(musicSheetPayDto.getMusicSheetId());
+                    if (musicSheet == null) {
+                        throw new BizException("不存在曲目信息");
+                    }
 
-        // 检查已经购买
-        checkoutPay(orderReqInfo.getUserId(), musicSheetPayDto.getMusicSheetId(), musicSheetPayDto.getClientType());
+                    orderCreateRes.setRes(true);
+                    if (!musicSheet.getSourceType().getCode().equals(SourceTypeEnum.PLATFORM.getCode())) {
+                        orderCreateRes.setMerchId(musicSheet.getUserId());
+                    }
 
-        orderCreateRes.setRes(true);
-        if (!musicSheet.getSourceType().getCode().equals(SourceTypeEnum.PLATFORM.getCode())) {
-            orderCreateRes.setMerchId(musicSheet.getUserId());
+
+                    orderCreateRes.setBizId(musicSheet.getId());
+                    orderCreateRes.setOriginalPrice(musicSheet.getMusicPrice());
+                    orderCreateRes.setExpectPrice(musicSheet.getMusicPrice());
+                }
+                break;
+            case ALBUM: // 专辑
+                {
+                    MusicAlbum album = musicAlbumMapper.selectById(musicSheetPayDto.getMusicSheetId());
+
+                    if (Objects.isNull(album)) {
+                        throw new BizException("无效的专辑信息");
+                    }
+
+                    orderCreateRes.setRes(true);
+                    orderCreateRes.setMerchId(0L);
+                    orderCreateRes.setBizId(album.getId());
+                    orderCreateRes.setOriginalPrice(BigDecimal.valueOf(album.getAlbumPrice()));
+                    orderCreateRes.setExpectPrice(BigDecimal.valueOf(album.getAlbumPrice()));
+                }
+                break;
+            default:
+                break;
         }
-        orderCreateRes.setGoodType(orderCreateRes.getGoodType());
-        orderCreateRes.setBizId(musicSheet.getId());
-        orderCreateRes.setGoodNum(1);
-        orderCreateRes.setOriginalPrice(musicSheet.getMusicPrice());
-        orderCreateRes.setExpectPrice(musicSheet.getMusicPrice());
+
+        // 检查已经购买,抛出已购买异常
+        checkoutPay(orderReqInfo.getUserId(), musicSheetPayDto.getMusicSheetId(), musicSheetPayDto.getClientType(),
+                PurchaseRecordTypeEnum.valueOf(orderReqInfo.getGoodType().getCode()));
+
         return HttpResponseResult.succeed(orderCreateRes);
 
     }
@@ -656,12 +737,13 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
      * @param musicSheetId 曲目id
      * @param clientType
      */
-    private void checkoutPay(Long userId, Long musicSheetId, String clientType) {
+    private void checkoutPay(Long userId, Long musicSheetId, String clientType, PurchaseRecordTypeEnum purchaseType) {
         List<MusicSheetPurchaseRecord> list = musicSheetPurchaseRecordService
                 .lambdaQuery()
                 .eq(MusicSheetPurchaseRecord::getMusicSheetId, musicSheetId)
                 .eq(MusicSheetPurchaseRecord::getStudentId, userId)
                 .eq(MusicSheetPurchaseRecord::getClientType, clientType)
+                .eq(MusicSheetPurchaseRecord::getPurchaseType, purchaseType)
                 .eq(MusicSheetPurchaseRecord::getOrderStatus, OrderStatusEnum.PAID)
                 .list();
         if (!CollectionUtils.isEmpty(list)) {
@@ -768,8 +850,11 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
      * @param serviceFeeAmount  服务费
      */
     private void addMusicSheetPurchaseRecord(UserOrderDetailVo userOrderDetailVo, BigDecimal actualPrice, BigDecimal serviceFeeAmount) {
-        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService
-                .checkPurchase(userOrderDetailVo.getUserId(), userOrderDetailVo.getBizId(), userOrderDetailVo.getOrderClient());
+        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
+                userOrderDetailVo.getUserId(),
+                userOrderDetailVo.getBizId(),
+                userOrderDetailVo.getOrderClient(),
+                PurchaseRecordTypeEnum.valueOf(userOrderDetailVo.getOrderType().getCode()));
         if (musicSheetPurchaseRecord == null) {
             musicSheetPurchaseRecord = new MusicSheetPurchaseRecord();
         }
@@ -783,6 +868,7 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         musicSheetPurchaseRecord.setMusicSheetServiceFee(serviceFeeAmount);
         musicSheetPurchaseRecord.setOrderStatus(OrderStatusEnum.PAID);
         musicSheetPurchaseRecord.setStudentId(userOrderDetailVo.getUserId());
+        musicSheetPurchaseRecord.setPurchaseType(PurchaseRecordTypeEnum.valueOf(userOrderDetailVo.getGoodType().getCode()));
         musicSheetPurchaseRecordService.saveOrUpdate(musicSheetPurchaseRecord);
     }
 
@@ -808,8 +894,11 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
     @Transactional(rollbackFor = Exception.class)
     public void orderAfterSheet(UserOrderDetailVo userOrderDetailVo) {
         // 保存购买记录
-        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService
-                .checkPurchase(userOrderDetailVo.getUserId(), userOrderDetailVo.getBizId(), userOrderDetailVo.getOrderClient());
+        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
+                userOrderDetailVo.getUserId(),
+                userOrderDetailVo.getBizId(),
+                userOrderDetailVo.getOrderClient(),
+                PurchaseRecordTypeEnum.valueOf(userOrderDetailVo.getOrderType().getCode()));
         if (musicSheetPurchaseRecord == null) {
             musicSheetPurchaseRecord = new MusicSheetPurchaseRecord();
         }
@@ -820,14 +909,19 @@ public class MusicSheetServiceImpl extends ServiceImpl<MusicSheetDao, MusicSheet
         musicSheetPurchaseRecord.setOriginalPrice(userOrderDetailVo.getOriginalPrice());
         musicSheetPurchaseRecord.setOrderStatus(OrderStatusEnum.WAIT_PAY);
         musicSheetPurchaseRecord.setStudentId(userOrderDetailVo.getUserId());
+        musicSheetPurchaseRecord.setPurchaseType(PurchaseRecordTypeEnum.valueOf(userOrderDetailVo.getGoodType().getCode()));
+
         musicSheetPurchaseRecordService.saveOrUpdate(musicSheetPurchaseRecord);
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void buyMusicSheetCancel(UserOrderDetailVo userOrderDetailVo) {
-        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService
-                .checkPurchase(userOrderDetailVo.getUserId(), userOrderDetailVo.getBizId(), userOrderDetailVo.getOrderClient());
+        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
+                userOrderDetailVo.getUserId(),
+                userOrderDetailVo.getBizId(),
+                userOrderDetailVo.getOrderClient(),
+                PurchaseRecordTypeEnum.valueOf(userOrderDetailVo.getGoodType().getCode()));
 
         if (musicSheetPurchaseRecord == null) return;
         musicSheetPurchaseRecordService.removeById(musicSheetPurchaseRecord.getId());

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

@@ -1,12 +1,23 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 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.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
+import com.yonge.cooleshow.biz.dal.service.SysUserContractRecordService;
 import com.yonge.cooleshow.biz.dal.service.SysUserService;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
+import com.yonge.cooleshow.common.enums.SysUserType;
 import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.thirdparty.user.realname.RealnameAuthenticationPlugin;
+import com.yonge.toolset.utils.idcard.IdcardInfoExtractor;
+import com.yonge.toolset.utils.idcard.IdcardValidator;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.util.Optional;
 
 @Service
@@ -15,6 +26,13 @@ public class SysUserServiceImpl implements SysUserService {
     @Autowired
     private SysUserFeignService sysUserFeignService;
 
+    @Autowired
+    private RealnameAuthenticationPlugin realnameAuthenticationPlugin;
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Resource
+    private SysUserContractRecordService sysUserContractRecordService;
     @Override
     public Long getUserId() {
         return Optional.ofNullable(sysUserFeignService.queryUserInfo()).
@@ -37,4 +55,52 @@ public class SysUserServiceImpl implements SysUserService {
                 orElseThrow(()-> new BizException("请登录"));
         return optional.get();
     }
+
+    @Override
+    public IdcardInfoExtractor updateUserCard(RealnameAuthReq realNameAuthDto, SysUser sysUser,ClientEnum client) {
+        IdcardValidator idcardValidator = new IdcardValidator();
+        //验证身份证号合法性
+        boolean validatedAllIdcard = idcardValidator.isValidatedAllIdcard(realNameAuthDto.getIdCardNo());
+        if (!validatedAllIdcard) {
+            throw new BizException("身份证号不合法");
+        }
+        //通过身份证号获取身份信息
+        IdcardInfoExtractor idcardInfoExtractor = new IdcardInfoExtractor(realNameAuthDto.getIdCardNo(), validatedAllIdcard);
+        //todo 通过环境,不做实名判断
+        try {
+            boolean verify = realnameAuthenticationPlugin.verify(realNameAuthDto.getRealName(), realNameAuthDto.getIdCardNo());
+            if (!verify) {
+                throw new BizException("未通过实名认证");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BizException("未通过实名认证");
+        }
+
+        if (realNameAuthDto.getSave()) {
+            realNameAuthDto.setUserId(sysUser.getId());
+            realNameAuthDto.setGender(idcardInfoExtractor.getGender());
+            realNameAuthDto.setBirthday(idcardInfoExtractor.getBirthday());
+            //实名认证通过后立刻保存
+            sysUserMapper.updateUserCard(realNameAuthDto);
+        }
+        // 签订用户注册协议
+
+        // 判断是否已经签署
+        Boolean contractSign = sysUserContractRecordService.checkContractSign(sysUser.getId(),
+                                                                              SysUserType.valueOf(client.getCode()),
+                                                                              ContractTemplateTypeEnum.REGISTER);
+        if (!contractSign && realNameAuthDto.getContract()) {
+            sysUser.setRealName(realNameAuthDto.getRealName());
+            sysUser.setIdCardNo(realNameAuthDto.getIdCardNo());
+            sysUser.setGender(realNameAuthDto.getGender());
+            sysUser.setBirthdate(realNameAuthDto.getBirthday());
+            HttpResponseResult<Boolean> sign = sysUserContractRecordService.sign(ContractTemplateTypeEnum.REGISTER,
+                                                                                 SysUserType.valueOf(client.getCode()),sysUser);
+            if (!sign.getStatus() || !sign.getData()) {
+                throw new BizException(sign.getMsg());
+            }
+        }
+        return idcardInfoExtractor;
+    }
 }

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

@@ -7,11 +7,16 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 import javax.annotation.Resource;
 
+import com.google.common.collect.Lists;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherQueryInfo;
+import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.teacher.TeacherWrapper;
 import org.redisson.api.RMap;
 import org.redisson.api.RedissonClient;
 import org.slf4j.Logger;
@@ -205,6 +210,13 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
         teacherHomeVo.setMusicAlbumNum(null == total.getMusicAlbumNum() ? 0 : total.getMusicAlbumNum());
         teacherHomeVo.setMusicSheetNum(null == total.getMusicSheetNum() ? 0 : total.getMusicSheetNum());
 
+        // 老师学生人数统计
+        List<Long> teacherIds = Lists.newArrayList(userId);
+        Map<Long, Integer> studentNumsMap = getBaseMapper().selectTeacherStudentNumberStatInfo(teacherIds).stream()
+                .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
+
+        teacherHomeVo.setStudentNums(studentNumsMap.getOrDefault(userId, 0));
+
         //取直播缓存
         RMap<Long, String> liveMap = redissonClient.getMap(TEACHER_TEMP_LIVE_ROOM);
         String roomUid = liveMap.get(userId);
@@ -602,7 +614,21 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
 
 
     public IPage<MyFens> queryMyFans(IPage<MyFens> page, Long teacherId) {
-        List<MyFens> teacherVos = baseMapper.queryMyFans(page, teacherId);
+        List<MyFens> teacherVos = baseMapper.queryMyFans(page, TeacherQueryInfo.FansQuery.builder().teacherId(teacherId).build());
+        return page.setRecords(teacherVos);
+    }
+
+    /**
+     * 老师粉丝查询
+     *
+     * @param page  IPage<MyFens>
+     * @param query TeacherQueryInfo.FansQuery
+     * @return IPage<MyFens>
+     */
+    @Override
+    public IPage<MyFens> queryMyFans(IPage<MyFens> page, TeacherQueryInfo.FansQuery query) {
+
+        List<MyFens> teacherVos = baseMapper.queryMyFans(page, query);
         return page.setRecords(teacherVos);
     }
 
@@ -651,7 +677,7 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
 		return hotTeacherList;
 	}
 
-	private void setTagTime(TeacherTagEnum teacherTagEnum, TeacherVo teacherVo) {
+    private void setTagTime(TeacherTagEnum teacherTagEnum, TeacherVo teacherVo) {
         if (teacherTagEnum.equals(TeacherTagEnum.LIVE)) {
             teacherVo.setLiveDate(new Date());
         } else if (teacherTagEnum.equals(TeacherTagEnum.MUSIC)) {
@@ -663,4 +689,94 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
         }
     }
 
+
+    /**
+     * 老师详情信息
+     *
+     * @param teacherId 用户ID
+     * @return TeacherVo
+     */
+    @Override
+    public TeacherVo findTeacherDetailInfo(Long teacherId) {
+
+        // 用户详情基本信息
+        TeacherVo teacherInfo = detail(teacherId);
+
+        if (Objects.nonNull(teacherInfo)) {
+
+            // 设置默认数据
+            teacherInfo
+                    .starGrade(0)
+                    .fansNum(0)
+                    .expTime(0)
+                    .unExpTime(0)
+                    .musicSheetNum(0)
+                    .musicAlbumNum(0)
+                    .studentNums(0);
+
+            // 老师相关统计信息
+            TeacherTotal total = totalService.getTotalById(teacherId);
+
+            if (Objects.nonNull(total)) {
+
+                teacherInfo
+                        .starGrade(total.getStarGrade().intValue())
+                        .fansNum(total.getFansNum())
+                        .expTime(total.getExpTime())
+                        .unExpTime(total.getUnExpTime())
+                        .musicAlbumNum(total.getMusicAlbumNum())
+                        .musicSheetNum(total.getMusicSheetNum());
+            }
+
+            // 老师学生人数统计
+            Map<Long, Integer> studentNumsMap = getBaseMapper().selectTeacherStudentNumberStatInfo(Lists.newArrayList(teacherId)).stream()
+                    .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
+
+            teacherInfo.setStudentNums(studentNumsMap.getOrDefault(teacherId, 0));
+        }
+
+        return teacherInfo;
+    }
+
+    /**
+     * 老师统计指标信息
+     *
+     * @param userId 用户ID
+     * @return TeacherWrapper.TeacherStatInfo
+     */
+    @Override
+    public TeacherWrapper.TeacherStatInfo findTeacherStatInfoById(Long userId) {
+
+        TeacherWrapper.TeacherStatInfo wrapper = TeacherWrapper.TeacherStatInfo.builder()
+                .fansNum(0)
+                .studentNums(0)
+                .starGrade(0)
+                .expTime(0)
+                .unExpTime(0)
+                .musicAlbumNum(0)
+                .musicSheetNum(0)
+                .build();
+
+        // 查询老师统计指标
+        TeacherTotal total = totalService.getTotalById(userId);
+        if (Objects.nonNull(total)) {
+
+            wrapper.starGrade(total.getStarGrade().intValue())
+                    .fansNum(total.getFansNum())
+                    .expTime(total.getExpTime())
+                    .unExpTime(total.getUnExpTime())
+                    .musicAlbumNum(total.getMusicAlbumNum())
+                    .musicSheetNum(total.getMusicSheetNum());
+        }
+
+        // 老师学生端人数统计
+        List<Long> teacherIds = Lists.newArrayList(userId);
+        Map<Long, Integer> studentNumsMap = getBaseMapper().selectTeacherStudentNumberStatInfo(teacherIds).stream()
+                .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));
+
+        wrapper.setStudentNums(studentNumsMap.getOrDefault(userId, 0));
+
+        return wrapper;
+    }
+
 }

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

@@ -1,18 +1,41 @@
 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.yonge.cooleshow.biz.dal.dao.CourseScheduleDao;
+import com.yonge.cooleshow.biz.dal.dao.StudentDao;
+import com.yonge.cooleshow.biz.dal.dao.SubjectDao;
 import com.yonge.cooleshow.biz.dal.dao.UserBindingTeacherDao;
+import com.yonge.cooleshow.biz.dal.entity.Student;
+import com.yonge.cooleshow.biz.dal.entity.StudentAttendance;
+import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher;
-import com.yonge.cooleshow.biz.dal.service.SysConfigService;
-import com.yonge.cooleshow.biz.dal.service.UserBindingTeacherService;
+import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
+import com.yonge.cooleshow.biz.dal.enums.StudentCourseEnum;
+import com.yonge.cooleshow.biz.dal.mapper.CourseScheduleMapper;
+import com.yonge.cooleshow.biz.dal.mapper.StudentMapper;
+import com.yonge.cooleshow.biz.dal.mapper.SubjectMapper;
+import com.yonge.cooleshow.biz.dal.queryInfo.TeacherBindingUserQueryInfo;
+import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.vo.LiveCourseGroupStudentCourseVo;
+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 com.yonge.toolset.utils.date.DateUtil;
+import org.joda.time.DateTime;
+import org.joda.time.Period;
+import org.joda.time.PeriodType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -20,20 +43,157 @@ import java.util.stream.Collectors;
  * @Date: 2022/5/26
  */
 @Service("userBindingTeacherService")
-public class UserBindingTeacherServiceImpl extends ServiceImpl<UserBindingTeacherDao, UserBindingTeacher> implements UserBindingTeacherService {
+public class UserBindingTeacherServiceImpl extends ServiceImpl<UserBindingTeacherDao, UserBindingTeacher>
+        implements UserBindingTeacherService {
     private final static Logger log = LoggerFactory.getLogger(UserBindingTeacherServiceImpl.class);
 
     @Autowired
     private SysConfigService sysConfigService;
 
+    @Autowired
+    private StudentDao studentDao;
+
+    @Autowired
+    private SubjectDao subjectDao;
+
+    @Autowired
+    private CourseScheduleDao courseScheduleDao;
+
+    @Autowired
+    private StudentAttendanceService studentAttendanceService;
+
     @Override
     public void unbindTask() {
         String days = sysConfigService.findConfigValue(SysConfigConstant.PIANO_ROOM_UNBIND_DAYS);
         int i = Integer.parseInt(days);
         List<UserBindingTeacher> userBindingTeachers = baseMapper.queryUnbindList(i);
-        if(!CollectionUtils.isEmpty(userBindingTeachers)){
+        if (!CollectionUtils.isEmpty(userBindingTeachers)) {
             removeByIds(userBindingTeachers.stream().map(UserBindingTeacher::getId).collect(Collectors.toList()));
         }
     }
+
+    @Override
+    public IPage<UserBindingTeacherWrapper> selectBindingUserPage(IPage<UserBindingTeacherWrapper> page, TeacherBindingUserQueryInfo.BindingUserQuery query) {
+        if (query.getTeacherId() == null) {
+            throw new BizException("老师id不能为空");
+        }
+
+        IPage<UserBindingTeacherWrapper> bindingUserPage = baseMapper.selectBindingUserPage(page, query);
+
+        List<UserBindingTeacherWrapper> records = bindingUserPage.getRecords();
+        if (CollectionUtils.isEmpty(records)) {
+            return bindingUserPage;
+        }
+
+        // 学生id集合
+        List<Long> studentIdList = records.stream()
+                                          .map(UserBindingTeacherWrapper::getUserId)
+                                          .collect(Collectors.toList());
+
+
+        // 生日
+        records.forEach(userBindingTeacherWrapper -> {
+            Integer age = null;
+            if (userBindingTeacherWrapper.getBirthdate() != null) {
+                age = new Period(new DateTime(userBindingTeacherWrapper.getBirthdate()), DateTime.now(), PeriodType.years()).getYears();
+            }
+            userBindingTeacherWrapper.setAge(age);
+        });
+
+        // vip
+        List<Student> students = studentDao.selectBatchIds(studentIdList);
+
+        Map<Long, YesOrNoEnum> userIdVipMap = students.stream()
+                                                      .collect(Collectors.toMap(Student::getUserId,
+                                           student -> student.getMembershipEndTime() != null && student.getMembershipEndTime()
+                                           .compareTo(new Date()) > 0?YesOrNoEnum.YES:YesOrNoEnum.NO, (o, n) -> n));
+
+        // 声部
+        List<Long> subjectIdList = new ArrayList<>();
+        for (Student student1 : students) {
+            if (!StringUtil.isEmpty(student1.getSubjectId())) {
+                Long aLong = Long.valueOf(student1.getSubjectId());
+                subjectIdList.add(aLong);
+            }
+        }
+        List<Subject> subjectList = subjectDao.findBySubjectIds(subjectIdList);
+        Map<Long, String> userIdSubjectMap = students.stream()
+                      .collect(Collectors.toMap(Student::getUserId,student -> subjectList.stream()
+                                 .filter(subject -> student.getSubjectId().equals(subject.getId().toString())).findFirst().get().getName(), (o, n) -> n));
+
+        // 课程数
+        List<UserBindingTeacherWrapper.CourseNum> courseNumList = courseScheduleDao.selectStudentPianoCourse(query.getTeacherId(),studentIdList);
+        Map<Long, List<UserBindingTeacherWrapper.CourseNum>> userIdCourseStatusMap = courseNumList.stream()
+                                                                                    .collect(Collectors.groupingBy(
+                                                                                            UserBindingTeacherWrapper.CourseNum::getStudentId));
+
+        for (UserBindingTeacherWrapper record : records) {
+            record.setIsVip(userIdVipMap.get(record.getUserId()));
+            record.setSubjectName(userIdSubjectMap.get(record.getUserId()));
+
+            List<UserBindingTeacherWrapper.CourseNum> courseNums = userIdCourseStatusMap.get(record.getUserId());
+
+            Integer endCourseNum = 0;
+            Integer noStartCourseNum = 0;
+            record.setCourseNum(0);
+            if (!CollectionUtils.isEmpty(courseNums)) {
+                record.setCourseNum(courseNums.size());
+                for (UserBindingTeacherWrapper.CourseNum courseNum : courseNums) {
+                    if (courseNum.getStatus().equals("COMPLETE")) {
+                        endCourseNum++;
+                    } else {
+                        noStartCourseNum++;
+                    }
+                }
+            }
+            record.setEndCourseNum(endCourseNum);
+            record.setNoStartCourseNum(noStartCourseNum);
+
+        }
+        bindingUserPage.setRecords(records);
+        return bindingUserPage;
+    }
+
+    @Override
+    public IPage<UserBindingCourseWrapper> selectBindingUserCoursePage(IPage<UserBindingCourseWrapper> page, TeacherBindingUserQueryInfo.BindingStudentCourseQuery query) {
+        IPage<UserBindingCourseWrapper> userBindingCourseWrapperIPage = courseScheduleDao.selectBindingUserCoursePage(
+                page, query);
+        List<UserBindingCourseWrapper> records = userBindingCourseWrapperIPage.getRecords();
+        if (CollectionUtils.isEmpty(records)) {
+            return  userBindingCourseWrapperIPage;
+        }
+
+        // 声部
+        List<Long> subjectIdList = records.stream().map(UserBindingCourseWrapper::getSubjectId)
+                                          .collect(Collectors.toList());
+        List<Subject> subjectList = subjectDao.findBySubjectIds(subjectIdList);
+        Map<Long, String> subjectIdSubjectNameMap = subjectList.stream()
+                                                     .collect(Collectors.toMap(Subject::getId,Subject::getName, (o, n) -> n));
+
+        // 考勤
+        List<Long> courseIdList = records.stream().map(UserBindingCourseWrapper::getCourseId).collect(Collectors.toList());
+        List<StudentAttendance> studentAttendanceList = studentAttendanceService.lambdaQuery()
+                                                               .in(StudentAttendance::getCourseScheduleId, courseIdList)
+                                                               .list();
+        Set<Long> courseAttendanceList = studentAttendanceList.stream()
+                                                 .map(StudentAttendance::getCourseScheduleId)
+                                                 .collect(Collectors.toSet());
+
+        // 设置学生上课状态
+        for (UserBindingCourseWrapper record : records) {
+            record.setSubjectName(subjectIdSubjectNameMap.get(record.getSubjectId()));
+            if (CourseScheduleEnum.NOT_START.getCode().equals(record.getCourseStatus())) {
+                record.setStatus(StudentCourseEnum.NOTSTART);
+            } else {
+                if (courseAttendanceList.contains(record.getCourseId())) {
+                    record.setStatus(StudentCourseEnum.ATTENDCLASS);
+                } else {
+                    record.setStatus(StudentCourseEnum.TRUANT);
+                }
+            }
+        }
+        userBindingCourseWrapperIPage.setRecords(records);
+        return userBindingCourseWrapperIPage;
+    }
 }
 

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

@@ -160,6 +160,8 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         orderCreate.put(GoodTypeEnum.VIDEO, recordService::buyVideoCourse);
         //曲目购买
         orderCreate.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetCheck);
+        // 专辑购买
+        orderCreate.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetCheck);
         //琴房时长
         orderCreate.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderCreate);
         //活动报名
@@ -168,6 +170,8 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         /**********订单生成后******************/
         //曲目购买
         orderAfter.put(GoodTypeEnum.MUSIC, musicSheetService::orderAfterSheet);
+        // 专辑购买
+        orderAfter.put(GoodTypeEnum.ALBUM, musicSheetService::orderAfterSheet);
 
         /**********订单完成后******************/
         //vip开通缴费
@@ -180,6 +184,8 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         orderSuccess.put(GoodTypeEnum.VIDEO, recordService::buyVideoCourseSuccess);
         //曲目购买
         orderSuccess.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetSuccess);
+        // 专辑购买
+        orderSuccess.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetSuccess);
         //琴房时长
         orderSuccess.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderSuccess);
         //活动报名
@@ -194,6 +200,8 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         orderCancel.put(GoodTypeEnum.LIVE, courseGroupService::buyLiveCourseCancel);
         // 曲目购买
         orderCancel.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetCancel);
+        // 专辑购买
+        orderCancel.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetCancel);
     }
 
     @Override
@@ -349,6 +357,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
                 return HttpResponseResult.failed("订单商品信息获取失败");
             }
             info.setOrderNo(orderReq.getOrderNo());
+            info.setOrderType(orderReq.getOrderType());
             Long subOrderNo = idGeneratorService.generatorId("subOrderNo");
             info.setSubOrderNo(Long.toString(subOrderNo));
             info.setUserId(orderReq.getUserId());
@@ -663,6 +672,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
 
             UserOrderDetailVo orderDetail = new UserOrderDetailVo();
             orderDetail.setOrderNo(data.getOrderNo());
+            orderDetail.setOrderType(orderReq.getOrderType());
             orderDetail.setSubOrderNo(data.getSubOrderNo());
             orderDetail.setMerchId(res.getMerchId());
             orderDetail.setGoodType(res.getGoodType());
@@ -804,6 +814,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         for (UserOrderDetailVo orderDetailVo : orderDetailList) {
             orderDetailVo.setUserId(userOrder.getUserId());
             orderDetailVo.setOrderId(userOrder.getId());
+
             //调用业务
             Consumer<UserOrderDetailVo> userOrderVoConsumer = orderCancel.get(orderDetailVo.getGoodType());
             if (!Objects.isNull(userOrderVoConsumer)) {
@@ -841,6 +852,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
                 && !OrderStatusEnum.PAYING.equals(detail.getStatus())) {
             return;
         }
+
         //修改订单状态
         Date now = new Date();
         detail.setStatus(OrderStatusEnum.PAID);
@@ -882,6 +894,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
             orderDetailVo.setRecomUserId(detail.getRecomUserId());
             orderDetailVo.setActivityId(detail.getActivityId());
             orderDetailVo.setRewardId(detail.getRewardId());
+
             //调用业务
             Consumer<UserOrderDetailVo> userOrderVoConsumer = orderSuccess.get(orderDetailVo.getGoodType());
             if (!Objects.isNull(userOrderVoConsumer)) {

+ 11 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityEvaluationVo.java

@@ -26,6 +26,9 @@ public class ActivityEvaluationVo extends ActivityEvaluation{
 	@ApiModelProperty(value = "销售价格")
 	private BigDecimal musicPrice;
 
+	@ApiModelProperty(value = "曲目声部ID")
+	private String subjectId;
+
 	public String getMusicSheetName() {
 		return musicSheetName;
 	}
@@ -65,4 +68,12 @@ public class ActivityEvaluationVo extends ActivityEvaluation{
 	public void setMusicPrice(BigDecimal musicPrice) {
 		this.musicPrice = musicPrice;
 	}
+
+	public String getSubjectId() {
+		return subjectId;
+	}
+
+	public void setSubjectId(String subjectId) {
+		this.subjectId = subjectId;
+	}
 }

+ 70 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityMusicVo.java

@@ -47,6 +47,18 @@ public class ActivityMusicVo {
     @ApiModelProperty("最高分用户声部")
     private String userSubject;
 
+    @ApiModelProperty("声部ID")
+    private String subjectId;
+
+    @ApiModelProperty("作曲人")
+    private String composer;
+
+    @ApiModelProperty("曲目图片")
+    private String musicImage;
+
+    @ApiModelProperty("评测难度 BEGINNER 入门级 ADVANCED 进阶级 PERFORMER 大师级")
+    private String  evaluationDifficulty;
+
     public Long getUserId() {
         return userId;
     }
@@ -126,4 +138,62 @@ public class ActivityMusicVo {
     public void setUserSubject(String userSubject) {
         this.userSubject = userSubject;
     }
+
+    public String getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(String subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    public String getComposer() {
+        return composer;
+    }
+
+    public void setComposer(String composer) {
+        this.composer = composer;
+    }
+
+    public String getEvaluationDifficulty() {
+        return evaluationDifficulty;
+    }
+
+    public void setEvaluationDifficulty(String evaluationDifficulty) {
+        this.evaluationDifficulty = evaluationDifficulty;
+    }
+
+    public String getMusicImage() {
+        return musicImage;
+    }
+
+    public void setMusicImage(String musicImage) {
+        this.musicImage = musicImage;
+    }
+
+
+    public ActivityMusicVo score(double score) {
+        this.score = score;
+        return this;
+    }
+
+    public ActivityMusicVo userId(Long userId) {
+        this.userId = userId;
+        return this;
+    }
+
+    public ActivityMusicVo userAvatar(String userAvatar) {
+        this.userAvatar = userAvatar;
+        return this;
+    }
+
+    public ActivityMusicVo username(String username) {
+        this.username = username;
+        return this;
+    }
+
+    public ActivityMusicVo userSubject(String userSubject) {
+        this.userSubject = userSubject;
+        return this;
+    }
 }

+ 11 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityRankingVo.java

@@ -27,6 +27,9 @@ public class ActivityRankingVo {
     @ApiModelProperty("次数")
     private int times;
 
+	@ApiModelProperty("资源ID")
+	private Long resourceId;
+
 	public double getScore() {
 		return score;
 	}
@@ -82,4 +85,12 @@ public class ActivityRankingVo {
 	public void setTimes(int times) {
 		this.times = times;
 	}
+
+	public Long getResourceId() {
+		return resourceId;
+	}
+
+	public void setResourceId(Long resourceId) {
+		this.resourceId = resourceId;
+	}
 }

+ 38 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ActivityRegistrationVo.java

@@ -1,9 +1,13 @@
 package com.yonge.cooleshow.biz.dal.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.yonge.cooleshow.biz.dal.entity.ActivityRegistration;
+import com.yonge.cooleshow.biz.dal.enums.MK;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
+import java.util.Date;
+
 /**
  * @Author: liweifan
  * @Data: 2022-08-04 10:19:49
@@ -39,9 +43,17 @@ public class ActivityRegistrationVo extends ActivityRegistration{
 	// 用户高最排名信息
 	@ApiModelProperty("最高排名分数")
 	private Double score;
+	
 	@ApiModelProperty("最高排名次数")
 	private Integer times;
 
+	@ApiModelProperty("曲子声部")
+	private String subjectName;
+
+	@ApiModelProperty("最高分时间")
+	@JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
+	private Date scoreTime;
+
 	public String getRealName() {
 		return realName;
 	}
@@ -122,6 +134,22 @@ public class ActivityRegistrationVo extends ActivityRegistration{
 		this.times = times;
 	}
 
+	public String getSubjectName() {
+		return subjectName;
+	}
+
+	public void setSubjectName(String subjectName) {
+		this.subjectName = subjectName;
+	}
+
+	public Date getScoreTime() {
+		return scoreTime;
+	}
+
+	public void setScoreTime(Date scoreTime) {
+		this.scoreTime = scoreTime;
+	}
+
 	public ActivityRegistrationVo score(Double score) {
 		this.score = score;
 		return this;
@@ -131,4 +159,14 @@ public class ActivityRegistrationVo extends ActivityRegistration{
 		this.times = times;
 		return this;
 	}
+
+	public ActivityRegistrationVo subjectName(String subjectName) {
+		this.subjectName = subjectName;
+		return this;
+	}
+
+	public ActivityRegistrationVo scoreTime(Date scoreTime) {
+		this.scoreTime = scoreTime;
+		return this;
+	}
 }

+ 56 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/AlbumDetailVo.java

@@ -1,5 +1,6 @@
 package com.yonge.cooleshow.biz.dal.vo;
 
+import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.page.PageInfo;
 import io.swagger.annotations.ApiModelProperty;
@@ -56,6 +57,37 @@ public class AlbumDetailVo {
     @ApiModelProperty("相关专辑")
     private List<MusicAlbumVo> relatedMusicAlbum;
 
+    @ApiModelProperty("专辑价格 ")
+    private Double albumPrice;
+
+    @ApiModelProperty("专辑价格 ")
+    private String paymentType;
+
+    @ApiModelProperty("专辑曲目付费方式")
+    private List<String> musicPaymentTypes;
+
+
+    @ApiModelProperty("订单状态(WAIT_PAY:待支付;PAYING:支付中,PAID:已付款)")
+    private OrderStatusEnum orderStatus;
+
+    @ApiModelProperty("支付订单号")
+    private String orderNo;
+
+    public OrderStatusEnum getOrderStatus() {
+        return orderStatus;
+    }
+
+    public void setOrderStatus(OrderStatusEnum orderStatus) {
+        this.orderStatus = orderStatus;
+    }
+
+    public String getOrderNo() {
+        return orderNo;
+    }
+
+    public void setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+    }
 
     public String getSubjectId() {
         return subjectId;
@@ -179,4 +211,28 @@ public class AlbumDetailVo {
     public void setFavorite(YesOrNoEnum favorite) {
         this.favorite = favorite;
     }
+
+    public Double getAlbumPrice() {
+        return albumPrice;
+    }
+
+    public void setAlbumPrice(Double albumPrice) {
+        this.albumPrice = albumPrice;
+    }
+
+    public String getPaymentType() {
+        return paymentType;
+    }
+
+    public void setPaymentType(String paymentType) {
+        this.paymentType = paymentType;
+    }
+
+    public List<String> getMusicPaymentTypes() {
+        return musicPaymentTypes;
+    }
+
+    public void setMusicPaymentTypes(List<String> musicPaymentTypes) {
+        this.musicPaymentTypes = musicPaymentTypes;
+    }
 }

+ 79 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/MusicActivityVo.java

@@ -5,7 +5,12 @@ import com.yonge.cooleshow.biz.dal.entity.ActivityReward;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 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;
 import java.util.List;
 
 /**
@@ -29,6 +34,9 @@ public class MusicActivityVo extends ActivityPlan {
     @ApiModelProperty("是否已经报名参与 0 :否 1:是")
     private YesOrNoEnum join;
 
+    @ApiModelProperty("活动声部信息")
+    private List<SubjectInfo> subjectInfos;
+
     public YesOrNoEnum getJoin() {
         return join;
     }
@@ -60,4 +68,75 @@ public class MusicActivityVo extends ActivityPlan {
     public void setEvaluationDifficulty(String evaluationDifficulty) {
         this.evaluationDifficulty = evaluationDifficulty;
     }
+
+    public List<SubjectInfo> getSubjectInfos() {
+        return subjectInfos;
+    }
+
+    public void setSubjectInfos(List<SubjectInfo> subjectInfos) {
+        this.subjectInfos = subjectInfos;
+    }
+
+    /**
+     * 活动曲目声部信息
+     */
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class SubjectInfo implements Serializable {
+
+        @ApiModelProperty("声部ID")
+        private String subjectId;
+
+        @ApiModelProperty("声部名称")
+        private String subjectName;
+
+        @ApiModelProperty("是否已经报名参与 ")
+        private Integer join;
+
+        @ApiModelProperty("最高分")
+        private double score;
+
+        @ApiModelProperty("最高分的用户id")
+        private Long userId;
+
+        @ApiModelProperty("最高分用户头像")
+        private String userAvatar;
+
+        @ApiModelProperty("最高分用户声部")
+        private String userSubject;
+
+        @ApiModelProperty("最高分用户名")
+        private String username;
+
+        @ApiModelProperty("声部曲目数")
+        private Integer musicNums;
+
+
+        public SubjectInfo score(double score) {
+            this.score = score;
+            return this;
+        }
+
+        public SubjectInfo userId(Long userId) {
+            this.userId = userId;
+            return this;
+        }
+
+        public SubjectInfo userAvatar(String userAvatar) {
+            this.userAvatar = userAvatar;
+            return this;
+        }
+
+        public SubjectInfo username(String username) {
+            this.username = username;
+            return this;
+        }
+
+        public SubjectInfo userSubject(String userSubject) {
+            this.userSubject = userSubject;
+            return this;
+        }
+    }
 }

+ 10 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/MusicSheetVo.java

@@ -38,6 +38,8 @@ public class MusicSheetVo extends MusicSheet {
     @ApiModelProperty("专辑中曲目的排序号")
     private Integer albumSortNumber;  //排序号
 
+    @ApiModelProperty("单曲专辑数")
+    private Integer albumNums;
 
     public Integer getAlbumSortNumber() {
         return albumSortNumber;
@@ -102,4 +104,12 @@ public class MusicSheetVo extends MusicSheet {
     public void setPlay(YesOrNoEnum play) {
         this.play = play;
     }
+
+    public Integer getAlbumNums() {
+        return albumNums;
+    }
+
+    public void setAlbumNums(Integer albumNums) {
+        this.albumNums = albumNums;
+    }
 }

+ 67 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/MyFens.java

@@ -1,16 +1,27 @@
 package com.yonge.cooleshow.biz.dal.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.yonge.cooleshow.biz.dal.enums.GenderEnum;
-import com.yonge.cooleshow.common.entity.BaseEntity;
+import com.yonge.cooleshow.biz.dal.enums.MK;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import org.joda.time.DateTime;
+import org.joda.time.Period;
+import org.joda.time.PeriodType;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Objects;
 
 /**
  * @Author: cy
  * @Date: 2022/5/12
  */
-public class MyFens extends BaseEntity {
-    @ApiModelProperty("昵称")
+@ApiModel("老师粉丝响应信息")
+public class MyFens implements Serializable {
+
+    @ApiModelProperty("用户编号")
     private String userId;
     @ApiModelProperty("昵称")
     private String userName;
@@ -25,6 +36,19 @@ public class MyFens extends BaseEntity {
     @ApiModelProperty(value = "是否会员 0否 1是")
     private YesOrNoEnum isVip;
 
+    @ApiModelProperty("手机号")
+    private String phone;
+
+    @ApiModelProperty("关注时间")
+    @JsonFormat(pattern = MK.TIME_PATTERN, timezone = MK.TIME_ZONE)
+    private Date starTime;
+
+    @ApiModelProperty("出生日期")
+    private Date birthdate;
+
+    @ApiModelProperty("出生日期")
+    private Integer age;
+
     public String getSubjectName() {
         return subjectName;
     }
@@ -84,4 +108,44 @@ public class MyFens extends BaseEntity {
     public void setIsVip(YesOrNoEnum isVip) {
         this.isVip = isVip;
     }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public Date getStarTime() {
+        return starTime;
+    }
+
+    public void setStarTime(Date starTime) {
+        this.starTime = starTime;
+    }
+
+    public void setGender(GenderEnum gender) {
+        this.gender = gender;
+    }
+
+    public Date getBirthdate() {
+        return birthdate;
+    }
+
+    public void setBirthdate(Date birthdate) {
+        this.birthdate = birthdate;
+    }
+
+    public Integer getAge() {
+        if (Objects.nonNull(getBirthdate())) {
+
+            return new Period(new DateTime(getBirthdate()), DateTime.now(), PeriodType.years()).getYears();
+        }
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
 }

+ 11 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherHomeVo.java

@@ -40,6 +40,9 @@ public class TeacherHomeVo extends Teacher implements Serializable {
     @ApiModelProperty("曲谱数 ")
     private Integer musicSheetNum;
 
+    @ApiModelProperty("学生数")
+    private Integer studentNums;
+
     @ApiModelProperty(value = "声部名称(支持多个,用逗号分隔) ")
     private String subjectName;
     @ApiModelProperty(value = "性别 0女 1男")
@@ -291,4 +294,12 @@ public class TeacherHomeVo extends Teacher implements Serializable {
     public void setMusicSheetNum(Integer musicSheetNum) {
         this.musicSheetNum = musicSheetNum;
     }
+
+    public Integer getStudentNums() {
+        return studentNums;
+    }
+
+    public void setStudentNums(Integer studentNums) {
+        this.studentNums = studentNums;
+    }
 }

+ 107 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherVo.java

@@ -68,6 +68,21 @@ public class TeacherVo extends Teacher {
     @ApiModelProperty(value = "用户状态 NORMAL-正常   LOCKED-冻结  CLOSED-关闭")
     private UserStatusEnum userStatus;
 
+    @ApiModelProperty("星级")
+    private Integer starGrade;
+    @ApiModelProperty("粉丝数")
+    private Integer fansNum;
+    @ApiModelProperty("已上课时")
+    private Integer expTime;
+    @ApiModelProperty("未上课时")
+    private Integer unExpTime;
+    @ApiModelProperty("专辑数 ")
+    private Integer musicAlbumNum;
+    @ApiModelProperty("曲谱数 ")
+    private Integer musicSheetNum;
+    @ApiModelProperty("学生数")
+    private Integer studentNums;
+
     public YesOrNoEnum getDelFlag() {
         return delFlag;
     }
@@ -237,4 +252,96 @@ public class TeacherVo extends Teacher {
 	public void setUserStatus(UserStatusEnum userStatus) {
 		this.userStatus = userStatus;
 	}
+
+    public Integer getStarGrade() {
+        return starGrade;
+    }
+
+    public void setStarGrade(Integer starGrade) {
+        this.starGrade = starGrade;
+    }
+
+    public Integer getFansNum() {
+        return fansNum;
+    }
+
+    public void setFansNum(Integer fansNum) {
+        this.fansNum = fansNum;
+    }
+
+    public Integer getExpTime() {
+        return expTime;
+    }
+
+    public void setExpTime(Integer expTime) {
+        this.expTime = expTime;
+    }
+
+    public Integer getUnExpTime() {
+        return unExpTime;
+    }
+
+    public void setUnExpTime(Integer unExpTime) {
+        this.unExpTime = unExpTime;
+    }
+
+    public Integer getMusicAlbumNum() {
+        return musicAlbumNum;
+    }
+
+    public void setMusicAlbumNum(Integer musicAlbumNum) {
+        this.musicAlbumNum = musicAlbumNum;
+    }
+
+    public Integer getMusicSheetNum() {
+        return musicSheetNum;
+    }
+
+    public void setMusicSheetNum(Integer musicSheetNum) {
+        this.musicSheetNum = musicSheetNum;
+    }
+
+    public Integer getStudentNums() {
+        return studentNums;
+    }
+
+    public void setStudentNums(Integer studentNums) {
+        this.studentNums = studentNums;
+    }
+
+
+    public TeacherVo starGrade(Integer starGrade) {
+        this.starGrade = starGrade;
+        return this;
+    }
+
+    public TeacherVo fansNum(Integer fansNum) {
+        this.fansNum = fansNum;
+        return this;
+    }
+
+    public TeacherVo expTime(Integer expTime) {
+        this.expTime = expTime;
+        return this;
+    }
+
+    public TeacherVo unExpTime(Integer unExpTime) {
+        this.unExpTime = unExpTime;
+        return this;
+    }
+
+    public TeacherVo musicAlbumNum(Integer musicAlbumNum) {
+        this.musicAlbumNum = musicAlbumNum;
+        return this;
+    }
+
+    public TeacherVo musicSheetNum(Integer musicSheetNum) {
+        this.musicSheetNum = musicSheetNum;
+        return this;
+    }
+
+    public TeacherVo studentNums(Integer studentNums) {
+        this.studentNums = studentNums;
+        return this;
+    }
 }

+ 12 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/UserOrderDetailVo.java

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.biz.dal.vo;
 
 import com.yonge.cooleshow.biz.dal.entity.UserOrderDetail;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -42,6 +43,9 @@ public class UserOrderDetailVo extends UserOrderDetail {
     @ApiModelProperty("活动奖品id")
     private Long rewardId;
 
+    // 透传订单类型
+    private OrderTypeEnum orderType;
+
     public Long getRewardId() {
         return rewardId;
     }
@@ -121,4 +125,12 @@ public class UserOrderDetailVo extends UserOrderDetail {
     public void setRecomUserId(Long recomUserId) {
         this.recomUserId = recomUserId;
     }
+
+    public OrderTypeEnum getOrderType() {
+        return orderType;
+    }
+
+    public void setOrderType(OrderTypeEnum orderType) {
+        this.orderType = orderType;
+    }
 }

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

@@ -0,0 +1,87 @@
+package com.yonge.cooleshow.biz.dal.vo.activity;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.common.enums.RewardTypeEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-10-09
+ */
+public class UserRewardWrapper {
+
+
+    // ("领奖id")
+    private Long receiveRewardId;
+
+    // ("奖品名称 ")
+    private String rewardName;
+
+     // ("奖品类型:  ACTUAL 实物 VIP 小酷AI会员 PIAMO_ROOM 琴房时长 COUPON(优惠券)")
+    private RewardTypeEnum rewardType;
+
+    // ("奖品描述 ")
+    private String rewardDescribe;
+
+    // ("奖品图片 ")
+    private String imgUrl;
+
+    // ("获奖时间")
+    private Date winningTime;
+
+    public Long getReceiveRewardId() {
+        return receiveRewardId;
+    }
+
+    public void setReceiveRewardId(Long receiveRewardId) {
+        this.receiveRewardId = receiveRewardId;
+    }
+
+    public String getRewardName() {
+        return rewardName;
+    }
+
+    public void setRewardName(String rewardName) {
+        this.rewardName = rewardName;
+    }
+
+    public RewardTypeEnum getRewardType() {
+        return rewardType;
+    }
+
+    public void setRewardType(RewardTypeEnum rewardType) {
+        this.rewardType = rewardType;
+    }
+
+    public String getRewardDescribe() {
+        return rewardDescribe;
+    }
+
+    public void setRewardDescribe(String rewardDescribe) {
+        this.rewardDescribe = rewardDescribe;
+    }
+
+    public String getImgUrl() {
+        return imgUrl;
+    }
+
+    public void setImgUrl(String imgUrl) {
+        this.imgUrl = imgUrl;
+    }
+
+    public Date getWinningTime() {
+        return winningTime;
+    }
+
+    public void setWinningTime(Date winningTime) {
+        this.winningTime = winningTime;
+    }
+
+    public String jsonString() {
+        return JSON.toJSONString(this);
+    }
+}

+ 12 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/res/OrderCreateRes.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.biz.dal.vo.res;
 
 import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -42,6 +43,9 @@ public class OrderCreateRes {
     @ApiModelProperty(value = "冗余字段,用于传递参数用")
     private Object bizParam;
 
+    // 透传订单类型
+    private OrderTypeEnum orderType;
+
     public Long getRewardId() {
         return rewardId;
     }
@@ -145,4 +149,12 @@ public class OrderCreateRes {
     public void setCouponAmount(BigDecimal couponAmount) {
         this.couponAmount = couponAmount;
     }
+
+    public OrderTypeEnum getOrderType() {
+        return orderType;
+    }
+
+    public void setOrderType(OrderTypeEnum orderType) {
+        this.orderType = orderType;
+    }
 }

+ 125 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/userBindingTeacher/UserBindingCourseWrapper.java

@@ -0,0 +1,125 @@
+package com.yonge.cooleshow.biz.dal.vo.userBindingTeacher;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.biz.dal.enums.StudentCourseEnum;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-10-08
+ */
+public class UserBindingCourseWrapper {
+
+    //("课程编号")
+    private Long courseId;
+
+    // 声部id
+    private Long subjectId;
+
+    //("课程声部")
+    private String subjectName;
+
+    //("学员考勤")
+    private StudentCourseEnum status;
+    //(value = "课程状态 NOT_START未开始 ING进行中 COMPLETE已完成 CANCEL已取消  CourseScheduleEnum")
+    private String courseStatus;
+
+    // ("上课时间")
+    private Date classDate;
+    // 课程开始时间
+    private Date startTime;
+
+    //课程结束时间
+    private Date endTime;
+
+    // 学生id
+    private Long studentId;
+
+    // 考勤id
+    private Long studentAttendanceId;
+
+    public Long getStudentAttendanceId() {
+        return studentAttendanceId;
+    }
+
+    public void setStudentAttendanceId(Long studentAttendanceId) {
+        this.studentAttendanceId = studentAttendanceId;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public Long getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(Long subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    public Long getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Long studentId) {
+        this.studentId = studentId;
+    }
+
+    public Long getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(Long courseId) {
+        this.courseId = courseId;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public StudentCourseEnum getStatus() {
+        return status;
+    }
+
+    public void setStatus(StudentCourseEnum status) {
+        this.status = status;
+    }
+
+    public String getCourseStatus() {
+        return courseStatus;
+    }
+
+    public void setCourseStatus(String courseStatus) {
+        this.courseStatus = courseStatus;
+    }
+
+    public Date getClassDate() {
+        return classDate;
+    }
+
+    public void setClassDate(Date classDate) {
+        this.classDate = classDate;
+    }
+}

+ 179 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/userBindingTeacher/UserBindingTeacherWrapper.java

@@ -0,0 +1,179 @@
+package com.yonge.cooleshow.biz.dal.vo.userBindingTeacher;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-10-08
+ */
+public class UserBindingTeacherWrapper {
+
+    // 学生编号
+    private Long userId;
+
+    // 昵称
+    private String username;
+
+
+    // 性别0女1男
+    private Integer gender;
+
+    // 年龄
+    private Integer age;
+
+    // 生日
+    private Date birthdate;
+
+    // 声部
+    private String subjectName;
+
+    // 手机号
+    private String phone;
+
+    // 是否会员 0否 1是
+    private YesOrNoEnum isVip;
+
+
+    // 课程数
+    private Integer courseNum;
+
+    // 已结束课时数
+    private Integer endCourseNum;
+
+    // 未开始课程数
+    private Integer noStartCourseNum;
+
+    // 绑定时间
+    private Date bindingTime;
+
+    public String jsonString() {
+        return JSON.toJSONString(this);
+    }
+    public Long getUserId() {
+        return userId;
+    }
+
+    public Date getBirthdate() {
+        return birthdate;
+    }
+
+    public void setBirthdate(Date birthdate) {
+        this.birthdate = birthdate;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public Integer getGender() {
+        return gender;
+    }
+
+    public void setGender(Integer gender) {
+        this.gender = gender;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public YesOrNoEnum getIsVip() {
+        return isVip;
+    }
+
+    public void setIsVip(YesOrNoEnum isVip) {
+        this.isVip = isVip;
+    }
+
+    public Integer getCourseNum() {
+        return courseNum;
+    }
+
+    public void setCourseNum(Integer courseNum) {
+        this.courseNum = courseNum;
+    }
+
+    public Integer getEndCourseNum() {
+        return endCourseNum;
+    }
+
+    public void setEndCourseNum(Integer endCourseNum) {
+        this.endCourseNum = endCourseNum;
+    }
+
+    public Integer getNoStartCourseNum() {
+        return noStartCourseNum;
+    }
+
+    public void setNoStartCourseNum(Integer noStartCourseNum) {
+        this.noStartCourseNum = noStartCourseNum;
+    }
+
+    public Date getBindingTime() {
+        return bindingTime;
+    }
+
+    public void setBindingTime(Date bindingTime) {
+        this.bindingTime = bindingTime;
+    }
+
+    public static class CourseNum {
+
+        // 学生id
+        private Long studentId;
+
+        // 课程数
+        private String status;
+
+
+        public Long getStudentId() {
+            return studentId;
+        }
+
+        public void setStudentId(Long studentId) {
+            this.studentId = studentId;
+        }
+
+        public String getStatus() {
+            return status;
+        }
+
+        public void setStatus(String status) {
+            this.status = status;
+        }
+    }
+}

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/StatGroupWrapper.java

@@ -20,5 +20,6 @@ public class StatGroupWrapper implements Serializable {
     private Long id;
     private Integer total;
     private String gid; // 字符串分组ID
+    private Double number;
 
 }

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

@@ -0,0 +1,39 @@
+package com.yonge.cooleshow.biz.dal.wrapper.im;
+
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 客服消息
+ * Created by Eric.Shang on 2022/9/30.
+ */
+public class CustomerService {
+
+    /**
+     * 客服通知消息
+     */
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class NotifyMessage implements Serializable {
+
+        private List<String> receives;
+
+        private String title;
+        private String txtMessage;
+        private String imgMessage;
+        private String imgUrl;
+
+        public static NotifyMessage from(String recv) {
+
+            return JSON.parseObject(recv, NotifyMessage.class);
+        }
+    }
+}

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

@@ -0,0 +1,77 @@
+package com.yonge.cooleshow.biz.dal.wrapper.teacher;
+
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * Created by Eric.Shang on 2022/10/8.
+ */
+public class TeacherWrapper {
+
+    /**
+     * 老师统计指标信息
+     */
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class TeacherStatInfo implements Serializable {
+
+        // 星级
+        private Integer starGrade;
+        // 粉丝数
+        private Integer fansNum;
+        // 已上课时
+        private Integer expTime;
+        // 未上课时
+        private Integer unExpTime;
+        // 专辑数
+        private Integer musicAlbumNum;
+        // 曲谱数
+        private Integer musicSheetNum;
+        // 学生数
+        private Integer studentNums;
+
+        public String jsonString() {
+
+            return JSON.toJSONString(this);
+        }
+
+
+        public TeacherStatInfo starGrade(Integer starGrade) {
+            this.starGrade = starGrade;
+            return this;
+        }
+
+        public TeacherStatInfo fansNum(Integer fansNum) {
+            this.fansNum = fansNum;
+            return this;
+        }
+
+        public TeacherStatInfo expTime(Integer expTime) {
+            this.expTime = expTime;
+            return this;
+        }
+
+        public TeacherStatInfo unExpTime(Integer unExpTime) {
+            this.unExpTime = unExpTime;
+            return this;
+        }
+
+        public TeacherStatInfo musicAlbumNum(Integer musicAlbumNum) {
+            this.musicAlbumNum = musicAlbumNum;
+            return this;
+        }
+
+        public TeacherStatInfo musicSheetNum(Integer musicSheetNum) {
+            this.musicSheetNum = musicSheetNum;
+            return this;
+        }
+
+    }
+}

+ 30 - 11
cooleshow-user/user-biz/src/main/resources/config/mybatis/ActivityEvaluationMapper.xml

@@ -16,6 +16,7 @@
         , t.activity_id_ as activityId
         , t.music_sheet_id_ as musicSheetId
         , t.resource_type_ as resourceType
+        , t.evaluation_difficulty_ as evaluationDifficulty
         , t.create_time_ as createTime
         , t.create_by_ as createBy
     </sql>
@@ -30,14 +31,13 @@
 
     <sql id="selectSql">
         SELECT
-            <include refid="baseColumns" />,
-            ms.music_sheet_name_ as musicSheetName,
-            (select group_concat(mt.name_) from music_tag mt
-                where find_in_set(mt.id_,ms.music_tag_) and mt.del_flag_ = 0  and mt.state_ = 1) as musicTagNames,
-            (select group_concat(s.name_) from subject s
-                where find_in_set(s.id_,ms.music_subject_) and s.del_flag_ = 0 ) as subjectNames,
-            ms.source_type_ as sourceType,
-            ms.music_price_ as musicPrice
+            <include refid="baseColumns" />
+            , ms.music_sheet_name_ as musicSheetName
+            , ms.music_subject_ AS subjectId
+            , (select group_concat(mt.name_) from music_tag mt where find_in_set(mt.id_,ms.music_tag_) and mt.del_flag_ = 0  and mt.state_ = 1) as musicTagNames
+            , (select group_concat(s.name_) from subject s where find_in_set(s.id_,ms.music_subject_) and s.del_flag_ = 0 ) as subjectNames
+            , ms.source_type_ as sourceType
+            , ms.music_price_ as musicPrice
         FROM activity_evaluation t
         left join music_sheet ms on t.music_sheet_id_ = ms.id_
         <where>
@@ -67,11 +67,13 @@
 
         select ms.id_ as musicSheetId
         ,ms.music_sheet_name_ as musicSheetName
+        , ms.music_subject_ AS subjectId
+        , ms.title_img_ AS musicImage
         ,s.name_ as musicSubject
+        , ms.composer_ AS composer
         ,ae.id_ as evaluationId
-        ,(select if(count(1)>0,1,0) as `join` from activity_evaluation_record aer
-            where aer.evaluation_id_ = ae.id_ and aer.user_id_ = #{userId}
-        ) as `join`
+        , ae.evaluation_difficulty_ AS evaluationDifficulty
+        ,(select if(count(1)>0,1,0) as `join` from activity_evaluation_record aer where aer.evaluation_id_ = ae.id_ and aer.user_id_ = #{userId}) as `join`
         from activity_evaluation ae
         left join music_sheet ms on ms.id_ = ae.music_sheet_id_
         left join subject s on s.id_ = ms.music_subject_
@@ -241,4 +243,21 @@
         </where>
     </select>
     <!--时间匹配活动老师信息-->
+
+    <!--评测活动声部曲目最多分-->
+    <select id="selectSubjectMusicHighestScoreStat"
+            resultType="com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper">
+        SELECT t1.evaluation_id_ AS id, MAX(t1.score_) AS number FROM activity_evaluation_record t1
+        <where>
+            t1.score_ IS NOT NULL
+            <if test="activityId != null">
+                AND t1.activity_id_ = #{activityId}
+            </if>
+            <if test="userId != null">
+                AND t1.user_id_ = #{userId}
+            </if>
+        </where>
+        GROUP BY t1.evaluation_id_
+    </select>
+    <!--评测活动声部曲目最多分-->
 </mapper>

+ 48 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/ActivityPlanMapper.xml

@@ -17,6 +17,11 @@
 	        <result column="registration_method_" property="registrationMethod" />
 	        <result column="registration_price_" property="registrationPrice" />
             <result column="share_rate_" property="shareRate" />
+            <result column="share_type_" property="shareType" />
+            <result column="ranking_" property="ranking" />
+            <result column="ranking_rule_" property="rankingRule" />
+            <result column="ranking_method_" property="rankingMethod" />
+            <result column="ranking_score_" property="rankingScore" />
 	        <result column="draft_flag_" property="draftFlag" />
 	        <result column="activity_state_" property="activityState" />
 	        <result column="create_time_" property="createTime" />
@@ -45,6 +50,8 @@
         , t.share_type_ as shareType
         , t.ranking_ as ranking
         , t.ranking_rule_ as rankingRule
+        , t.ranking_method_ as rankingMethod
+        , t.ranking_score_ as rankingScore
         , t.draft_flag_ as draftFlag
         , if(t.activity_state_ = 1, 1, 0) as activityState
         , t.create_time_ as createTime
@@ -158,4 +165,45 @@
     </select>
     <!--活动参与人数、获奖人数统计-->
 
+    <!--活动总分用户排名-->
+    <select id="selectActivityHighestScoreRankingInfo"
+            resultType="com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo">
+        SELECT
+            t1.score_, t1.user_id_, t1.resource_id_, t1.create_time_ AS joinDate, t1.times_, t2.avatar_ AS userAvatar, t2.username_ AS username
+        FROM
+            activity_evaluation_record t1 LEFT JOIN sys_user t2 ON t1.user_id_ = t2.id_
+        WHERE
+            t1.activity_id_ = #{activityId} AND t1.ranking_method_ = 'TOTAL_SCORE' AND t1.score_ >= #{rankingScore}
+            <if test="subjectId != null">
+                AND t1.resource_id_ = #{subjectId}
+            </if>
+            <if test="subjectId == null">
+                AND t1.user_id_ NOT IN (SELECT t3.user_id_ FROM activity_user_reward t3 WHERE t3.activity_id_ = #{activityId})
+            </if>
+        ORDER BY
+            t1.score_ DESC,
+            t1.registration_time_ ASC
+        LIMIT #{limit}
+    </select>
+
+    <select id="selectActivityHighestScoreUserRanking"
+            resultType="com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo">
+        SELECT
+            t1.score_, t1.user_id_, t1.resource_id_, t1.create_time_ AS joinDate, t1.times_, t2.avatar_ AS userAvatar, t2.username_ AS username
+        FROM
+            activity_evaluation_record t1 LEFT JOIN sys_user t2 ON t1.user_id_ = t2.id_
+        WHERE
+            t1.activity_id_ = #{activityId} AND t1.ranking_method_ = 'TOTAL_SCORE' AND t1.score_ >= #{rankingScore}
+            <if test="subjectId != null">
+                AND t1.resource_id_ = #{subjectId}
+            </if>
+            <if test="userId != null">
+                AND t1.user_id_ = #{userId}
+            </if>
+        ORDER BY
+            t1.score_ DESC,
+            t1.registration_time_ ASC
+        LIMIT 1
+    </select>
+    <!--活动总分用户排名-->
 </mapper>

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

@@ -63,6 +63,9 @@
                     <if test="param.activityId != null">
                         and aer.activity_id_ = #{param.activityId}
                     </if>
+		            <if test="param.subjectIds != null and param.subjectIds.size() > 0">
+                        AND aer.resource_id_ IN (<foreach collection="param.subjectIds" separator="," item="item">#{item}</foreach>)
+                    </if>
 		            <if test="param.musicSheetIds != null and param.musicSheetIds.size()>0">
                         and ae.music_sheet_id_ IN
                         <foreach collection="param.musicSheetIds" item="item" separator="," open="(" close=")">

+ 45 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/ActivityUserRewardMapper.xml

@@ -10,6 +10,7 @@
         <result column="unit_" property="unit" />
         <result column="grant_flag_" property="grantFlag" />
         <result column="receive_flag_" property="receiveFlag" />
+        <result column="receive_time_" property="receiveTime" />
         <result column="create_time_" property="createTime" />
         <result column="update_time_" property="updateTime" />
     </resultMap>
@@ -26,6 +27,7 @@
         , t.receive_flag_ as receiveFlag
         , t.create_time_ as createTime
         , t.update_time_ as updateTime
+        , t.receive_time_ as receiveTime
     </sql>
 
     <select id="detail" resultType="com.yonge.cooleshow.biz.dal.vo.ActivityUserRewardVo">
@@ -88,6 +90,49 @@
         FROM sys_user t1 JOIN activity_evaluation t2 ON t1.id_ = t2.music_sheet_id_ JOIN activity_evaluation_record t3 ON t2.id_ = t3.evaluation_id_
         WHERE t3.activity_id_ = #{activityId} AND t3.user_id_ IN (<foreach collection="userIds" separator="," item="item">#{item}</foreach>)
     </select>
+
+    <select id="selectReceiveRewardCount" resultType="int">
+
+        select count(1) from
+        activity_user_reward aur
+        left join activity_plan ap on ap.id_ = aur.activity_id_
+        left join activity_reward ar on ar.id_ = aur.reward_id_
+        <include refid="selectReceiveRewardSql"/>
+    </select>
+
+    <update id="receiveReward">
+        update  activity_user_reward set receive_flag_ = 1 ,receive_time_ = #{receiveTime} where grant_flag_=1 and receive_flag_ = 0 and id_ = #{receiveRewardId} and user_id_ = #{userId}
+
+    </update>
+    <sql id="selectReceiveRewardSql">
+        <where>
+            ar.reward_type_ != 'ACTUAL'
+            <if test="query.userId != null">
+                and aur.user_id_ = #{query.userId}
+            </if>
+            <if test="query.client != null">
+                and ap.activity_client_ = #{query.client}
+            </if>
+            <if test="query.receive != null">
+                and aur.receive_flag_ = #{query.receive}
+            </if>
+        </where>
+    </sql>
+
+    <select id="selectReceiveRewardList" resultType="com.yonge.cooleshow.biz.dal.vo.activity.UserRewardWrapper">
+        select
+            aur.id_ as receiveRewardId,
+            ar.reward_name_ as rewardName,
+            ar.reward_type_ as rewardType,
+            ar.reward_describe_ as rewardDescribe,
+            ar.img_url_ as imgUrl,
+            aur.winning_time_ as winningTime
+        from
+        activity_user_reward aur
+        left join activity_plan ap on ap.id_ = aur.activity_id_
+        left join activity_reward ar on ar.id_ = aur.reward_id_
+        <include refid="selectReceiveRewardSql"/>
+    </select>
     <!--分享活动关联老师-->
 
 </mapper>

+ 39 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

@@ -946,4 +946,43 @@
         AND ts.status_ = 'WAIT'
         <![CDATA[ AND DATE_FORMAT(ts.update_time_,'%Y-%m-%d') <= #{day}]]>
     </select>
+
+    <select id="selectStudentPianoCourse"
+            resultType="com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingTeacherWrapper$CourseNum">
+        select cssp.user_id_ as studentId
+            ,cs.status_ as status
+        from course_schedule_student_payment cssp
+        left join course_group cg on cg.id_ = cssp.course_group_id_
+        left join course_schedule cs on cs.id_ = cssp.course_id_
+        <where>
+            cssp.course_type_ = 'PIANO_ROOM_CLASS'
+            and #{teacherId} = cg.teacher_id_
+            and cs.status_ in ('NOT_START','ING','COMPLETE')
+            and cssp.user_id_ in
+            <foreach collection="studentIdList" close=")" open="(" item="item" separator=",">
+                #{item}
+            </foreach>
+        </where>
+    </select>
+
+    <select id="selectBindingUserCoursePage"
+            resultType="com.yonge.cooleshow.biz.dal.vo.userBindingTeacher.UserBindingCourseWrapper">
+        select cssp.user_id_ as studentId
+        ,cs.status_ as courseStatus
+        ,cs.id_ as courseId
+        ,cg.subject_id_ as subjectId
+        ,cs.class_date_ as classDate
+        ,cs.start_time_ as startTime
+        ,cs.end_time_ as endTime
+        ,cg.subject_id_ as subjectId
+        from course_schedule_student_payment cssp
+        left join course_group cg on cg.id_ = cssp.course_group_id_
+        left join course_schedule cs on cs.id_ = cssp.course_id_
+        <where>
+            cssp.course_type_ = 'PIANO_ROOM_CLASS'
+            and #{query.teacherId} = cg.teacher_id_
+            and cs.status_ in ('NOT_START','ING','COMPLETE')
+            and cssp.user_id_ =#{query.studentId}
+        </where>
+    </select>
 </mapper>

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

@@ -34,6 +34,8 @@
         t.create_time_,
         t.audit_version_,
         t.create_by_,
+        t.album_price_,
+        t.payment_type_,
         t.update_time_,
         t.update_by_
     </sql>
@@ -102,14 +104,35 @@
         ,(select group_concat(s.name_) from subject s
         where find_in_set(s.id_,t.subject_id_) and s.del_flag_ = 0 ) as subjectNames
         from music_album t
-        left join album_favorite af2 on af2.album_id_ = t.id_
+        <if test="query.albumFavorite != null">
+            left join album_favorite af2 on af2.album_id_ = t.id_
+        </if>
+        <if test="query.albumPurchased != null">
+            JOIN music_sheet_purchase_record t2 ON (t.id_ = t2.music_sheet_id_)
+        </if>
         <where>
-            t.del_flag_ = 0
-            <if test="query.studentId != null">
-                and af2.user_id_ = #{query.studentId}
+            <if test="query.albumFavorite != null">
+                t.del_flag_ = 0
+                <if test="query.studentId != null">
+                    and af2.user_id_ = #{query.studentId}
+                </if>
+                <if test="clientType != null">
+                    AND af2.client_type_ = #{clientType}
+                </if>
             </if>
-            <if test="clientType != null">
-                AND af2.client_type_ = #{clientType}
+            <if test="query.albumPurchased != null">
+                <if test="query.clientType != null">
+                    AND t2.client_type_ = #{query.clientType}
+                </if>
+                <if test="query.orderStatus != null">
+                    AND t2.order_status_ = #{query.orderStatus}
+                </if>
+                <if test="query.purchaseType != null">
+                    AND t2.purchase_type_ = #{query.purchaseType}
+                </if>
+                <if test="query.studentId != null">
+                    AND t2.student_id_ = #{query.studentId}
+                </if>
             </if>
             <if test="query.idAndName != null and query.idAndName != ''">
                 and (t.id_ like concat('%',#{query.idAndName},'%') or
@@ -134,7 +157,9 @@
                 and t.album_status_ = #{query.albumStatus}
             </if>
         </where>
-        order by  af2.favorite_time_ desc
+        <if test="query.albumFavorite != null">
+            order by  af2.favorite_time_ desc
+        </if>
     </select>
 
     <select id="selectFavoriteNumAndMusicNum" resultType="com.yonge.cooleshow.biz.dal.vo.MusicAlbumVo">
@@ -206,6 +231,9 @@
        and amr.album_id_ = t.id_) as musicSheetCount
         ,if(t2.num >0,t2.num,0) as albumFavoriteCount
         from music_album t
+        <if test="query.musicId != null">
+            JOIN album_music_relate t1 ON (t.id_ = t1.album_id_ AND t1.music_sheet_id_ = #{query.musicId})
+        </if>
         left join (select count(1) as num,af.album_id_ from album_favorite af
             left join sys_user su on (af.user_id_ = su.id_ <if test="clientType != null"> AND af.client_type_ = #{clientType} </if>)
             where su.del_flag_ = 0 group by af.album_id_
@@ -245,4 +273,22 @@
         </if>
         ,t.id_ desc
     </select>
+
+    <!--专辑曲目付费方式统计-->
+    <select id="selectAlbumMusicSheetStatInfo"
+            resultType="com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper">
+        SELECT t1.album_id_ AS id, COUNT(t1.id_) AS total
+        FROM album_music_relate t1 JOIN music_sheet t2 ON (t1.music_sheet_id_ = t2.id_)
+        <where>
+            <if test="albumId != null">
+                AND t1.album_id_ = #{albumId}
+            </if>
+            <if test="paymentType != null">
+                AND t2.payment_type_ = #{paymentType}
+            </if>
+        </where>
+        GROUP BY t1.album_id_
+    </select>
+    <!--专辑曲目付费方式统计-->
+
 </mapper>

+ 22 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/MusicSheetMapper.xml

@@ -191,6 +191,15 @@
             <if test="param.delFlag != null">
                 and t.del_flag_ = #{param.delFlag}
             </if>
+            <if test="param.sourceType != null">
+                AND t.source_type_ = #{param.sourceType}
+            </if>
+            <if test="param.chargeType != null">
+                AND (t.payment_type_ = 'FREE' OR FIND_IN_SET(#{param.chargeType}, t.payment_type_))
+            </if>
+            <if test="param.paymentTypes != null">
+                AND t.payment_type_ IN (<foreach collection="param.paymentTypes" separator="," item="item">#{item}</foreach>)
+            </if>
             <if test="param.id != null">
                 <if test="param.type == 2">
                     and amr.album_id_ = #{param.id}
@@ -713,4 +722,17 @@
 
         order by msar.id_ desc
     </select>
+
+    <!--单曲专辑数量统计-->
+    <select id="selectMusicAlbumStatInfo" resultType="com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper">
+        SELECT t1.music_sheet_id_ AS id, COUNT(DISTINCT t1.id_) AS total
+        FROM album_music_relate t1 JOIN music_sheet t2 ON (t1.music_sheet_id_ = t2.id_)
+        <where>
+            <if test="musicIds != null">
+                AND t1.music_sheet_id_ IN (<foreach collection="musicIds" separator="," item="item">#{item}</foreach>)
+            </if>
+        </where>
+        GROUP BY t1.music_sheet_id_
+    </select>
+    <!--单曲专辑数量统计-->
 </mapper>

部分文件因为文件数量过多而无法显示