Jelajahi Sumber

Merge branch 'feature/1015-cbs-music' into saas

刘俊驰 2 minggu lalu
induk
melakukan
5288064af0
46 mengubah file dengan 3292 tambahan dan 32 penghapusan
  1. 3 0
      mec-application/src/main/java/com/ym/mec/config/WebMvcConfig.java
  2. 139 0
      mec-application/src/main/java/com/ym/mec/student/controller/MusicPracticeRecordController.java
  3. 155 0
      mec-application/src/main/java/com/ym/mec/student/controller/MusicSheetController.java
  4. 94 7
      mec-application/src/main/java/com/ym/mec/student/controller/StudentManageController.java
  5. 19 0
      mec-application/src/main/java/com/ym/mec/student/controller/UserMusicController.java
  6. 88 0
      mec-application/src/main/java/com/ym/mec/student/controller/open/OpenMusicSheetController.java
  7. 140 0
      mec-application/src/main/java/com/ym/mec/teacher/controller/MusicPracticeRecordController.java
  8. 159 0
      mec-application/src/main/java/com/ym/mec/teacher/controller/MusicSheetController.java
  9. 16 0
      mec-application/src/main/java/com/ym/mec/teacher/controller/UserMusicController.java
  10. 88 0
      mec-application/src/main/java/com/ym/mec/teacher/controller/open/OpenMusicSheetController.java
  11. 107 0
      mec-application/src/main/java/com/ym/mec/vo/MusicSheetAccompanimentVo.java
  12. 705 0
      mec-application/src/main/java/com/ym/mec/vo/MusicSheetVo.java
  13. 23 0
      mec-application/src/main/java/com/ym/mec/vo/MusicalInstrumentWrapper.java
  14. 138 0
      mec-application/src/main/java/com/ym/mec/web/controller/MusicPracticeRecordController.java
  15. 1 1
      mec-application/src/main/java/com/ym/mec/web/controller/MusicSheetApplicationExtendController.java
  16. 147 0
      mec-application/src/main/java/com/ym/mec/web/controller/MusicSheetController.java
  17. 1 1
      mec-application/src/main/java/com/ym/mec/web/controller/SysMusicScoreController.java
  18. 88 0
      mec-application/src/main/java/com/ym/mec/web/controller/open/OpenMusicSheetController.java
  19. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/InstrumentDao.java
  20. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/SysMusicCompareRecordDao.java
  21. 12 2
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/Student.java
  22. 18 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicCompareRecord.java
  23. 7 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicScore.java
  24. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/UserMusic.java
  25. 35 2
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/FeatureType.java
  26. 16 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/SysExamSongQueryInfo.java
  27. 560 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/MusicPracticeRecordWrapper.java
  28. 132 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/MusicSheetAccompanimentWrapper.java
  29. 38 3
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/MusicSheetWrapper.java
  30. 14 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/UserMusicWrapper.java
  31. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/service/InstrumentService.java
  32. 31 0
      mec-biz/src/main/java/com/ym/mec/biz/service/MusicPracticeRecordService.java
  33. 4 1
      mec-biz/src/main/java/com/ym/mec/biz/service/SysMusicCompareRecordService.java
  34. 16 1
      mec-biz/src/main/java/com/ym/mec/biz/service/SysMusicScoreService.java
  35. 7 5
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/InstrumentServiceImpl.java
  36. 122 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicPracticeRecordServiceImpl.java
  37. 19 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java
  38. 41 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreServiceImpl.java
  39. 12 2
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/UserMusicServiceImpl.java
  40. 6 0
      mec-biz/src/main/resources/config/mybatis/InstrumentMapper.xml
  41. 1 0
      mec-biz/src/main/resources/config/mybatis/SubjectMapper.xml
  42. 46 2
      mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml
  43. 2 1
      mec-biz/src/main/resources/config/mybatis/SysMusicScoreAccompanimentMapper.xml
  44. 14 1
      mec-biz/src/main/resources/config/mybatis/SysMusicScoreMapper.xml
  45. 8 0
      mec-biz/src/main/resources/config/mybatis/UserMusicMapper.xml
  46. 5 0
      mec-common/common-core/src/main/java/com/ym/mec/common/config/LocalFastJsonHttpMessageConverter.java

+ 3 - 0
mec-application/src/main/java/com/ym/mec/config/WebMvcConfig.java

@@ -11,6 +11,7 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
 import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+import com.microsvc.toolkit.common.webportal.converter.EnumsConvertorFactory;
 import com.ym.mec.common.config.EnumConverterFactory;
 import com.ym.mec.common.config.LocalFastJsonHttpMessageConverter;
 import com.ym.mec.common.enums.BaseEnum;
@@ -52,6 +53,8 @@ public class WebMvcConfig implements WebMvcConfigurer {
 	@Override
 	public void addFormatters(FormatterRegistry registry) {
 		registry.addConverterFactory(new EnumConverterFactory());
+		// 枚举映射转换
+		registry.addConverterFactory(new EnumsConvertorFactory());
 	}
 
 	@Override

+ 139 - 0
mec-application/src/main/java/com/ym/mec/student/controller/MusicPracticeRecordController.java

@@ -0,0 +1,139 @@
+package com.ym.mec.student.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.common.enums.music.EEvaluationStandard;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.common.response.template.R;
+import com.microsvc.toolkit.common.webportal.exception.BizException;
+import com.microsvc.toolkit.config.validator.group.ValidGroups;
+import com.ym.mec.biz.dal.entity.UserMusic;
+import com.ym.mec.biz.dal.enums.ClientEnum;
+import com.ym.mec.biz.dal.wrapper.MusicPracticeRecordWrapper;
+import com.ym.mec.biz.service.MusicPracticeRecordService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.biz.service.UserMusicService;
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+import java.util.Objects;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.student:}/musicPracticeRecord")
+@Api(tags = "曲目练习记录")
+public class MusicPracticeRecordController {
+
+    @Autowired
+    private MusicPracticeRecordService musicPracticeRecordService;
+
+    @Autowired
+    private UserMusicService userMusicService;
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    /**
+     * 查询单条
+     * @param id 详情ID
+     * @return R<MusicPracticeRecordVo.MusicPracticeRecord>
+     */
+    @ApiOperation(value = "详情", notes = "曲目练习记录-根据详情ID查询单条, 传入id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/detail/{id}")
+    public R<MusicPracticeRecordWrapper.MusicPracticeRecord> detail(@PathVariable("id") Long id) {
+
+        MusicPracticeRecordWrapper.Entity wrapper = musicPracticeRecordService.detail(id);
+
+        if (wrapper == null) {
+            throw new BizException("记录不存在");
+        }
+
+        // 上传过作品,用作品视频路径覆盖上传视频路径
+        // ID集合
+        Map<Long, UserMusic> userMusicMap = userMusicService.getMapByMusicPracticeRecordIds(Lists.newArrayList(Long.parseLong(wrapper.getId())));
+
+        UserMusic userMusic = userMusicMap.get(Long.parseLong(wrapper.getId()));
+        if (Objects.nonNull(userMusic)) {
+            wrapper.setVideoFilePath(userMusic.getVideoUrl());
+        }
+        MusicPracticeRecordWrapper.MusicPracticeRecord from = MusicPracticeRecordWrapper.MusicPracticeRecord.from(JSON.toJSONString(wrapper));
+
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(Integer.parseInt(wrapper.getMusicSheetId()));
+        if (musicSheet != null) {
+            from.setRhythmFlag(musicSheet.getEvaluationStandard() != EEvaluationStandard.FREQUENCY);
+        }
+
+        return R.from(from);
+    }
+
+
+    /**
+     * 新增
+     * @param record MusicPracticeRecordVo.MusicPracticeRecord
+     * @return R<Boolean>
+     */
+    @ApiOperation(value = "新增", notes = "曲目练习记录- 传入 MusicPracticeRecordVo.MusicPracticeRecord")
+    @PostMapping("/save")
+    public R<String> add(@Validated(ValidGroups.Add.class) @RequestBody MusicPracticeRecordWrapper.MusicPracticeRecord record) {
+
+        Integer userId = sysUserService.getUserId();
+        record.userId(String.valueOf(userId)).clientType(ClientEnum.STUDENT.getCode());
+
+        // 新增数据
+        MusicPracticeRecordWrapper.MusicPracticeRecord from = MusicPracticeRecordWrapper.MusicPracticeRecord.from(record.jsonString());
+        if (record.getDelFlag() !=null && record.getDelFlag()) {
+            from.setDelFlag(false);
+            from.setHiddenFlag(true);
+        }
+
+        return R.from(musicPracticeRecordService.add(from));
+    }
+
+    @ApiOperation(value = "用户最后一次评测数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "recordId", value = "曲目练习记录Id", dataType = "long")
+    })
+    @GetMapping("/getLastEvaluationMusicalNotesPlayStats")
+    public Object getLastEvaluationMusicalNotesPlayStats(Long recordId){
+        return R.from(musicPracticeRecordService.getLastEvaluationMusicalNotesPlayStats(recordId));
+    }
+
+    @ApiOperation(value = "上传音频文件")
+    @PostMapping("videoUpload")
+    public R<Boolean> videoUpload( @RequestBody MusicPracticeRecordWrapper.MusicPracticeRecord record){
+
+        if (Objects.isNull(record.getId())) {
+            throw BizException.from("recordId不能为空");
+        }
+        if (Objects.isNull(record.getVideoFilePath())) {
+            throw BizException.from("videoUrl不能为空");
+        }
+
+        MusicPracticeRecordWrapper.Entity practiceRecord = musicPracticeRecordService.getById(record.getId());
+        if (Objects.isNull(practiceRecord)) {
+            throw BizException.from("记录不存在");
+        }
+
+        practiceRecord.setVideoFilePath(record.getVideoFilePath());
+        musicPracticeRecordService.update(practiceRecord);
+
+        return R.from(true);
+    }
+
+}

+ 155 - 0
mec-application/src/main/java/com/ym/mec/student/controller/MusicSheetController.java

@@ -0,0 +1,155 @@
+package com.ym.mec.student.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.microsvc.toolkit.common.response.template.R;
+import com.ym.mec.biz.dal.entity.Instrument;
+import com.ym.mec.biz.dal.entity.Student;
+import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.entity.Teacher;
+import com.ym.mec.biz.dal.enums.ClientEnum;
+import com.ym.mec.biz.dal.enums.ClientTypeEnum;
+import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
+import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
+import com.ym.mec.biz.dal.wrapper.MusicSheetWrapper;
+import com.ym.mec.biz.service.InstrumentService;
+import com.ym.mec.biz.service.StudentService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.vo.MusicSheetVo;
+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.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.student:}/musicSheet")
+@Api(tags = "曲谱表")
+public class MusicSheetController {
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private InstrumentService instrumentService;
+
+
+    @Resource
+    private SysUserService sysUserService;
+
+    @Autowired
+    private StudentService studentService;
+
+    /**
+     * 查询单条
+     *
+     * @param id 详情ID
+     * @return R<MusicSheetVo.MusicSheet>
+     */
+    @ApiOperation(value = "查询内容平台数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/cbsDetail/{id}")
+    public R<MusicSheetVo.MusicSheetDetail> cbsDetail(@PathVariable("id") Integer id) {
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(id);
+        musicSheet.setBizId(Long.valueOf(id));
+
+        MusicSheetVo.MusicSheetDetail musicSheetDetail = JSON.parseObject(JSON.toJSONString(musicSheet), MusicSheetVo.MusicSheetDetail.class);
+        SysMusicScore detail = musicSheetService.get(id);
+        if (detail == null) {
+            musicSheetDetail.setBizMusicCategoryId(null);
+        } else {
+            // 设置曲目付费类型
+            musicSheetDetail.setPaymentType(StringUtils.isBlank(detail.getRankIds()) ? "FREE" : "VIP");
+            // 设置业务端曲目分类
+            musicSheetDetail.setBizMusicCategoryId(detail.getCategoriesId() == null ? null : detail.getCategoriesId().longValue());
+            musicSheetDetail.setScoreType(detail.getScoreType());
+            musicSheetDetail.setIsConvertibleScore(detail.getIsConvertibleScore());
+        }
+
+        // 设置乐器信息
+        if (StringUtils.isNotBlank(musicSheetDetail.getMusicalInstrumentIds())) {
+            List<Integer> instrumentIds = Arrays.stream(musicSheetDetail.getMusicalInstrumentIds().split(","))
+                .map(Integer::parseInt).collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(instrumentIds) && CollectionUtils.isNotEmpty(musicSheetDetail.getMusicalInstruments())) {
+                Map<Integer, InstrumentWrapper.Instrument> instrumentMap = instrumentService.getMapByIds(instrumentIds);
+                for (CbsMusicSheetWrapper.MusicalInstrument musicalInstrument : musicSheetDetail.getMusicalInstruments()) {
+                    InstrumentWrapper.Instrument instrument = instrumentMap.get(musicalInstrument.getId());
+                    if (instrument != null) {
+                        musicalInstrument.setOrientation(instrument.getOrientation());
+                    }
+
+                }
+            }
+        }
+        return R.from(musicSheetDetail);
+    }
+
+    @ApiOperation(value = "查询分页", notes = "曲谱表- 传入 MusicSheetVo.MusicSheetQuery")
+    @PostMapping("/page")
+    public R<PageInfo<MusicSheetWrapper.MusicSheet>> page(@RequestBody MusicSheetVo.MusicSheetQuery query) {
+
+        SysExamSongQueryInfo queryInfo = new SysExamSongQueryInfo();
+
+        Integer userId = sysUserService.getUserId();
+        Student student = studentService.get(userId);
+        if(query.getMusicSheetCategoriesId() != null) {
+            queryInfo.setCategoriesId(query.getMusicSheetCategoriesId().toString());
+        }
+        if (query.getMusicalInstrumentId() != null) {
+            // 乐器转换为声部
+            Instrument instrument = instrumentService.getById(query.getMusicalInstrumentId());
+            if (instrument != null) {
+                queryInfo.setSubjectId(instrument.getSubjectId());
+            }
+        } else if (StringUtils.isNotBlank(student.getSubjectIdList())){
+            queryInfo.setSubjectId(Integer.parseInt(student.getSubjectIdList()));
+        }
+        queryInfo.setPage(query.getPage());
+        queryInfo.setRows(query.getRows());
+        queryInfo.setName(query.getName());
+        queryInfo.setType("COMMON");
+        queryInfo.setClientFlag(true);
+        queryInfo.setClientType(ClientTypeEnum.SMART_PRACTICE);
+        queryInfo.setRecentFlag(query.getRecentFlag());
+        queryInfo.setUserId(userId);
+        queryInfo.setClientId(ClientEnum.STUDENT.getCode().toLowerCase());
+        PageInfo<SysMusicScore> sysMusicScorePageInfo1 = musicSheetService.queryMusicScorePageInfo(queryInfo);
+        PageInfo<MusicSheetWrapper.MusicSheet> convert = sysMusicScorePageInfo1.convert(o -> {
+            MusicSheetWrapper.MusicSheet musicSheet = new MusicSheetWrapper.MusicSheet();
+            musicSheet.setId(o.getId().toString());
+            musicSheet.setMusicSheetCategoriesId(o.getCategoriesId());
+            musicSheet.setMusicSheetName(o.getName());
+            musicSheet.setTitleImg(o.getTitleImg());
+            musicSheet.setComposer(o.getComposer());
+            musicSheet.setCbsMusicSheetId(o.getCbsMusicSheetId());
+            musicSheet.setUsedNum(0L);
+            musicSheet.setPaymentType(StringUtils.isNotBlank(o.getRankIds()) && o.getRankIds().contains("1") ? "VIP" : "FREE");
+            musicSheet.setAudioPlayTypes(o.getAudioPlayTypes());
+
+            return musicSheet;
+        });
+
+
+        return R.from(convert);
+    }
+}

+ 94 - 7
mec-application/src/main/java/com/ym/mec/student/controller/StudentManageController.java

@@ -1,7 +1,8 @@
 package com.ym.mec.student.controller;
 
+import com.beust.jcommander.internal.Lists;
+import com.google.common.collect.Sets;
 import com.microsvc.toolkit.middleware.oss.wrapper.OssWrapper;
-import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.CloudTeacherOrderDao;
 import com.ym.mec.biz.dal.dto.CashAccountDetail;
@@ -25,16 +26,11 @@ import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Api(tags = "学生管理")
@@ -82,6 +78,9 @@ public class StudentManageController extends BaseController {
     @Autowired
     private ImGroupCoreService imGroupCoreService;
 
+    @Autowired
+    private InstrumentService instrumentService;
+
     private final static Logger LOGGER = LoggerFactory.getLogger(StudentManageController.class);
 
     @Autowired
@@ -176,6 +175,7 @@ public class StudentManageController extends BaseController {
 		student.setImToken(user.getImToken());
 		student.setOrganId(user.getOrganId());
 
+
         // 注册IM用户Token
         try {
             ImGroupWrapper.ImUserInfo register = imGroupCoreService.getUserSig(String.valueOf(student.getId()),
@@ -253,6 +253,93 @@ public class StudentManageController extends BaseController {
                 }
             }
         }
+
+        // 通过学生声部换乐器ID
+        if (StringUtils.isNotBlank(student.getSubjectIdList())) {
+            String subjectId = student.getSubjectIdList();
+            if ("5".equals(student.getSubjectIdList())) {
+                subjectId = "6";
+            } else  if("122".equals(student.getSubjectIdList())){
+                subjectId = "122,121,113,23";
+            }
+            List<Integer> instrumentIdsBySubjectId = instrumentService.getInstrumentIdsBySubjectId(subjectId)
+                .stream().map(Instrument::getId).collect(Collectors.toList());
+            if (CollectionUtils.isNotEmpty(instrumentIdsBySubjectId)) {
+                // 逗号隔开
+                datas.put("instrumentId", StringUtils.join(instrumentIdsBySubjectId, ","));
+            }
+        }
+
+        // 扩展乐器
+        if (student.getExtSjectNamesMap() !=null && !student.getExtSjectNamesMap().isEmpty()) {
+            Set<Integer> integers = student.getExtSjectNamesMap().keySet();
+            Set<Integer> extInstrumentIds = Sets.newConcurrentHashSet();
+            for (Integer integer : integers) {
+                extInstrumentIds.add(integer);
+
+                if ("5".equals(integer.toString())) {
+                    extInstrumentIds.add(6);
+                } else  if("122".equals(integer.toString())){
+                    extInstrumentIds.add(121);
+                    extInstrumentIds.add(113);
+                    extInstrumentIds.add(23);
+                }
+            }
+
+            // 根据声部查询对应乐器信息
+            List<Instrument> instruments = instrumentService.getInstrumentIdsBySubjectId(StringUtils.join(extInstrumentIds, ","));
+            List<Map<String, Object>> extInstrumentNames = Lists.newArrayList();
+            if (CollectionUtils.isNotEmpty(instruments)) {
+
+                Map<Integer, List<Instrument>> collect = instruments.stream().collect(Collectors.groupingBy(Instrument::getSubjectId, Collectors.toList()));
+                for (Map.Entry<Integer, String> entry : student.getExtSjectNamesMap().entrySet()) {
+
+                    // 默认声部映射乐器ID
+                    String instrumentIds = "";
+                    if (collect.containsKey(entry.getKey())) {
+                        instrumentIds = collect.get(entry.getKey()).stream()
+                            .map(Instrument::getId).map(String::valueOf).collect(Collectors.joining(","));
+                    }
+
+                    // 萨克斯乐器,对应中音萨克斯
+                    if (entry.getKey() == 5 || entry.getKey() == 6) {
+
+                        instrumentIds = collect.entrySet().stream()
+                            .filter(x -> x.getKey() == 5 || x.getKey() == 6)
+                            .flatMap(x -> x.getValue().stream())
+                            .map(Instrument::getId)
+                            .map(String::valueOf).collect(Collectors.joining(","));
+                    }
+
+                    // 打击乐器,对应小军鼓,打击乐(键盘),打击乐(键盘+小鼓),打击乐
+                    if (entry.getKey() == 122 || entry.getKey() == 121 || entry.getKey() == 113 || entry.getKey() == 23) {
+
+                        instrumentIds = collect.entrySet().stream()
+                            .filter(x -> x.getKey() == 122 || x.getKey() == 121 || x.getKey() == 113 || x.getKey() == 23)
+                            .flatMap(x -> x.getValue().stream())
+                            .map(Instrument::getId)
+                            .map(String::valueOf).collect(Collectors.joining(","));
+                    }
+                    String finalInstrumentIds = instrumentIds;
+                    extInstrumentNames.add(new HashMap<String, Object>(){{
+                        put("subjectId", entry.getKey());
+                        put("subjectName", entry.getValue());
+                        put("instrumentIds", finalInstrumentIds);
+                    }});
+                }
+
+                /*List<Integer> instrumentIdsBySubjectId = instruments.stream().map(Instrument::getId).collect(Collectors.toList());
+                Map<Integer, InstrumentWrapper.Instrument> mapByIds = instrumentService.getMapByIds(instrumentIdsBySubjectId);
+                mapByIds.forEach((k,v)->{
+                    if (v !=null) {
+                        extInstrumentNamesMap.put(k, v.getName());
+                    }
+                });*/
+            }
+            student.setExtInstrumentNames(extInstrumentNames);
+        }
+
+
 		return succeed(datas);
 	}
 

+ 19 - 0
mec-application/src/main/java/com/ym/mec/student/controller/UserMusicController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.microsvc.toolkit.common.response.paging.PageInfo;
 import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import com.microsvc.toolkit.common.response.template.R;
 import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
@@ -20,8 +21,10 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
 
 import java.util.Arrays;
 import java.util.List;
@@ -59,6 +62,22 @@ public class UserMusicController  extends BaseController {
         return succeed(records.get(0));
     }
 
+
+
+    @ApiOperation(value = "详情")
+    @GetMapping("/musicPracticeRecord/{id}")
+    public R<UserMusicWrapper.UserMusic> musicPracticeRecord(@PathVariable("id") Long id) {
+
+        UserMusicWrapper.UserMusicQuery build = UserMusicWrapper.UserMusicQuery.builder().musicPracticeRecordId(id).build();
+        IPage<UserMusicWrapper.UserMusic> pages = userMusicService.selectPage(QueryInfo.getPage(build), build);
+        List<UserMusicWrapper.UserMusic> records = pages.getRecords();
+        if (records.isEmpty()) {
+            return R.from(new UserMusicWrapper.UserMusic()).data(null);
+        }
+
+        return R.from(records.get(0));
+    }
+
     @ApiOperation(value = "查询分页", notes = "用户曲目作品- 传入 UserMusicWrapper.UserMusicQuery")
     @PostMapping("/page")
     public HttpResponseResult<PageInfo<UserMusicWrapper.UserMusic>> page(@RequestBody UserMusicWrapper.UserMusicQuery query) {

+ 88 - 0
mec-application/src/main/java/com/ym/mec/student/controller/open/OpenMusicSheetController.java

@@ -0,0 +1,88 @@
+package com.ym.mec.student.controller.open;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.microsvc.toolkit.common.response.template.R;
+import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
+import com.ym.mec.biz.service.InstrumentService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.vo.MusicSheetVo;
+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.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.student:}/open/musicSheet")
+@Api(tags = "曲谱表")
+public class OpenMusicSheetController {
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private InstrumentService instrumentService;
+
+    /**
+     * 查询单条
+     *
+     * @param id 详情ID
+     * @return R<MusicSheetVo.MusicSheet>
+     */
+    @ApiOperation(value = "查询内容平台数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/cbsDetail/{id}")
+    public R<MusicSheetVo.OpenMusicSheetDetail> cbsDetail(@PathVariable("id") Integer id) {
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(id);
+        musicSheet.setBizId(Long.valueOf(id));
+
+        MusicSheetVo.MusicSheetDetail musicSheetDetail = JSON.parseObject(JSON.toJSONString(musicSheet), MusicSheetVo.MusicSheetDetail.class);
+        SysMusicScore detail = musicSheetService.get(id);
+        if (detail == null) {
+            musicSheetDetail.setBizMusicCategoryId(null);
+        } else {
+            // 设置曲目付费类型
+            musicSheetDetail.setPaymentType(StringUtils.isBlank(detail.getRankIds()) ? "FREE" : "VIP");
+            // 设置业务端曲目分类
+            musicSheetDetail.setBizMusicCategoryId(detail.getCategoriesId() == null ? null : detail.getCategoriesId().longValue());
+        }
+
+        // 设置乐器信息
+        if (StringUtils.isNotBlank(musicSheetDetail.getMusicalInstrumentIds())) {
+            List<Integer> instrumentIds = Arrays.stream(musicSheetDetail.getMusicalInstrumentIds().split(","))
+                .map(Integer::parseInt).collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(instrumentIds) && CollectionUtils.isNotEmpty(musicSheetDetail.getMusicalInstruments())) {
+                Map<Integer, InstrumentWrapper.Instrument> instrumentMap = instrumentService.getMapByIds(instrumentIds);
+                for (CbsMusicSheetWrapper.MusicalInstrument musicalInstrument : musicSheetDetail.getMusicalInstruments()) {
+                    InstrumentWrapper.Instrument instrument = instrumentMap.get(musicalInstrument.getId());
+                    if (instrument != null) {
+                        musicalInstrument.setOrientation(instrument.getOrientation());
+                    }
+
+                }
+            }
+        }
+        return R.from(MusicSheetVo.OpenMusicSheetDetail.from(musicSheetDetail.jsonString()));
+    }
+
+}

+ 140 - 0
mec-application/src/main/java/com/ym/mec/teacher/controller/MusicPracticeRecordController.java

@@ -0,0 +1,140 @@
+package com.ym.mec.teacher.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.common.enums.music.EEvaluationStandard;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.common.response.template.R;
+import com.microsvc.toolkit.common.webportal.exception.BizException;
+import com.microsvc.toolkit.config.validator.group.ValidGroups;
+import com.ym.mec.biz.dal.entity.UserMusic;
+import com.ym.mec.biz.dal.enums.ClientEnum;
+import com.ym.mec.biz.dal.wrapper.MusicPracticeRecordWrapper;
+import com.ym.mec.biz.service.MusicPracticeRecordService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.biz.service.UserMusicService;
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.math.BigDecimal;
+import java.util.Map;
+import java.util.Objects;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.teacher:}/musicPracticeRecord")
+@Api(tags = "曲目练习记录")
+public class MusicPracticeRecordController {
+
+    @Autowired
+    private MusicPracticeRecordService musicPracticeRecordService;
+
+    @Autowired
+    private UserMusicService userMusicService;
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    /**
+     * 查询单条
+     * @param id 详情ID
+     * @return R<MusicPracticeRecordVo.MusicPracticeRecord>
+     */
+    @ApiOperation(value = "详情", notes = "曲目练习记录-根据详情ID查询单条, 传入id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/detail/{id}")
+    public R<MusicPracticeRecordWrapper.MusicPracticeRecord> detail(@PathVariable("id") Long id) {
+
+        MusicPracticeRecordWrapper.Entity wrapper = musicPracticeRecordService.detail(id);
+
+        if (wrapper == null) {
+            throw new BizException("记录不存在");
+        }
+
+        // 上传过作品,用作品视频路径覆盖上传视频路径
+        // ID集合
+        Map<Long, UserMusic> userMusicMap = userMusicService.getMapByMusicPracticeRecordIds(Lists.newArrayList(Long.parseLong(wrapper.getId())));
+
+        UserMusic userMusic = userMusicMap.get(Long.parseLong(wrapper.getId()));
+        if (Objects.nonNull(userMusic)) {
+            wrapper.setVideoFilePath(userMusic.getVideoUrl());
+        }
+        MusicPracticeRecordWrapper.MusicPracticeRecord from = MusicPracticeRecordWrapper.MusicPracticeRecord.from(JSON.toJSONString(wrapper));
+
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(Integer.parseInt(wrapper.getMusicSheetId()));
+        if (musicSheet != null) {
+            from.setRhythmFlag(musicSheet.getEvaluationStandard() != EEvaluationStandard.FREQUENCY);
+        }
+
+        return R.from(from);
+    }
+
+
+    /**
+     * 新增
+     * @param record MusicPracticeRecordVo.MusicPracticeRecord
+     * @return R<Boolean>
+     */
+    @ApiOperation(value = "新增", notes = "曲目练习记录- 传入 MusicPracticeRecordVo.MusicPracticeRecord")
+    @PostMapping("/save")
+    public R<String> add(@Validated(ValidGroups.Add.class) @RequestBody MusicPracticeRecordWrapper.MusicPracticeRecord record) {
+
+        Integer userId = sysUserService.getUserId();
+        record.userId(String.valueOf(userId)).clientType(ClientEnum.TEACHER.getCode());
+
+        // 新增数据
+        MusicPracticeRecordWrapper.MusicPracticeRecord from = MusicPracticeRecordWrapper.MusicPracticeRecord.from(record.jsonString());
+        if (record.getDelFlag() !=null && record.getDelFlag()) {
+            from.setDelFlag(false);
+            from.setHiddenFlag(true);
+        }
+
+        return R.from(musicPracticeRecordService.add(from));
+    }
+
+    @ApiOperation(value = "用户最后一次评测数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "recordId", value = "曲目练习记录Id", dataType = "long")
+    })
+    @GetMapping("/getLastEvaluationMusicalNotesPlayStats")
+    public Object getLastEvaluationMusicalNotesPlayStats(Long recordId){
+        return R.from(musicPracticeRecordService.getLastEvaluationMusicalNotesPlayStats(recordId));
+    }
+
+    @ApiOperation(value = "上传音频文件")
+    @PostMapping("videoUpload")
+    public R<Boolean> videoUpload( @RequestBody MusicPracticeRecordWrapper.MusicPracticeRecord record){
+
+        if (Objects.isNull(record.getId())) {
+            throw BizException.from("recordId不能为空");
+        }
+        if (Objects.isNull(record.getVideoFilePath())) {
+            throw BizException.from("videoUrl不能为空");
+        }
+
+        MusicPracticeRecordWrapper.Entity practiceRecord = musicPracticeRecordService.getById(record.getId());
+        if (Objects.isNull(practiceRecord)) {
+            throw BizException.from("记录不存在");
+        }
+
+        practiceRecord.setVideoFilePath(record.getVideoFilePath());
+        musicPracticeRecordService.update(practiceRecord);
+
+        return R.from(true);
+    }
+
+}

+ 159 - 0
mec-application/src/main/java/com/ym/mec/teacher/controller/MusicSheetController.java

@@ -0,0 +1,159 @@
+package com.ym.mec.teacher.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.microsvc.toolkit.common.response.template.R;
+import com.ym.mec.biz.dal.dao.TeacherDao;
+import com.ym.mec.biz.dal.entity.Instrument;
+import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.entity.Teacher;
+import com.ym.mec.biz.dal.enums.ClientEnum;
+import com.ym.mec.biz.dal.enums.ClientTypeEnum;
+import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
+import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
+import com.ym.mec.biz.dal.wrapper.MusicSheetWrapper;
+import com.ym.mec.biz.service.InstrumentService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.vo.MusicSheetVo;
+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.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.teacher:}/musicSheet")
+@Api(tags = "曲谱表")
+public class MusicSheetController {
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private InstrumentService instrumentService;
+
+    @Resource
+    private TeacherDao teacherDao;
+    @Resource
+    private SysUserService sysUserService;
+
+    /**
+     * 查询单条
+     *
+     * @param id 详情ID
+     * @return R<MusicSheetVo.MusicSheet>
+     */
+    @ApiOperation(value = "查询内容平台数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/cbsDetail/{id}")
+    public R<MusicSheetVo.MusicSheetDetail> cbsDetail(@PathVariable("id") Integer id) {
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(id);
+        musicSheet.setBizId(Long.valueOf(id));
+
+        MusicSheetVo.MusicSheetDetail musicSheetDetail = JSON.parseObject(JSON.toJSONString(musicSheet), MusicSheetVo.MusicSheetDetail.class);
+        SysMusicScore detail = musicSheetService.get(id);
+        if (detail == null) {
+            musicSheetDetail.setBizMusicCategoryId(null);
+        } else {
+            // 设置曲目付费类型
+            musicSheetDetail.setPaymentType(StringUtils.isBlank(detail.getRankIds()) ? "FREE" : "VIP");
+            // 设置业务端曲目分类
+            musicSheetDetail.setBizMusicCategoryId(detail.getCategoriesId() == null ? null : detail.getCategoriesId().longValue());
+            musicSheetDetail.setScoreType(detail.getScoreType());
+            musicSheetDetail.setIsConvertibleScore(detail.getIsConvertibleScore());
+        }
+
+        // 设置乐器信息
+        if (StringUtils.isNotBlank(musicSheetDetail.getMusicalInstrumentIds())) {
+            List<Integer> instrumentIds = Arrays.stream(musicSheetDetail.getMusicalInstrumentIds().split(","))
+                .map(Integer::parseInt).collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(instrumentIds) && CollectionUtils.isNotEmpty(musicSheetDetail.getMusicalInstruments())) {
+                Map<Integer, InstrumentWrapper.Instrument> instrumentMap = instrumentService.getMapByIds(instrumentIds);
+                for (CbsMusicSheetWrapper.MusicalInstrument musicalInstrument : musicSheetDetail.getMusicalInstruments()) {
+                    InstrumentWrapper.Instrument instrument = instrumentMap.get(musicalInstrument.getId());
+                    if (instrument != null) {
+                        musicalInstrument.setOrientation(instrument.getOrientation());
+                    }
+
+                }
+            }
+        }
+        return R.from(musicSheetDetail);
+    }
+
+
+    @ApiOperation(value = "查询分页", notes = "曲谱表- 传入 MusicSheetVo.MusicSheetQuery")
+    @PostMapping("/page")
+    public R<PageInfo<MusicSheetWrapper.MusicSheet>> page(@RequestBody MusicSheetVo.MusicSheetQuery query) {
+
+        //判断用户是否可以访问云练习
+        Integer userId = sysUserService.getUserId();
+        Teacher teacher = teacherDao.get(userId);
+        if (teacher == null) {
+            throw new BizException("老师信息不存在");
+        }
+        //是否限制用户使用云教练
+        if(teacher.getCoursewareLimit()){
+            throw new BizException("您没有权限使用云练习");
+        }
+        SysExamSongQueryInfo queryInfo = new SysExamSongQueryInfo();
+
+        if(query.getMusicSheetCategoriesId() != null) {
+            queryInfo.setCategoriesId(query.getMusicSheetCategoriesId().toString());
+        }
+        if (query.getMusicalInstrumentId() != null) {
+            // 乐器转换为声部
+            Instrument instrument = instrumentService.getById(query.getMusicalInstrumentId());
+            if (instrument != null) {
+                queryInfo.setSubjectId(instrument.getSubjectId());
+            }
+        }
+
+        queryInfo.setPage(query.getPage());
+        queryInfo.setRows(query.getRows());
+        queryInfo.setName(query.getName());
+        queryInfo.setType("COMMON");
+        queryInfo.setClientFlag(true);
+        queryInfo.setClientType(ClientTypeEnum.SMART_PRACTICE);
+        queryInfo.setUserId(userId);
+        queryInfo.setRecentFlag(query.getRecentFlag());
+        queryInfo.setClientId(ClientEnum.TEACHER.getCode().toLowerCase());
+        PageInfo<SysMusicScore> sysMusicScorePageInfo1 = musicSheetService.queryMusicScorePageInfo(queryInfo);
+        PageInfo<MusicSheetWrapper.MusicSheet> convert = sysMusicScorePageInfo1.convert(o -> {
+            MusicSheetWrapper.MusicSheet musicSheet = new MusicSheetWrapper.MusicSheet();
+            musicSheet.setId(o.getId().toString());
+            musicSheet.setMusicSheetCategoriesId(o.getCategoriesId());
+            musicSheet.setMusicSheetName(o.getName());
+            musicSheet.setTitleImg(o.getTitleImg());
+            musicSheet.setComposer(o.getComposer());
+            musicSheet.setCbsMusicSheetId(o.getCbsMusicSheetId());
+            musicSheet.setUsedNum(0L);
+            musicSheet.setPaymentType(StringUtils.isNotBlank(o.getRankIds()) && o.getRankIds().contains("1") ? "VIP" : "FREE");
+            musicSheet.setAudioPlayTypes(o.getAudioPlayTypes());
+
+            return musicSheet;
+        });
+
+
+        return R.from(convert);
+    }
+}

+ 16 - 0
mec-application/src/main/java/com/ym/mec/teacher/controller/UserMusicController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.microsvc.toolkit.common.response.paging.PageInfo;
 import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import com.microsvc.toolkit.common.response.template.R;
 import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
@@ -57,6 +58,21 @@ public class UserMusicController  extends BaseController {
         return succeed(records.get(0));
     }
 
+    @ApiOperation(value = "详情")
+    @GetMapping("/musicPracticeRecord/{id}")
+    public R<UserMusicWrapper.UserMusic> musicPracticeRecord(@PathVariable("id") Long id) {
+
+        UserMusicWrapper.UserMusicQuery build = UserMusicWrapper.UserMusicQuery.builder().musicPracticeRecordId(id).build();
+        IPage<UserMusicWrapper.UserMusic> pages = userMusicService.selectPage(QueryInfo.getPage(build), build);
+        List<UserMusicWrapper.UserMusic> records = pages.getRecords();
+        if (records.isEmpty()) {
+            return R.from(new UserMusicWrapper.UserMusic()).data(null);
+        }
+
+        return R.from(records.get(0));
+    }
+
+
     @ApiOperation(value = "查询分页", notes = "用户曲目作品- 传入 UserMusicWrapper.UserMusicQuery")
     @PostMapping("/page")
     public HttpResponseResult<PageInfo<UserMusicWrapper.UserMusic>> page(@RequestBody UserMusicWrapper.UserMusicQuery query) {

+ 88 - 0
mec-application/src/main/java/com/ym/mec/teacher/controller/open/OpenMusicSheetController.java

@@ -0,0 +1,88 @@
+package com.ym.mec.teacher.controller.open;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.microsvc.toolkit.common.response.template.R;
+import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
+import com.ym.mec.biz.service.InstrumentService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.vo.MusicSheetVo;
+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.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.teacher:}/open/musicSheet")
+@Api(tags = "曲谱表")
+public class OpenMusicSheetController {
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private InstrumentService instrumentService;
+
+    /**
+     * 查询单条
+     *
+     * @param id 详情ID
+     * @return R<MusicSheetVo.MusicSheet>
+     */
+    @ApiOperation(value = "查询内容平台数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/cbsDetail/{id}")
+    public R<MusicSheetVo.OpenMusicSheetDetail> cbsDetail(@PathVariable("id") Integer id) {
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(id);
+        musicSheet.setBizId(Long.valueOf(id));
+
+        MusicSheetVo.MusicSheetDetail musicSheetDetail = JSON.parseObject(JSON.toJSONString(musicSheet), MusicSheetVo.MusicSheetDetail.class);
+        SysMusicScore detail = musicSheetService.get(id);
+        if (detail == null) {
+            musicSheetDetail.setBizMusicCategoryId(null);
+        } else {
+            // 设置曲目付费类型
+            musicSheetDetail.setPaymentType(StringUtils.isBlank(detail.getRankIds()) ? "FREE" : "VIP");
+            // 设置业务端曲目分类
+            musicSheetDetail.setBizMusicCategoryId(detail.getCategoriesId() == null ? null : detail.getCategoriesId().longValue());
+        }
+
+        // 设置乐器信息
+        if (StringUtils.isNotBlank(musicSheetDetail.getMusicalInstrumentIds())) {
+            List<Integer> instrumentIds = Arrays.stream(musicSheetDetail.getMusicalInstrumentIds().split(","))
+                .map(Integer::parseInt).collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(instrumentIds) && CollectionUtils.isNotEmpty(musicSheetDetail.getMusicalInstruments())) {
+                Map<Integer, InstrumentWrapper.Instrument> instrumentMap = instrumentService.getMapByIds(instrumentIds);
+                for (CbsMusicSheetWrapper.MusicalInstrument musicalInstrument : musicSheetDetail.getMusicalInstruments()) {
+                    InstrumentWrapper.Instrument instrument = instrumentMap.get(musicalInstrument.getId());
+                    if (instrument != null) {
+                        musicalInstrument.setOrientation(instrument.getOrientation());
+                    }
+
+                }
+            }
+        }
+        return R.from(MusicSheetVo.OpenMusicSheetDetail.from(musicSheetDetail.jsonString()));
+    }
+
+}

+ 107 - 0
mec-application/src/main/java/com/ym/mec/vo/MusicSheetAccompanimentVo.java

@@ -0,0 +1,107 @@
+package com.ym.mec.vo;
+
+import com.alibaba.fastjson.JSON;
+import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 曲谱伴奏表
+ * 2022-12-07 10:16:58
+ */
+@ApiModel(value = "MusicSheetAccompanimentVo对象", description = "曲谱伴奏表查询视图对象")
+public class MusicSheetAccompanimentVo {
+
+    @Data
+    @ApiModel(" MusicSheetAccompanimentQuery-曲谱伴奏表")
+    public static class MusicSheetAccompanimentQuery implements QueryInfo {
+
+        @ApiModelProperty("当前页")
+        private Integer page;
+
+        @ApiModelProperty("分页行数")
+        private Integer rows;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicSheetAccompanimentQuery from(String json) {
+            return JSON.parseObject(json, MusicSheetAccompanimentQuery.class);
+        }
+    }
+
+    @Data
+    @ApiModel(" MusicSheetAccompaniment-曲谱伴奏表")
+    public static class MusicSheetAccompaniment {
+
+
+		@ApiModelProperty("主键")
+        private Long id;
+
+
+		@ApiModelProperty("曲谱ID")
+        private Long musicId;
+
+
+		@ApiModelProperty("声部")
+        private String musicSubject;
+
+
+		@ApiModelProperty("MP3原声音频文件URL")
+        private String audioFileUrl;
+
+
+		@ApiModelProperty("map节拍器伴奏")
+        private String metronomeUrl;
+
+
+		@ApiModelProperty("伴奏轨迹")
+        private String track;
+
+
+		@ApiModelProperty("排序号")
+        private Boolean sortNumber;
+
+
+		@ApiModelProperty("速度")
+        private String speed;
+
+        @ApiModelProperty("曲目缓存")
+        private String musicSvg;
+
+		@ApiModelProperty("创建人(老师或者是后台平台用户)")
+        private Long createBy;
+
+
+		@ApiModelProperty("创建时间")
+        private Date createTime;
+
+
+        @ApiModelProperty("五线谱PDF文件")
+        private String musicPdfUrl;
+
+
+        @ApiModelProperty("首调PDF文件")
+        private String firstPdfUrl;
+
+
+        @ApiModelProperty("固定调PDF文件")
+        private String jianPdfUrl;
+
+
+        @ApiModelProperty("音频类型,SING:演唱,PLAY:演奏")
+        private String audioPlayType;
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicSheetAccompaniment from(String json) {
+            return JSON.parseObject(json, MusicSheetAccompaniment.class);
+        }
+    }
+
+}

+ 705 - 0
mec-application/src/main/java/com/ym/mec/vo/MusicSheetVo.java

@@ -0,0 +1,705 @@
+package com.ym.mec.vo;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.common.enums.music.EAudioType;
+import com.dayaedu.cbs.common.enums.music.EEvaluationStandard;
+import com.dayaedu.cbs.common.enums.music.EMusicAvailableType;
+import com.dayaedu.cbs.common.enums.music.EMusicPlayMode;
+import com.dayaedu.cbs.common.enums.music.EMusicSourceType;
+import com.dayaedu.cbs.common.enums.school.EMusicSheetType;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 曲谱表
+ * 2022-12-07 10:16:58
+ */
+@ApiModel(value = "MusicSheetVo对象", description = "曲谱表查询视图对象")
+public class MusicSheetVo {
+
+    @Data
+    @ApiModel(" MusicSheetQuery-曲谱表")
+    public static class MusicSheetQuery implements QueryInfo {
+
+        @ApiModelProperty("当前页")
+        private Integer page;
+
+        @ApiModelProperty("分页行数")
+        private Integer rows;
+
+        @ApiModelProperty("关键字匹配")
+        private String keyword;
+
+        @ApiModelProperty("仅匹配资源名称")
+        private String name;
+
+        @ApiModelProperty("声部Id")
+        private String musicSubject;
+
+        @ApiModelProperty("曲目乐器Id")
+        private Long musicalInstrumentId;
+
+        @ApiModelProperty("曲谱分类编号")
+        private Integer musicSheetCategoriesId;
+
+        private List<Integer> musicSheetCategoriesIdList;
+
+        @ApiModelProperty(value = "删除标识", hidden = true)
+        private Boolean delFlag;
+
+        @ApiModelProperty(value = "启用停用标识,曲目状态(0:停用,1:启用)")
+        private Boolean status;
+
+        @ApiModelProperty(value = "排序 0:默认 1:首页热门,2热门列表")
+        private Integer sortType = 0;
+
+        @ApiModelProperty(value = "是否审核数据")
+        private Boolean versionFlag = false;
+
+        @ApiModelProperty(value = "用户ID",hidden = true)
+        private Long userId;
+
+        @ApiModelProperty(value = "用户类型",hidden = true)
+        private String clientType;
+
+        @ApiModelProperty("是否最近练习")
+        private Boolean recentFlag = false;
+
+        @ApiModelProperty("最近练习 当前曲目ID")
+        private Long excludeMusicId;
+
+        @ApiModelProperty("app版本")
+        private String version;
+
+        @ApiModelProperty("platform")
+        private String platform;
+
+        @ApiModelProperty("id集合")
+        private List<Long> ids;
+
+        @ApiModelProperty("曲目教程id集合")
+        private String musicTutorialIds;
+
+        @ApiModelProperty("曲目标签id集合")
+        private String musicTagIds;
+
+        @ApiModelProperty("内容平台ID为null")
+        private Boolean cbsIdIsNull;
+
+        @ApiModelProperty("是否转换")
+        private Boolean convertFlag;
+
+        @ApiModelProperty("教材版本ID/ 曲目标签ID")
+        private Long bookVersionId;
+
+        @ApiModelProperty("音频类型,SING:演唱,PLAY:演奏")
+        private List<String> audioPlayTypes;
+
+        @ApiModelProperty("标签分类搜索 HOT 热门,NEW 最新,RECOMMEND 推荐")
+        private String searchType;
+
+        @ApiModelProperty("是否只查询基础信息")
+        private Boolean basicFlag = false;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicSheetQuery from(String json) {
+            return JSON.parseObject(json, MusicSheetQuery.class);
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" MusicSheet-曲谱表")
+    public static class MusicSheet {
+
+		@ApiModelProperty("主键")
+        private Long id;
+
+        @ApiModelProperty("曲谱分类")
+        private Integer musicSheetCategoriesId;
+
+//        @ApiModelProperty(value = "曲谱类型(SINGLE:单曲,CONCERT:合奏)")
+//        private EMusicSheetType musicSheetType;
+
+        @ApiModelProperty("曲谱分类名称")
+        private String musicSheetCategoriesName;
+
+		@ApiModelProperty("曲谱名称")
+        private String musicSheetName;
+
+		@ApiModelProperty("封面图")
+        private String titleImg;
+
+		@ApiModelProperty("曲谱来源id")
+        private Long userId;
+
+//		@ApiModelProperty("曲目来源类型 TEACHER 老师 PLATFORM 平台")
+//        private ESourceFrom sourceType;
+
+        @ApiModelProperty("多声轨选择")
+        private String multiTracksSelection;
+
+        @ApiModelProperty("是否公开")
+        private Boolean openFlag;
+
+        @ApiModelProperty("作曲人")
+        private String composer;
+
+        @ApiModelProperty("上传人")
+        private String uploadUser;
+
+		@ApiModelProperty("曲谱声部(适用的乐器,可能是多个,用逗号分隔)")
+        private String musicSubject;
+
+		@ApiModelProperty("mp3曲谱类型  MP3;MP3_METRONOME")
+        private String mp3Type;
+
+		@ApiModelProperty("曲目图片")
+        private String musicImg;
+
+		@ApiModelProperty("曲谱音频文件类型(midi;mp3)")
+        private EAudioType audioType;
+
+		@ApiModelProperty("是否可以转简谱(0:否,1:是)")
+        private Integer notation;
+
+		@ApiModelProperty("曲谱标签(多个标签用逗号分隔)")
+        private String musicTag;
+
+		@ApiModelProperty("默认播放速度")
+        private String playSpeed;
+
+		@ApiModelProperty("是否可以评测(0:否;1:是)")
+        private Boolean canEvaluate;
+
+        @ApiModelProperty("是否支持混音节拍器")
+        private Boolean isMixBeat;
+
+		@ApiModelProperty("伴奏类型  HOMEMODE:自制 COMMON:普通")
+        private String accompanimentType;
+
+		@ApiModelProperty("是否展示指法(0:否;1:是)")
+        private Boolean showFingering;
+
+		@ApiModelProperty("曲目状态(0:停用,1:启用)")
+        private Boolean status;
+
+		@ApiModelProperty("曲目停用原因")
+        private String reason;
+
+		@ApiModelProperty("排序号")
+        private Integer sortNumber;
+
+		@ApiModelProperty("midi路径")
+        private String midiUrl;
+
+		@ApiModelProperty("伴奏含节拍器路径")
+        private String metronomeUrl;
+
+		@ApiModelProperty("伴奏(不含节拍器)路径")
+        private String url;
+
+		@ApiModelProperty("音频文件存储路径")
+        private String audioFileUrl;
+
+		@ApiModelProperty("XML文件存储路径")
+        private String xmlFileUrl;
+
+		@ApiModelProperty("是否自带节拍器(0:否;1:是)")
+        private Boolean hasBeat;
+
+		@ApiModelProperty("曲目配置")
+        private String extConfigJson;
+
+
+        @ApiModelProperty("是否节奏音乐")
+        private Boolean rhythmFlag;
+
+
+        @ApiModelProperty("创建时间")
+        private Date createTime;
+
+		@ApiModelProperty("创建人(老师或者是后台平台用户)")
+        private Long createBy;
+
+        @ApiModelProperty("创建用户")
+        private String createUser;
+
+		@ApiModelProperty("更新时间")
+        private Date updateTime;
+
+		@ApiModelProperty("更新人(老师或者是后台平台用户)")
+        private Long updateBy;
+
+        @ApiModelProperty("更新用户")
+        private String updateUser;
+
+		@ApiModelProperty("备注")
+        private String remark;
+
+		@ApiModelProperty("假删除标识 0:未删除 1:已删除")
+        private Boolean delFlag;
+
+        @ApiModelProperty("伴奏")
+        private List<MusicSheetAccompanimentVo.MusicSheetAccompaniment> background;
+
+        @ApiModelProperty("曲目缓存")
+        private String musicJSON;
+
+        @ApiModelProperty("曲目缓存svg")
+        private String musicSvg;
+
+        @ApiModelProperty("曲目缓存简谱svg")
+        private String musicJianSvg;
+
+        @ApiModelProperty("曲目缓存首调svg")
+        private String musicFirstSvg;
+
+
+        @ApiModelProperty("被使用次数")
+        private Long usedNum = 0L;
+
+        @ApiModelProperty("曲目赏析")
+        private String appreciationUrl;
+
+        @ApiModelProperty("曲目创作ID")
+        private Long musicSheetCreationId;
+
+        @ApiModelProperty(" 可用乐器(多个,用逗号分隔)")
+        private String cbsMusicalInstrumentIds;
+
+
+
+        @ApiModelProperty(" 可用乐器(多个,用逗号分隔)")
+        private String cbsMusicalInstrumentIdNames;
+
+        @ApiModelProperty("内容平台曲目ID")
+        private Long cbsMusicSheetId;
+
+        @ApiModelProperty("首调图片")
+        private String musicFirstImg;
+        @ApiModelProperty("固定调图片")
+        private String musicJianImg;
+
+
+        @ApiModelProperty("五线谱PDF文件")
+        private String musicPdfUrl;
+
+
+        @ApiModelProperty("首调PDF文件")
+        private String firstPdfUrl;
+
+
+        @ApiModelProperty("固定调PDF文件")
+        private String jianPdfUrl;
+
+
+
+        @ApiModelProperty("曲目类型(SINGLE:单曲 CONCERT:合奏)")
+        private String musicSheetType;
+
+        @ApiModelProperty("乐器信息")
+        private List<InstrumentWrapper.Instrument> musicalInstruments;
+
+        @ApiModelProperty("收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费)")
+        private String paymentType;
+
+
+
+        @ApiModelProperty("是否可转谱(0:否; 1:是)")
+        private Boolean isConvertibleScore;
+
+        @ApiModelProperty("谱面类型")
+        private String scoreType;
+
+
+        @ApiModelProperty("音频类型,SING:演唱,PLAY:演奏")
+        private String audioPlayTypes;
+
+
+        @ApiModelProperty("是否总谱渲染")
+        private Boolean isScoreRender;
+
+        @ApiModelProperty("演奏是否默认展示总谱渲染")
+        private Boolean defaultScoreRender;
+
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicSheet from(String json) {
+            return JSON.parseObject(json, MusicSheet.class);
+        }
+
+
+        public MusicSheet createBy(String createBy) {
+            this.createBy = Long.parseLong(createBy);
+            return this;
+        }
+
+        public MusicSheet createUser(String createUser) {
+            this.createUser = createUser;
+            return this;
+        }
+
+        public MusicSheet updateBy(String updateBy) {
+            this.updateBy = Long.parseLong(updateBy);
+            return this;
+        }
+
+        public MusicSheet updateUser(String updateUser) {
+            this.updateUser = updateUser;
+            return this;
+        }
+
+        public MusicSheet notation(Integer notation) {
+            this.notation = notation;
+            return this;
+        }
+
+        public MusicSheet userId(String userId) {
+            this.userId = Long.valueOf(userId);
+            return this;
+        }
+    }
+
+
+    @Data
+    @EqualsAndHashCode(callSuper = true)
+    public static class MusicSheetDetail extends CbsMusicSheetWrapper.MusicSheet {
+        @ApiModelProperty
+        private Long bizMusicCategoryId;
+
+        @ApiModelProperty("收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费)")
+        private String paymentType;
+
+        @ApiModelProperty("是否可转谱(0:否; 1:是)")
+        private Boolean isConvertibleScore;
+
+        @ApiModelProperty("谱面类型")
+        private String scoreType;
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" MusicSheet-曲谱表")
+    public static class OpenMusicSheetDetail implements Serializable {
+
+        @ApiModelProperty("主键")
+        private Long id;
+
+        @ApiModelProperty("业务平台曲目ID")
+        private Long bizId;
+
+        @ApiModelProperty("曲目分类ID")
+        private Long musicCategoryId;
+
+        @ApiModelProperty("曲目分类名称")
+        private String musicCategoryName;
+
+        @ApiModelProperty("曲目标签")
+        private String musicTag;
+
+        @ApiModelProperty("曲目标签名称")
+        private String musicTagNames;
+
+        @ApiModelProperty("曲目封面图")
+        private String musicCover;
+
+        @ApiModelProperty("曲目名称")
+        private String name;
+
+        @ApiModelProperty("是否审核版本")
+        private Boolean appAuditFlag;
+
+        @ApiModelProperty("曲目声部(多个,用逗号分隔)")
+        private String subjectIds;
+
+        @ApiModelProperty("曲目声部code")
+        private String subjectCodes;
+
+        @ApiModelProperty("曲目声部名称")
+        private String subjectNames;
+
+        @ApiModelProperty("曲目乐器(多个,用逗号分隔)")
+        private String musicalInstrumentIds;
+
+        @ApiModelProperty("曲目乐器code")
+        private String musicalInstrumentIdCodes;
+
+        @ApiModelProperty("曲目乐器名称")
+        private String musicalInstrumentNames;
+
+        @ApiModelProperty("作曲人/音乐人")
+        private String composer;
+
+        @ApiModelProperty("曲目类型(SINGLE:单曲 CONCERT:合奏)")
+        private EMusicSheetType musicSheetType;
+
+        @ApiModelProperty("是否使用系统节拍器(0:否;1:是)")
+        private Boolean isUseSystemBeat;
+
+        @ApiModelProperty("是否可评测(0:否;1:是)")
+        private Boolean isEvaluated;
+
+        @ApiModelProperty("是否可转谱(0:否; 1:是)")
+        private Boolean isConvertibleScore;
+
+        @ApiModelProperty("是否展示指法(0:否;1:是)")
+        private Boolean isShowFingering;
+
+        @ApiModelProperty("是否播入节拍器(0: 否 1:是)")
+        private Boolean isPlayBeat;
+
+        @ApiModelProperty("多声轨选择")
+        private String multiTracksSelection;
+
+        @ApiModelProperty("播放速度")
+        private String playSpeed;
+
+        @ApiModelProperty("播放模式(MIDI;MP3)")
+        private EMusicPlayMode playMode;
+
+        @ApiModelProperty("XML文件")
+        private String xmlFileUrl;
+
+        @ApiModelProperty("MIDI文件(保留字段)")
+        private String midiFileUrl;
+
+        @ApiModelProperty("曲目JSON")
+        private String musicJson;
+
+        @ApiModelProperty("曲目缓存JSON(后续使用)")
+        private String musicSvgJson;
+
+        @ApiModelProperty("曲目缓存")
+        private String musicSvg;
+
+        @ApiModelProperty("评测标准 节奏 AMPLITUDE 音准 FREQUENCY 分贝 DECIBELS")
+        private EEvaluationStandard evaluationStandard;
+
+        @ApiModelProperty("简谱缓存")
+        private String musicJianSvg;
+
+        @ApiModelProperty("首调缓存")
+        private String musicFirstSvg;
+
+        @ApiModelProperty("谱面图片JSON(后续使用)")
+        private String musicImgJson;
+
+        @ApiModelProperty("五线谱图片")
+        private String musicImg;
+
+        @ApiModelProperty("首调图片")
+        private String musicFirstImg;
+
+        @ApiModelProperty("固定调图片")
+        private String musicJianImg;
+
+        @ApiModelProperty("谱面参数设置")
+        private String extConfigJson;
+
+        @ApiModelProperty("谱面样式参数设置")
+        private String extStyleConfigJson;
+
+        @ApiModelProperty("可用类型(PLATFORM: 平台; ORG: 机构; PERSON: 个人)")
+        private EMusicAvailableType availableType;
+
+        @ApiModelProperty("来源类型/作者属性(PLATFORM: 平台; ORG: 机构; PERSON: 个人)")
+        private EMusicSourceType sourceType;
+
+        @ApiModelProperty("音频类型(HOMEMODE: 自制 COMMON: 普通)")
+        private EAudioType audioType;
+
+        @ApiModelProperty("曲目状态(0:停用,1:启用)")
+        private Boolean status;
+
+        @ApiModelProperty("停用原因")
+        private String reason;
+
+        @ApiModelProperty("备注")
+        private String remark;
+
+        @ApiModelProperty("逻辑删除标识(0: 未删 1:已删)")
+        private Boolean delFlag;
+
+        @ApiModelProperty("评测频率,详情返回,指定应用端")
+        private String evaluationFrequency;
+
+        @ApiModelProperty("乐器信息")
+        private List<CbsMusicSheetWrapper.MusicalInstrument> musicalInstruments;
+
+        @ApiModelProperty
+        private Long bizMusicCategoryId;
+
+        @ApiModelProperty("收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费)")
+        private String paymentType;
+
+        public static OpenMusicSheetDetail from(String json) {
+            return JSON.parseObject(json, OpenMusicSheetDetail.class);
+        }
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" MusicSheet-曲谱表")
+    public static class OpenMusicSheet implements Serializable {
+
+        @ApiModelProperty("主键")
+        private Long id;
+
+        @ApiModelProperty("曲谱分类")
+        private Integer musicSheetCategoriesId;
+
+        @ApiModelProperty("曲谱分类名称")
+        private String musicSheetCategoriesName;
+
+        @ApiModelProperty("曲谱名称")
+        private String musicSheetName;
+
+        @ApiModelProperty("封面图")
+        private String titleImg;
+
+//        @ApiModelProperty("曲目来源类型 TEACHER 老师 PLATFORM 平台")
+//        private ESourceFrom sourceType;
+
+        @ApiModelProperty("多声轨选择")
+        private String multiTracksSelection;
+
+        @ApiModelProperty("是否公开")
+        private Boolean openFlag;
+
+        @ApiModelProperty("作曲人")
+        private String composer;
+
+        @ApiModelProperty("曲谱声部(适用的乐器,可能是多个,用逗号分隔)")
+        private String musicSubject;
+
+        @ApiModelProperty("mp3曲谱类型  MP3;MP3_METRONOME")
+        private String mp3Type;
+
+        @ApiModelProperty("曲目图片")
+        private String musicImg;
+
+        @ApiModelProperty("曲谱音频文件类型(midi;mp3)")
+        private EAudioType audioType;
+
+        @ApiModelProperty("是否可以转简谱(0:否,1:是)")
+        private Integer notation;
+
+        @ApiModelProperty("曲谱标签(多个标签用逗号分隔)")
+        private String musicTag;
+
+        @ApiModelProperty("默认播放速度")
+        private String playSpeed;
+
+        @ApiModelProperty("是否可以评测(0:否;1:是)")
+        private Boolean canEvaluate;
+
+        @ApiModelProperty("伴奏类型  HOMEMODE:自制 COMMON:普通")
+        private String accompanimentType;
+
+        @ApiModelProperty("是否展示指法(0:否;1:是)")
+        private Boolean showFingering;
+
+        @ApiModelProperty("曲目状态(0:停用,1:启用)")
+        private Boolean status;
+
+        @ApiModelProperty("曲目停用原因")
+        private String reason;
+
+        @ApiModelProperty("排序号")
+        private Integer sortNumber;
+
+        @ApiModelProperty("midi路径")
+        private String midiUrl;
+
+        @ApiModelProperty("XML文件存储路径")
+        private String xmlFileUrl;
+
+        @ApiModelProperty("是否自带节拍器(0:否;1:是)")
+        private Boolean hasBeat;
+
+        @ApiModelProperty("曲目配置")
+        private String extConfigJson;
+
+        @ApiModelProperty("是否节奏音乐")
+        private Boolean rhythmFlag;
+
+        @ApiModelProperty("备注")
+        private String remark;
+
+        @ApiModelProperty("假删除标识 0:未删除 1:已删除")
+        private Boolean delFlag;
+
+        @ApiModelProperty("曲目缓存")
+        private String musicJSON;
+
+        @ApiModelProperty("曲目缓存svg")
+        private String musicSvg;
+
+        @ApiModelProperty("曲目缓存简谱svg")
+        private String musicJianSvg;
+
+        @ApiModelProperty("曲目缓存首调svg")
+        private String musicFirstSvg;
+
+        @ApiModelProperty("被使用次数")
+        private Long usedNum = 0L;
+
+        @ApiModelProperty("曲目赏析")
+        private String appreciationUrl;
+
+        @ApiModelProperty("曲目创作ID")
+        private Long musicSheetCreationId;
+
+        @ApiModelProperty(" 可用乐器(多个,用逗号分隔)")
+        private String cbsMusicalInstrumentIds;
+
+        @ApiModelProperty(" 可用乐器(多个,用逗号分隔)")
+        private String cbsMusicalInstrumentIdNames;
+
+        @ApiModelProperty("内容平台曲目ID")
+        private Long cbsMusicSheetId;
+
+        @ApiModelProperty("首调图片")
+        private String musicFirstImg;
+
+        @ApiModelProperty("固定调图片")
+        private String musicJianImg;
+
+        @ApiModelProperty("曲目类型(SINGLE:单曲 CONCERT:合奏)")
+        private String musicSheetType;
+
+        /*@ApiModelProperty("乐器信息")
+        private List<InstrumentWrapper.Instrument> musicalInstruments;*/
+
+        @ApiModelProperty("收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费)")
+        private String paymentType;
+
+        public static OpenMusicSheet from(String json) {
+            return JSON.parseObject(json, OpenMusicSheet.class);
+        }
+
+    }
+}

+ 23 - 0
mec-application/src/main/java/com/ym/mec/vo/MusicalInstrumentWrapper.java

@@ -0,0 +1,23 @@
+package com.ym.mec.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+public class MusicalInstrumentWrapper {
+
+
+    @Data
+    @ApiModel(" MusicalInstrumentQuery-曲目乐器")
+    public static class MusicalInstrumentQuery  {
+
+        @ApiModelProperty("声部")
+        private Integer subjectId;
+        @ApiModelProperty("声部")
+        private List<Integer> subjectIds;
+        @ApiModelProperty("是否启用")
+        private Boolean enableFlag;
+    }
+}

+ 138 - 0
mec-application/src/main/java/com/ym/mec/web/controller/MusicPracticeRecordController.java

@@ -0,0 +1,138 @@
+package com.ym.mec.web.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.common.enums.music.EEvaluationStandard;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.common.response.template.R;
+import com.microsvc.toolkit.common.webportal.exception.BizException;
+import com.microsvc.toolkit.config.validator.group.ValidGroups;
+import com.ym.mec.biz.dal.entity.UserMusic;
+import com.ym.mec.biz.dal.enums.ClientEnum;
+import com.ym.mec.biz.dal.wrapper.MusicPracticeRecordWrapper;
+import com.ym.mec.biz.service.MusicPracticeRecordService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.biz.service.UserMusicService;
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+import java.util.Objects;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.web:}/musicPracticeRecord")
+@Api(tags = "曲目练习记录")
+public class MusicPracticeRecordController {
+
+    @Autowired
+    private MusicPracticeRecordService musicPracticeRecordService;
+
+    @Autowired
+    private UserMusicService userMusicService;
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    /**
+     * 查询单条
+     * @param id 详情ID
+     * @return R<MusicPracticeRecordVo.MusicPracticeRecord>
+     */
+    @ApiOperation(value = "详情", notes = "曲目练习记录-根据详情ID查询单条, 传入id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/detail/{id}")
+    public R<MusicPracticeRecordWrapper.MusicPracticeRecord> detail(@PathVariable("id") Long id) {
+
+        MusicPracticeRecordWrapper.Entity wrapper = musicPracticeRecordService.detail(id);
+
+        if (wrapper == null) {
+            throw new BizException("记录不存在");
+        }
+
+        // 上传过作品,用作品视频路径覆盖上传视频路径
+        // ID集合
+        Map<Long, UserMusic> userMusicMap = userMusicService.getMapByMusicPracticeRecordIds(Lists.newArrayList(Long.parseLong(wrapper.getId())));
+
+        UserMusic userMusic = userMusicMap.get(Long.parseLong(wrapper.getId()));
+        if (Objects.nonNull(userMusic)) {
+            wrapper.setVideoFilePath(userMusic.getVideoUrl());
+        }
+        MusicPracticeRecordWrapper.MusicPracticeRecord from = MusicPracticeRecordWrapper.MusicPracticeRecord.from(JSON.toJSONString(wrapper));
+
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(Integer.parseInt(wrapper.getMusicSheetId()));
+        if (musicSheet != null) {
+            from.setRhythmFlag(musicSheet.getEvaluationStandard() != EEvaluationStandard.FREQUENCY);
+        }
+
+        return R.from(from);
+    }
+
+
+    /**
+     * 新增
+     * @param record MusicPracticeRecordVo.MusicPracticeRecord
+     * @return R<Boolean>
+     */
+    @ApiOperation(value = "新增", notes = "曲目练习记录- 传入 MusicPracticeRecordVo.MusicPracticeRecord")
+    @PostMapping("/save")
+    public R<String> add(@Validated(ValidGroups.Add.class) @RequestBody MusicPracticeRecordWrapper.MusicPracticeRecord record) {
+
+        Integer userId = sysUserService.getUserId();
+        record.userId(String.valueOf(userId)).clientType("education");
+
+        // 新增数据
+        MusicPracticeRecordWrapper.MusicPracticeRecord from = MusicPracticeRecordWrapper.MusicPracticeRecord.from(record.jsonString());
+        if (record.getDelFlag() !=null && record.getDelFlag()) {
+            from.setDelFlag(false);
+            from.setHiddenFlag(true);
+        }
+
+        return R.from(musicPracticeRecordService.add(from));
+    }
+
+    @ApiOperation(value = "用户最后一次评测数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "recordId", value = "曲目练习记录Id", dataType = "long")
+    })
+    @GetMapping("/getLastEvaluationMusicalNotesPlayStats")
+    public Object getLastEvaluationMusicalNotesPlayStats(Long recordId){
+        return R.from(musicPracticeRecordService.getLastEvaluationMusicalNotesPlayStats(recordId));
+    }
+
+    @ApiOperation(value = "上传音频文件")
+    @PostMapping("videoUpload")
+    public R<Boolean> videoUpload( @RequestBody MusicPracticeRecordWrapper.MusicPracticeRecord record){
+
+        if (Objects.isNull(record.getId())) {
+            throw BizException.from("recordId不能为空");
+        }
+        if (Objects.isNull(record.getVideoFilePath())) {
+            throw BizException.from("videoUrl不能为空");
+        }
+
+        MusicPracticeRecordWrapper.Entity practiceRecord = musicPracticeRecordService.getById(record.getId());
+        if (Objects.isNull(practiceRecord)) {
+            throw BizException.from("记录不存在");
+        }
+
+        practiceRecord.setVideoFilePath(record.getVideoFilePath());
+        musicPracticeRecordService.update(practiceRecord);
+
+        return R.from(true);
+    }
+
+}

+ 1 - 1
mec-application/src/main/java/com/ym/mec/web/controller/MusicSheetApplicationExtendController.java

@@ -1,7 +1,6 @@
 package com.ym.mec.web.controller;
 
 import com.alibaba.fastjson.JSONObject;
-import com.dayaedu.cbs.domain.wrapper.MusicSheetWrapper;
 import com.dayaedu.cbs.openfeign.client.MusicFeignClientService;
 import com.dayaedu.cbs.openfeign.properties.OpenFeignClientConfigProperties;
 import com.dayaedu.cbs.openfeign.service.CbsMusicSheetService;
@@ -13,6 +12,7 @@ import com.microsvc.toolkit.common.response.paging.PageInfo;
 import com.microsvc.toolkit.common.response.template.R;
 import com.microsvc.toolkit.common.webportal.exception.BizException;
 import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.wrapper.MusicSheetWrapper;
 import com.ym.mec.biz.service.SysMusicScoreService;
 import com.ym.mec.vo.PageUtil;
 import io.swagger.annotations.Api;

+ 147 - 0
mec-application/src/main/java/com/ym/mec/web/controller/MusicSheetController.java

@@ -0,0 +1,147 @@
+package com.ym.mec.web.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.microsvc.toolkit.common.response.template.R;
+import com.ym.mec.biz.dal.entity.Instrument;
+import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.enums.ClientEnum;
+import com.ym.mec.biz.dal.enums.ClientTypeEnum;
+import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
+import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
+import com.ym.mec.biz.dal.wrapper.MusicSheetWrapper;
+import com.ym.mec.biz.service.InstrumentService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.vo.MusicSheetVo;
+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.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.web:}/musicSheet")
+@Api(tags = "曲谱表")
+public class MusicSheetController {
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private InstrumentService instrumentService;
+
+    @Resource
+    private SysUserService sysUserService;
+    /**
+     * 查询单条
+     *
+     * @param id 详情ID
+     * @return R<MusicSheetVo.MusicSheet>
+     */
+    @ApiOperation(value = "查询内容平台数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/cbsDetail/{id}")
+    public R<MusicSheetVo.MusicSheetDetail> cbsDetail(@PathVariable("id") Integer id) {
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(id);
+        musicSheet.setBizId(Long.valueOf(id));
+
+        MusicSheetVo.MusicSheetDetail musicSheetDetail = JSON.parseObject(JSON.toJSONString(musicSheet), MusicSheetVo.MusicSheetDetail.class);
+        SysMusicScore detail = musicSheetService.get(id);
+        if (detail == null) {
+            musicSheetDetail.setBizMusicCategoryId(null);
+        } else {
+            // 设置曲目付费类型
+            musicSheetDetail.setPaymentType(StringUtils.isBlank(detail.getRankIds()) ? "FREE" : "VIP");
+            // 设置业务端曲目分类
+            musicSheetDetail.setBizMusicCategoryId(detail.getCategoriesId() == null ? null : detail.getCategoriesId().longValue());
+            musicSheetDetail.setScoreType(detail.getScoreType());
+            musicSheetDetail.setIsConvertibleScore(detail.getIsConvertibleScore());
+        }
+
+        // 设置乐器信息
+        if (StringUtils.isNotBlank(musicSheetDetail.getMusicalInstrumentIds())) {
+            List<Integer> instrumentIds = Arrays.stream(musicSheetDetail.getMusicalInstrumentIds().split(","))
+                .map(Integer::parseInt).collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(instrumentIds) && CollectionUtils.isNotEmpty(musicSheetDetail.getMusicalInstruments())) {
+                Map<Integer, InstrumentWrapper.Instrument> instrumentMap = instrumentService.getMapByIds(instrumentIds);
+                for (CbsMusicSheetWrapper.MusicalInstrument musicalInstrument : musicSheetDetail.getMusicalInstruments()) {
+                    InstrumentWrapper.Instrument instrument = instrumentMap.get(musicalInstrument.getId());
+                    if (instrument != null) {
+                        musicalInstrument.setOrientation(instrument.getOrientation());
+                    }
+
+                }
+            }
+        }
+        return R.from(musicSheetDetail);
+    }
+
+    @ApiOperation(value = "查询分页", notes = "曲谱表- 传入 MusicSheetVo.MusicSheetQuery")
+    @PostMapping("/page")
+    public R<PageInfo<MusicSheetWrapper.MusicSheet>> page(@RequestBody MusicSheetVo.MusicSheetQuery query) {
+
+        SysExamSongQueryInfo queryInfo = new SysExamSongQueryInfo();
+
+        Integer userId = sysUserService.getUserId();
+        if(query.getMusicSheetCategoriesId() != null) {
+            queryInfo.setCategoriesId(query.getMusicSheetCategoriesId().toString());
+        }
+        if (query.getMusicalInstrumentId() != null) {
+            // 乐器转换为声部
+            Instrument instrument = instrumentService.getById(query.getMusicalInstrumentId());
+            if (instrument != null) {
+                queryInfo.setSubjectId(instrument.getSubjectId());
+            } else {
+                queryInfo.setSubjectId(-1);
+            }
+        }
+
+        queryInfo.setPage(query.getPage());
+        queryInfo.setRows(query.getRows());
+        queryInfo.setName(query.getName());
+        queryInfo.setRecentFlag(query.getRecentFlag());
+        queryInfo.setExcludeMusicId(query.getExcludeMusicId());
+        queryInfo.setType("COMMON");
+        queryInfo.setClientFlag(true);
+        queryInfo.setClientType(ClientTypeEnum.SMART_PRACTICE);
+        queryInfo.setUserId(userId);
+        queryInfo.setRecentFlag(query.getRecentFlag());
+        queryInfo.setClientId("education");
+        PageInfo<SysMusicScore> sysMusicScorePageInfo = musicSheetService.queryMusicScorePage(queryInfo);
+        PageInfo<MusicSheetWrapper.MusicSheet> convert = sysMusicScorePageInfo.convert(o -> {
+            MusicSheetWrapper.MusicSheet musicSheet = new MusicSheetWrapper.MusicSheet();
+            musicSheet.setId(o.getId().toString());
+            musicSheet.setMusicSheetCategoriesId(o.getCategoriesId());
+            musicSheet.setMusicSheetName(o.getName());
+            musicSheet.setTitleImg(o.getTitleImg());
+            musicSheet.setComposer(o.getComposer());
+            musicSheet.setCbsMusicSheetId(o.getCbsMusicSheetId());
+            musicSheet.setUsedNum(0L);
+            musicSheet.setPaymentType(StringUtils.isNotBlank(o.getRankIds()) && o.getRankIds().contains("1") ? "VIP" : "FREE");
+            musicSheet.setAudioPlayTypes(o.getAudioPlayTypes());
+
+            return musicSheet;
+        });
+
+
+        return R.from(convert);
+    }
+}

+ 1 - 1
mec-application/src/main/java/com/ym/mec/web/controller/SysMusicScoreController.java

@@ -1,11 +1,11 @@
 package com.ym.mec.web.controller;
 
-import com.dayaedu.cbs.domain.wrapper.MusicSheetWrapper;
 import com.ym.mec.biz.dal.dto.ReasonDto;
 import com.ym.mec.biz.dal.entity.SysMusicScore;
 import com.ym.mec.biz.dal.enums.ClientTypeEnum;
 import com.ym.mec.biz.dal.enums.YesOrNoEnum;
 import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
+import com.ym.mec.biz.dal.wrapper.MusicSheetWrapper;
 import com.ym.mec.biz.service.SysMusicScoreService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.entity.HttpResponseResult;

+ 88 - 0
mec-application/src/main/java/com/ym/mec/web/controller/open/OpenMusicSheetController.java

@@ -0,0 +1,88 @@
+package com.ym.mec.web.controller.open;
+
+import com.alibaba.fastjson.JSON;
+import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
+import com.microsvc.toolkit.common.response.template.R;
+import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
+import com.ym.mec.biz.service.InstrumentService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.vo.MusicSheetVo;
+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.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("${app-config.url.web:}/open/musicSheet")
+@Api(tags = "曲谱表")
+public class OpenMusicSheetController {
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private InstrumentService instrumentService;
+
+    /**
+     * 查询单条
+     *
+     * @param id 详情ID
+     * @return R<MusicSheetVo.MusicSheet>
+     */
+    @ApiOperation(value = "查询内容平台数据")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "id", value = "id", dataType = "long")
+    })
+    @GetMapping("/cbsDetail/{id}")
+    public R<MusicSheetVo.OpenMusicSheetDetail> cbsDetail(@PathVariable("id") Integer id) {
+        CbsMusicSheetWrapper.MusicSheet musicSheet = musicSheetService.cbsDetail(id);
+        musicSheet.setBizId(Long.valueOf(id));
+
+        MusicSheetVo.MusicSheetDetail musicSheetDetail = JSON.parseObject(JSON.toJSONString(musicSheet), MusicSheetVo.MusicSheetDetail.class);
+        SysMusicScore detail = musicSheetService.get(id);
+        if (detail == null) {
+            musicSheetDetail.setBizMusicCategoryId(null);
+        } else {
+            // 设置曲目付费类型
+            musicSheetDetail.setPaymentType(StringUtils.isBlank(detail.getRankIds()) ? "FREE" : "VIP");
+            // 设置业务端曲目分类
+            musicSheetDetail.setBizMusicCategoryId(detail.getCategoriesId() == null ? null : detail.getCategoriesId().longValue());
+        }
+
+        // 设置乐器信息
+        if (StringUtils.isNotBlank(musicSheetDetail.getMusicalInstrumentIds())) {
+            List<Integer> instrumentIds = Arrays.stream(musicSheetDetail.getMusicalInstrumentIds().split(","))
+                .map(Integer::parseInt).collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(instrumentIds) && CollectionUtils.isNotEmpty(musicSheetDetail.getMusicalInstruments())) {
+                Map<Integer, InstrumentWrapper.Instrument> instrumentMap = instrumentService.getMapByIds(instrumentIds);
+                for (CbsMusicSheetWrapper.MusicalInstrument musicalInstrument : musicSheetDetail.getMusicalInstruments()) {
+                    InstrumentWrapper.Instrument instrument = instrumentMap.get(musicalInstrument.getId());
+                    if (instrument != null) {
+                        musicalInstrument.setOrientation(instrument.getOrientation());
+                    }
+
+                }
+            }
+        }
+        return R.from(MusicSheetVo.OpenMusicSheetDetail.from(musicSheetDetail.jsonString()));
+    }
+
+}

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

@@ -22,4 +22,5 @@ public interface InstrumentDao extends BaseMapper<Instrument> {
 	 */
 	List<InstrumentWrapper.Instrument> selectPage(@Param("page") IPage<InstrumentWrapper.Instrument> page, @Param("param") InstrumentWrapper.InstrumentQuery param);
 
+    List<Instrument> getBySubjectId(@Param("subjectId") String subjectId);
 }

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

@@ -132,4 +132,6 @@ public interface SysMusicCompareRecordDao extends BaseDAO<Long, SysMusicCompareR
     int countByStudent(Map<String, Object> params);
 
     List<MusicCompareRecordWapper.Result> queryPageByStudent(Map<String, Object> params);
+
+    Long getLastData(@Param("clientId") String clientId, @Param("userId") Integer userId, @Param("feature") String feature, @Param("sysMusicScoreId") Integer sysMusicScoreId);
 }

+ 12 - 2
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/Student.java

@@ -1,12 +1,13 @@
 package com.ym.mec.biz.dal.entity;
 
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.ym.mec.auth.api.entity.SysUser;
 import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -79,6 +80,7 @@ public class Student extends SysUser {
 	private String extSubjectIds;
 	
 	private Map<Integer,String> extSjectNamesMap = new HashMap<Integer, String>();
+	private List<Map<String, Object>> extInstrumentNames = new ArrayList<>();
 
 	@ApiModelProperty(value = "家长姓名")
 	private String parentName;
@@ -92,8 +94,16 @@ public class Student extends SysUser {
     @ApiModelProperty("IM绑定设备")
     private String imDeviceId;
 
+	public List<Map<String, Object>> getExtInstrumentNames() {
+		return extInstrumentNames;
+	}
+
+	public Student setExtInstrumentNames(List<Map<String, Object>> extInstrumentNames) {
+		this.extInstrumentNames = extInstrumentNames;
+		return this;
+	}
 
-    public String getImDeviceId() {
+	public String getImDeviceId() {
         return imDeviceId;
     }
 

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

@@ -87,6 +87,24 @@ public class SysMusicCompareRecord extends BaseEntity {
 
 	private Integer subjectId;
 
+    private String customConfiguration;
+
+    private String practiceTime;
+
+    private String practiceSource;
+
+    private String resultAnalyze;
+
+    private Boolean headphoneFlag;
+
+    private Long instrumentId;
+
+    private Boolean hiddenFlag;
+
+    private Boolean delFlag;
+
+    private Float playRate;
+
 	public SysMusicCompareRecord(FeatureType feature) {
 		this.feature = feature;
 	}

+ 7 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicScore.java

@@ -180,6 +180,13 @@ public class SysMusicScore {
 
 	private List<SysMusicScoreAccompaniment> background;
 
+    private String titleImg;
+
+    private String composer;
+
+
+    @ApiModelProperty("音频类型,SING:演唱,PLAY:演奏")
+    private String audioPlayTypes;
 	@Override
 	public String toString() {
 		return ToStringBuilder.reflectionToString(this);

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/UserMusic.java

@@ -66,6 +66,11 @@ public class UserMusic implements Serializable {
 	@TableField(value = "video_url_")
     private String videoUrl;
 
+    @ApiModelProperty("文件类型") // .mp4 视频,其他为音频
+    @TableField(value = "file_type_")
+    private String fileType;
+
+
     @ApiModelProperty("json配置")
 	@TableField(value = "json_config_")
     private String jsonConfig;
@@ -86,6 +91,12 @@ public class UserMusic implements Serializable {
     @TableField(value = "submit_time_")
     private Date submitTime;
 
+
+
+    @ApiModelProperty("是否能被看到评级、评分字段")
+    @TableField(value = "select_flag_")
+    private Boolean selectFlag;
+
     @TableField(value = "create_time_")
     private Date createTime;
 

+ 35 - 2
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/FeatureType.java

@@ -4,7 +4,8 @@ import com.ym.mec.common.enums.BaseEnum;
 
 public enum FeatureType implements BaseEnum<String, FeatureType> {
 	CLOUD_STUDY_TRAIN("CLOUD_STUDY_TRAIN", "云教练训练"),
-	CLOUD_STUDY_EVALUATION("CLOUD_STUDY_EVALUATION", "云教练评测");
+	CLOUD_STUDY_EVALUATION("CLOUD_STUDY_EVALUATION", "云教练评测"),
+    FOLLOW_UP_TRAINING("FOLLOW_UP_TRAINING", "跟练");
 
 	private String code;
 
@@ -15,7 +16,27 @@ public enum FeatureType implements BaseEnum<String, FeatureType> {
 		this.desc = desc;
 	}
 
-	@Override
+    public static FeatureType format(String feature) {
+        switch (feature){
+
+//            UNIT_TEST("单元测试"),
+//                PRACTICE("自主练习"),
+//                EVALUATION("评测"),
+//                LESSON_TRAINING("课后练习"),
+//                FOLLOW_UP_TRAINING("跟练"),
+            case "PRACTICE":
+                return CLOUD_STUDY_TRAIN;
+            case "FOLLOW_UP_TRAINING":
+                return FOLLOW_UP_TRAINING;
+            case "EVALUATION":
+                return CLOUD_STUDY_EVALUATION;
+            default:
+                return CLOUD_STUDY_TRAIN;
+        }
+
+    }
+
+    @Override
 	public String getCode() {
 		return code;
 	}
@@ -24,4 +45,16 @@ public enum FeatureType implements BaseEnum<String, FeatureType> {
 		return desc;
 	}
 
+    public String toCbs() {
+        switch (this) {
+            case CLOUD_STUDY_TRAIN:
+                return "PRACTICE";
+            case FOLLOW_UP_TRAINING:
+                return "FOLLOW_UP_TRAINING";
+            case CLOUD_STUDY_EVALUATION:
+                return "EVALUATION";
+            default:
+                return "PRACTICE";
+        }
+    }
 }

+ 16 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/SysExamSongQueryInfo.java

@@ -57,4 +57,20 @@ public class SysExamSongQueryInfo extends QueryInfo {
 
     @ApiModelProperty("谱面类型")
     private String scoreType;
+
+
+    @ApiModelProperty("是否最近练习")
+    private Boolean recentFlag = false;
+
+    @ApiModelProperty("最近练习 当前曲目ID")
+    private Long excludeMusicId;
+
+    @ApiModelProperty(value = "用户ID",hidden = true)
+    private Integer userId;
+
+    @ApiModelProperty(value = "用户类型",hidden = true)
+    private String clientId;
+
+    @ApiModelProperty("仅匹配资源名称")
+    private String name;
 }

+ 560 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/MusicPracticeRecordWrapper.java

@@ -0,0 +1,560 @@
+package com.ym.mec.biz.dal.wrapper;
+
+import com.alibaba.fastjson.JSON;
+import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
+import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
+import com.ym.mec.biz.dal.enums.FeatureType;
+import com.ym.mec.biz.dal.enums.HeardLevelEnum;
+import com.ym.mec.biz.dal.enums.im.CK;
+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 org.joda.time.DateTime;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.WeekFields;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.OptionalInt;
+
+/**
+ * 曲目练习记录
+ * 2022-12-07 10:16:58
+ */
+@ApiModel(value = "MusicPracticeRecordWrapper对象", description = "曲目练习记录查询对象")
+public class MusicPracticeRecordWrapper {
+
+    @Data
+	@Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" MusicPracticeRecordQuery-曲目练习记录")
+    public static class MusicPracticeRecordQuery implements QueryInfo {
+
+    	@ApiModelProperty("当前页")
+        private Integer page;
+
+        @ApiModelProperty("分页行数")
+        private Integer rows;
+
+        @ApiModelProperty("曲目名称")
+        private String musicSheetName;
+
+        @ApiModelProperty("评测难度")
+        private String heardLevel;
+
+
+        @ApiModelProperty("最低总分")
+        private BigDecimal minScore = BigDecimal.ZERO;
+
+
+        @ApiModelProperty("最高总分")
+        private BigDecimal maxScore = new BigDecimal(100);
+
+        @ApiModelProperty("是否生成作品")
+        private Boolean userMusicFlag;
+
+        @ApiModelProperty("生成作品开始时间")
+        private Date userMusicStartTime;
+
+        @ApiModelProperty("生成作品结束时间")
+        private Date userMusicEndTime;
+
+        @ApiModelProperty("关键字匹配")
+		private String keyword;
+
+        @ApiModelProperty("用户编号")
+        private Long userId;
+
+        @ApiModelProperty("客户端类型")
+        private String clientType;
+
+
+        @ApiModelProperty("班级ID")
+        private Long classGroupId;
+
+        @ApiModelProperty("曲目编号")
+        private Long musicSheetId;
+
+        @ApiModelProperty("功能")
+        private String feature;
+
+        @ApiModelProperty("练习类型")
+        private List<String> practiceTypes;
+
+        @ApiModelProperty("评测结果数据 ")
+        private Boolean scoreData;
+
+        @ApiModelProperty("练习时间(按月:202209)")
+        private String practiceMonth;
+
+        @ApiModelProperty("练习来源")
+        private String practiceSource;
+
+
+        @ApiModelProperty("评测乐器ID")
+        private Long instrumentId;
+
+
+        @ApiModelProperty("声部Id")
+        private String subjectId;
+
+        @ApiModelProperty("乐团Id")
+        private String orchestraId;
+
+        @ApiModelProperty("学校Id")
+        private Long schoolId;
+
+        @ApiModelProperty("开始时间")
+        private Date startTime;
+
+        @ApiModelProperty("结束时间")
+        private Date endTime;
+
+        @ApiModelProperty("伴学老师Id")
+        private Long teacherId;
+
+        @ApiModelProperty("删除标记")
+        private Boolean delFlag;
+
+        @ApiModelProperty("练习达标时间")
+        private Integer practiceTargetMinute;
+
+        @ApiModelProperty("周练习达标匹配")
+        private Boolean practiceTargetMatch;
+
+        @ApiModelProperty("周练习匹配")
+        private Boolean practiceMatch;
+
+        @ApiModelProperty("老师统计查询")
+        private Boolean teacherStatQuery;
+
+        @ApiModelProperty("学校统计查询")
+        private Boolean schoolStatQuery;
+
+        @ApiModelProperty("完整评测标记")
+        private Boolean completeEvaluation;
+
+        @ApiModelProperty("排除学生人数")
+        private List<Long> excludeStudentIds;
+
+        @ApiModelProperty("排序字段,1:综合得分,2:音准,3:节奏:4:完整度,5:评测时间 6:生成时间,7:评测进度")
+        private Integer sortType;
+
+        @ApiModelProperty("是否升序")
+        private Boolean asc;
+
+
+        public String getKeyword() {
+            return Optional.ofNullable(keyword).filter(StringUtils::isNotBlank).orElse(null);
+        }
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicPracticeRecordQuery from(String json) {
+            return JSON.parseObject(json, MusicPracticeRecordQuery.class);
+        }
+
+        public String getSubjectId() {
+            return Optional.ofNullable(subjectId).filter(StringUtils::isNotBlank).orElse(null);
+        }
+
+        public String getOrchestraId() {
+            return Optional.ofNullable(orchestraId).filter(StringUtils::isNotBlank).orElse(null);
+        }
+
+        public String getPracticeMonth() {
+            return Optional.ofNullable(practiceMonth).filter(StringUtils::isNotBlank).orElse(null);
+        }
+
+        public MusicPracticeRecordQuery scoreData(Boolean scoreData) {
+            this.scoreData = scoreData;
+            return this;
+        }
+
+
+        public MusicPracticeRecordQuery userId(String userId) {
+            this.userId = Long.parseLong(userId);
+            return this;
+        }
+
+        public MusicPracticeRecordQuery clientType(String clientType) {
+            this.clientType = clientType;
+            return this;
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+	@ApiModel(" MusicPracticeRecord-曲目练习记录")
+    public static class MusicPracticeRecord {
+
+        @ApiModelProperty("主键ID")
+        private Long id;
+
+        @ApiModelProperty("用户编号")
+        private Long userId;
+
+        @ApiModelProperty("客户端类型")
+        private String clientType;
+
+        @ApiModelProperty("曲目编号")
+        private Long musicSheetId;
+
+        @ApiModelProperty("曲目名称")
+        private String musicSheetName;
+
+        @ApiModelProperty("行为编号,同一编号为一次")
+        private String behaviorId;
+
+        @ApiModelProperty("评分数据")
+        private String scoreData;
+
+        @ApiModelProperty("总分")
+        private BigDecimal score;
+
+        @ApiModelProperty("音准")
+        private BigDecimal intonation;
+
+        @ApiModelProperty("节奏")
+        private BigDecimal cadence;
+
+        @ApiModelProperty("完成度")
+        private BigDecimal integrity;
+
+        @ApiModelProperty("录音文件地址")
+        private String recordFilePath;
+
+        @ApiModelProperty("录像文件地址")
+        private String videoFilePath;
+
+        @ApiModelProperty("设备类型")
+        private String deviceType;
+
+        @ApiModelProperty("源音时长")
+        private Float sourceTime;
+
+        @ApiModelProperty("演奏时长")
+        private Float playTime;
+
+
+        @ApiModelProperty("演奏倍率")
+        private Float playRate;
+
+
+        @ApiModelProperty("速度")
+        private String speed;
+
+        @ApiModelProperty("周一日期")
+        private String monday;
+
+        @ApiModelProperty("功能")
+        private String feature;
+
+        @ApiModelProperty("评测难度")
+        private String heardLevel;
+
+        @ApiModelProperty("部分索引")
+        private String partIndex;
+
+        @ApiModelProperty("自定义配置 默认空字符串")
+        private String customConfiguration;
+
+        @ApiModelProperty("练习时间")
+        private String practiceTime;
+
+        @ApiModelProperty("练习来源")
+        private String practiceSource;
+
+        @ApiModelProperty("更新时间")
+        private Date updateTime;
+
+        @ApiModelProperty("创建时间")
+        private Date createTime;
+
+        @ApiModelProperty("评测乐器ID")
+        private Long instrumentId;
+
+        @ApiModelProperty("评测乐器")
+        private String instrumentName;
+
+        @ApiModelProperty("是否节奏音乐")
+        private Boolean rhythmFlag;
+
+        @ApiModelProperty("收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费)")
+        private String paymentType;
+
+        @ApiModelProperty("是否生成作品")
+        private Boolean userMusicFlag;
+
+        @ApiModelProperty("生成作品时间")
+        private Date userMusicTime;
+
+        @ApiModelProperty("评测进度")
+        private BigDecimal evaluationProgressNumber;
+
+        @ApiModelProperty("评测进度")
+        private String evaluationProgress;
+
+        @ApiModelProperty("是否佩戴耳机")
+        private Boolean headphoneFlag;
+
+        @ApiModelProperty("假删除标识 0:未删除 1:已删除")
+        private Boolean delFlag;
+
+
+        @ApiModelProperty("是否隐藏评测记录 0:不隐藏 1:隐藏")
+        private Boolean hiddenFlag;
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicPracticeRecord from(String json) {
+            return JSON.parseObject(json, MusicPracticeRecord.class);
+        }
+
+        // 初始化默认值
+        public MusicPracticeRecord initDefaultValue() {
+
+            return this.customConfiguration(Optional.ofNullable(getCustomConfiguration()).orElse(""))
+                .monday(Optional.ofNullable(getMonday()).orElse(LocalDate.now().with(WeekFields.of(DayOfWeek.MONDAY, 1).dayOfWeek(), DayOfWeek.MONDAY.getValue()).toString()))
+                .sourceTime(Optional.ofNullable(getSourceTime()).orElse(0F))
+                .playTime(Optional.ofNullable(getPlayTime()).orElse(0F))
+                .speed(Optional.ofNullable(getSpeed()).orElse("90"))
+                .practiceTime(Optional.ofNullable(getPracticeTime()).orElse(DateTime.now().toString(CK.FORMAT_YYYY_MM_DD)));
+        }
+
+
+        public MusicPracticeRecord sourceTime(Float sourceTime) {
+            this.sourceTime = sourceTime;
+            return this;
+        }
+
+        public MusicPracticeRecord playTime(Float playTime) {
+            this.playTime = playTime;
+            return this;
+        }
+
+        public MusicPracticeRecord speed(String speed) {
+            this.speed = speed;
+            return this;
+        }
+
+        public MusicPracticeRecord monday(String monday) {
+            this.monday = monday;
+            return this;
+        }
+
+        public MusicPracticeRecord customConfiguration(String customConfiguration) {
+            this.customConfiguration = customConfiguration;
+            return this;
+        }
+
+        public MusicPracticeRecord practiceTime(String practiceTime) {
+            this.practiceTime = practiceTime;
+            return this;
+        }
+
+        public MusicPracticeRecord userId(String userId) {
+            this.userId = Long.parseLong(userId);
+            return this;
+        }
+
+        public MusicPracticeRecord clientType(String clientType) {
+            this.clientType = clientType;
+            return this;
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class Entity{
+
+        @ApiModelProperty("主键ID")
+        private String id;
+
+        @ApiModelProperty("用户编号")
+        private String userId;
+
+        @ApiModelProperty("客户端类型")
+        private String clientType;
+
+        @ApiModelProperty("曲目编号")
+        private String musicSheetId;
+
+        @ApiModelProperty("行为编号,同一编号为一次")
+        private String behaviorId;
+
+        @ApiModelProperty("评分数据")
+        private String scoreData;
+
+        @ApiModelProperty("总分")
+        private BigDecimal score;
+
+        @ApiModelProperty("音准")
+        private BigDecimal intonation;
+
+        @ApiModelProperty("节奏")
+        private BigDecimal cadence;
+
+        @ApiModelProperty("完成度")
+        private BigDecimal integrity;
+
+        @ApiModelProperty("录音文件地址")
+        private String recordFilePath;
+
+        @ApiModelProperty("录像文件地址")
+        private String videoFilePath;
+
+        @ApiModelProperty("设备类型")
+        private String deviceType;
+
+        @ApiModelProperty("源音时长")
+        private Float sourceTime;
+
+        @ApiModelProperty("演奏时长")
+        private Float playTime;
+
+
+
+        @ApiModelProperty("演奏倍率")
+        private Float playRate;
+
+
+        @ApiModelProperty("速度")
+        private String speed;
+
+        @ApiModelProperty("周一日期")
+        private String monday;
+
+        @ApiModelProperty("功能")
+        private String feature;
+
+        @ApiModelProperty("评测难度")
+        private String heardLevel;
+
+
+        @ApiModelProperty("评测乐器ID")
+        private String instrumentId;
+
+
+        @ApiModelProperty("评测结果分析")
+        private String resultAnalyze;
+
+        @ApiModelProperty("部分索引")
+        private String partIndex;
+
+        @ApiModelProperty("练习时间")
+        private String practiceTime;
+
+        @ApiModelProperty("练习来源")
+        private String practiceSource;
+
+        @ApiModelProperty("自定义配置 默认空字符串")
+        private String customConfiguration;
+
+
+        @ApiModelProperty("是否佩戴耳机")
+        private Boolean headphoneFlag;
+
+        @ApiModelProperty("更新时间")
+        private Date updateTime;
+
+        @ApiModelProperty("创建时间")
+        private Date createTime;
+
+        @ApiModelProperty("假删除标识 0:未删除 1:已删除")
+        private Boolean delFlag;
+
+
+        public static MusicPracticeRecordWrapper.Entity toEntity(SysMusicCompareRecord record) {
+            if (record ==null) {
+                return null;
+            }
+            return Entity.builder()
+                .id(record.getId().toString())
+                .userId(Optional.ofNullable(record.getUserId()).orElse(0).toString())
+                .clientType(record.getClientId()!=null?record.getClientId().toUpperCase():null)
+                .musicSheetId(record.getSysMusicScoreId()!=null? record.getSysMusicScoreId().toString():null)
+                .behaviorId(record.getBehaviorId())
+                .scoreData(record.getScoreData())
+                .score(record.getScore())
+                .intonation(record.getIntonation())
+                .cadence(record.getCadence())
+                .integrity(record.getIntegrity())
+                .recordFilePath(record.getRecordFilePath())
+                .videoFilePath(record.getVideoFilePath())
+                .deviceType(record.getDeviceType() !=null?record.getDeviceType().name():null)
+                .sourceTime(record.getSourceTime())
+                .playTime(record.getPlayTime())
+                .playRate(record.getPlayRate())
+                .speed(String.valueOf(OptionalInt.of(record.getSpeed()).orElse(0)))
+                .monday(record.getMonday())
+                .feature(record.getFeature()!=null?record.getFeature().toCbs():null)
+                .heardLevel(record.getHeardLevel() !=null?record.getHeardLevel().getCode():null)
+                .instrumentId(record.getInstrumentId()!=null?record.getInstrumentId().toString():null)
+                .resultAnalyze(record.getResultAnalyze())
+                .partIndex(record.getPartIndex())
+                .practiceTime(record.getPracticeTime())
+                .practiceSource(record.getPracticeSource())
+                .customConfiguration(record.getCustomConfiguration())
+                .headphoneFlag(record.getHeadphoneFlag())
+                .updateTime(record.getCreateTime())
+                .createTime(record.getCreateTime())
+                .delFlag(record.getDelFlag())
+                .build();
+        }
+
+        public SysMusicCompareRecord toSysMusicCompareRecord(){
+            SysMusicCompareRecord sysMusicCompareRecord = new SysMusicCompareRecord();
+            sysMusicCompareRecord.setId((this.id!=null?Long.parseLong(this.id):null));
+            sysMusicCompareRecord.setBehaviorId((this.behaviorId));
+            sysMusicCompareRecord.setUserId(this.userId!=null?Integer.parseInt(this.userId):null);
+            sysMusicCompareRecord.setSysMusicScoreId(this.musicSheetId!=null?Integer.parseInt(this.musicSheetId):null);
+            sysMusicCompareRecord.setHeardLevel(this.heardLevel!=null? HeardLevelEnum.valueOf(this.heardLevel):null);
+            sysMusicCompareRecord.setScoreData(this.scoreData);
+            sysMusicCompareRecord.setScore(this.score);
+            sysMusicCompareRecord.setIntonation(this.intonation);
+            sysMusicCompareRecord.setCadence(this.cadence);
+            sysMusicCompareRecord.setIntegrity(this.integrity);
+            sysMusicCompareRecord.setRecordFilePath(this.recordFilePath);
+            sysMusicCompareRecord.setVideoFilePath(this.videoFilePath);
+            sysMusicCompareRecord.setClientId(this.clientType!=null?this.clientType.toLowerCase():null);
+            sysMusicCompareRecord.setDeviceType(DeviceTypeEnum.valueOf(this.deviceType));
+            sysMusicCompareRecord.setSourceTime(this.sourceTime);
+            sysMusicCompareRecord.setPlayTime(this.playTime);
+            sysMusicCompareRecord.setSpeed(this.speed!=null?Integer.parseInt(this.speed):90);
+            sysMusicCompareRecord.setMonday(this.monday);
+            sysMusicCompareRecord.setFeature(this.feature!=null? FeatureType.format(this.feature):null);
+            sysMusicCompareRecord.setHeardLevel(this.heardLevel!=null? HeardLevelEnum.valueOf(this.heardLevel):null);
+            sysMusicCompareRecord.setCreateTime(this.createTime);
+            sysMusicCompareRecord.setPartIndex(this.partIndex);
+            sysMusicCompareRecord.setCustomConfiguration(this.customConfiguration);
+            sysMusicCompareRecord.setPracticeTime(this.practiceTime);
+            sysMusicCompareRecord.setPracticeSource(this.practiceSource);
+            sysMusicCompareRecord.setResultAnalyze(this.resultAnalyze);
+            sysMusicCompareRecord.setHeadphoneFlag(this.headphoneFlag);
+            sysMusicCompareRecord.setInstrumentId(this.instrumentId!=null?Long.parseLong(this.instrumentId):null);
+            sysMusicCompareRecord.setDelFlag(this.delFlag);
+            sysMusicCompareRecord.setPlayRate(this.playRate);
+
+            return sysMusicCompareRecord;
+
+        }
+    }
+}

+ 132 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/MusicSheetAccompanimentWrapper.java

@@ -0,0 +1,132 @@
+package com.ym.mec.biz.dal.wrapper;
+
+import com.alibaba.fastjson.JSON;
+import com.microsvc.toolkit.common.response.paging.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-07 10:16:58
+ */
+@ApiModel(value = "MusicSheetAccompanimentWrapper对象", description = "曲谱伴奏表查询对象")
+public class MusicSheetAccompanimentWrapper {
+
+    @Data
+	@Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" MusicSheetAccompanimentQuery-曲谱伴奏表")
+    public static class MusicSheetAccompanimentQuery implements QueryInfo {
+
+    	@ApiModelProperty("当前页")
+        private Integer page;
+
+        @ApiModelProperty("分页行数")
+        private Integer rows;
+
+        @ApiModelProperty("关键字匹配")
+		private String keyword;
+
+        public String getKeyword() {
+            return Optional.ofNullable(keyword).filter(StringUtils::isNotBlank).orElse(null);
+        }
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicSheetAccompanimentQuery from(String json) {
+            return JSON.parseObject(json, MusicSheetAccompanimentQuery.class);
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+	@ApiModel(" MusicSheetAccompaniment-曲谱伴奏表")
+    public static class MusicSheetAccompaniment {
+
+        @ApiModelProperty("主键")
+        private Long id;
+
+        @ApiModelProperty("曲谱ID")
+        private Long musicId;
+
+        @ApiModelProperty("声部")
+        private String musicSubject;
+
+        @ApiModelProperty("MP3原声音频文件URL")
+        private String audioFileUrl;
+
+        @ApiModelProperty("map节拍器伴奏")
+        private String metronomeUrl;
+
+        @ApiModelProperty("伴奏轨迹")
+        private String track;
+
+        @ApiModelProperty("排序号")
+        private Boolean sortNumber;
+
+        @ApiModelProperty("速度")
+        private String speed;
+
+        @ApiModelProperty("曲目缓存")
+        private String musicSvg;
+
+        @ApiModelProperty("创建人(老师或者是后台平台用户)")
+        private Long createBy;
+
+        @ApiModelProperty("创建时间")
+        private Date createTime;
+
+        @ApiModelProperty("五线谱PDF文件")
+        private String musicPdfUrl;
+
+
+        @ApiModelProperty("首调PDF文件")
+        private String firstPdfUrl;
+
+
+        @ApiModelProperty("固定调PDF文件")
+        private String jianPdfUrl;
+
+
+        @ApiModelProperty("音频类型,SING:演唱,PLAY:演奏")
+        private String audioPlayType;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static MusicSheetAccompaniment from(String json) {
+            return JSON.parseObject(json, MusicSheetAccompaniment.class);
+        }
+
+
+        public MusicSheetAccompaniment musicId(Long musicId) {
+            this.musicId = musicId;
+            return this;
+        }
+
+        public MusicSheetAccompaniment musicSubject(String musicSubject) {
+            this.musicSubject = musicSubject;
+            return this;
+        }
+
+        public MusicSheetAccompaniment createBy(Long createBy) {
+            this.createBy = createBy;
+            return this;
+        }
+    }
+
+}

+ 38 - 3
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/MusicSheetWrapper.java

@@ -1,4 +1,4 @@
-package com.dayaedu.cbs.domain.wrapper;
+package com.ym.mec.biz.dal.wrapper;
 
 import com.alibaba.fastjson.JSON;
 import com.dayaedu.cbs.common.enums.music.*;
@@ -55,9 +55,44 @@ public class MusicSheetWrapper {
         }
     }
 
-	@ApiModel(" MusicSheet-曲谱表")
+    @Data
+    @ApiModel(" MusicSheet-曲谱表")
     public static class MusicSheet {
 
+        @ApiModelProperty("主键")
+        private String id;
+
+        @ApiModelProperty("曲谱分类")
+        private Integer musicSheetCategoriesId;
+
+        @ApiModelProperty("曲谱名称")
+        private String musicSheetName;
+
+
+        @ApiModelProperty("封面图")
+        private String titleImg;
+
+
+
+        @ApiModelProperty("作曲人")
+        private String composer;
+
+
+        @ApiModelProperty("内容平台曲目ID")
+        private String cbsMusicSheetId;
+
+
+
+        @ApiModelProperty("被使用次数")
+        private Long usedNum;
+
+        @ApiModelProperty("收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费)")
+        private String paymentType;
+
+
+        @ApiModelProperty("音频类型,SING:演唱,PLAY:演奏")
+        private String audioPlayTypes;
+
         public String jsonString() {
             return JSON.toJSONString(this);
         }
@@ -65,7 +100,7 @@ public class MusicSheetWrapper {
         public static MusicSheet from(String json) {
             return JSON.parseObject(json, MusicSheet.class);
         }
-	}
+    }
 
     @Data
     @ApiModel(" AddMusicSheet-曲谱新增/修改表")

+ 14 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/UserMusicWrapper.java

@@ -51,6 +51,11 @@ public class UserMusicWrapper {
         @ApiModelProperty(value = "id",hidden = true)
         private Long id;
 
+        @ApiModelProperty("文件类型 音频 AUDIO,视频:VIDEO")
+        private String fileType;
+
+        @ApiModelProperty("关联练习数据ID")
+        private Long musicPracticeRecordId;
 
         @ApiModelProperty(value = "去除的ID,推荐作品列表需要去除原本作品")
         private Long exclusionId;
@@ -140,6 +145,9 @@ public class UserMusicWrapper {
         private String videoUrl;
 
 
+        @ApiModelProperty("文件类型") // .mp4 视频,其他为音频
+        private String fileType;
+
         @ApiModelProperty("录音文件地址")
         private String recordFilePath;
 
@@ -162,6 +170,9 @@ public class UserMusicWrapper {
         @ApiModelProperty("发布作品时间")
         private Date submitTime;
 
+        @ApiModelProperty("是否能被看到评级、评分字段")
+        private Boolean selectFlag;
+
         @ApiModelProperty("录制上传时间")
         private Date createTime;
 
@@ -221,6 +232,9 @@ public class UserMusicWrapper {
         @ApiModelProperty("json配置")
         private String jsonConfig;
 
+        @ApiModelProperty("是否能被看到评级、评分字段")
+        private Boolean selectFlag;
+
     }
 
 }

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

@@ -53,7 +53,7 @@ public interface InstrumentService extends IService<Instrument>  {
 
     List<InstrumentWrapper.Instrument> getList(InstrumentWrapper.InstrumentQuery query);
 
-    List<Integer> getInstrumentIdsBySubjectId(Integer subjectId);
+    List<Instrument> getInstrumentIdsBySubjectId(String subjectId);
 
     void modify(InstrumentWrapper.Update update);
 }

+ 31 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/MusicPracticeRecordService.java

@@ -0,0 +1,31 @@
+package com.ym.mec.biz.service;
+
+import com.ym.mec.biz.dal.wrapper.MusicPracticeRecordWrapper;
+
+public interface MusicPracticeRecordService {
+
+    /**
+     * 查询记录详情
+     */
+    MusicPracticeRecordWrapper.Entity detail(Long id);
+
+    /**
+     * 添加记录
+     */
+    String add(MusicPracticeRecordWrapper.MusicPracticeRecord from);
+
+
+    Object getLastEvaluationMusicalNotesPlayStats(Long recordId);
+
+    /**
+     * 查询记录
+     *
+     */
+    MusicPracticeRecordWrapper.Entity getById(Long id);
+
+    /**
+     * 更新练习记录
+     *
+     */
+    void update(MusicPracticeRecordWrapper.Entity practiceRecord);
+}

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

@@ -8,8 +8,8 @@ import com.ym.mec.biz.dal.page.MusicCompareRecordWapper;
 import com.ym.mec.biz.dal.page.SysMusicCompareRecordQueryInfo;
 import com.ym.mec.biz.dal.page.TeacherCloudTrainingQueryInfo;
 import com.ym.mec.common.page.PageInfo;
-import com.ym.mec.common.page.QueryInfo;
 import com.ym.mec.common.service.BaseService;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Map;
@@ -35,6 +35,9 @@ public interface SysMusicCompareRecordService extends BaseService<Long, SysMusic
      */
     void saveMusicCompareData(SysMusicCompareRecord sysMusicCompareRecord);
 
+    @Transactional
+    long insertMusicCompareData(SysMusicCompareRecord sysMusicCompareRecord);
+
     /**
      * @describe 用户最后一次评测数据
      * @author Joburgess

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

@@ -4,7 +4,6 @@ package com.ym.mec.biz.service;
 import java.util.List;
 import java.util.Map;
 
-import com.dayaedu.cbs.domain.wrapper.MusicSheetWrapper;
 import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
 import com.dayaedu.cbs.openfeign.wrapper.musicInstrument.CbsMusicalInstrumentWrapper;
 import com.ym.mec.biz.dal.dao.SysMusicScoreDao;
@@ -12,6 +11,7 @@ import com.ym.mec.biz.dal.dto.MusicScoreDto;
 import com.ym.mec.biz.dal.dto.ReasonDto;
 import com.ym.mec.biz.dal.entity.SysMusicScore;
 import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
+import com.ym.mec.biz.dal.wrapper.MusicSheetWrapper;
 import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.BaseService;
 
@@ -47,4 +47,19 @@ public interface SysMusicScoreService extends BaseService<Integer, SysMusicScore
     void sync();
 
     void del(Long id);
+
+    /**
+     * 查询总控平台曲目信息
+     * @param musicSheetId 业务端曲目ID
+     * @return CbsMusicSheetWrapper.MusicSheet
+     */
+    CbsMusicSheetWrapper.MusicSheet cbsDetail(Integer musicSheetId);
+
+    /**
+     * 查询总控平台曲目信息
+     * @param cbsMusicSheetId 总控平台曲目ID
+     * @return CbsMusicSheetWrapper.MusicSheet
+     */
+    CbsMusicSheetWrapper.MusicSheet getCbsMusicSheetByCbsId(Long cbsMusicSheetId);
+
 }

+ 7 - 5
mec-biz/src/main/java/com/ym/mec/biz/service/impl/InstrumentServiceImpl.java

@@ -14,6 +14,7 @@ import com.ym.mec.biz.dal.wrapper.InstrumentWrapper;
 import com.ym.mec.biz.service.InstrumentService;
 import com.ym.mec.biz.service.SubjectService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
@@ -36,6 +37,9 @@ public class InstrumentServiceImpl extends ServiceImpl<InstrumentDao, Instrument
     @Resource
     private SubjectService subjectService;
 
+    @Autowired
+    private InstrumentDao instrumentDao;
+
     /**
      * 查询详情
      *
@@ -189,14 +193,12 @@ public class InstrumentServiceImpl extends ServiceImpl<InstrumentDao, Instrument
     }
 
     @Override
-    public List<Integer> getInstrumentIdsBySubjectId(Integer subjectId) {
-        List<Instrument> list = this.lambdaQuery()
-            .eq(Instrument::getSubjectId, subjectId)
-            .list();
+    public List<Instrument> getInstrumentIdsBySubjectId(String subjectId) {
+        List<Instrument> list = instrumentDao.getBySubjectId(subjectId);
         if (CollectionUtils.isEmpty(list)) {
             return new ArrayList<>();
         }
-        return list.stream().map(Instrument::getId).collect(Collectors.toList());
+        return list;
     }
 
     @Override

+ 122 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicPracticeRecordServiceImpl.java

@@ -0,0 +1,122 @@
+package com.ym.mec.biz.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ym.mec.biz.dal.dao.SysMusicCompareRecordDao;
+import com.ym.mec.biz.dal.dao.SysMusicScoreDao;
+import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
+import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.enums.FeatureType;
+import com.ym.mec.biz.dal.wrapper.MusicPracticeRecordWrapper;
+import com.ym.mec.biz.service.MusicPracticeRecordService;
+import com.ym.mec.biz.service.SysMusicCompareRecordService;
+import com.ym.mec.biz.service.SysMusicScoreService;
+import com.ym.mec.common.exception.BizException;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.Objects;
+
+@Service
+public class MusicPracticeRecordServiceImpl implements MusicPracticeRecordService {
+
+    @Autowired
+    private SysMusicCompareRecordService sysMusicCompareRecordService;
+
+    @Autowired
+    private SysMusicScoreService musicSheetService;
+
+    @Autowired
+    private SysMusicCompareRecordDao sysMusicCompareRecordDao;
+
+    /**
+     * 查询记录详情
+     *
+     * @param id
+     */
+    @Override
+    public MusicPracticeRecordWrapper.Entity detail(Long id) {
+        SysMusicCompareRecord sysMusicCompareRecord = sysMusicCompareRecordService.get(id);
+        if (sysMusicCompareRecord == null) {
+            throw new BizException("记录不存在");
+        }
+        return MusicPracticeRecordWrapper.Entity.toEntity(sysMusicCompareRecord);
+
+    }
+
+    /**
+     * 添加记录
+     *
+     * @param from
+     */
+    @Override
+    public String add(MusicPracticeRecordWrapper.MusicPracticeRecord from) {
+
+
+        // 曲目练习记录
+        from.setCreateTime(new Date());
+        MusicPracticeRecordWrapper.Entity musicPracticeRecord = JSON.parseObject(from.initDefaultValue().jsonString(),
+            MusicPracticeRecordWrapper.Entity.class);
+        SysMusicCompareRecord sysMusicCompareRecord = musicPracticeRecord.toSysMusicCompareRecord();
+        Long id = null;
+        if (sysMusicCompareRecord.getFeature() == FeatureType.CLOUD_STUDY_EVALUATION) {
+            id = sysMusicCompareRecordService.insertMusicCompareData(sysMusicCompareRecord);
+        } else {
+            id = sysMusicCompareRecordService.insert(sysMusicCompareRecord);
+        }
+
+        return String.valueOf(id);
+    }
+
+    @Override
+    public Object getLastEvaluationMusicalNotesPlayStats(Long recordId) {
+        MusicPracticeRecordWrapper.Entity userLastEvaluationData = detail(recordId);
+        if(Objects.isNull(userLastEvaluationData)){
+            return null;
+        }
+        if(StringUtils.isBlank(userLastEvaluationData.getScoreData())){
+            return null;
+        }
+
+        JSONObject jsonObject = JSON.parseObject(userLastEvaluationData.getScoreData());
+        jsonObject.put("recordId", userLastEvaluationData.getId());
+        jsonObject.put("score", userLastEvaluationData.getScore());
+        jsonObject.put("cadence", userLastEvaluationData.getCadence());
+        jsonObject.put("intonation", userLastEvaluationData.getIntonation());
+        jsonObject.put("integrity", userLastEvaluationData.getIntegrity());
+        jsonObject.put("heardLevel", userLastEvaluationData.getHeardLevel());
+        jsonObject.put("videoFilePath", userLastEvaluationData.getVideoFilePath());
+        jsonObject.put("partIndex", userLastEvaluationData.getPartIndex());
+        jsonObject.put("customConfiguration", userLastEvaluationData.getCustomConfiguration());
+
+        SysMusicScore sysMusicScore = musicSheetService.get(Integer.parseInt(userLastEvaluationData.getMusicSheetId()));
+        if(Objects.nonNull(sysMusicScore)){
+            jsonObject.put("sysMusicScoreName", sysMusicScore.getName());
+        }
+        return jsonObject;
+    }
+
+    /**
+     * 查询记录
+     *
+     * @param id
+     */
+    @Override
+    public MusicPracticeRecordWrapper.Entity getById(Long id) {
+        return detail(id);
+    }
+
+    /**
+     * 更新练习记录
+     *
+     * @param practiceRecord
+     */
+    @Override
+    public void update(MusicPracticeRecordWrapper.Entity practiceRecord) {
+
+        SysMusicCompareRecord sysMusicCompareRecord = practiceRecord.toSysMusicCompareRecord();
+        sysMusicCompareRecordService.update(sysMusicCompareRecord);
+    }
+}

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

@@ -93,7 +93,9 @@ public class SysMusicCompareRecordServiceImpl extends BaseServiceImpl<Long, SysM
 
 			updateCampData(bean);
 		}
-		return insert;
+
+        return sysMusicCompareRecordDao.getLastData(bean.getClientId(),bean.getUserId()
+            ,bean.getFeature().getCode(),bean.getSysMusicScoreId());
 	}
 
     @Override
@@ -165,6 +167,22 @@ public class SysMusicCompareRecordServiceImpl extends BaseServiceImpl<Long, SysM
 				.updateUserWeekTrainData(userId, LocalDate.now().with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()));
 	}
 
+    @Override
+    @Transactional
+    public long insertMusicCompareData(SysMusicCompareRecord sysMusicCompareRecord) {
+
+        Integer userId = sysMusicCompareRecord.getUserId();
+
+        sysMusicCompareRecordDao.insert(sysMusicCompareRecord);
+        Long id = sysMusicCompareRecordDao.getLastData(sysMusicCompareRecord.getClientId(),sysMusicCompareRecord.getUserId()
+            ,sysMusicCompareRecord.getFeature().getCode(),sysMusicCompareRecord.getSysMusicScoreId());
+        studentDao.addStudentCloudStudySequenceDays(userId);
+        updateCampData(sysMusicCompareRecord);
+        sysMusicCompareWeekDataService
+            .updateUserWeekTrainData(userId, LocalDate.now().with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()));
+        return id;
+    }
+
 	@Override
 	public JSONObject getLastEvaluationMusicalNotesPlayStats(Integer userId, Long recordId) {
 		SysMusicCompareRecord userLastEvaluationData;

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

@@ -9,7 +9,6 @@ import com.dayaedu.cbs.common.enums.music.EMusicAvailableType;
 import com.dayaedu.cbs.common.enums.music.EMusicPlayMode;
 import com.dayaedu.cbs.common.enums.music.EMusicSourceType;
 import com.dayaedu.cbs.common.enums.school.EMusicSheetType;
-import com.dayaedu.cbs.domain.wrapper.MusicSheetWrapper;
 import com.dayaedu.cbs.openfeign.client.MusicFeignClientService;
 import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetApplicationExtendClientWrapper;
 import com.dayaedu.cbs.openfeign.wrapper.music.CbsMusicSheetWrapper;
@@ -22,6 +21,7 @@ import com.ym.mec.biz.dal.dto.ReasonDto;
 import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.enums.YesOrNoEnum;
 import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
+import com.ym.mec.biz.dal.wrapper.MusicSheetWrapper;
 import com.ym.mec.biz.service.*;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.exception.BizException;
@@ -210,6 +210,9 @@ public class SysMusicScoreServiceImpl extends BaseServiceImpl<Integer, SysMusicS
 //            record.setMusicScoreCategoriesId(musicSheetApplication.getMusicSheetCategoryId().intValue());
 //            record.setCategoriesId(musicSheetApplication.getMusicSheetCategoryId().intValue());
 //        }
+        record.setAudioPlayTypes(musicSheetApplication.getAudioPlayTypes());
+        record.setTitleImg(musicSheetApplication.getMusicCover());
+        record.setComposer(musicSheetApplication.getComposer());
         record.setName(musicSheetApplication.getName());
         record.setCategoriesName(musicSheetApplication.getMusicSheetCategoryName());
         record.setSpeed(musicSheetApplication.getPlaySpeed());
@@ -590,4 +593,41 @@ public class SysMusicScoreServiceImpl extends BaseServiceImpl<Integer, SysMusicS
 
     }
 
+    /**
+     * @param musicSheetId 业务端曲目ID
+     * @return CbsMusicSheetWrapper.MusicSheet
+     */
+    @Override
+    public CbsMusicSheetWrapper.MusicSheet cbsDetail(Integer musicSheetId) {
+        // 曲目信息
+        SysMusicScore musicSheet = getDao().get(musicSheetId);
+        if (Objects.isNull(musicSheet)) {
+            throw new BizException("曲目信息不存在");
+        }
+
+
+        if (StringUtils.isBlank(musicSheet.getCbsMusicSheetId())) {
+            throw new BizException("曲目信息异常");
+        }
+        return getCbsMusicSheetByCbsId(Long.parseLong(musicSheet.getCbsMusicSheetId()));
+    }
+
+    /**
+     * 查询总控平台曲目信息
+     *
+     * @param cbsMusicSheetId 总控平台曲目ID
+     * @return CbsMusicSheetWrapper.MusicSheet
+     */
+    @Override
+    public CbsMusicSheetWrapper.MusicSheet getCbsMusicSheetByCbsId(Long cbsMusicSheetId) {
+        try {
+
+            R<CbsMusicSheetWrapper.MusicSheet> musicSheetR = musicFeignClientService.musicSheetDetail(cbsMusicSheetId, applicationId);
+
+            return musicSheetR.feignData();
+        } catch (Exception e) {
+            log.error("调用音乐服务异常", e);
+            throw new BizException("内容平台服务异常");
+        }
+    }
 }

+ 12 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/impl/UserMusicServiceImpl.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.alipay.service.schema.util.StringUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import com.microsvc.toolkit.common.webportal.exception.BizException;
 import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
 import com.ym.mec.auth.api.entity.SysUser;
@@ -71,6 +72,7 @@ public class UserMusicServiceImpl extends ServiceImpl<UserMusicMapper, UserMusic
     private UserMusicMapper userMusicMapper;
 
 
+    private static  final List<String> videoList = Lists.newArrayList(".mp4");
     /**
      * 查询详情
      * @param id 详情ID
@@ -187,12 +189,20 @@ public class UserMusicServiceImpl extends ServiceImpl<UserMusicMapper, UserMusic
                 throw new BizException("已发布的作品不能修改为草稿");
             }
         }
-
+        Date date = new Date();
         if (entity.getType() == null) {
         } else if (entity.getType().equals(EUserMusicType.DRAFT)) {
             entity.setSubmitTime(null);
         } else if (old == null || old.getType().equals(EUserMusicType.DRAFT)) {
-            entity.setSubmitTime(new Date());
+            entity.setSubmitTime(date);
+        }
+        entity.setUpdateTime(date);
+        if (!StringUtil.isEmpty(entity.getVideoUrl())) {
+            if (videoList.stream().noneMatch(entity.getVideoUrl()::endsWith)) {
+                entity.setFileType("AUDIO");
+            } else {
+                entity.setFileType("VIDEO");
+            }
         }
         userMusicService.saveOrUpdate(entity);
         return entity.getId();

+ 6 - 0
mec-biz/src/main/resources/config/mybatis/InstrumentMapper.xml

@@ -36,4 +36,10 @@
         </where>
 	</select>
 
+    <select id="getBySubjectId" resultType="com.ym.mec.biz.dal.entity.Instrument">
+        SELECT
+            <include refid="baseColumns" />
+        FROM instrument t
+        WHERE find_in_set(t.subject_id_, #{subjectId})
+    </select>
 </mapper>

+ 1 - 0
mec-biz/src/main/resources/config/mybatis/SubjectMapper.xml

@@ -15,6 +15,7 @@
         <result column="img_" property="img"/>
         <result column="create_time_" property="createTime"/>
         <result column="update_time_" property="updateTime"/>
+        <result column="instrumentIds" property="instrumentIds"/>
         <result column="del_flag_" property="delFlag" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
     </resultMap>
 

+ 46 - 2
mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml

@@ -32,6 +32,15 @@
 		<result column="part_index_" property="partIndex" />
         <result column="tenant_id_" property="tenantId"/>
         <result column="subject_id_" property="subjectId"/>
+        <result column="custom_configuration_" property="customConfiguration"/>
+        <result column="practice_time_" property="practiceTime"/>
+        <result column="practice_source_" property="practiceSource"/>
+        <result column="result_analyze_" property="resultAnalyze"/>
+        <result column="headphone_flag_" property="headphoneFlag"/>
+        <result column="instrument_id_" property="instrumentId"/>
+        <result column="hidden_flag_" property="hiddenFlag"/>
+        <result column="del_flag_" property="delFlag"/>
+        <result column="play_rate_" property="playRate"/>
 	</resultMap>
 
 	<!-- 根据主键查询一条记录 -->
@@ -48,11 +57,13 @@
 	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.SysMusicCompareRecord" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
 		INSERT INTO sys_music_compare_record (id_,user_id_,sys_music_score_id_,heard_level_,behavior_id_,score_data_,score_,intonation_,cadence_,integrity_,
 		                                      record_file_path_,video_file_path_,device_type_,client_id_,play_time_,speed_,monday_,
-												source_time_,feature_,create_time_,create_date_,update_time_,part_index_,tenant_id_,subject_id_)
+												source_time_,feature_,create_time_,create_date_,update_time_,part_index_,tenant_id_,subject_id_,
+        custom_configuration_,practice_time_,practice_source_,result_analyze_,headphone_flag_,instrument_id_,hidden_flag_,del_flag_,play_rate_)
 		VALUES(#{id},#{userId},#{sysMusicScoreId},#{heardLevel,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{behaviorId},#{scoreData},
 		       #{score},#{intonation},#{cadence},#{integrity},
 		       #{recordFilePath},#{videoFilePath},#{deviceType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{clientId},#{playTime},#{speed},#{monday},
-		       #{sourceTime},#{feature,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}, #{createTime}, #{createDate}, NOW(),#{partIndex},#{tenantId},#{subjectId})
+		       #{sourceTime},#{feature,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}, #{createTime}, #{createDate}, NOW(),#{partIndex},#{tenantId},#{subjectId}
+            ,#{customConfiguration},#{practiceTime},#{practiceSource},#{resultAnalyze},#{headphoneFlag},#{instrumentId},#{hiddenFlag},#{delFlag},#{playRate})
 	</insert>
 	<insert id="init">
 		insert into sys_music_compare_day_data (user_id_, day_, train_num_, train_time_, tenant_id_)
@@ -125,6 +136,33 @@
 		<if test="heardLevel!=null">
 			heard_level_ = #{heardLevel,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},
 		</if>
+        <if test="customConfiguration != null and customConfiguration != ''">
+            custom_configuration_ = #{customConfiguration},
+        </if>
+        <if test="practiceSource != null and practiceSource != ''">
+            practice_source_ = #{practiceSource},
+        </if>
+        <if test="practiceSource != null and practiceSource != ''">
+            practice_time_ = #{practiceTime},
+        </if>
+        <if test="resultAnalyze != null and resultAnalyze != ''">
+            result_analyze_ = #{resultAnalyze},
+        </if>
+        <if test="headphoneFlag != null">
+            headphone_flag_ = #{headphoneFlag},
+        </if>
+        <if test="instrumentId != null">
+            instrument_id_ = #{instrumentId},
+        </if>
+        <if test="hiddenFlag != null">
+            hidden_flag_ = #{hiddenFlag},
+        </if>
+        <if test="delFlag != null">
+            del_flag_ = #{delFlag},
+        </if>
+        <if test="playRate != null">
+            play_rate_ = #{playRate},
+        </if>
 		update_time_ = NOW()
 	</set> WHERE id_ = #{id} and tenant_id_ = #{tenantId}
 	</update>
@@ -597,4 +635,10 @@
 		<include refid="queryPageByStudentSql"/>
 		order by mcr.create_date_ DESC
 	</select>
+
+	<select id="getLastData" resultType="java.lang.Long">
+        select id_ from sys_music_compare_record
+        where client_id_ =#{clientId} and user_id_ = #{userId} and feature_ = #{feature} and sys_music_score_id_ = #{sysMusicScoreId}
+        order by  create_time_ desc,id_ desc   limit 1
+    </select>
 </mapper>

+ 2 - 1
mec-biz/src/main/resources/config/mybatis/SysMusicScoreAccompanimentMapper.xml

@@ -154,8 +154,9 @@
 		<include refid="queryPageSql"/>
 	</select>
     <select id="querySubjectIds" resultMap="com.ym.mec.biz.dal.dao.SubjectDao.Subject">
-		SELECT s.* FROM sys_music_score sms
+		SELECT s.*,i.id_ as instrumentIds FROM sys_music_score sms
 		LEFT JOIN `subject` s ON FIND_IN_SET(s.id_,sms.subject_ids_)
+        left join instrument i on i.subject_id_ = s.id_
 		WHERE sms.del_flag_ = 0 AND sms.cbs_music_sheet_id_ IS NOT NULL AND s.id_ IS NOT NULL
 		<if test="categoriesIdList != null and categoriesIdList.size > 0">
 			AND sms.cbs_music_categories_id_ IN

+ 14 - 1
mec-biz/src/main/resources/config/mybatis/SysMusicScoreMapper.xml

@@ -146,9 +146,16 @@
 		SELECT ses.*,su.real_name_ create_user_name_,ses.cbs_music_categories_id_ categories_id_,ses.subject_ids_
 		FROM sys_music_score ses
 		LEFT JOIN sys_user su ON ses.create_user_id_ = su.id_
+        <if test="recentFlag !=null and recentFlag == true">
+            right JOIN sys_music_compare_record sms ON ses.id_ = sms.sys_music_score_id_ and sms.user_id_ = #{userId} and sms.client_id_ = #{clientId}
+        </if>
 		<include refid="queryPageSql"/>
 		GROUP BY ses.id_
-		ORDER BY ses.cbs_music_categories_id_ DESC,ses.order_ ASC,ses.create_time_ DESC,ses.id_ desc
+        order by
+        <if test="recentFlag !=null and recentFlag == true">
+             max(sms.create_time_) desc,
+        </if>
+		 ses.cbs_music_categories_id_ DESC,ses.order_ ASC,ses.create_time_ DESC,ses.id_ desc
 		<include refid="global.limit"/>
 	</select>
 	
@@ -267,6 +274,9 @@
 			<if test="search != null and search != ''">
 				AND (ses.cbs_music_sheet_id_ = #{search} OR ses.name_ LIKE CONCAT('%',#{search},'%'))
 			</if>
+            <if test="name != null and name != ''">
+                AND ses.name_ LIKE CONCAT('%',#{name},'%')
+            </if>
 			<if test="showFlag != null">
 				AND ses.show_flag_ = #{showFlag}
 			</if>
@@ -320,6 +330,9 @@
 					AND ses.create_user_id_ = #{createUserId}
 				</if>
 			</if>
+            <if test="excludeMusicId !=null">
+                AND ses.id_ != #{excludeMusicId}
+            </if>
 		</where>
 	</sql>
 </mapper>

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

@@ -21,6 +21,8 @@
                t.del_flag_,
                t.expire_flag_,
                t.submit_time_,
+                t.select_flag_,
+                t.file_type_ ,
                t.update_time_ as createTime
 		FROM user_music t
         left join sys_music_score t1 on t1.id_ = t.music_sheet_id_
@@ -44,6 +46,12 @@
             <if test="param.exclusionId != null">
                 and t.id_ != #{param.exclusionId}
             </if>
+            <if test="param.fileType != null">
+                and t.file_type_ = #{param.fileType}
+            </if>
+            <if test="param.musicPracticeRecordId != null">
+                and t.music_practice_record_id_ = #{param.musicPracticeRecordId}
+            </if>
         </where>
         <if test="param.sort != null">
             order by

+ 5 - 0
mec-common/common-core/src/main/java/com/ym/mec/common/config/LocalFastJsonHttpMessageConverter.java

@@ -6,6 +6,7 @@ import java.lang.reflect.Type;
 import java.math.BigDecimal;
 import java.util.Date;
 
+import com.microsvc.toolkit.common.enums.ConverterEnum;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.http.HttpInputMessage;
 import org.springframework.http.HttpOutputMessage;
@@ -69,6 +70,10 @@ class EnumFilter implements ValueFilter {
 		if (BaseEnum.class.isAssignableFrom(value.getClass())) {
 			return ((BaseEnum<?, ?>) value).getCode();
 		}
+		// ConverterEnum枚举映射转换
+		if (ConverterEnum.class.isAssignableFrom(value.getClass())) {
+			return ((ConverterEnum<?>) value).getCode();
+		}
 		return value;
 	}
 }