Browse Source

Merge branch 'ponline' into online

# Conflicts:
#	cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicSheetController.java
#	cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicSheet.java
Eric 2 years ago
parent
commit
dbf8bd6de2
39 changed files with 2260 additions and 121 deletions
  1. 6 1
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java
  2. 8 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java
  3. 22 0
      cooleshow-task/src/main/java/com/yonge/cooleshow/task/jobs/BatchSendingTask.java
  4. 175 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/CustomerServiceBatchSendingController.java
  5. 91 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/CustomerServiceReceiveController.java
  6. 15 16
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicAlbumController.java
  7. 2 2
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/MusicSheetController.java
  8. 1 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/OpenUserAccountController.java
  9. 101 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/CustomerServiceBatchSendingVo.java
  10. 59 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/CustomerServiceReceiveVo.java
  11. 26 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/task/TaskController.java
  12. 22 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/MusicImgDto.java
  13. 22 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/TeacherMusicSheetAuditReq.java
  14. 95 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CustomerServiceBatchSending.java
  15. 44 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CustomerServiceReceive.java
  16. 44 13
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicSheet.java
  17. 28 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImReceiveType.java
  18. 30 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImSendStatus.java
  19. 28 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/im/EImSendType.java
  20. 36 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CustomerServiceBatchSendingMapper.java
  21. 25 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/mapper/CustomerServiceReceiveMapper.java
  22. 61 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CustomerServiceBatchSendingService.java
  23. 43 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CustomerServiceReceiveService.java
  24. 4 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicSheetService.java
  25. 582 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceBatchSendingServiceImpl.java
  26. 93 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceReceiveServiceImpl.java
  27. 2 31
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java
  28. 101 23
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MusicSheetServiceImpl.java
  29. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerService.java
  30. 191 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerServiceBatchSendingWrapper.java
  31. 83 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerServiceReceiveWrapper.java
  32. 74 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CustomerServiceBatchSendingMapper.xml
  33. 28 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CustomerServiceReceiveMapper.xml
  34. 4 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/MusicSheetMapper.xml
  35. 26 21
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/open/OpenClient.java
  36. 16 4
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/open/OpenShareController.java
  37. 15 5
      cooleshow-user/user-website/src/main/java/com/yonge/cooleshow/website/controller/open/OpenMusicSheetController.java
  38. 12 0
      toolset/toolset-base/pom.xml
  39. 44 0
      toolset/toolset-base/src/main/java/com/yonge/toolset/base/util/ImUtil.java

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -168,10 +168,10 @@ public class MusicSheetController extends BaseController {
         if (musicSheet.getId()==null){
             return failed("缺少ID");
         }
-        MusicSheet service = musicSheetService.getById(musicSheet.getId());
+        /*MusicSheet service = musicSheetService.getById(musicSheet.getId());
         if (YesOrNoEnum.YES.getCode().equals(service.getState().getCode())) {
             return failed("启用状态不许修改");
-        }
+        }*/
 
         if (musicSheet.getNotation() == null) {
             musicSheet.setNotation(YesOrNoEnum.NO);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 44 - 13
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/MusicSheet.java

@@ -1,18 +1,5 @@
 package com.yonge.cooleshow.biz.dal.entity;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.Objects;
-import java.util.Optional;
-
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -22,8 +9,18 @@ import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
 import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang3.StringUtils;
 
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.Objects;
+
 /**
  * 曲谱表
  * @author yzp
@@ -237,6 +234,14 @@ public class MusicSheet implements Serializable {
 	@TableField("music_first_svg_")
 	private String musicFirstSvg;
 
+	@TableField("first_tone_")
+	@ApiModelProperty("首调")
+	private String firstTone;
+
+	@TableField("fixed_tone_")
+	@ApiModelProperty("固定调")
+	private String fixedTone;
+
 	@TableField("del_flag_")
 	@ApiModelProperty(value = "假删除标识 0:未删除 1:已删除")
 	private Boolean delFlag;
@@ -597,6 +602,22 @@ public class MusicSheet implements Serializable {
 		this.paymentType = paymentType;
 	}
 
+	public String getFirstTone() {
+		return firstTone;
+	}
+
+	public void setFirstTone(String firstTone) {
+		this.firstTone = firstTone;
+	}
+
+	public String getFixedTone() {
+		return fixedTone;
+	}
+
+	public void setFixedTone(String fixedTone) {
+		this.fixedTone = fixedTone;
+	}
+
 	public MusicSheet notation(YesOrNoEnum notation) {
 		this.notation = notation;
 		return this;
@@ -663,4 +684,14 @@ public class MusicSheet implements Serializable {
 	public void setMusicFirstSvg(String musicFirstSvg) {
 		this.musicFirstSvg = musicFirstSvg;
 	}
+
+	public MusicSheet firstTone(String firstTone) {
+		this.firstTone = firstTone;
+		return this;
+	}
+
+	public MusicSheet fixedTone(String fixedTone) {
+		this.fixedTone = fixedTone;
+		return this;
+	}
 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -21,6 +21,7 @@ import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.ImUserWrapper;
 import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.util.ImUtil;
 import io.rong.messages.BaseMessage;
 import io.rong.messages.ImgMessage;
 import io.rong.messages.TxtMessage;
@@ -28,8 +29,6 @@ import io.rong.models.message.PrivateMessage;
 import io.rong.models.message.PushExt;
 import io.rong.models.response.ResponseResult;
 import lombok.extern.slf4j.Slf4j;
-import net.coobird.thumbnailator.Thumbnails;
-import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -37,11 +36,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.URL;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -299,7 +293,7 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
         }
 
         // 发送图片消息
-        ImgMessage imgMessage = new ImgMessage(imageToBase64(info.getImgMessage(), "png"), "", info.getImgUrl());
+        ImgMessage imgMessage = new ImgMessage(ImUtil.imageToBase64(info.getImgMessage(), "png"), "", info.getImgUrl());
 
         // 发送文本消息
         TxtMessage txtMessage = new TxtMessage(info.getTxtMessage(), "");
@@ -342,30 +336,7 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
 
     }
 
-    public static String imageToBase64(String imgMessage, String suffix) {
 
-        Base64 encoder = new Base64();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try {
-            URL url = new URL(imgMessage);
-            BufferedImage bufferedImage = Thumbnails.of(url).scale(0.1f).outputQuality(0.25f).asBufferedImage();
-            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-            ImageIO.write(bufferedImage, suffix, outputStream);
-
-            byte[] bytes = outputStream.toByteArray();
-            outputStream.close();
-            int length = bytes.length;
-            //文件大小不能超过393216 Bytes
-            if (length > 393216) {
-                throw new BizException("文件过大请调整 像素 或 文件大小");
-            }
-
-            ImageIO.write(bufferedImage, suffix, baos);
-        } catch (IOException e) {
-            log.error("imageToBase64", e);
-        }
-        return new String(encoder.encode((baos.toByteArray())));
-    }
 
     /**
      * 用户IM好友列表

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

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

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

@@ -29,6 +29,7 @@ public class CustomerService {
         private List<String> receives;
         private ClientEnum clientType;
         private String subjectId;
+        private List<String> subjectIds;
 
         private String title;
         private String txtMessage;

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

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

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

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

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

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

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

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE  mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.yonge.cooleshow.biz.dal.mapper.CustomerServiceReceiveMapper">
+
+	 
+    
+    <!-- 表字段 -->
+    <sql id="baseColumns">
+         t.id_ AS id
+        , t.batch_sending_id_ AS batchSendingId
+        , t.user_id_ AS userId
+        , t.client_type_ AS clientType
+        , t.create_time_ AS createTime
+    </sql>
+    
+    <select id="selectPage" resultType="com.yonge.cooleshow.biz.dal.wrapper.im.CustomerServiceReceiveWrapper$CustomerServiceReceive">
+		SELECT         
+        	<include refid="baseColumns" />
+		FROM customer_service_receive t
+		<where>
+            <if test="param.batchSendingId != null">
+                AND t.batch_sending_id_ = #{param.batchSendingId}
+            </if>
+        </where>
+        ORDER BY t.id_ DESC
+	</select>
+    
+</mapper>

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

@@ -35,6 +35,8 @@
         <result column="accompaniment_type_" jdbcType="VARCHAR" property="accompanimentType"/>
         <result column="title_img_" jdbcType="VARCHAR" property="titleImg"/>
         <result column="music_img_" jdbcType="VARCHAR" property="musicImg"/>
+        <result column="first_tone_" jdbcType="VARCHAR" property="firstTone"/>
+        <result column="fixed_tone_" jdbcType="VARCHAR" property="fixedTone"/>
     </resultMap>
 
     <sql id="Base_Column_List">
@@ -75,6 +77,8 @@
         t.submit_audit_time_ as submitAuditTime,
         t.accompaniment_type_ as accompanimentType,
         t.remark_ as remark,
+        t.first_tone_ as firstTone,
+        t.fixed_tone_ as fixedTone,
         t.title_img_ as titleImg,
         t.reason_ as reason,
         t.music_img_ as musicImg,

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

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

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

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

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

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

+ 12 - 0
toolset/toolset-base/pom.xml

@@ -20,5 +20,17 @@
     </properties>
 
     <dependencies>
+
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.11</version>
+        </dependency>
+
     </dependencies>
 </project>

+ 44 - 0
toolset/toolset-base/src/main/java/com/yonge/toolset/base/util/ImUtil.java

@@ -0,0 +1,44 @@
+package com.yonge.toolset.base.util;
+
+import com.yonge.toolset.base.exception.BizException;
+import lombok.extern.slf4j.Slf4j;
+import net.coobird.thumbnailator.Thumbnails;
+import org.apache.commons.codec.binary.Base64;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Created by Eric.Shang on 2022/12/12.
+ */
+@Slf4j
+public class ImUtil {
+
+    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())));
+    }
+}