浏览代码

Merge branch 'online1' into oa_fea

river 4 年之前
父节点
当前提交
3426aa2a8f
共有 47 个文件被更改,包括 1611 次插入614 次删除
  1. 11 3
      mec-biz/src/main/java/com/ym/mec/biz/dal/config/NioAudioInputStream.java
  2. 0 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/config/SoundCompareConfig.java
  3. 4 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CloudTeacherOrderDao.java
  4. 2 2
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentExtracurricularExercisesSituationDao.java
  5. 11 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/CourseHomeworkStudentDetailDto.java
  6. 68 7
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/SoundCompareHelper.java
  7. 57 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicCompareRecord.java
  8. 12 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysSuggestion.java
  9. 35 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/DeviceTypeEnum.java
  10. 27 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/FeatureType.java
  11. 23 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/PayStatus.java
  12. 34 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/SuggestionType.java
  13. 54 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/SysSuggestionQueryInfo.java
  14. 34 443
      mec-biz/src/main/java/com/ym/mec/biz/handler/WebSocketHandler.java
  15. 3 0
      mec-biz/src/main/java/com/ym/mec/biz/service/CloudTeacherOrderService.java
  16. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/service/SoundSocketService.java
  17. 3 0
      mec-biz/src/main/java/com/ym/mec/biz/service/StudentPaymentOrderService.java
  18. 53 0
      mec-biz/src/main/java/com/ym/mec/biz/service/WebSocketEventHandler.java
  19. 6 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/CloudTeacherOrderServiceImpl.java
  20. 15 14
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/CourseScheduleServiceImpl.java
  21. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ExtracurricularExercisesReplyServiceImpl.java
  22. 65 27
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java
  23. 537 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SoundCompareHandler.java
  24. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentCourseHomeworkServiceImpl.java
  25. 16 4
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentInstrumentServiceImpl.java
  26. 8 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentManageServiceImpl.java
  27. 4 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentPaymentOrderDetailServiceImpl.java
  28. 46 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentPaymentOrderServiceImpl.java
  29. 89 40
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentRegistrationServiceImpl.java
  30. 23 22
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentServeServiceImpl.java
  31. 50 7
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SubjectChangeServiceImpl.java
  32. 14 4
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java
  33. 13 2
      mec-biz/src/main/resources/config/mybatis/CloudTeacherOrderMapper.xml
  34. 1 1
      mec-biz/src/main/resources/config/mybatis/StudentExtracurricularExercisesSituationMapper.xml
  35. 7 3
      mec-biz/src/main/resources/config/mybatis/StudentPaymentOrderMapper.xml
  36. 19 4
      mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml
  37. 31 4
      mec-biz/src/main/resources/config/mybatis/SysSuggestionMapper.xml
  38. 2 1
      mec-student/src/main/java/com/ym/mec/student/controller/MusicGroupController.java
  39. 6 4
      mec-student/src/main/java/com/ym/mec/student/controller/StudentManageController.java
  40. 48 0
      mec-student/src/main/java/com/ym/mec/student/controller/SysMusicCompareRecordController.java
  41. 6 0
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/SoundController.java
  42. 48 0
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/SysMusicCompareRecordController.java
  43. 6 0
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/TeacherManageController.java
  44. 28 0
      mec-web/src/main/java/com/ym/mec/web/controller/SoundCompareController.java
  45. 1 8
      mec-web/src/main/java/com/ym/mec/web/controller/StudentRegistrationController.java
  46. 40 10
      mec-web/src/main/java/com/ym/mec/web/controller/SysSuggestionController.java
  47. 48 0
      mec-web/src/main/java/com/ym/mec/web/controller/education/SysMusicCompareRecordController.java

+ 11 - 3
mec-biz/src/main/java/com/ym/mec/biz/dal/config/NioAudioInputStream.java

@@ -2,7 +2,9 @@ package com.ym.mec.biz.dal.config;
 
 import be.tarsos.dsp.io.TarsosDSPAudioFormat;
 import be.tarsos.dsp.io.TarsosDSPAudioInputStream;
+import org.springframework.stereotype.Component;
 
+import javax.sound.sampled.AudioFormat;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 
@@ -12,10 +14,15 @@ import java.io.RandomAccessFile;
  */
 public class NioAudioInputStream implements TarsosDSPAudioInputStream {
 
-    private final RandomAccessFile randomAccessFile;
+    private RandomAccessFile randomAccessFile;
+    private AudioFormat format;
 
-    public NioAudioInputStream(RandomAccessFile randomAccessFile) {
+    public NioAudioInputStream() {
+    }
+
+    public NioAudioInputStream(RandomAccessFile randomAccessFile, AudioFormat audioFormat) {
         this.randomAccessFile = randomAccessFile;
+        this.format = audioFormat;
     }
 
     @Override
@@ -35,7 +42,8 @@ public class NioAudioInputStream implements TarsosDSPAudioInputStream {
 
     @Override
     public TarsosDSPAudioFormat getFormat() {
-        TarsosDSPAudioFormat tarsosDSPFormat = new TarsosDSPAudioFormat(44100, 16, 1, false, true);
+        boolean isSigned = format.getEncoding() == AudioFormat.Encoding.PCM_SIGNED;
+        TarsosDSPAudioFormat tarsosDSPFormat = new TarsosDSPAudioFormat(format.getSampleRate(), format.getSampleSizeInBits(), format.getChannels(), isSigned, format.isBigEndian());
         return tarsosDSPFormat;
     }
 

+ 0 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/config/SoundCompareConfig.java

@@ -1,6 +1,5 @@
 package com.ym.mec.biz.dal.config;
 
-import be.tarsos.dsp.SilenceDetector;
 import be.tarsos.dsp.pitch.PitchProcessor;
 
 import javax.sound.sampled.AudioFormat;

+ 4 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CloudTeacherOrderDao.java

@@ -1,6 +1,8 @@
 package com.ym.mec.biz.dal.dao;
 
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import org.apache.ibatis.annotations.Param;
 
@@ -46,4 +48,6 @@ public interface CloudTeacherOrderDao extends BaseDAO<Long, CloudTeacherOrder> {
      * @return
      */
     CloudTeacherOrderDto queryOrderInfoByOrderId(Long orderId);
+
+    List<Map<Long, String>> queryNoStartByUserIds(@Param("userIds") Set<Integer> userIds);
 }

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

@@ -108,10 +108,10 @@ public interface StudentExtracurricularExercisesSituationDao extends BaseDAO<Lon
      * @describe 统计指定星期的服务记录数量
      * @author Joburgess
      * @date 2020/12/25 0025
-     * @param sunday:
+     * @param monday:
      * @return int
      */
-    int countWeekServiceNum(@Param("sunday") String sunday);
+    int countWeekServiceNum(@Param("monday") String monday);
 
     /**
      * @describe 获取指定周指定学员的服务指标

+ 11 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/CourseHomeworkStudentDetailDto.java

@@ -64,7 +64,6 @@ public class CourseHomeworkStudentDetailDto {
 
     private String type;
 
-    @ApiModelProperty(value = "是否有会员",required = false)
     private Integer hasMember;
 
     public Integer getHasMember() {
@@ -75,6 +74,17 @@ public class CourseHomeworkStudentDetailDto {
         this.hasMember = hasMember;
     }
 
+    @ApiModelProperty(value = "提交云教练的作业开关",required = false)
+    private Integer homeworkOpenFlag;
+
+    public Integer getHomeworkOpenFlag() {
+        return homeworkOpenFlag;
+    }
+
+    public void setHomeworkOpenFlag(Integer homeworkOpenFlag) {
+        this.homeworkOpenFlag = homeworkOpenFlag;
+    }
+
     public Integer getMusicScoreId() {
         return musicScoreId;
     }

+ 68 - 7
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/SoundCompareHelper.java

@@ -1,27 +1,45 @@
 package com.ym.mec.biz.dal.dto;
 
+import be.tarsos.dsp.AudioEvent;
 import be.tarsos.dsp.SilenceDetector;
+import be.tarsos.dsp.pitch.PitchDetectionHandler;
+import be.tarsos.dsp.pitch.PitchDetectionResult;
+import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
+import com.ym.mec.biz.service.impl.SoundCompareHandler;
 import io.swagger.annotations.ApiModelProperty;
+import org.springframework.util.CollectionUtils;
 
+import java.io.File;
 import java.io.RandomAccessFile;
 import java.math.BigDecimal;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @Author Joburgess
  * @Date 2021/6/22 0022
  */
-public class SoundCompareHelper {
+public class SoundCompareHelper implements PitchDetectionHandler {
+
+    @ApiModelProperty(value = "设备类型")
+    private DeviceTypeEnum deviceType;
 
     @ApiModelProperty(value = "伴奏编号")
     private Integer musicScoreId;
 
+    @ApiModelProperty(value = "声部编号")
+    private Integer subjectId;
+
     @ApiModelProperty(value = "小节开始时间")
     private double measureStartTime = 0;
 
     @ApiModelProperty
     private RandomAccessFile accessFile;
 
+    private File file;
+
     @ApiModelProperty(value = "录音文件地址")
     private String recordFilePath;
 
@@ -47,7 +65,7 @@ public class SoundCompareHelper {
 
     private List<MusicPitchDetailDto> musicXmlInfos;
 
-    private byte[] preDataArray = new byte[0];
+    private String clientId;
     /**
      * @describe 分贝检测器
      */
@@ -69,12 +87,20 @@ public class SoundCompareHelper {
         this.musicalNotePitchMap = musicalNotePitchMap;
     }
 
-    public byte[] getPreDataArray() {
-        return preDataArray;
+    public Integer getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(Integer subjectId) {
+        this.subjectId = subjectId;
     }
 
-    public void setPreDataArray(byte[] preDataArray) {
-        this.preDataArray = preDataArray;
+    public DeviceTypeEnum getDeviceType() {
+        return deviceType;
+    }
+
+    public void setDeviceType(DeviceTypeEnum deviceType) {
+        this.deviceType = deviceType;
     }
 
     public int getOffsetTime() {
@@ -97,6 +123,14 @@ public class SoundCompareHelper {
         return accessFile;
     }
 
+    public File getFile() {
+        return file;
+    }
+
+    public void setFile(File file) {
+        this.file = file;
+    }
+
     public String getRecordFilePath() {
         return recordFilePath;
     }
@@ -109,6 +143,14 @@ public class SoundCompareHelper {
         this.accessFile = accessFile;
     }
 
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
     public double getMeasureStartTime() {
         return measureStartTime;
     }
@@ -156,4 +198,23 @@ public class SoundCompareHelper {
     public void setUserMeasureScoreMap(Map<Integer, Map<String, Object>> userMeasureScoreMap) {
         this.userMeasureScoreMap = userMeasureScoreMap;
     }
+
+    @Override
+    public void handlePitch(PitchDetectionResult pitchDetectionResult, AudioEvent audioEvent) {
+        int timeStamp = (int) (measureStartTime + audioEvent.getTimeStamp()*1000);
+        float pitch = pitchDetectionResult.getPitch();
+        if(offsetTime == -1 && !DeviceTypeEnum.IOS.equals(deviceType) && pitch>0){
+            int preTimeStamp = CollectionUtils.isEmpty(recordMeasurePithInfo)?0:recordMeasurePithInfo.get(recordMeasurePithInfo.size()-1).getTimeStamp();
+            offsetTime = timeStamp - (timeStamp - preTimeStamp)/2;
+            for (Map.Entry<Integer, MusicPitchDetailDto> musicPitchDetailDtoEntry : measureEndTime.entrySet()) {
+                musicPitchDetailDtoEntry.getValue().setTimeStamp(musicPitchDetailDtoEntry.getValue().getTimeStamp() + offsetTime);
+                musicPitchDetailDtoEntry.getValue().setEndTimeStamp(musicPitchDetailDtoEntry.getValue().getEndTimeStamp() + offsetTime);
+            }
+        }
+        if(silenceDetector.currentSPL()< SoundCompareHandler.soundCompareConfig.validDb){
+            pitch = -1;
+        }
+//            LOGGER.info("时间:{}, 频率:{}, 分贝:{}", timeStamp, pitch, silenceDetecor.currentSPL());
+        recordMeasurePithInfo.add(new MusicPitchDetailDto(timeStamp, pitch, silenceDetector.currentSPL()));
+    }
 }

+ 57 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicCompareRecord.java

@@ -1,8 +1,13 @@
 package com.ym.mec.biz.dal.entity;
 
+import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
+import com.ym.mec.biz.dal.enums.FeatureType;
+import com.ym.mec.util.date.DateUtil;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
 import java.math.BigDecimal;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
 
 /**
  * 对应数据库表(sys_music_compare_record):
@@ -35,9 +40,20 @@ public class SysMusicCompareRecord {
 
 	/** 录音文件地址 */
 	private String recordFilePath;
+
+	/** 周一日期 */
+	private String monday = LocalDate.now().with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()).toString();
+
+	private FeatureType feature;
 	
 	/** 创建时间 */
 	private java.util.Date createTime;
+
+	private DeviceTypeEnum deviceType;
+
+	private float playTime = 0;
+
+	private String clientId;
 	
 	public void setId(Long id){
 		this.id = id;
@@ -54,7 +70,15 @@ public class SysMusicCompareRecord {
 	public Integer getUserId(){
 		return this.userId;
 	}
-			
+
+	public String getClientId() {
+		return clientId;
+	}
+
+	public void setClientId(String clientId) {
+		this.clientId = clientId;
+	}
+
 	public void setSysMusicScoreId(Integer sysMusicScoreId){
 		this.sysMusicScoreId = sysMusicScoreId;
 	}
@@ -111,6 +135,38 @@ public class SysMusicCompareRecord {
 		this.recordFilePath = recordFilePath;
 	}
 
+	public DeviceTypeEnum getDeviceType() {
+		return deviceType;
+	}
+
+	public void setDeviceType(DeviceTypeEnum deviceType) {
+		this.deviceType = deviceType;
+	}
+
+	public float getPlayTime() {
+		return playTime;
+	}
+
+	public void setPlayTime(float playTime) {
+		this.playTime = playTime;
+	}
+
+	public String getMonday() {
+		return monday;
+	}
+
+	public void setMonday(String monday) {
+		this.monday = monday;
+	}
+
+	public FeatureType getFeature() {
+		return feature;
+	}
+
+	public void setFeature(FeatureType feature) {
+		this.feature = feature;
+	}
+
 	public void setCreateTime(java.util.Date createTime){
 		this.createTime = createTime;
 	}

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysSuggestion.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.dal.entity;
 
+import com.ym.mec.biz.dal.enums.SuggestionType;
 import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
@@ -30,6 +31,9 @@ public class SysSuggestion {
 	@ApiModelProperty(value = "客户端类型",required = false)
 	private String clientType;
 
+	@ApiModelProperty(value = "建议类型")
+	private SuggestionType type = SuggestionType.APP;
+
 	@ApiModelProperty(value = "用户名",required = false)
 	private String username;
 	
@@ -92,6 +96,14 @@ public class SysSuggestion {
 		this.clientType = clientType;
 	}
 
+	public SuggestionType getType() {
+		return type;
+	}
+
+	public void setType(SuggestionType type) {
+		this.type = type;
+	}
+
 	public void setCreateTime(java.util.Date createTime){
 		this.createTime = createTime;
 	}

+ 35 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/DeviceTypeEnum.java

@@ -0,0 +1,35 @@
+package com.ym.mec.biz.dal.enums;
+
+import com.ym.mec.common.enums.BaseEnum;
+
+public enum DeviceTypeEnum implements BaseEnum<String, DeviceTypeEnum> {
+	IOS("IOS", "苹果"),
+	ANDROID("ANDROID", "安卓"),
+	WEB("WEB", "浏览器");
+
+	private String code;
+
+	private String msg;
+
+	DeviceTypeEnum(String code, String msg) {
+		this.code = code;
+		this.msg = msg;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	@Override
+	public String getCode() {
+		return this.code;
+	}
+}

+ 27 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/FeatureType.java

@@ -0,0 +1,27 @@
+package com.ym.mec.biz.dal.enums;
+
+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", "云教练评测");
+
+	private String code;
+
+	private String desc;
+
+	FeatureType(String code, String desc) {
+		this.code = code;
+		this.desc = desc;
+	}
+
+	@Override
+	public String getCode() {
+		return code;
+	}
+
+	public String getDesc() {
+		return desc;
+	}
+
+}

+ 23 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/PayStatus.java

@@ -0,0 +1,23 @@
+package com.ym.mec.biz.dal.enums;
+
+import com.ym.mec.common.enums.BaseEnum;
+
+public enum PayStatus implements BaseEnum<String, PayStatus> {
+
+	FAILED("支付失败"), WAIT_PAY("待支付"), PAYING("支付中"), SUCCESSED("支付成功");
+
+	private String desc;
+
+	private PayStatus(String desc) {
+		this.desc = desc;
+	}
+
+	@Override
+	public String getCode() {
+		return this.name();
+	}
+
+	public String getDesc() {
+		return desc;
+	}
+}

+ 34 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/SuggestionType.java

@@ -0,0 +1,34 @@
+package com.ym.mec.biz.dal.enums;
+
+import com.ym.mec.common.enums.BaseEnum;
+
+public enum SuggestionType implements BaseEnum<String, SuggestionType> {
+	APP("APP", "软件反馈"),
+	SMART_PRACTICE("SMART_PRACTICE", "智能陪练");
+
+	private String code;
+
+	private String msg;
+
+	SuggestionType(String code, String msg) {
+		this.code = code;
+		this.msg = msg;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	@Override
+	public String getCode() {
+		return this.code;
+	}
+}

+ 54 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/SysSuggestionQueryInfo.java

@@ -0,0 +1,54 @@
+package com.ym.mec.biz.dal.page;
+
+import com.ym.mec.biz.dal.enums.SuggestionType;
+import com.ym.mec.common.page.QueryInfo;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/10 0010
+ */
+public class SysSuggestionQueryInfo extends QueryInfo {
+
+    @ApiModelProperty(value = "建议类型")
+    private SuggestionType type;
+
+    private String startTime;
+
+    private String endTime;
+
+    @ApiModelProperty(value = "客户端类型",required = false)
+    private String clientType;
+
+    public SuggestionType getType() {
+        return type;
+    }
+
+    public void setType(SuggestionType type) {
+        this.type = type;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getClientType() {
+        return clientType;
+    }
+
+    public void setClientType(String clientType) {
+        this.clientType = clientType;
+    }
+}

+ 34 - 443
mec-biz/src/main/java/com/ym/mec/biz/handler/WebSocketHandler.java

@@ -1,34 +1,20 @@
 package com.ym.mec.biz.handler;
 
-import be.tarsos.dsp.AudioDispatcher;
-import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
-import be.tarsos.dsp.pitch.PitchProcessor;
-import be.tarsos.dsp.util.PitchConverter;
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.ym.mec.biz.dal.config.SoundCompareConfig;
-import com.ym.mec.biz.dal.dto.*;
+import com.ym.mec.biz.dal.dto.WebSocketClientDetail;
+import com.ym.mec.biz.dal.dto.WebSocketInfo;
 import com.ym.mec.biz.service.SoundSocketService;
-import com.ym.mec.biz.service.SysMusicCompareRecordService;
-import com.ym.mec.common.constant.CommonConstants;
-import org.apache.commons.io.FileUtils;
+import com.ym.mec.biz.service.WebSocketEventHandler;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
 import org.springframework.web.socket.*;
 import org.springframework.web.socket.handler.AbstractWebSocketHandler;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.Date;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
 
 /**
  * @Author Joburgess
@@ -37,35 +23,29 @@ import java.util.stream.Collectors;
 @Service
 public class WebSocketHandler extends AbstractWebSocketHandler {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class);
+    private final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class);
 
     /**
      * @describe 存储客户端链接
      */
     public static final Map<String, WebSocketClientDetail> WS_CLIENTS = new ConcurrentHashMap<>();
 
-    private BigDecimal oneHundred = new BigDecimal(100);
+    private static Map<String, WebSocketEventHandler> appMap = new ConcurrentHashMap<>();
 
-    private final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/";
-
-    /**
-     * @describe 用户对应评分信息
-     */
-    private Map<String, SoundCompareHelper> userSoundInfoMap = new ConcurrentHashMap<>();
     /**
-     * @describe 音频处理参数
+     * @describe 注册应用
+     * @author Joburgess
+     * @date 2021/8/5 0005
+     * @param tag:
+     * @param webSocketEventHandler:
+     * @return boolean
      */
-    private SoundCompareConfig soundCompareConfig = new SoundCompareConfig();
-
-    @Autowired
-    private SysMusicCompareRecordService sysMusicCompareRecordService;
-
-    public WebSocketHandler() {
-        super();
-        File soundDir = new File(tmpDir);
-        if(!soundDir.exists()){
-            soundDir.mkdir();
+    public static boolean regist(String tag, WebSocketEventHandler webSocketEventHandler){
+        if (appMap.containsKey(tag)){
+            return false;
         }
+        appMap.put(tag, webSocketEventHandler);
+        return true;
     }
 
     @Override
@@ -73,6 +53,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         String phone = session.getPrincipal().getName().split(":")[1];
         LOGGER.info("{}上线", phone);
         WS_CLIENTS.put(phone, new WebSocketClientDetail(session, new Date()));
+        appMap.values().forEach(e->e.afterConnectionEstablished(session, phone));
         super.afterConnectionEstablished(session);
     }
 
@@ -82,116 +63,25 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
     }
 
     @Override
-    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
+    protected void handleTextMessage(WebSocketSession session, TextMessage message){
         String phone = session.getPrincipal().getName().split(":")[1];
         LOGGER.info("{}: {}", phone, message.getPayload());
         WebSocketInfo webSocketInfo = JSON.parseObject(message.getPayload(), WebSocketInfo.class);
-        JSONObject bodyObject = (JSONObject) webSocketInfo.getBody();
-
-        String commond = "";
-        if(webSocketInfo.getHeader().containsKey(SoundSocketService.COMMOND)){
-            commond = webSocketInfo.getHeader().get(SoundSocketService.COMMOND);
+        String tag = "";
+        if(webSocketInfo.getHeader().containsKey(SoundSocketService.TAG)){
+            tag = webSocketInfo.getHeader().get(SoundSocketService.TAG);
         }
-        switch (commond){
-            case SoundSocketService.MUSIC_XML:
-                userSoundInfoMap.put(phone, new SoundCompareHelper());
-                List<MusicPitchDetailDto> musicXmlInfos = JSON.parseArray(bodyObject.getString("musicXmlInfos"), MusicPitchDetailDto.class);
-                userSoundInfoMap.get(phone).setMusicXmlInfos(musicXmlInfos);
-                musicXmlInfos = musicXmlInfos.stream().filter(m->!m.getDontEvaluating()).collect(Collectors.toList());
-                userSoundInfoMap.get(phone).setMusicScoreId(bodyObject.getInteger("id"));
-                userSoundInfoMap.get(phone).setMeasureXmlInfoMap(musicXmlInfos.stream().collect(Collectors.groupingBy(MusicPitchDetailDto::getMeasureIndex)));
-                musicXmlInfos.forEach(e->userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(e.getMusicalNotesIndex(), e.getFrequency()));
-                for (Map.Entry<Integer, List<MusicPitchDetailDto>> userMeasureXmlInfoEntry : userSoundInfoMap.get(phone).getMeasureXmlInfoMap().entrySet()) {
-                    MusicPitchDetailDto firstPitch = userMeasureXmlInfoEntry.getValue().stream().min(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get();
-                    MusicPitchDetailDto lastPitch = userMeasureXmlInfoEntry.getValue().stream().max(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get();
-                    long dc = userMeasureXmlInfoEntry.getValue().stream().filter(m -> m.getDontEvaluating()).count();
-                    MusicPitchDetailDto musicPitchDetailDto = new MusicPitchDetailDto(firstPitch.getTimeStamp(), lastPitch.getTimeStamp() + lastPitch.getDuration());
-                    musicPitchDetailDto.setDuration(musicPitchDetailDto.getEndTimeStamp()-musicPitchDetailDto.getTimeStamp());
-                    musicPitchDetailDto.setDontEvaluating(dc == userMeasureXmlInfoEntry.getValue().size());
-                    userSoundInfoMap.get(phone).getMeasureEndTime().put(userMeasureXmlInfoEntry.getKey(), musicPitchDetailDto);
-                }
-                break;
-            case SoundSocketService.RECORD_START:
-                if(!userSoundInfoMap.containsKey(phone)){
-                    break;
-                }
-                File file = new File(tmpDir+phone + "_"+ userSoundInfoMap.get(phone).getMusicScoreId() +"_"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +".wav");
-                userSoundInfoMap.get(phone).setAccessFile(new RandomAccessFile(file, "rw"));
-                userSoundInfoMap.get(phone).setRecordFilePath(file.getAbsolutePath());
-                break;
-            case SoundSocketService.RECORD_END:
-                if(!userSoundInfoMap.containsKey(phone)){
-                    break;
-                }
-                if(!CollectionUtils.isEmpty(userSoundInfoMap.get(phone).getMeasureEndTime())){
-                    Integer lastMeasureIndex = userSoundInfoMap.get(phone).getMeasureEndTime().keySet().stream().min(Integer::compareTo).get();
-                    double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
-                    //如果结束时时长大于某小节,则此小节需要评分
-                    if(recordTime>userSoundInfoMap.get(phone).getMeasureEndTime().get(lastMeasureIndex).getEndTimeStamp()){
-                        measureCompare(phone, lastMeasureIndex);
-                        userSoundInfoMap.get(phone).getMeasureEndTime().remove(lastMeasureIndex);
-                    }
-                }
-                calTotalScore(phone);
-                createHeader(phone);
-                break;
-            case SoundSocketService.RECORD_CANCEL:
-                createHeader(phone);
-                break;
-            case SoundSocketService.PROXY_MESSAGE:
-//                if(bodyObject.containsKey(SoundSocketService.OFFSET_TIME)){
-//                    int offsetTime = bodyObject.getIntValue(SoundSocketService.OFFSET_TIME);
-//                    calOffsetTime(phone, offsetTime);
-//                }
-                break;
-            default:
-                break;
+        if(StringUtils.isNotBlank(tag)){
+            appMap.get(tag).receiveTextMessage(session, phone, message);
+        }else{
+            appMap.values().forEach(e->e.receiveTextMessage(session, phone, message));
         }
     }
 
     @Override
-    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
+    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
         String phone = session.getPrincipal().getName().split(":")[1];
-        if(!userSoundInfoMap.containsKey(phone)){
-            return;
-        }
-        if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
-            userSoundInfoMap.get(phone).getAccessFile().write(message.getPayload().array());
-        }
-
-        AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), soundCompareConfig.audioFormat, soundCompareConfig.simpleSize, soundCompareConfig.overlap);
-        dispatcher.addAudioProcessor(userSoundInfoMap.get(phone).silenceDetector);
-        dispatcher.addAudioProcessor(new PitchProcessor(soundCompareConfig.algo, soundCompareConfig.simpleRate, soundCompareConfig.simpleSize, (pitchDetectionResult, audioEvent) -> {
-            int timeStamp = (int) (userSoundInfoMap.get(phone).getMeasureStartTime() + audioEvent.getTimeStamp()*1000);
-            float pitch = pitchDetectionResult.getPitch();
-            if(pitch>0 && userSoundInfoMap.get(phone).getOffsetTime() == -1){
-                int preTimeStamp = CollectionUtils.isEmpty(userSoundInfoMap.get(phone).getRecordMeasurePithInfo())?0:userSoundInfoMap.get(phone).getRecordMeasurePithInfo().get(userSoundInfoMap.get(phone).getRecordMeasurePithInfo().size()-1).getTimeStamp();
-                calOffsetTime(phone, timeStamp - (timeStamp - preTimeStamp)/2);
-            }
-            if(userSoundInfoMap.get(phone).silenceDetector.currentSPL()<soundCompareConfig.validDb){
-                pitch = -1;
-            }
-//            LOGGER.info("时间:{}, 频率:{}, 分贝:{}", timeStamp, pitch, silenceDetecor.currentSPL());
-            userSoundInfoMap.get(phone).getRecordMeasurePithInfo().add(new MusicPitchDetailDto(timeStamp, pitch, userSoundInfoMap.get(phone).silenceDetector.currentSPL()));
-        }));
-        dispatcher.run();
-        if(Objects.isNull(userSoundInfoMap.get(phone).getAccessFile())){
-            return;
-        }
-
-        double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
-        userSoundInfoMap.get(phone).setMeasureStartTime(recordTime);
-        for (Map.Entry<Integer, MusicPitchDetailDto> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
-            if(recordTime>(userMeasureEndTimeMapEntry.getValue().getEndTimeStamp())){
-                if(userMeasureEndTimeMapEntry.getValue().getDontEvaluating()){
-                    continue;
-                }else{
-                    measureCompare(phone, userMeasureEndTimeMapEntry.getKey());
-                }
-                userSoundInfoMap.get(phone).getMeasureEndTime().remove(userMeasureEndTimeMapEntry.getKey());
-                break;
-            }
-        }
+        appMap.values().forEach(e->e.receiveBinaryMessage(session, phone, message));
     }
 
     @Override
@@ -204,14 +94,13 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
     public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
         String phone = session.getPrincipal().getName().split(":")[1];
         session.close();
+        LOGGER.info("发生了错误,移除客户端: {}", phone);
+        appMap.values().forEach(e->e.afterConnectionClosed(session, phone));
+        exception.printStackTrace();
         if(!WS_CLIENTS.containsKey(phone)){
             return;
         }
-        exception.printStackTrace();
-        LOGGER.info("发生了错误,移除客户端: {}", phone);
         WS_CLIENTS.remove(phone);
-        userSoundInfoMap.remove(phone);
-        createHeader(phone);
     }
 
     @Override
@@ -219,310 +108,12 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         super.afterConnectionClosed(session, status);
         String phone = session.getPrincipal().getName().split(":")[1];
         LOGGER.info("{}离线", phone);
-        createHeader(phone);
+        appMap.values().forEach(e->e.afterConnectionClosed(session, phone));
         WS_CLIENTS.remove(phone);
-        userSoundInfoMap.remove(phone);
     }
 
     @Override
     public boolean supportsPartialMessages() {
         return super.supportsPartialMessages();
     }
-
-    /**
-     * @describe 处理时间偏移
-     * @author Joburgess
-     * @date 2021/7/5 0005
-     * @param phone:
-     * @param offsetTime:
-     * @return void
-     */
-    private void calOffsetTime(String phone, int offsetTime){
-        userSoundInfoMap.get(phone).setOffsetTime(offsetTime);
-        for (Map.Entry<Integer, MusicPitchDetailDto> musicPitchDetailDtoEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
-            musicPitchDetailDtoEntry.getValue().setTimeStamp(musicPitchDetailDtoEntry.getValue().getTimeStamp() + offsetTime);
-            musicPitchDetailDtoEntry.getValue().setEndTimeStamp(musicPitchDetailDtoEntry.getValue().getEndTimeStamp() + offsetTime);
-        }
-    }
-
-    /**
-     * @describe 保存录音数据,并生成wav头信息
-     * @author Joburgess
-     * @date 2021/6/25 0025
-     * @param phone:
-     * @return void
-     */
-    private void createHeader(String phone) throws IOException {
-        if(!userSoundInfoMap.containsKey(phone)){
-            return;
-        }
-        if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
-            RandomAccessFile randomAccessFile = userSoundInfoMap.get(phone).getAccessFile();
-            LOGGER.info("音频时长:{}", randomAccessFile.length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000);
-            randomAccessFile.seek(0);
-            randomAccessFile.write(WavHeader.getWaveHeader(randomAccessFile.length(), (long) soundCompareConfig.audioFormat.getFrameRate(), soundCompareConfig.audioFormat.getSampleSizeInBits()));
-            randomAccessFile.close();
-            userSoundInfoMap.get(phone).setAccessFile(null);
-        }
-//        userSoundInfoMap.get(phone).setRecordMeasurePithInfo(null);
-        userSoundInfoMap.remove(phone);
-    }
-
-    /**
-     * @describe 数据比对,生成分数
-     * @author Joburgess
-     * @date 2021/6/25 0025
-     * @param phone:
-     * @param measureIndex:
-     * @return void
-     */
-    private void measureCompare(String phone, int measureIndex) throws IOException {
-        if (userSoundInfoMap.get(phone).getOffsetTime() == -1){
-            userSoundInfoMap.get(phone).setOffsetTime(0);
-        }
-
-        //相似度
-        BigDecimal intonation = BigDecimal.ZERO;
-        //节奏
-        BigDecimal cadence = BigDecimal.ZERO;
-        //完整度
-        BigDecimal integrity = BigDecimal.ZERO;
-
-        try {
-            //音准分数
-            float intonationScore = 0;
-
-            //节奏匹配数量
-            float cadenceNum = 0;
-
-            //完整性分数
-            float integrityScore = 0;
-
-            int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size();
-
-            for (int i = 0; i < userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size(); i++) {
-                MusicPitchDetailDto musicXmlInfo = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).get(i);
-
-                int ot5 = (int) (musicXmlInfo.getDuration()*0.1);
-                int startTimeStamp = musicXmlInfo.getTimeStamp() + userSoundInfoMap.get(phone).getOffsetTime() + ot5;
-                int endTimeStamp = musicXmlInfo.getTimeStamp()  + userSoundInfoMap.get(phone).getOffsetTime() + musicXmlInfo.getDuration() - ot5;
-
-                //时间范围内有效节奏数量
-                float cadenceValidNum = 0;
-                //时间范围内有效音频数量
-                float integrityValidNum = 0;
-                //时间范围内匹配次数
-                float compareNum = 0;
-
-                List<MusicPitchDetailDto> measureSoundPitchInfos = new ArrayList<>();
-
-                for (int j = 0; j < userSoundInfoMap.get(phone).getRecordMeasurePithInfo().size(); j++) {
-                    MusicPitchDetailDto recordInfo = userSoundInfoMap.get(phone).getRecordMeasurePithInfo().get(j);
-                    //如果在时间范围之外直接跳过
-                    if(recordInfo.getTimeStamp()<startTimeStamp||recordInfo.getTimeStamp()>endTimeStamp){
-                        continue;
-                    }
-                    measureSoundPitchInfos.add(recordInfo);
-                    compareNum++;
-                    //如果在最低有效频率以下则跳过
-                    if(recordInfo.getFrequency()<soundCompareConfig.validFrequency&&musicXmlInfo.getFrequency()!=-1){
-                        continue;
-                    }
-                    cadenceValidNum++;
-                    //如果频率差值在节奏误差范围内
-                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=soundCompareConfig.integrityFrequencyRange){
-                        integrityValidNum++;
-                    }
-                }
-
-                //非正常频率次数
-                int errPitchNum = 0;
-                //分贝变化次数
-                int decibelChangeNum = 0;
-
-                if(CollectionUtils.isEmpty(measureSoundPitchInfos)){
-                    userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(musicXmlInfo.getMusicalNotesIndex(), (float) 0);
-                }else{
-                    Map<Integer, Long> collect = measureSoundPitchInfos.stream().map(pitch -> (int)pitch.getFrequency()).collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()));
-                    //出现次数最多的频率
-                    Integer pitch = collect.entrySet().stream().max(Comparator.comparing(e -> e.getValue())).get().getKey();
-                    //当前频率
-                    double cf = -1;
-                    //频率持续数量
-                    int fnum = 0;
-                    //是否演奏中
-                    boolean ing = false;
-                    //当前分贝
-                    double cd = 0;
-                    //分贝变化方向,-1变小,1变大
-                    int dcd = -1;
-                    //分贝持续数量
-                    int dnum = 0;
-                    for (MusicPitchDetailDto musicalNotesPitch : measureSoundPitchInfos) {
-                        //计算频率断层次数
-                        if (Math.abs(musicalNotesPitch.getFrequency() - cf) > 20){
-                            fnum ++;
-                        }
-                        if (fnum>=5){
-                            cf = musicalNotesPitch.getFrequency();
-                            fnum = 0;
-                            if (cf != -1){
-                                errPitchNum ++;
-                                ing = true;
-                                cd = musicalNotesPitch.getDecibel();
-                            }
-                        }
-                        //计算声音大小断层册数
-                        if(ing && Math.abs(musicalNotesPitch.getDecibel() - cd) > 10){
-                            dnum ++;
-                        }
-                        if (dnum > 2){
-                            int tdcd = cd > musicalNotesPitch.getDecibel() ? -1 : 1;
-                            cd = musicalNotesPitch.getDecibel();
-                            dnum = 0;
-                            if (tdcd != dcd) {
-                                decibelChangeNum++;
-                            }
-                            dcd = tdcd;
-                        }
-                    }
-                    userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(musicXmlInfo.getMusicalNotesIndex(), (float) pitch);
-                }
-
-                //有效节奏占比
-                float cadenceDuty = cadenceValidNum/compareNum;
-                //如果频率出现断层或这个音量出现断层,则当前音符节奏无效
-                if(errPitchNum>=2 || decibelChangeNum>1){
-                    cadenceDuty = 0;
-                }
-                //节奏
-                if(cadenceDuty>=soundCompareConfig.cadenceValidDuty){
-                    cadenceNum++;
-                }
-                //音准
-                if (!CollectionUtils.isEmpty(measureSoundPitchInfos)){
-                    Double avgPitch = measureSoundPitchInfos.stream().filter(pitch -> Math.abs((pitch.getFrequency()-musicXmlInfo.getFrequency()))<5).collect(Collectors.averagingDouble(pitch -> pitch.getFrequency()));
-                    //音分
-                    double recordCents = 0;
-                    if (avgPitch > 0){
-                        recordCents = PitchConverter.hertzToAbsoluteCent(avgPitch);
-                    }
-                    double cents = PitchConverter.hertzToAbsoluteCent(musicXmlInfo.getFrequency());
-                    double score = 100 - Math.round(Math.abs(cents - recordCents)) + soundCompareConfig.intonationCentsRange;
-                    if (score < 0){
-                        score = 0;
-                    }else if(score > 100){
-                        score = 100;
-                    }
-                    intonationScore += score;
-                    musicXmlInfo.setAvgFrequency(avgPitch.floatValue());
-                }
-                //完成度
-                if(integrityValidNum>0){
-                    integrityValidNum = integrityValidNum;
-                }
-                if(integrityValidNum > compareNum){
-                    integrityValidNum = compareNum;
-                }
-                float integrityDuty = integrityValidNum/compareNum;
-                integrityScore += integrityDuty;
-            }
-
-            BigDecimal measureNum = new BigDecimal(totalCompareNum);
-
-            intonation = new BigDecimal(intonationScore).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP);
-            cadence = new BigDecimal(cadenceNum).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_UP);
-            integrity = new BigDecimal(integrityScore).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_UP);
-
-        } catch (ArithmeticException e){
-            LOGGER.info("无musicXml信息");
-        }
-
-        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("intonation")){
-            userSoundInfoMap.get(phone).getUserScoreMap().put("intonation", intonation.add(userSoundInfoMap.get(phone).getUserScoreMap().get("intonation")));
-        }else{
-            userSoundInfoMap.get(phone).getUserScoreMap().put("intonation", intonation);
-        }
-
-        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("cadence")){
-            userSoundInfoMap.get(phone).getUserScoreMap().put("cadence", cadence.add(userSoundInfoMap.get(phone).getUserScoreMap().get("cadence")));
-        }else{
-            userSoundInfoMap.get(phone).getUserScoreMap().put("cadence", cadence);
-        }
-
-        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("integrity")){
-            userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity.add(userSoundInfoMap.get(phone).getUserScoreMap().get("integrity")));
-        }else{
-            userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity);
-        }
-
-        //计算分数并推送
-        createPushInfo(phone, "measureScore", measureIndex, intonation, cadence, integrity);
-    }
-
-    /**
-     * @describe 计算最终评分
-     * @author Joburgess
-     * @date 2021/6/25 0025
-     * @param phone:
-     * @return void
-     */
-    private void calTotalScore(String phone) throws IOException {
-        int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().keySet().size();
-        int currentCompareNum = totalCompareNum-userSoundInfoMap.get(phone).getMeasureEndTime().keySet().size();
-        BigDecimal intonation = BigDecimal.ZERO;
-        BigDecimal cadence = BigDecimal.ZERO;
-        BigDecimal integrity = BigDecimal.ZERO;
-
-        if(currentCompareNum>0){
-            intonation = userSoundInfoMap.get(phone).getUserScoreMap().get("intonation").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
-            cadence = userSoundInfoMap.get(phone).getUserScoreMap().get("cadence").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
-            integrity = userSoundInfoMap.get(phone).getUserScoreMap().get("integrity").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
-        }
-
-        //计算分数并推送
-        createPushInfo(phone, "overall", -1, intonation, cadence, integrity);
-
-        //存储评分数据
-        sysMusicCompareRecordService.saveMusicCompareData(phone, userSoundInfoMap.get(phone));
-
-        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone)));
-    }
-
-    /**
-     * @describe 生成评分结果
-     * @author Joburgess
-     * @date 2021/6/25 0025
-     * @param command:
-     * @param measureIndex:
-     * @param intonation:
-     * @param cadence:
-     * @param integrity:
-     * @return com.ym.mec.biz.dal.dto.WebSocketInfo
-     */
-    private WebSocketInfo createPushInfo(String phone, String command, Integer measureIndex,
-                                         BigDecimal intonation, BigDecimal cadence, BigDecimal integrity) throws IOException {
-        WebSocketInfo webSocketInfo = new WebSocketInfo();
-        HashMap<String, String> header = new HashMap<>();
-        header.put("commond", command);
-        webSocketInfo.setHeader(header);
-        Map<String, Object> result = new HashMap<>();
-//        BigDecimal score = intonation.multiply(new BigDecimal(0.5)).add(cadence.multiply(new BigDecimal(0.5))).setScale(0, BigDecimal.ROUND_HALF_UP);
-        BigDecimal score = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP);
-//        BigDecimal score = integrity.setScale(0, BigDecimal.ROUND_HALF_UP);
-        result.put("score", score);
-        result.put("intonation", intonation);
-        result.put("cadence", cadence);
-        result.put("integrity", integrity);
-        result.put("measureIndex", measureIndex);
-        webSocketInfo.setBody(result);
-
-        userSoundInfoMap.get(phone).getUserMeasureScoreMap().put(measureIndex, result);
-
-        LOGGER.info("小节频分:{}", JSON.toJSONString(webSocketInfo));
-
-        //推送结果
-        WS_CLIENTS.get(phone).getSession().sendMessage(new TextMessage(JSON.toJSONString(webSocketInfo)));
-        return webSocketInfo;
-    }
 }

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

@@ -8,6 +8,8 @@ import com.ym.mec.common.service.BaseService;
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 
 public interface CloudTeacherOrderService extends BaseService<Long, CloudTeacherOrder> {
@@ -84,4 +86,5 @@ public interface CloudTeacherOrderService extends BaseService<Long, CloudTeacher
      */
     CloudTeacherOrderDto queryOrderInfoByOrderId(Long orderId);
 
+    List<Map<Long, String>> queryNoStartByUserIds(Set<Integer> userIds);
 }

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

@@ -6,6 +6,7 @@ package com.ym.mec.biz.service;
  */
 public interface SoundSocketService {
 
+    String TAG = "TAG";
     String COMMOND = "commond";
     String MUSIC_XML = "musicXml";
     String RECORD_START = "recordStart";

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

@@ -15,6 +15,7 @@ import com.ym.mec.biz.dal.enums.DealStatusEnum;
 import com.ym.mec.biz.dal.enums.GroupType;
 import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
 import com.ym.mec.biz.dal.enums.OrderTypeEnum;
+import com.ym.mec.biz.dal.enums.PayStatus;
 import com.ym.mec.biz.dal.page.SporadicOrderQueryInfo;
 import com.ym.mec.biz.dal.page.StudentPaymentOrderQueryInfo;
 import com.ym.mec.common.page.PageInfo;
@@ -185,5 +186,7 @@ public interface StudentPaymentOrderService extends BaseService<Long, StudentPay
     void callOrderCallBack(StudentPaymentOrder order) throws Exception;
     
     int batchUpdate(List<StudentPaymentOrder> studentPaymentOrderList);
+    
+    PayStatus queryPayStatus(String paymentChannel, String orderNo, String transNo) throws Exception;
 
 }

+ 53 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/WebSocketEventHandler.java

@@ -0,0 +1,53 @@
+package com.ym.mec.biz.service;
+
+import org.springframework.web.socket.BinaryMessage;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/5 0005
+ **/
+public interface WebSocketEventHandler {
+
+
+
+    /**
+     * @describe 连接成功
+     * @author Joburgess
+     * @date 2021/8/5 0005
+     * @param session: 会话信息
+     * @return void
+     */
+    void afterConnectionEstablished(WebSocketSession session, String phone);
+
+    /**
+     * @describe 接受到文本信息
+     * @author Joburgess
+     * @date 2021/8/5 0005
+     * @param session: 会话信息
+     * @param message: 文本信息
+     * @return void
+     */
+    void receiveTextMessage(WebSocketSession session, String phone, TextMessage message);
+
+    /**
+     * @describe 接收到二进制数据
+     * @author Joburgess
+     * @date 2021/8/5 0005
+     * @param session: 会话信息
+     * @param message: 二进制数据
+     * @return void
+     */
+    void receiveBinaryMessage(WebSocketSession session, String phone, BinaryMessage message);
+
+    /**
+     * @describe 连接关闭
+     * @author Joburgess
+     * @date 2021/8/5 0005
+     * @param session: 会话信息
+     * @return void
+     */
+    void afterConnectionClosed(WebSocketSession session, String phone);
+
+}

+ 6 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/CloudTeacherOrderServiceImpl.java

@@ -22,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
 import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -241,4 +242,9 @@ public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTea
 	public CloudTeacherOrderDto queryOrderInfoByOrderId(Long orderId) {
 		return cloudTeacherOrderDao.queryOrderInfoByOrderId(orderId);
 	}
+
+    @Override
+    public List<Map<Long, String>> queryNoStartByUserIds(Set<Integer> userIds) {
+        return cloudTeacherOrderDao.queryNoStartByUserIds(userIds);
+    }
 }

+ 15 - 14
mec-biz/src/main/java/com/ym/mec/biz/service/impl/CourseScheduleServiceImpl.java

@@ -235,20 +235,21 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 			currentCourseDetail.setCoursePlan(planList.get(courseNumNo - 1).getPlan());
 		}
 		//获取有会员的学员数
-		String configValue = sysConfigDao.findConfigValue(SysConfigService.HOMEWORK_OPEN_FLAG);
-		if(StringUtils.isEmpty(configValue)){
-			configValue = "0";
-		}
-		if(configValue.equals("0")){
-			currentCourseDetail.setMemberNum(0);
-		}else {
-			MusicGroup musicGroup = musicGroupDao.get(courseSchedule.getMusicGroupId());
-			if(musicGroup != null){
-				currentCourseDetail.setCourseViewType(musicGroup.getCourseViewType());
-			}
-			List<BasicUserDto> students = courseScheduleStudentPaymentDao.findStudents(courseID);
-			currentCourseDetail.setMemberNum(studentDao.getMemberNum(StringUtils.join(students, ",")));
-		}
+//		String configValue = sysConfigDao.findConfigValue(SysConfigService.HOMEWORK_OPEN_FLAG);
+//		if(StringUtils.isEmpty(configValue)){
+//			configValue = "0";
+//		}
+//		if(configValue.equals("0")){
+//			currentCourseDetail.setMemberNum(0);
+//		}else {
+//			CourseSchedule courseSchedule = courseScheduleDao.get(courseID);
+//			MusicGroup musicGroup = musicGroupDao.get(courseSchedule.getMusicGroupId());
+//			if(musicGroup != null){
+//				currentCourseDetail.setCourseViewType(musicGroup.getCourseViewType());
+//			}
+//			List<BasicUserDto> students = courseScheduleStudentPaymentDao.findStudents(courseID);
+//			currentCourseDetail.setMemberNum(studentDao.getMemberNum(StringUtils.join(students, ",")));
+//		}
 		return currentCourseDetail;
     }
 

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

@@ -107,6 +107,7 @@ public class ExtracurricularExercisesReplyServiceImpl extends BaseServiceImpl<Lo
 		if(StringUtils.isEmpty(configValue)){
 			configValue = "0";
 		}
+		detail.setHomeworkOpenFlag(Integer.parseInt(configValue));
 		if(configValue.equals("0")){
 			detail.setHasMember(0);
 		}else {

+ 65 - 27
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java

@@ -595,8 +595,8 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
         if (isCheckStudentNum) {
             // 查询乐团已报名人数
             List<StudentPreRegistration> studentPreRegistrationList = studentPreRegistrationDao.queryByMusicGroupId(musicGroupId);
-            if (studentPreRegistrationList == null || studentPreRegistrationList.size() < 120) {
-                throw new BizException("操作失败:报名人数没有达到120人");
+            if (studentPreRegistrationList == null || studentPreRegistrationList.size() < 80) {
+                throw new BizException("操作失败:报名人数没有达到80人");
             }
         }
         musicGroup.setStatus(MusicGroupStatusEnum.PRE_BUILD_FEE);
@@ -2180,29 +2180,41 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                     studentLastChange = subjectChangeDao.getStudentLastChange(userId, musicGroupId);
                 }
                 
-				if (studentLastChange != null && minPaymentOrderId <= studentLastChange.getOriginalOrderId()) {
-					if (isRefundInstrumentFee) {
-						amount = amount.add(studentLastChange.getChangeMusicalPrice());
-					}
+    			if (studentLastChange != null && minPaymentOrderId <= studentLastChange.getOriginalOrderId()) {
+    				if (isRefundInstrumentFee) {
+    					amount = amount.add(studentLastChange.getChangeMusicalPrice());
+    					
+    					StudentInstrument studentMaintenance = studentInstrumentDao.getByOrderId(studentLastChange.getOrderId().longValue());
+    		            if (studentMaintenance != null) {
+    		                studentMaintenance.setDelFlag(1);
+    		                studentInstrumentDao.update(studentMaintenance);
+    		            }
+    				}
 
-					if (isRefundTeachingAssistantsFee) {
-						amount = amount.add(studentLastChange.getChangeAccessoriesPrice());
-					}
-				} else {
-					for (StudentPaymentOrderDetail detail : orderDetailList) {
-
-						// 退乐器费用
-						if (isRefundInstrumentFee && detail.getType() == OrderDetailTypeEnum.MUSICAL) {
-							amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());
-						}
-
-						// 退教辅费用
-						if (isRefundTeachingAssistantsFee
-								&& (detail.getType() == OrderDetailTypeEnum.ACCESSORIES || detail.getType() == OrderDetailTypeEnum.TEACHING)) {
-							amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());
-						}
-					}
-				}
+    				if (isRefundTeachingAssistantsFee) {
+    					amount = amount.add(studentLastChange.getChangeAccessoriesPrice());
+    				}
+    			} else {
+    				for (StudentPaymentOrderDetail detail : orderDetailList) {
+
+    					// 退乐器费用
+    					if (isRefundInstrumentFee && detail.getType() == OrderDetailTypeEnum.MUSICAL) {
+    						amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());
+    						
+    						StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
+    			            if (studentMaintenance != null) {
+    			                studentMaintenance.setDelFlag(1);
+    			                studentInstrumentDao.update(studentMaintenance);
+    			            }
+    					}
+
+    					// 退教辅费用
+    					if (isRefundTeachingAssistantsFee
+    							&& (detail.getType() == OrderDetailTypeEnum.ACCESSORIES || detail.getType() == OrderDetailTypeEnum.TEACHING)) {
+    						amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());
+    					}
+    				}
+    			}
             }
 
             //退乐保费用
@@ -2215,7 +2227,9 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                 }
                 amount = amount.add(maintenanceFee);
                 if (maintenanceFee.compareTo(BigDecimal.ZERO) > 0 && studentMaintenance != null) {
-                    studentMaintenance.setDelFlag(1);
+                    studentMaintenance.setStatus(0);
+                    studentMaintenance.setStartTime(null);
+                    studentMaintenance.setEndTime(null);
                     studentInstrumentDao.update(studentMaintenance);
                 }
             }
@@ -2463,6 +2477,12 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 			if (studentLastChange != null && minPaymentOrderId <= studentLastChange.getOriginalOrderId()) {
 				if (isRefundInstrumentFee) {
 					amount = amount.add(studentLastChange.getChangeMusicalPrice());
+					
+					StudentInstrument studentMaintenance = studentInstrumentDao.getByOrderId(studentLastChange.getOrderId().longValue());
+		            if (studentMaintenance != null) {
+		                studentMaintenance.setDelFlag(1);
+		                studentInstrumentDao.update(studentMaintenance);
+		            }
 				}
 
 				if (isRefundTeachingAssistantsFee) {
@@ -2474,6 +2494,12 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 					// 退乐器费用
 					if (isRefundInstrumentFee && detail.getType() == OrderDetailTypeEnum.MUSICAL) {
 						amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());
+						
+						StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
+			            if (studentMaintenance != null) {
+			                studentMaintenance.setDelFlag(1);
+			                studentInstrumentDao.update(studentMaintenance);
+			            }
 					}
 
 					// 退教辅费用
@@ -2496,7 +2522,9 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
             }
             amount = amount.add(maintenanceFee);
             if (maintenanceFee.compareTo(BigDecimal.ZERO) > 0 && studentMaintenance != null) {
-                studentMaintenance.setDelFlag(1);
+                studentMaintenance.setStatus(0);
+                studentMaintenance.setStartTime(null);
+                studentMaintenance.setEndTime(null);
                 studentInstrumentDao.update(studentMaintenance);
             }
         }
@@ -3684,6 +3712,13 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 			throw new BizException("乐器已发货,请勿重复操作");
 		}
 		
+		Set<String> musicGroupIds = new HashSet<String>();
+        musicGroupIds.add(musicGroupId);
+        List<MusicGroupPurchaseList> musicGroupPurchaseListCount = musicGroupPurchaseListDao.getCount(musicGroupIds);
+        if (musicGroupPurchaseListCount == null || musicGroupPurchaseListCount.size() == 0) {
+            throw new BizException("乐器清单未确认,不能确认发货");
+        }
+		
 		Date date = new Date();
 		
 		musicGroup.setMusicalInstrumentsProvideStatus(1);
@@ -3700,12 +3735,15 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 		List<StudentInstrument> updateList = new ArrayList<StudentInstrument>();
 		
 		for (StudentInstrument si : studentInstrumentList) {
+			if (si.getDelFlag() == 1) {
+				continue;
+			}
 			if (si.getStatus() == 0 && si.getStartTime() == null) {
 				si.setStatus(1);
 				si.setStartTime(date);
 				si.setEndTime(DateUtil.addYears(date, 1));
 				si.setUpdateTime(date);
-				
+
 				updateList.add(si);
 			}
 		}

+ 537 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SoundCompareHandler.java

@@ -0,0 +1,537 @@
+package com.ym.mec.biz.service.impl;
+
+import be.tarsos.dsp.AudioDispatcher;
+import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
+import be.tarsos.dsp.pitch.PitchProcessor;
+import be.tarsos.dsp.util.PitchConverter;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ym.mec.biz.dal.config.SoundCompareConfig;
+import com.ym.mec.biz.dal.dao.SysMusicScoreAccompanimentDao;
+import com.ym.mec.biz.dal.dto.MusicPitchDetailDto;
+import com.ym.mec.biz.dal.dto.SoundCompareHelper;
+import com.ym.mec.biz.dal.dto.WavHeader;
+import com.ym.mec.biz.dal.dto.WebSocketInfo;
+import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
+import com.ym.mec.biz.handler.WebSocketHandler;
+import com.ym.mec.biz.service.SoundSocketService;
+import com.ym.mec.biz.service.SysMusicCompareRecordService;
+import com.ym.mec.biz.service.WebSocketEventHandler;
+import com.ym.mec.common.constant.CommonConstants;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.thirdparty.storage.StoragePluginContext;
+import com.ym.mec.thirdparty.storage.provider.KS3StoragePlugin;
+import com.ym.mec.util.upload.UploadUtil;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.socket.BinaryMessage;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+
+import javax.sound.sampled.UnsupportedAudioFileException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/5 0005
+ */
+@Service
+public class SoundCompareHandler implements WebSocketEventHandler {
+
+    private final Logger LOGGER = LoggerFactory.getLogger(SoundCompareHandler.class);
+
+    private BigDecimal oneHundred = new BigDecimal(100);
+
+    private final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/";
+    /**
+     * @describe 用户对应评分信息
+     */
+    private Map<String, SoundCompareHelper> userSoundInfoMap = new ConcurrentHashMap<>();
+    /**
+     * @describe 音频处理参数
+     */
+    public static final SoundCompareConfig soundCompareConfig = new SoundCompareConfig();
+
+    @Autowired
+    private StoragePluginContext storagePluginContext;
+    @Autowired
+    private SysMusicCompareRecordService sysMusicCompareRecordService;
+    @Autowired
+    private SysMusicScoreAccompanimentDao sysMusicScoreAccompanimentDao;
+
+    public SoundCompareHandler() {
+        WebSocketHandler.regist("SOUND_COMPARE", this);
+        File soundDir = new File(tmpDir);
+        if(!soundDir.exists()){
+            soundDir.mkdir();
+        }
+    }
+
+    @Override
+    public void afterConnectionEstablished(WebSocketSession session, String phone) {
+
+    }
+
+    @Override
+    public void receiveTextMessage(WebSocketSession session, String phone, TextMessage message) {
+        WebSocketInfo webSocketInfo = JSON.parseObject(message.getPayload(), WebSocketInfo.class);
+        JSONObject bodyObject = (JSONObject) webSocketInfo.getBody();
+
+        String commond = "";
+        if(webSocketInfo.getHeader().containsKey(SoundSocketService.COMMOND)){
+            commond = webSocketInfo.getHeader().get(SoundSocketService.COMMOND);
+        }
+        switch (commond){
+            case SoundSocketService.MUSIC_XML:
+                userSoundInfoMap.put(phone, new SoundCompareHelper());
+                userSoundInfoMap.get(phone).setClientId(((OAuth2Authentication)session.getPrincipal()).getOAuth2Request().getClientId());
+                List<MusicPitchDetailDto> musicXmlInfos = JSON.parseArray(bodyObject.getString("musicXmlInfos"), MusicPitchDetailDto.class);
+                userSoundInfoMap.get(phone).setMusicXmlInfos(musicXmlInfos);
+                musicXmlInfos = musicXmlInfos.stream().filter(m->!m.getDontEvaluating()).collect(Collectors.toList());
+                userSoundInfoMap.get(phone).setMusicScoreId(bodyObject.getInteger("id"));
+                if(bodyObject.containsKey("platform")){
+                    userSoundInfoMap.get(phone).setDeviceType(DeviceTypeEnum.valueOf(bodyObject.getString("platform")));
+                }
+                List<Integer> subjectIds = sysMusicScoreAccompanimentDao.findSubjectByMusicScoreId(userSoundInfoMap.get(phone).getMusicScoreId(), null);
+                if(!CollectionUtils.isEmpty(subjectIds)){
+                    userSoundInfoMap.get(phone).setSubjectId(subjectIds.get(0));
+                }
+                userSoundInfoMap.get(phone).setMeasureXmlInfoMap(musicXmlInfos.stream().collect(Collectors.groupingBy(MusicPitchDetailDto::getMeasureIndex)));
+                musicXmlInfos.forEach(e->userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(e.getMusicalNotesIndex(), e.getFrequency()));
+                for (Map.Entry<Integer, List<MusicPitchDetailDto>> userMeasureXmlInfoEntry : userSoundInfoMap.get(phone).getMeasureXmlInfoMap().entrySet()) {
+                    MusicPitchDetailDto firstPitch = userMeasureXmlInfoEntry.getValue().stream().min(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get();
+                    MusicPitchDetailDto lastPitch = userMeasureXmlInfoEntry.getValue().stream().max(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get();
+                    long dc = userMeasureXmlInfoEntry.getValue().stream().filter(m -> m.getDontEvaluating()).count();
+                    MusicPitchDetailDto musicPitchDetailDto = new MusicPitchDetailDto(firstPitch.getTimeStamp(), lastPitch.getTimeStamp() + lastPitch.getDuration());
+                    musicPitchDetailDto.setDuration(musicPitchDetailDto.getEndTimeStamp()-musicPitchDetailDto.getTimeStamp());
+                    musicPitchDetailDto.setDontEvaluating(dc == userMeasureXmlInfoEntry.getValue().size());
+                    userSoundInfoMap.get(phone).getMeasureEndTime().put(userMeasureXmlInfoEntry.getKey(), musicPitchDetailDto);
+                }
+
+                break;
+            case SoundSocketService.RECORD_START:
+                if(!userSoundInfoMap.containsKey(phone)){
+                    break;
+                }
+                try {
+                    File file = new File(tmpDir+phone + "_"+ userSoundInfoMap.get(phone).getMusicScoreId() +"_"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +".wav");
+                    userSoundInfoMap.get(phone).setFile(file);
+                    userSoundInfoMap.get(phone).setAccessFile(new RandomAccessFile(file, "rw"));
+                    userSoundInfoMap.get(phone).setRecordFilePath(file.getAbsolutePath());
+                } catch (FileNotFoundException e) {
+                    throw new BizException("文件创建失败:", e);
+                }
+                break;
+            case SoundSocketService.RECORD_END:
+                if(!userSoundInfoMap.containsKey(phone)){
+                    break;
+                }
+                try {
+                    if(!CollectionUtils.isEmpty(userSoundInfoMap.get(phone).getMeasureEndTime())){
+                        Integer lastMeasureIndex = userSoundInfoMap.get(phone).getMeasureEndTime().keySet().stream().min(Integer::compareTo).get();
+                        double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
+                        //如果结束时时长大于某小节,则此小节需要评分
+                        if(recordTime>userSoundInfoMap.get(phone).getMeasureEndTime().get(lastMeasureIndex).getEndTimeStamp()){
+                            measureCompare(phone, lastMeasureIndex);
+                            userSoundInfoMap.get(phone).getMeasureEndTime().remove(lastMeasureIndex);
+                        }
+                    }
+                    calTotalScore(phone);
+                } catch (IOException e) {
+                    throw new BizException("评分错误:", e);
+                }
+                createHeader(phone);
+                break;
+            case SoundSocketService.RECORD_CANCEL:
+                createHeader(phone);
+                break;
+            case SoundSocketService.PROXY_MESSAGE:
+                if(DeviceTypeEnum.IOS.equals(userSoundInfoMap.get(phone).getDeviceType())&&bodyObject.containsKey(SoundSocketService.OFFSET_TIME)){
+                    int offsetTime = bodyObject.getIntValue(SoundSocketService.OFFSET_TIME);
+                    calOffsetTime(phone, offsetTime);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void receiveBinaryMessage(WebSocketSession session, String phone, BinaryMessage message) {
+        if(!userSoundInfoMap.containsKey(phone)){
+            return;
+        }
+        try {
+            if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
+                userSoundInfoMap.get(phone).getAccessFile().write(message.getPayload().array());
+            }
+
+            AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), soundCompareConfig.audioFormat, soundCompareConfig.simpleSize, soundCompareConfig.overlap);
+
+            dispatcher.addAudioProcessor(userSoundInfoMap.get(phone).silenceDetector);
+            dispatcher.addAudioProcessor(new PitchProcessor(soundCompareConfig.algo, soundCompareConfig.simpleRate, soundCompareConfig.simpleSize, userSoundInfoMap.get(phone)));
+            dispatcher.run();
+            if(Objects.isNull(userSoundInfoMap.get(phone).getAccessFile())){
+                return;
+            }
+
+            double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
+            userSoundInfoMap.get(phone).setMeasureStartTime(recordTime);
+            for (Map.Entry<Integer, MusicPitchDetailDto> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
+                if(recordTime>(userMeasureEndTimeMapEntry.getValue().getEndTimeStamp())){
+                    if(userMeasureEndTimeMapEntry.getValue().getDontEvaluating()){
+                        continue;
+                    }else{
+                        measureCompare(phone, userMeasureEndTimeMapEntry.getKey());
+                    }
+                    userSoundInfoMap.get(phone).getMeasureEndTime().remove(userMeasureEndTimeMapEntry.getKey());
+                    break;
+                }
+            }
+        } catch (UnsupportedAudioFileException | IOException e) {
+            throw new BizException("{}评分异常:{}", phone, e);
+        }
+    }
+
+    @Override
+    public void afterConnectionClosed(WebSocketSession session, String phone){
+        createHeader(phone);
+    }
+
+    /**
+     * @describe 处理时间偏移
+     * @author Joburgess
+     * @date 2021/7/5 0005
+     * @param phone:
+     * @param offsetTime:
+     * @return void
+     */
+    private void calOffsetTime(String phone, int offsetTime){
+        userSoundInfoMap.get(phone).setOffsetTime(offsetTime);
+        for (Map.Entry<Integer, MusicPitchDetailDto> musicPitchDetailDtoEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
+            musicPitchDetailDtoEntry.getValue().setTimeStamp(musicPitchDetailDtoEntry.getValue().getTimeStamp() + offsetTime);
+            musicPitchDetailDtoEntry.getValue().setEndTimeStamp(musicPitchDetailDtoEntry.getValue().getEndTimeStamp() + offsetTime);
+        }
+    }
+
+    /**
+     * @describe 保存录音数据,并生成wav头信息
+     * @author Joburgess
+     * @date 2021/6/25 0025
+     * @param phone:
+     * @return void
+     */
+    private void createHeader(String phone){
+        if(!userSoundInfoMap.containsKey(phone)){
+            return;
+        }
+        if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
+            try {
+                RandomAccessFile randomAccessFile = userSoundInfoMap.get(phone).getAccessFile();
+                LOGGER.info("音频时长:{}", randomAccessFile.length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000);
+                randomAccessFile.seek(0);
+                randomAccessFile.write(WavHeader.getWaveHeader(randomAccessFile.length(), (long) soundCompareConfig.audioFormat.getFrameRate(), soundCompareConfig.audioFormat.getSampleSizeInBits()));
+                randomAccessFile.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            userSoundInfoMap.get(phone).setAccessFile(null);
+        }
+
+        if(Objects.nonNull(userSoundInfoMap.get(phone).getFile())){
+            String url = null;
+            try {
+                String folder = UploadUtil.getFileFloder();
+                url = storagePluginContext.uploadFile(KS3StoragePlugin.PLUGIN_NAME,"soundCompare/" + folder, userSoundInfoMap.get(phone).getFile());
+            } catch (Exception e) {
+                LOGGER.error("录音文件上传失败:{}", e);
+            }
+            userSoundInfoMap.get(phone).setRecordFilePath(url);
+        }
+        //存储评分数据
+        sysMusicCompareRecordService.saveMusicCompareData(phone, userSoundInfoMap.get(phone));
+
+        if(Objects.nonNull(userSoundInfoMap.get(phone).getFile())){
+            userSoundInfoMap.get(phone).getFile().deleteOnExit();
+        }
+
+        userSoundInfoMap.remove(phone);
+    }
+
+    /**
+     * @describe 数据比对,生成分数
+     * @author Joburgess
+     * @date 2021/6/25 0025
+     * @param phone:
+     * @param measureIndex:
+     * @return void
+     */
+    private void measureCompare(String phone, int measureIndex){
+        if (userSoundInfoMap.get(phone).getOffsetTime() == -1){
+            userSoundInfoMap.get(phone).setOffsetTime(0);
+        }
+
+        //相似度
+        BigDecimal intonation = BigDecimal.ZERO;
+        //节奏
+        BigDecimal cadence = BigDecimal.ZERO;
+        //完整度
+        BigDecimal integrity = BigDecimal.ZERO;
+
+        try {
+            //音准分数
+            float intonationScore = 0;
+
+            //节奏匹配数量
+            float cadenceNum = 0;
+
+            //完整性分数
+            float integrityScore = 0;
+
+            int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size();
+
+            for (int i = 0; i < userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size(); i++) {
+                MusicPitchDetailDto musicXmlInfo = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).get(i);
+
+                int ot5 = (int) (musicXmlInfo.getDuration()*0.1);
+                int startTimeStamp = musicXmlInfo.getTimeStamp() + userSoundInfoMap.get(phone).getOffsetTime() + ot5;
+                int endTimeStamp = musicXmlInfo.getTimeStamp()  + userSoundInfoMap.get(phone).getOffsetTime() + musicXmlInfo.getDuration() - ot5;
+
+                //时间范围内有效节奏数量
+                float cadenceValidNum = 0;
+                //时间范围内有效音频数量
+                float integrityValidNum = 0;
+                //时间范围内匹配次数
+                float compareNum = 0;
+
+                List<MusicPitchDetailDto> measureSoundPitchInfos = new ArrayList<>();
+
+                for (int j = 0; j < userSoundInfoMap.get(phone).getRecordMeasurePithInfo().size(); j++) {
+                    MusicPitchDetailDto recordInfo = userSoundInfoMap.get(phone).getRecordMeasurePithInfo().get(j);
+                    //如果在时间范围之外直接跳过
+                    if(recordInfo.getTimeStamp()<startTimeStamp||recordInfo.getTimeStamp()>endTimeStamp){
+                        continue;
+                    }
+                    measureSoundPitchInfos.add(recordInfo);
+                    compareNum++;
+                    //如果在最低有效频率以下则跳过
+                    if(recordInfo.getFrequency()<soundCompareConfig.validFrequency&&musicXmlInfo.getFrequency()!=-1){
+                        continue;
+                    }
+                    cadenceValidNum++;
+                    //如果频率差值在节奏误差范围内
+                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=soundCompareConfig.integrityFrequencyRange){
+                        integrityValidNum++;
+                    }
+                }
+
+                //非正常频率次数
+                int errPitchNum = 0;
+                //分贝变化次数
+                int decibelChangeNum = 0;
+
+                if(CollectionUtils.isEmpty(measureSoundPitchInfos)){
+                    userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(musicXmlInfo.getMusicalNotesIndex(), (float) 0);
+                }else{
+                    Map<Integer, Long> collect = measureSoundPitchInfos.stream().map(pitch -> (int)pitch.getFrequency()).collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()));
+                    //出现次数最多的频率
+                    Integer pitch = collect.entrySet().stream().max(Comparator.comparing(e -> e.getValue())).get().getKey();
+                    //当前频率
+                    double cf = -1;
+                    //频率持续数量
+                    int fnum = 0;
+                    //是否演奏中
+                    boolean ing = false;
+                    //当前分贝
+                    double cd = 0;
+                    //分贝变化方向,-1变小,1变大
+                    int dcd = -1;
+                    //分贝持续数量
+                    int dnum = 0;
+                    for (MusicPitchDetailDto musicalNotesPitch : measureSoundPitchInfos) {
+                        //计算频率断层次数
+                        if (Math.abs(musicalNotesPitch.getFrequency() - cf) > 20){
+                            fnum ++;
+                        }
+                        if (fnum>=5){
+                            cf = musicalNotesPitch.getFrequency();
+                            fnum = 0;
+                            if (cf != -1){
+                                errPitchNum ++;
+                                ing = true;
+                                cd = musicalNotesPitch.getDecibel();
+                            }
+                        }
+                        //计算声音大小断层册数
+                        if(ing && Math.abs(musicalNotesPitch.getDecibel() - cd) > 10){
+                            dnum ++;
+                        }
+                        if (dnum > 2){
+                            int tdcd = cd > musicalNotesPitch.getDecibel() ? -1 : 1;
+                            cd = musicalNotesPitch.getDecibel();
+                            dnum = 0;
+                            if (tdcd != dcd) {
+                                decibelChangeNum++;
+                            }
+                            dcd = tdcd;
+                        }
+                    }
+                    userSoundInfoMap.get(phone).getMusicalNotePitchMap().put(musicXmlInfo.getMusicalNotesIndex(), (float) pitch);
+                }
+
+                //有效节奏占比
+                float cadenceDuty = cadenceValidNum/compareNum;
+                //如果频率出现断层或这个音量出现断层,则当前音符节奏无效
+                if(errPitchNum>=2 || decibelChangeNum>1){
+                    cadenceDuty = 0;
+                }
+                //节奏
+                if(cadenceDuty>=soundCompareConfig.cadenceValidDuty){
+                    cadenceNum++;
+                }
+                //音准
+                if (!CollectionUtils.isEmpty(measureSoundPitchInfos)){
+                    Double avgPitch = measureSoundPitchInfos.stream().filter(pitch -> Math.abs((pitch.getFrequency()-musicXmlInfo.getFrequency()))<5).collect(Collectors.averagingDouble(pitch -> pitch.getFrequency()));
+                    //音分
+                    double recordCents = 0;
+                    if (avgPitch > 0){
+                        recordCents = PitchConverter.hertzToAbsoluteCent(avgPitch);
+                    }
+                    double cents = 0;
+                    if(musicXmlInfo.getFrequency()>0){
+                        cents =  PitchConverter.hertzToAbsoluteCent(musicXmlInfo.getFrequency());
+                    }
+                    double score = 100 - Math.round(Math.abs(cents - recordCents)) + soundCompareConfig.intonationCentsRange;
+                    if (score < 0){
+                        score = 0;
+                    }else if(score > 100){
+                        score = 100;
+                    }
+                    intonationScore += score;
+                    musicXmlInfo.setAvgFrequency(avgPitch.floatValue());
+                }
+                //完成度
+                if(integrityValidNum>0){
+                    integrityValidNum = integrityValidNum;
+                }
+                if(integrityValidNum > compareNum){
+                    integrityValidNum = compareNum;
+                }
+                float integrityDuty = integrityValidNum/compareNum;
+                integrityScore += integrityDuty;
+            }
+
+            BigDecimal measureNum = new BigDecimal(totalCompareNum);
+
+            intonation = new BigDecimal(intonationScore).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP);
+            cadence = new BigDecimal(cadenceNum).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_UP);
+            integrity = new BigDecimal(integrityScore).divide(measureNum, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_UP);
+
+        } catch (ArithmeticException e){
+            LOGGER.info("无musicXml信息");
+        }
+
+        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("intonation")){
+            userSoundInfoMap.get(phone).getUserScoreMap().put("intonation", intonation.add(userSoundInfoMap.get(phone).getUserScoreMap().get("intonation")));
+        }else{
+            userSoundInfoMap.get(phone).getUserScoreMap().put("intonation", intonation);
+        }
+
+        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("cadence")){
+            userSoundInfoMap.get(phone).getUserScoreMap().put("cadence", cadence.add(userSoundInfoMap.get(phone).getUserScoreMap().get("cadence")));
+        }else{
+            userSoundInfoMap.get(phone).getUserScoreMap().put("cadence", cadence);
+        }
+
+        if(userSoundInfoMap.get(phone).getUserScoreMap().containsKey("integrity")){
+            userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity.add(userSoundInfoMap.get(phone).getUserScoreMap().get("integrity")));
+        }else{
+            userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity);
+        }
+
+        //计算分数并推送
+        createPushInfo(phone, "measureScore", measureIndex, intonation, cadence, integrity);
+    }
+
+    /**
+     * @describe 计算最终评分
+     * @author Joburgess
+     * @date 2021/6/25 0025
+     * @param phone:
+     * @return void
+     */
+    private void calTotalScore(String phone) {
+        int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().keySet().size();
+        int currentCompareNum = totalCompareNum-userSoundInfoMap.get(phone).getMeasureEndTime().keySet().size();
+        BigDecimal intonation = BigDecimal.ZERO;
+        BigDecimal cadence = BigDecimal.ZERO;
+        BigDecimal integrity = BigDecimal.ZERO;
+
+        if(currentCompareNum>0){
+            intonation = userSoundInfoMap.get(phone).getUserScoreMap().get("intonation").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
+            cadence = userSoundInfoMap.get(phone).getUserScoreMap().get("cadence").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
+            integrity = userSoundInfoMap.get(phone).getUserScoreMap().get("integrity").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
+        }
+
+        //计算分数并推送
+        createPushInfo(phone, "overall", -1, intonation, cadence, integrity);
+
+        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone)));
+    }
+
+    /**
+     * @describe 生成评分结果
+     * @author Joburgess
+     * @date 2021/6/25 0025
+     * @param command:
+     * @param measureIndex:
+     * @param intonation:
+     * @param cadence:
+     * @param integrity:
+     * @return com.ym.mec.biz.dal.dto.WebSocketInfo
+     */
+    private WebSocketInfo createPushInfo(String phone, String command, Integer measureIndex,
+                                         BigDecimal intonation, BigDecimal cadence, BigDecimal integrity){
+        WebSocketInfo webSocketInfo = new WebSocketInfo();
+        HashMap<String, String> header = new HashMap<>();
+        header.put("commond", command);
+        webSocketInfo.setHeader(header);
+        Map<String, Object> result = new HashMap<>(5);
+        BigDecimal score = cadence;
+        if(Objects.isNull(userSoundInfoMap.get(phone).getSubjectId())||userSoundInfoMap.get(phone).getSubjectId()!=23){
+            score = intonation.add(cadence).add(integrity).divide(new BigDecimal(3), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_UP);
+        }
+        result.put("score", score);
+        result.put("intonation", intonation);
+        result.put("cadence", cadence);
+        result.put("integrity", integrity);
+        result.put("measureIndex", measureIndex);
+        webSocketInfo.setBody(result);
+
+        userSoundInfoMap.get(phone).getUserMeasureScoreMap().put(measureIndex, result);
+
+        LOGGER.info("小节频分:{}", JSON.toJSONString(webSocketInfo));
+
+        //推送结果
+        try {
+            WebSocketHandler.WS_CLIENTS.get(phone).getSession().sendMessage(new TextMessage(JSON.toJSONString(webSocketInfo)));
+        } catch (IOException e) {
+            LOGGER.error("{}评分结果推送失败", phone);
+        }
+        return webSocketInfo;
+    }
+}

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

@@ -214,6 +214,7 @@ public class StudentCourseHomeworkServiceImpl extends BaseServiceImpl<Long, Stud
         if(StringUtils.isEmpty(configValue)){
             configValue = "0";
         }
+        courseHomeworkStudentDetail.setHomeworkOpenFlag(Integer.parseInt(configValue));
         if(configValue.equals("0")){
             courseHomeworkStudentDetail.setMusicScoreId(null);
             courseHomeworkStudentDetail.setMusicScoreName(null);

+ 16 - 4
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentInstrumentServiceImpl.java

@@ -381,17 +381,29 @@ public class StudentInstrumentServiceImpl extends BaseServiceImpl<Long, StudentI
 
     @Override
     public Boolean subjectChangeUpdateInstrument(SubjectChange subjectChange) {
-        if (subjectChange == null || subjectChange.getChangeMusical() == null ||
+        StudentInstrument studentInstrument = null;
+    	
+		if (subjectChange.getOriginalOrderId() != null) {
+			studentInstrument = studentInstrumentDao.getByOrderId(subjectChange.getOriginalOrderId().longValue());
+		}
+        
+		if (subjectChange == null || subjectChange.getChangeMusical() == null ||
                 KitGroupPurchaseTypeEnum.OWNED.equals(subjectChange.getKitGroupPurchaseType())) {
+        	
+        	if(studentInstrument != null){
+        		studentInstrument.setDelFlag(1);
+        		update(studentInstrument);
+        	}
+        	
             return false;
         }
-        StudentInstrument studentInstrument = studentInstrumentDao.getByOrderId(subjectChange.getOriginalOrderId().longValue());
-
         if (studentInstrument == null) {
             studentInstrument = new StudentInstrument();
             studentInstrument.setStudentId(subjectChange.getStudentId());
             studentInstrument.setOrganId(subjectChange.getOrganId());
-            studentInstrument.setOrderId(subjectChange.getOriginalOrderId().longValue());
+            if (subjectChange.getOriginalOrderId() != null) {
+            	studentInstrument.setOrderId(subjectChange.getOriginalOrderId().longValue());
+            }
             studentInstrument.setStatus(0);
         }
         studentInstrument.setChangeOrderId(subjectChange.getOrderId().longValue());

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

@@ -141,7 +141,7 @@ public class StudentManageServiceImpl implements StudentManageService {
         if(!CollectionUtils.isEmpty(userAllContract)){
             userContractVersionMap = userAllContract.stream().collect(Collectors.groupingBy(SysUserContracts::getUserId, Collectors.mapping(SysUserContracts::getVersion, Collectors.toSet())));
         }
-
+        Map<Long,String> cloudMap = MapUtil.convertMybatisMap(cloudTeacherOrderService.queryNoStartByUserIds(userIds));
         //List<Subject> studentSubject = studentManageDao.getStudentSubject(userIds);
         StudentListCourseDto studentListCourseDto = null;
         for (StudentManageListDto dto : dataList) {
@@ -165,6 +165,13 @@ public class StudentManageServiceImpl implements StudentManageService {
                 dto.setHasCourse(YesOrNoEnum.NO);
                 dto.setHasPracticeCourse(YesOrNoEnum.NO);
             }
+            //如果会员已过期、是否有未生效的会员
+            if(dto.getMemberRankSettingId() == null){
+                String s = cloudMap.get(dto.getUserId().longValue());
+                if(StringUtils.isNotEmpty(s)){
+                    dto.setMembershipEndTime(DateUtil.toDateTime(s));
+                }
+            }
 
             if(userContractVersionMap.containsKey(dto.getUserId())){
 //                dto.setContractVersions(StringUtils.join(userContractVersionMap.get(dto.getUserId()), ","));

+ 4 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentPaymentOrderDetailServiceImpl.java

@@ -419,6 +419,10 @@ public class StudentPaymentOrderDetailServiceImpl extends BaseServiceImpl<Long,
 
     @Override
 	public List<StudentPaymentOrderDetail> getOrderDetail(Long orderId) {
+    	
+    	if(orderId == null){
+    		return new ArrayList<StudentPaymentOrderDetail>();
+    	}
 		
     	List<Long> orderIdList = new ArrayList<Long>();
     	orderIdList.add(orderId);

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

@@ -31,6 +31,7 @@ import com.ym.mec.biz.dal.enums.DealStatusEnum;
 import com.ym.mec.biz.dal.enums.GroupType;
 import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
 import com.ym.mec.biz.dal.enums.OrderTypeEnum;
+import com.ym.mec.biz.dal.enums.PayStatus;
 import com.ym.mec.biz.dal.enums.PlatformCashAccountDetailTypeEnum;
 import com.ym.mec.biz.dal.enums.SporadicChargeTypeEnum;
 import com.ym.mec.biz.dal.page.SporadicOrderQueryInfo;
@@ -645,4 +646,49 @@ public class StudentPaymentOrderServiceImpl extends BaseServiceImpl<Long, Studen
 	public int batchUpdate(List<StudentPaymentOrder> studentPaymentOrderList) {
 		return studentPaymentOrderDao.batchUpdate(studentPaymentOrderList);
 	}
+
+	@Override
+	public PayStatus queryPayStatus(String paymentChannel, String orderNo, String transNo) throws Exception {
+		if (StringUtils.isBlank(transNo)) {
+			return PayStatus.FAILED;
+		}
+
+		if (StringUtils.equals(paymentChannel, "ADAPAY")) {
+			Map<String, Object> payment = Payment.queryPayment(transNo);
+			String status = (String) payment.get("status");
+			if (status.equals("succeeded")) {
+				return PayStatus.SUCCESSED;
+			} else if (status.equals("failed")) {
+				return PayStatus.FAILED;
+			} else {
+				return PayStatus.PAYING;
+			}
+		} else if (StringUtils.equals(paymentChannel, "YQPAY")) {
+			String notifyUrl = ""; // 回调地址
+			Map<String, Object> resultMap = new LinkedHashMap<>();
+			resultMap.put("merOrderNoList", orderNo);
+			Map<String, Object> requestMap = YqPayUtil.getRequestMap(notifyUrl, resultMap);
+
+			RsqMsg rsqMsg = new RsqMsg(requestMap);
+
+			Msg queryRs = yqPayFeignService.orderQuery(rsqMsg);
+
+			if (queryRs.getCode().equals("88")) {
+				// 更新订单状态
+				String responseParameters = queryRs.getResponseParameters();
+				List<Map<String, String>> responseList = JSON.parseObject(responseParameters, List.class);
+				for (Map<String, String> response : responseList) {
+
+					if (StringUtils.equals(response.get("tradeState"), "1")) {
+						return PayStatus.SUCCESSED;
+					} else if (StringUtils.equals(response.get("tradeState"), "0") || StringUtils.equals(response.get("tradeState"), "7")) {
+						return PayStatus.FAILED;
+					} else {
+						return PayStatus.PAYING;
+					}
+				}
+			}
+		}
+		throw new BizException("支付渠道错误");
+	}
 }

+ 89 - 40
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentRegistrationServiceImpl.java

@@ -341,7 +341,10 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
 
 		List<Long> orderIdList = studentPaymentOrderList.stream().map(t -> t.getId()).collect(Collectors.toList());
 
-		List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = studentPaymentOrderDetailService.getOrderDetail(orderIdList);
+		List<StudentPaymentOrderDetail> studentPaymentOrderDetailList =new ArrayList<StudentPaymentOrderDetail>();
+		if(orderIdList != null && orderIdList.size() > 0){
+			studentPaymentOrderDetailList = studentPaymentOrderDetailService.getOrderDetail(orderIdList);
+		}
 
 		SubjectChange studentLastChange = subjectChangeDao.getStudentLastChange(studentId, musicGroupId);
 		
@@ -376,7 +379,9 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
 				if (goods != null && goods.size() > 0) {
 					detail.setName(goods.stream().map(t -> t.getName()).collect(Collectors.joining(",")));
 				}
-				detail.setPaymentOrderId((long) studentLastChange.getOriginalOrderId());
+				if(studentLastChange.getOriginalOrderId() != null){
+					detail.setPaymentOrderId((long) studentLastChange.getOriginalOrderId());
+				}
 				detail.setPrice(studentLastChange.getChangeMusicalPrice());
 				detail.setType(OrderDetailTypeEnum.MUSICAL);
 				detail.setCreateTime(studentLastChange.getCreateTime());
@@ -640,31 +645,35 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
 
         MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());
         
-        //判断之前是否已有订单
-        List<StudentPaymentOrder> oldStudentPaymentOrderList = studentPaymentOrderService.queryByCondition(GroupType.MUSIC, studentRegistration.getMusicGroupId(), studentRegistration.getUserId(),DealStatusEnum.SUCCESS , OrderTypeEnum.APPLY);
-        
-        int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
-        int paidZeroNum = musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum();
-        if ((musicGroup.getCourseViewType().equals(CourseViewTypeEnum.MEMBER_FEE) && !buyCloudTeacher))
-        {
-            paidZeroFlag = true;
-            if (studentRegistration.getNoneNeedCloudTeacher().equals(1) && (oldStudentPaymentOrderList == null || oldStudentPaymentOrderList.size() == 0)) {
-                musicOneSubjectClassPlan.setPaidZeroNum(paidZeroNum + 1);
-                musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
-            }
-        } else {
-			if (oldStudentPaymentOrderList == null || oldStudentPaymentOrderList.size() == 0) {
-				musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
+		if (studentRegistration.getMusicGroupStatus() != StudentMusicGroupStatusEnum.NORMAL) {
+			// 判断之前是否已有订单
+			List<StudentPaymentOrder> oldStudentPaymentOrderList = studentPaymentOrderService.queryByCondition(GroupType.MUSIC,
+					studentRegistration.getMusicGroupId(), studentRegistration.getUserId(), DealStatusEnum.SUCCESS, OrderTypeEnum.APPLY);
+
+			int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
+			int paidZeroNum = musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum();
+			if ((musicGroup.getCourseViewType().equals(CourseViewTypeEnum.MEMBER_FEE) && !buyCloudTeacher && StringUtils.isBlank(maintenanceGoodsId))) {
+				if (studentRegistration.getPaymentStatus() != YES) {
+					paidZeroFlag = true;
+				}
+				if (studentRegistration.getNoneNeedCloudTeacher().equals(1) && (oldStudentPaymentOrderList == null || oldStudentPaymentOrderList.size() == 0)) {
+					musicOneSubjectClassPlan.setPaidZeroNum(paidZeroNum + 1);
+					musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
+				}
+			} else {
+				if (oldStudentPaymentOrderList == null || oldStudentPaymentOrderList.size() == 0) {
+					musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
+				}
 			}
-        }
-        if (musicOneSubjectClassPlan.getPaidStudentNum() > musicOneSubjectClassPlan.getExpectedStudentNum()) {
-            throw new BizException("乐团该声部人数暂时已满,请稍后再试");
-        }
-        
-        int count = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
-        if (count <= 0) {
-            throw new BizException("排队人数过多,请重试");
-        }
+			if (musicOneSubjectClassPlan.getPaidStudentNum() > musicOneSubjectClassPlan.getExpectedStudentNum()) {
+				throw new BizException("乐团该声部人数暂时已满,请稍后再试");
+			}
+
+			int count = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
+			if (count <= 0) {
+				throw new BizException("排队人数过多,请重试");
+			}
+		}
         if (paidZeroFlag) {
             studentPaymentOrder.setVersion(0);
             String code = studentRegistration.getNoneNeedCloudTeacher().equals(1) ? "200" : "205";
@@ -1180,11 +1189,13 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
 					studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
 				}
 				
-				if (orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER)
-						|| orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER_PLUS)) {
+				if (orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER) || orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER_PLUS)
+						|| orderTypeList.contains(OrderDetailTypeEnum.MUSICAL)) {
 					studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
-					studentRegistration.setNoneNeedCloudTeacher(1);
-					studentRegistration.setHasCloudTeacher(1);
+					//studentRegistration.setNoneNeedCloudTeacher(1);
+					if (orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER) || orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER_PLUS)) {
+						studentRegistration.setHasCloudTeacher(1);
+					}
 				}
 			} else {
 				studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
@@ -1681,14 +1692,25 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
         for (int i = 0; i < 10; i++) {
             MusicGroupSubjectPlan originalSubjectPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(musicGroupId, originalSubjectId);
             int originalPaidNum = originalSubjectPlan.getPaidStudentNum() == null ? 0 : originalSubjectPlan.getPaidStudentNum();
+            int originalZeroPaidNum = originalSubjectPlan.getPaidZeroNum() == null ? 0 : originalSubjectPlan.getPaidZeroNum();
             int originalPaidCount = 1;
             if (originalPaidNum > 0) {
                 originalSubjectPlan.setPaidStudentNum(originalPaidNum - 1);
+                //是否是0元入团
+                if(studentRegistration.getNoneNeedCloudTeacher() != null && studentRegistration.getNoneNeedCloudTeacher() == 1){
+                	originalSubjectPlan.setPaidZeroNum(originalZeroPaidNum - 1);
+                }
                 originalPaidCount = musicGroupSubjectPlanService.update(originalSubjectPlan);
             }
             MusicGroupSubjectPlan changeSubjectPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(musicGroupId, changeSubjectId);
             int changelPaidNum = changeSubjectPlan.getPaidStudentNum() == null ? 0 : changeSubjectPlan.getPaidStudentNum();
             changeSubjectPlan.setPaidStudentNum(changelPaidNum + 1);
+            if(studentRegistration.getNoneNeedCloudTeacher() != null && studentRegistration.getNoneNeedCloudTeacher() == 1){
+            	if(changeSubjectPlan.getPaidZeroNum() != null && changeSubjectPlan.getPaidZeroNum() > 0){
+            		throw new BizException("声部更换失败,当前用户是0元入团,且当前声部已有0元入团学生");
+            	}
+            	changeSubjectPlan.setPaidZeroNum(1);
+            }
             int changePaidCount = musicGroupSubjectPlanService.update(changeSubjectPlan);
             if (originalPaidCount > 0 && changePaidCount > 0) {
                 updateFlag = true;
@@ -1962,6 +1984,7 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
         }
         studentRegistration.setPayingStatus(0);
         studentRegistration.setNoneNeedCloudTeacher(1);
+        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
         if (studentRegistrationDao.update(studentRegistration) <= 0) {
             throw new BizException("设置失败,请重试");
         }
@@ -1971,16 +1994,23 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
     @Override
     @Transactional(rollbackFor = Exception.class)
     public HttpResponseResult<Boolean> addPaidNum(Long id, boolean isContinue) {
-        StudentRegistration studentRegistration = studentRegistrationDao.get(id);
+        StudentRegistration studentRegistration = studentRegistrationDao.lock(id);
         if (!studentRegistration.getPayingStatus().equals(2)) {
             throw new BizException("该学生不在审核");
         }
-        if (!studentRegistration.getPaymentStatus().equals(YES)) {
-            throw new BizException("该学生状态已更新,请刷新查看");
+        if (studentRegistration.getNoneNeedCloudTeacher().equals(1)) {
+            throw new BizException("该学生已设置");
         }
 
         MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());
         
+        int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
+        int paidZeroNum = musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum();
+        
+        if(paidZeroNum > 0){
+        	throw new BizException("每个声部只能有一个免费入团名额");
+        }
+        
         if(!isContinue){
         	if (musicOneSubjectClassPlan.getPaidStudentNum() >= musicOneSubjectClassPlan.getExpectedStudentNum()) {
                 return new HttpResponseResult<Boolean>(true, HttpStatus.CONTINUE, null, "乐团该声部招生人数已满,是否继续操作?");
@@ -1989,16 +2019,35 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
         
         studentRegistration.setPayingStatus(0);
         studentRegistration.setNoneNeedCloudTeacher(1);
+        studentRegistration.setPaymentStatus(YES);
         studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
         studentRegistrationDao.update(studentRegistration);
-        StudentPaymentOrder order = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(studentRegistration.getUserId(), studentRegistration.getMusicGroupId(), DealStatusEnum.SUCCESS);
-        order.setPaymentAccountNo("200");
-        if(studentPaymentOrderService.update(order)<=0){
-            throw new BizException("订单处理失败,请重试");
-        }
+        /*StudentPaymentOrder order = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(studentRegistration.getUserId(), studentRegistration.getMusicGroupId(), DealStatusEnum.SUCCESS);
+		if (order != null) {
+			order.setPaymentAccountNo("200");
+			if (studentPaymentOrderService.update(order) <= 0) {
+				throw new BizException("订单处理失败,请重试");
+			}
+		}*/
+        
+		List<StudentPaymentOrder> studentPaymentOrderList = studentPaymentOrderService.queryByCondition(GroupType.MUSIC, studentRegistration.getMusicGroupId(), studentRegistration.getUserId(), DealStatusEnum.ING, OrderTypeEnum.APPLY);
+		
+		List<StudentPaymentOrder> updateList = new ArrayList<StudentPaymentOrder>();
+		
+		if(studentPaymentOrderList != null && studentPaymentOrderList.size() > 0){
+			for(StudentPaymentOrder studentPaymentOrder : studentPaymentOrderList){
+				if(StringUtils.equals("205", studentPaymentOrder.getPaymentAccountNo())){
+					studentPaymentOrder.setStatus(DealStatusEnum.CLOSE);
+					studentPaymentOrder.setMemo("用户未支付");
+					updateList.add(studentPaymentOrder);
+				}
+			}
+		}
+		
+		if(updateList.size() > 0){
+			studentPaymentOrderService.batchUpdate(updateList);
+		}
         
-        int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
-        int paidZeroNum = musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum();
         musicOneSubjectClassPlan.setPaidZeroNum(paidZeroNum + 1);
         musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
         int count = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);

+ 23 - 22
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentServeServiceImpl.java

@@ -299,8 +299,9 @@ public class StudentServeServiceImpl implements StudentServeService {
     public void exercisesSituationStatistics2(String monday, List<Integer> studentIds) {
         LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();
 
+        int preWeekServiceNum = studentExtracurricularExercisesSituationDao.countWeekServiceNum(nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()).plusDays(-7).toString());
         int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.plusDays(-nowDate.getDayOfWeek().getValue()).toString());
-        if(lastWeekTodayUpdateNum<=0){
+        if(preWeekServiceNum>0 && lastWeekTodayUpdateNum<=0){
             nowDate = nowDate.plusDays(-nowDate.getDayOfWeek().getValue());
         }
 
@@ -913,18 +914,18 @@ public class StudentServeServiceImpl implements StudentServeService {
             return result;
         }
 
-        String configValue = sysConfigDao.findConfigValue(SysConfigService.HOMEWORK_OPEN_FLAG);
-        if(StringUtils.isEmpty(configValue)){
-            configValue = "0";
-        }
+//        String configValue = sysConfigDao.findConfigValue(SysConfigService.HOMEWORK_OPEN_FLAG);
+//        if(StringUtils.isEmpty(configValue)){
+//            configValue = "0";
+//        }
         List<Integer> studentIds=new ArrayList<>();
         if(StringUtils.isNotBlank(studentIdsStr)){
-            if(configValue.equals("0")){
-                result.put("memberNum",0);
-            }else {
+//            if(configValue.equals("0")){
+//                result.put("memberNum",0);
+//            }else {
                 //获取有会员的学员数
-                result.put("memberNum", studentDao.getMemberNum(studentIdsStr));
-            }
+//                result.put("memberNum", studentDao.getMemberNum(studentIdsStr));
+//            }
             studentIds= Arrays.asList(studentIdsStr.split(",")).stream().map(id->Integer.valueOf(id)).collect(Collectors.toList());
         }
 
@@ -938,18 +939,18 @@ public class StudentServeServiceImpl implements StudentServeService {
                 result.put("isAssignHomework", 0);
                 return result;
             }
-            if(configValue.equals("0")){
-                result.put("memberNum",0);
-                result.put("courseViewType", CourseViewTypeEnum.COURSE_FEE);
-            }else {
-                MusicGroup musicGroup = musicGroupDao.get(courseSchedule.getMusicGroupId());
-                if(musicGroup != null){
-                    result.put("courseViewType", musicGroup.getCourseViewType());
-                }else if(result.get("memberNum") == null){
-                    Set<Integer> collect = students.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
-                    result.put("memberNum", studentDao.getMemberNum(StringUtils.join(collect,",")));
-                }
-            }
+//            if(configValue.equals("0")){
+//                result.put("memberNum",0);
+//                result.put("courseViewType", CourseViewTypeEnum.COURSE_FEE);
+//            }else {
+//                MusicGroup musicGroup = musicGroupDao.get(courseSchedule.getMusicGroupId());
+//                if(musicGroup != null){
+//                    result.put("courseViewType", musicGroup.getCourseViewType());
+//                }else if(result.get("memberNum") == null){
+//                    Set<Integer> collect = students.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
+//                    result.put("memberNum", studentDao.getMemberNum(StringUtils.join(collect,",")));
+//                }
+//            }
 
             localDate=LocalDateTime.ofInstant(courseSchedule.getClassDate().toInstant(), DateUtil.zoneId).toLocalDate();
             List<CourseScheduleStudentPayment> courseScheduleStudentPayments = courseScheduleStudentPaymentDao.findByCourseSchedule(courseScheduleId);

+ 50 - 7
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SubjectChangeServiceImpl.java

@@ -77,6 +77,8 @@ public class SubjectChangeServiceImpl extends BaseServiceImpl<Integer, SubjectCh
     private MusicGroupPurchaseListDao musicGroupPurchaseListDao;
     @Autowired
     private StudentRegistrationDao studentRegistrationDao;
+    @Autowired
+    private MusicGroupSubjectPlanService musicGroupSubjectPlanService;
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
@@ -229,10 +231,41 @@ public class SubjectChangeServiceImpl extends BaseServiceImpl<Integer, SubjectCh
     @Override
     @Transactional(rollbackFor = Exception.class)
     public SubjectChange addChange(SubjectChange subjectChange) {
-        SubjectChange studentWaitPay = subjectChangeDao.getStudentWaitPay(subjectChange.getStudentId(), subjectChange.getMusicGroupId());
+    	String musicGroupId = subjectChange.getMusicGroupId();
+        SubjectChange studentWaitPay = subjectChangeDao.getStudentWaitPay(subjectChange.getStudentId(), musicGroupId);
         if (studentWaitPay != null) {
             throw new BizException("已有未支付的声部更改,请勿重复创建");
         }
+        
+        studentWaitPay = subjectChangeDao.getStudentLastChange(subjectChange.getStudentId(), musicGroupId);
+        if (studentWaitPay != null) {
+            throw new BizException("声部更换只能操作一次,请勿重复操作");
+        }
+        
+        Set<String> musicGroupIds = new HashSet<String>();
+        musicGroupIds.add(musicGroupId);
+        
+        List<MusicGroupPurchaseList> musicGroupPurchaseListCount = musicGroupPurchaseListDao.getCount(musicGroupIds);
+        if (musicGroupPurchaseListCount.size() > 0) {
+            throw new BizException("乐器清单已确认,不能做声部更改");
+        }
+        
+        //判断新声部人数是否已满
+        MusicGroupSubjectPlan changeSubjectPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(musicGroupId, subjectChange.getChangeSubjectId());
+		if (changeSubjectPlan.getExpectedStudentNum() <= changeSubjectPlan.getPaidStudentNum()) {
+			throw new BizException("当前声部人数已满");
+		}
+		
+		StudentRegistration studentRegistration = studentRegistrationDao.getStudentRegister(musicGroupId, subjectChange.getStudentId());
+		if(studentRegistration == null){
+			throw new BizException("用户乐团报名信息查询失败");
+		}
+        
+        if(studentRegistration.getNoneNeedCloudTeacher() != null && studentRegistration.getNoneNeedCloudTeacher() == 1){
+        	if(changeSubjectPlan.getPaidZeroNum() != null && changeSubjectPlan.getPaidZeroNum() > 0){
+        		throw new BizException("声部更换失败,当前用户是0元入团,且当前声部已有0元入团学生");
+        	}
+        }        
         Date nowDate = new Date();
         SubjectChange studentOriginal = getStudentOriginal(subjectChange.getStudentId(), subjectChange.getMusicGroupId());
         if(studentOriginal != null){
@@ -403,8 +436,10 @@ public class SubjectChangeServiceImpl extends BaseServiceImpl<Integer, SubjectCh
         
         List<Long> paymentOrderIdList = studentPaymentOrderList.stream().map(t -> t.getId()).collect(Collectors.toList());
 
-        List<StudentPaymentOrderDetail> details = studentPaymentOrderDetailDao.getWithIds(paymentOrderIdList);
-        
+        List<StudentPaymentOrderDetail> details = new ArrayList<StudentPaymentOrderDetail>();
+		if (paymentOrderIdList != null && paymentOrderIdList.size() > 0) {
+			details = studentPaymentOrderDetailDao.getWithIds(paymentOrderIdList);
+		}
 
         //查询乐器订单
         StudentPaymentOrderDetail musicalOrderDetail =null, accessoriesOrderDetail = null;
@@ -417,8 +452,11 @@ public class SubjectChangeServiceImpl extends BaseServiceImpl<Integer, SubjectCh
         	}
         }
 
-        Set<Integer> refundSellOrderGoodsIds = getRefundGoodsId(details.stream().map(t -> t.getPaymentOrderId()).collect(Collectors.toList()));
-
+		Set<Integer> refundSellOrderGoodsIds = new HashSet<Integer>();
+		if (details.size() > 0) {
+			refundSellOrderGoodsIds = getRefundGoodsId(details.stream().map(t -> t.getPaymentOrderId()).collect(Collectors.toList()));
+		}
+		
         MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
         subjectChange.setStudentId(studentId);
         subjectChange.setOrganId(musicGroup.getOrganId());
@@ -466,7 +504,10 @@ public class SubjectChangeServiceImpl extends BaseServiceImpl<Integer, SubjectCh
             subjectChange.setOriginalAccessoriesPrice(price);
         }
         //2.2 计算销售成本
-        BigDecimal orderSellCost = sellOrderDao.getOrderSellCost(paymentOrderIdList);
+        BigDecimal orderSellCost = BigDecimal.ZERO;
+        if (paymentOrderIdList != null && paymentOrderIdList.size() > 0) {
+        	orderSellCost = sellOrderDao.getOrderSellCost(paymentOrderIdList);
+        }
         subjectChange.setOriginalCost(orderSellCost == null ? BigDecimal.ZERO : orderSellCost);
         return subjectChange;
     }
@@ -541,7 +582,9 @@ public class SubjectChangeServiceImpl extends BaseServiceImpl<Integer, SubjectCh
             if (StringUtils.isNotBlank(goodsIds)) {
                 List<Integer> goodsIdList = Arrays.stream(goodsIds.split(",")).map(Integer::parseInt).collect(Collectors.toList());
                 //退原订单商品
-                sellOrderService.refundByOrderId(subjectChange.getOriginalOrderId().longValue(), false);
+                if(subjectChange.getOriginalOrderId() != null){
+                	sellOrderService.refundByOrderId(subjectChange.getOriginalOrderId().longValue(), false);
+                }
                 //添加新订单
                 this.addSellOrder(studentPaymentOrder.getId(), subjectChange.getMusicGroupId(), goodsIdList, studentPaymentOrder.getExpectAmount(), studentPaymentOrder.getBalancePaymentAmount(), subjectChange.getKitGroupPurchaseType());
             }

+ 14 - 4
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java

@@ -2,17 +2,21 @@ package com.ym.mec.biz.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.dao.SysMusicCompareRecordDao;
 import com.ym.mec.biz.dal.dao.TeacherDao;
 import com.ym.mec.biz.dal.dto.SoundCompareHelper;
-import com.ym.mec.common.dal.BaseDAO;
-import org.springframework.beans.factory.annotation.Autowired;
-import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
+import com.ym.mec.biz.dal.enums.FeatureType;
 import com.ym.mec.biz.service.SysMusicCompareRecordService;
-import com.ym.mec.biz.dal.dao.SysMusicCompareRecordDao;
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.service.impl.BaseServiceImpl;
+import com.ym.mec.util.date.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
 import java.util.Map;
 import java.util.Objects;
 
@@ -47,6 +51,12 @@ public class SysMusicCompareRecordServiceImpl extends BaseServiceImpl<Long, SysM
 			sysMusicCompareRecord.setIntegrity((BigDecimal) finalScore.get("integrity"));
 		}
 		sysMusicCompareRecord.setRecordFilePath(soundCompareInfo.getRecordFilePath());
+		sysMusicCompareRecord.setDeviceType(soundCompareInfo.getDeviceType());
+		sysMusicCompareRecord.setClientId(soundCompareInfo.getClientId());
+		if(Objects.nonNull(soundCompareInfo.getFile())){
+			sysMusicCompareRecord.setPlayTime(soundCompareInfo.getFile().length()/(SoundCompareHandler.soundCompareConfig.audioFormat.getFrameSize()*SoundCompareHandler.soundCompareConfig.audioFormat.getFrameRate()));
+		}
+		sysMusicCompareRecord.setFeature(FeatureType.CLOUD_STUDY_EVALUATION);
 		sysMusicCompareRecordDao.insert(sysMusicCompareRecord);
 	}
 }

+ 13 - 2
mec-biz/src/main/resources/config/mybatis/CloudTeacherOrderMapper.xml

@@ -22,7 +22,7 @@
         <result column="update_time_" property="updateTime"/>
         <result column="music_group_id_" property="musicGroupId"/>
     </resultMap>
-
+    
     <resultMap type="com.ym.mec.biz.dal.dto.CloudTeacherOrderDto" id="CloudTeacherOrderDto">
     	<id column="id_" property="cloudTeacherOrder.id"/>
         <result column="organ_id_" property="cloudTeacherOrder.organId"/>
@@ -186,11 +186,22 @@
         SELECT cto.* FROM cloud_teacher_order cto
         WHERE order_id_ = #{orderId}
     </select>
-
+    
     <select id="queryOrderInfoByOrderId" resultMap="CloudTeacherOrderDto">
         SELECT cto.*,spo.status_ trans_status_,spo.expect_amount_,mrs.name_,mrs.icon_ FROM cloud_teacher_order cto
        left join student_payment_order spo on cto.order_id_ = spo.id_
        left join member_rank_setting mrs on mrs.id_ = cto.level_
         where spo.type_ = 'MEMBER' and order_id_ = #{orderId}
     </select>
+    <select id="queryNoStartByUserIds" resultType="java.util.Map">
+        SELECT student_id_ 'key',create_time_ 'value' FROM cloud_teacher_order
+        WHERE status_ = 1
+        <if test="userIds != null and userIds.size > 0">
+            AND student_id_ IN
+            <foreach collection="userIds" separator="," item="userId" open="(" close=")">
+                #{userId}
+            </foreach>
+        </if>
+        GROUP BY student_id_
+    </select>
 </mapper>

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

@@ -471,7 +471,7 @@
 	</select>
 
 	<select id="countWeekServiceNum" resultType="int">
-		SELECT COUNT(id_) FROM student_extracurricular_exercises_situation_ WHERE monday_=#{sunday}
+		SELECT COUNT(id_) FROM student_extracurricular_exercises_situation_ WHERE monday_=#{monday}
 	</select>
 
 	<select id="findWeekServiceWithStudents" resultMap="StudentExtracurricularExercisesSituation">

+ 7 - 3
mec-biz/src/main/resources/config/mybatis/StudentPaymentOrderMapper.xml

@@ -984,12 +984,16 @@
     </select>
 
     <select id="getMoneyInMusicApply" resultMap="Mapper">
-        SELECT sum(spo.expect_amount_) value_,spo.music_group_id_ key_ 
-        FROM student_payment_order spo WHERE spo.music_group_id_ IN
+        SELECT spo.music_group_id_ key_, sum(case when a.id_ is null then spo.expect_amount_ else (spo.expect_amount_ + a.goods_margin_) end) value_ from student_payment_order spo LEFT JOIN
+		(
+		SELECT * FROM subject_change WHERE id_ in
+		(SELECT max(sc.id_) id_ from subject_change sc WHERE sc.status_ = 2 GROUP BY music_group_id_,student_id_ ORDER BY id_ desc)
+		) a on spo.music_group_id_ = a.music_group_id_ and spo.user_id_ = a.student_id_
+		WHERE spo.music_group_id_ IN
         <foreach collection="musicGroupIds" item="musicGroupId" open="(" close=")" separator=",">
             #{musicGroupId}
         </foreach>
         AND spo.type_ = 'APPLY' and spo.status_ = 'SUCCESS'
-        GROUP BY spo.music_group_id_
+		GROUP BY spo.music_group_id_
     </select>
 </mapper>

+ 19 - 4
mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml

@@ -16,6 +16,11 @@
 		<result column="cadence_" property="cadence" />
 		<result column="integrity_" property="integrity" />
 		<result column="record_file_path_" property="recordFilePath" />
+		<result column="device_type_" property="deviceType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler" />
+		<result column="client_id_" property="clientId" />
+		<result column="play_time_" property="playTime"/>
+		<result column="feature_" property="feature" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler" />
+		<result column="monday_" property="monday"/>
 		<result column="create_time_" property="createTime" />
 	</resultMap>
 
@@ -36,8 +41,12 @@
 		SELECT SEQ_WSDEFINITION_ID.nextval AS ID FROM DUAL 
 		</selectKey>
 		-->
-		INSERT INTO sys_music_compare_record (id_,user_id_,sys_music_score_id_,score_data_,score_,intonation_,cadence_,integrity_,record_file_path_,create_time_)
-		VALUES(#{id},#{userId},#{sysMusicScoreId},#{scoreData},#{score},#{intonation},#{cadence},#{integrity},#{recordFilePath},NOW())
+		INSERT INTO sys_music_compare_record (id_,user_id_,sys_music_score_id_,score_data_,score_,intonation_,cadence_,integrity_,
+		                                      record_file_path_,device_type_,client_id_,play_time_,monday_,
+											feature_,create_time_)
+		VALUES(#{id},#{userId},#{sysMusicScoreId},#{scoreData},#{score},#{intonation},#{cadence},#{integrity},
+		       #{recordFilePath},#{deviceType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{clientId},#{playTime},#{monday},
+		       #{feature,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}, NOW())
 	</insert>
 
 	<!-- 根据主键查询一条记录 -->
@@ -70,8 +79,14 @@
 		<if test="recordFilePath != null">
 			record_file_path_ = #{recordFilePath},
 		</if>
-		<if test="createTime != null">
-			create_time_ = #{createTime},
+		<if test="clientId != null">
+			client_id_ = #{clientId},
+		</if>
+		<if test="playTime != null">
+			play_time_ = #{playTime},
+		</if>
+		<if test="monday != null">
+			monday_ = #{monday},
 		</if>
 	</set> WHERE id_ = #{id}
 	</update>

+ 31 - 4
mec-biz/src/main/resources/config/mybatis/SysSuggestionMapper.xml

@@ -15,6 +15,7 @@
         <result column="username_" property="username"/>
         <result column="create_time_" property="createTime"/>
         <result column="client_type_" property="clientType"/>
+        <result column="type_" property="type" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
     </resultMap>
 
     <!-- 根据主键查询一条记录 -->
@@ -30,8 +31,8 @@
     <!-- 向数据库增加一条记录 -->
     <insert id="insert" parameterType="com.ym.mec.biz.dal.entity.SysSuggestion" useGeneratedKeys="true" keyColumn="id"
             keyProperty="id">
-        INSERT INTO sys_suggestion (id_,mobile_no_,title_,content_,user_id_,create_time_,client_type_)
-        VALUES(#{id},#{mobileNo},#{title},#{content},#{userId},now(),#{clientType})
+        INSERT INTO sys_suggestion (id_,mobile_no_,title_,content_,user_id_,create_time_,client_type_,type_)
+        VALUES(#{id},#{mobileNo},#{title},#{content},#{userId},now(),#{clientType},#{type, typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler})
     </insert>
 
     <!-- 根据主键查询一条记录 -->
@@ -53,6 +54,9 @@
             <if test="mobileNo != null">
                 mobile_no_ = #{mobileNo},
             </if>
+            <if test="type != null">
+                type_ = #{type, typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},
+            </if>
         </set>
         WHERE id_ = #{id}
     </update>
@@ -62,16 +66,39 @@
 		DELETE FROM sys_suggestion WHERE id_ = #{id} 
 	</delete>
 
+    <sql id="queryCondition">
+        <where>
+            <if test="type!=null">
+                AND ss.type_ = #{type, typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+            </if>
+            <if test="clientType!=null">
+                AND ss.client_type_ = #{clientType}
+            </if>
+            <if test="startTime!=null and startTime!=''">
+                AND DATE_FORMAT(ss.create_time_,'%Y-%m-%d') &gt;= #{startTime}
+            </if>
+            <if test="endTime!=null and endTime!=''">
+                AND DATE_FORMAT(ss.create_time_,'%Y-%m-%d') &lt;= #{endTime}
+            </if>
+            <if test="search!=null and search!=''">
+                AND (su.real_name_ LIKE CONCAT('%', #{search}, '%') OR su.username_ LIKE CONCAT('%', #{search}, '%') OR ss.user_id_=#{search} OR su.phone_=#{search})
+            </if>
+        </where>
+    </sql>
+
     <!-- 分页查询 -->
     <select id="queryPage" resultMap="SysSuggestion" parameterType="map">
-        SELECT ss.*,CASE WHEN su.real_name_ IS NULL THEN su.username_ ELSE su.real_name_ END username_ FROM sys_suggestion ss
+        SELECT ss.*,CASE WHEN ss.client_type_='STUDENT' THEN su.username_ ELSE su.real_name_ END username_ FROM sys_suggestion ss
         LEFT JOIN sys_user su ON su.id_ = ss.user_id_
+        <include refid="queryCondition" />
         ORDER BY ss.id_ DESC
         <include refid="global.limit"/>
     </select>
 
     <!-- 查询当前表的总记录数 -->
     <select id="queryCount" resultType="int">
-		SELECT COUNT(*) FROM sys_suggestion
+		SELECT COUNT(ss.id_) FROM sys_suggestion ss
+        LEFT JOIN sys_user su ON su.id_ = ss.user_id_
+        <include refid="queryCondition" />
 	</select>
 </mapper>

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

@@ -181,7 +181,8 @@ public class MusicGroupController extends BaseController {
         	//判断是否所有类型都购买完
 			if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {
 				if ((typeList.contains(OrderDetailTypeEnum.MUSICAL) || typeList.contains(OrderDetailTypeEnum.ACCESSORIES))
-						&& (typeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER) || typeList.contains(OrderDetailTypeEnum.COURSE)
+						&& typeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER)
+						&& (typeList.contains(OrderDetailTypeEnum.COURSE)
 								|| typeList.contains(OrderDetailTypeEnum.HIGH_ONLINE_COURSE) || typeList.contains(OrderDetailTypeEnum.SINGLE)
 								|| typeList.contains(OrderDetailTypeEnum.MIX) || typeList.contains(OrderDetailTypeEnum.HIGH)
 								|| typeList.contains(OrderDetailTypeEnum.VIP) || typeList.contains(OrderDetailTypeEnum.DEMO)

+ 6 - 4
mec-student/src/main/java/com/ym/mec/student/controller/StudentManageController.java

@@ -1,13 +1,11 @@
 package com.ym.mec.student.controller;
 
+import com.ym.mec.biz.dal.enums.SuggestionType;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -121,6 +119,9 @@ public class StudentManageController extends BaseController {
         }
     	sysSuggestion.setClientType("STUDENT");
         sysSuggestion.setUserId(sysUser.getId().longValue());
+        if(StringUtils.isEmpty(sysSuggestion.getMobileNo())){
+            sysSuggestion.setMobileNo(sysUser.getPhone());
+        }
         suggestionService.insert(sysSuggestion);
         return succeed();
     }
@@ -136,6 +137,7 @@ public class StudentManageController extends BaseController {
 		Student student = studentService.get(user.getId());
 		student.setId(user.getId());
 		student.setUsername(user.getUsername());
+		student.setAvatar(user.getAvatar());
 		student.setPhone(user.getPhone());
 		student.setCurrentClass(user.getCurrentClass());
 		student.setCurrentGrade(user.getCurrentGrade());

+ 48 - 0
mec-student/src/main/java/com/ym/mec/student/controller/SysMusicCompareRecordController.java

@@ -0,0 +1,48 @@
+package com.ym.mec.student.controller;
+
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
+import com.ym.mec.biz.service.SysMusicCompareRecordService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import com.ym.mec.common.exception.BizException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Objects;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/13 0013
+ */
+@Api(tags = "云教练记录")
+@RequestMapping("sysMusicRecord")
+@RestController
+public class SysMusicCompareRecordController extends BaseController {
+
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private SysMusicCompareRecordService sysMusicCompareRecordService;
+
+    @ApiOperation(value = "添加记录")
+    @PostMapping("add")
+    public HttpResponseResult add(SysMusicCompareRecord record){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if(sysUser == null){
+            throw new BizException("请登录");
+        }
+        if(Objects.isNull(record.getFeature())){
+            return failed("请设置功能点");
+        }
+        record.setUserId(sysUser.getId());
+        record.setClientId("student");
+        return succeed(sysMusicCompareRecordService.insert(record));
+    }
+
+}

+ 6 - 0
mec-teacher/src/main/java/com/ym/mec/teacher/controller/SoundController.java

@@ -49,6 +49,12 @@ public class SoundController extends BaseController {
         return soundService.measureCompare(musicXmlInfoList, record);
     }
 
+    @ApiOperation(value = "获取在线人数")
+    @GetMapping("getOnlineUserNum")
+    public HttpResponseResult getOnlineUserNum(){
+        return succeed(WebSocketHandler.WS_CLIENTS.size());
+    }
+
     @RequestMapping("sendToUser")
     public HttpResponseResult sendToUser(String phone, String message) throws IOException {
         if(!WebSocketHandler.WS_CLIENTS.containsKey(phone)){

+ 48 - 0
mec-teacher/src/main/java/com/ym/mec/teacher/controller/SysMusicCompareRecordController.java

@@ -0,0 +1,48 @@
+package com.ym.mec.teacher.controller;
+
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
+import com.ym.mec.biz.service.SysMusicCompareRecordService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import com.ym.mec.common.exception.BizException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Objects;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/13 0013
+ */
+@Api(tags = "云教练记录")
+@RequestMapping("sysMusicRecord")
+@RestController
+public class SysMusicCompareRecordController extends BaseController {
+
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private SysMusicCompareRecordService sysMusicCompareRecordService;
+
+    @ApiOperation(value = "添加记录")
+    @PostMapping("add")
+    public HttpResponseResult add(SysMusicCompareRecord record){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if(sysUser == null){
+            throw new BizException("请登录");
+        }
+        if(Objects.isNull(record.getFeature())){
+            return failed("请设置功能点");
+        }
+        record.setUserId(sysUser.getId());
+        record.setClientId("teacher");
+        return succeed(sysMusicCompareRecordService.insert(record));
+    }
+
+}

+ 6 - 0
mec-teacher/src/main/java/com/ym/mec/teacher/controller/TeacherManageController.java

@@ -1,5 +1,6 @@
 package com.ym.mec.teacher.controller;
 
+import com.ym.mec.biz.dal.enums.SuggestionType;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -30,6 +31,8 @@ import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.entity.UploadReturnBean;
 import com.ym.mec.util.upload.UploadUtil;
 
+import java.util.Objects;
+
 @Api(tags = "教师管理")
 @RestController
 public class TeacherManageController extends BaseController {
@@ -79,6 +82,9 @@ public class TeacherManageController extends BaseController {
         }
         sysSuggestion.setUserId(sysUser.getId().longValue());
     	sysSuggestion.setClientType("TEACHER");
+        if(StringUtils.isEmpty(sysSuggestion.getMobileNo())){
+            sysSuggestion.setMobileNo(sysUser.getPhone());
+        }
         suggestionService.insert(sysSuggestion);
         return succeed();
     }

+ 28 - 0
mec-web/src/main/java/com/ym/mec/web/controller/SoundCompareController.java

@@ -0,0 +1,28 @@
+package com.ym.mec.web.controller;
+
+import com.ym.mec.biz.handler.WebSocketHandler;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/10 0010
+ */
+@Api(tags = "音频服务")
+@RequestMapping("soundCompare")
+@RestController
+public class SoundCompareController extends BaseController {
+
+    @ApiOperation(value = "获取在线人数")
+    @GetMapping("getOnlineUserNum")
+    public HttpResponseResult getOnlineUserNum(){
+        return succeed(WebSocketHandler.WS_CLIENTS.size());
+    }
+
+}

+ 1 - 8
mec-web/src/main/java/com/ym/mec/web/controller/StudentRegistrationController.java

@@ -46,7 +46,6 @@ import com.ym.mec.biz.dal.entity.StudentPaymentOrderDetail;
 import com.ym.mec.biz.dal.entity.StudentRegistration;
 import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
 import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
-import com.ym.mec.biz.dal.enums.PaymentStatusEnum;
 import com.ym.mec.biz.dal.page.NoClassMusicStudentQueryInfo;
 import com.ym.mec.biz.dal.page.RegistrationOrPreQueryInfo;
 import com.ym.mec.biz.dal.page.StudentPreRegistrationQueryInfo;
@@ -443,13 +442,7 @@ public class StudentRegistrationController extends BaseController {
     	if(isContinue == null){
     		isContinue = false;
     	}
-        StudentRegistration studentRegistration = studentRegistrationService.get(id);
-        //已付费的增加,已缴费人数、和0元付费人数
-        if (studentRegistration.getPaymentStatus().equals(PaymentStatusEnum.YES)) {
-            return studentRegistrationService.addPaidNum(id, isContinue);
-        } else {
-            return succeed(studentRegistrationService.setNoneCloudTeacher(id));
-        }
+    	return studentRegistrationService.addPaidNum(id, isContinue);
     }
 
 

+ 40 - 10
mec-web/src/main/java/com/ym/mec/web/controller/SysSuggestionController.java

@@ -1,36 +1,66 @@
 package com.ym.mec.web.controller;
 
-import com.ym.mec.biz.dal.entity.ChargeType;
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.SysSuggestion;
-import com.ym.mec.biz.service.ChargeTypeService;
+import com.ym.mec.biz.dal.enums.SuggestionType;
+import com.ym.mec.biz.dal.page.SysSuggestionQueryInfo;
 import com.ym.mec.biz.service.SysSuggestionService;
 import com.ym.mec.common.controller.BaseController;
-import com.ym.mec.common.page.QueryInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Objects;
 
-@RequestMapping("sysSuggestion")
 @Api(tags = "意见反馈")
 @RestController
 public class SysSuggestionController extends BaseController {
 
     @Autowired
     private SysSuggestionService sysSuggestionService;
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
 
     @ApiOperation(value = "新增")
-    @RequestMapping("/add")
+    @RequestMapping("sysSuggestion/add")
     @PreAuthorize("@pcs.hasPermissions('sysSuggestion/add')")
     public Object add(SysSuggestion sysSuggestion) {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        sysSuggestion.setUserId(sysUser.getId().longValue());
+        sysSuggestion.setClientType("TEACHER");
+        if(StringUtils.isEmpty(sysSuggestion.getMobileNo())){
+            sysSuggestion.setMobileNo(sysUser.getPhone());
+        }
+        sysSuggestionService.insert(sysSuggestion);
+        return succeed();
+    }
+
+    @ApiOperation(value = "新增")
+    @RequestMapping("suggestion/add")
+    public Object suggestionAdd(SysSuggestion sysSuggestion) {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        sysSuggestion.setUserId(sysUser.getId().longValue());
+        sysSuggestion.setClientType("EDUCATION");
+        if(StringUtils.isEmpty(sysSuggestion.getMobileNo())){
+            sysSuggestion.setMobileNo(sysUser.getPhone());
+        }
         sysSuggestionService.insert(sysSuggestion);
         return succeed();
     }
 
     @ApiOperation(value = "删除")
-    @RequestMapping("/del")
+    @RequestMapping("sysSuggestion/del")
     @PreAuthorize("@pcs.hasPermissions('sysSuggestion/del')")
     public Object del(Long id) {
         sysSuggestionService.delete(id);
@@ -38,9 +68,9 @@ public class SysSuggestionController extends BaseController {
     }
 
     @ApiOperation(value = "分页查询")
-    @RequestMapping("/queryPage")
+    @RequestMapping("sysSuggestion/queryPage")
     @PreAuthorize("@pcs.hasPermissions('sysSuggestion/queryPage')")
-    public Object queryPage(QueryInfo queryInfo) {
+    public Object queryPage(SysSuggestionQueryInfo queryInfo) {
         return succeed(sysSuggestionService.queryPage(queryInfo));
     }
 

+ 48 - 0
mec-web/src/main/java/com/ym/mec/web/controller/education/SysMusicCompareRecordController.java

@@ -0,0 +1,48 @@
+package com.ym.mec.web.controller.education;
+
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
+import com.ym.mec.biz.service.SysMusicCompareRecordService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import com.ym.mec.common.exception.BizException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Objects;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/13 0013
+ */
+@Api(tags = "云教练记录")
+@RequestMapping("sysMusicRecord")
+@RestController
+public class SysMusicCompareRecordController extends BaseController {
+
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private SysMusicCompareRecordService sysMusicCompareRecordService;
+
+    @ApiOperation(value = "添加记录")
+    @PostMapping("add")
+    public HttpResponseResult add(SysMusicCompareRecord record){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if(sysUser == null){
+            throw new BizException("请登录");
+        }
+        if(Objects.isNull(record.getFeature())){
+            return failed("请设置功能点");
+        }
+        record.setUserId(sysUser.getId());
+        record.setClientId("education");
+        return succeed(sysMusicCompareRecordService.insert(record));
+    }
+
+}