Browse Source

Merge branch 'online1' of http://git.dayaedu.com/yonge/mec into hr_728

yonge 4 năm trước cách đây
mục cha
commit
aca6628b1c
57 tập tin đã thay đổi với 1187 bổ sung335 xóa
  1. 46 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/config/NioAudioInputStream.java
  2. 56 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/config/SoundCompareConfig.java
  3. 2 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ClassGroupDao.java
  4. 1 2
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CloudTeacherOrderDao.java
  5. 9 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentRegistrationDao.java
  6. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/EduHomeworkCardDto.java
  7. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/Mapper.java
  8. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupPaymentCalenderDto.java
  9. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupStudentsDto.java
  10. 65 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicPitchDetailDto.java
  11. 55 8
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/SoundCompareHelper.java
  12. 20 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherAttendanceComplaintsDto.java
  13. 53 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/WebSocketClientDetail.java
  14. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/MusicMemberDto.java
  15. 58 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/SysMusicCompareRecord.java
  16. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/MessageTypeEnum.java
  17. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/ArrearageStudentsQueryInfo.java
  18. 213 125
      mec-biz/src/main/java/com/ym/mec/biz/handler/WebSocketHandler.java
  19. 1 2
      mec-biz/src/main/java/com/ym/mec/biz/service/CloudTeacherOrderService.java
  20. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupPaymentCalenderDetailService.java
  21. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupPaymentCalenderService.java
  22. 5 0
      mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupPaymentStudentCourseDetailService.java
  23. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/service/SoundSocketService.java
  24. 2 6
      mec-biz/src/main/java/com/ym/mec/biz/service/StudentService.java
  25. 4 0
      mec-biz/src/main/java/com/ym/mec/biz/service/SysConfigService.java
  26. 3 2
      mec-biz/src/main/java/com/ym/mec/biz/service/SysMusicCompareRecordService.java
  27. 13 17
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/CloudTeacherOrderServiceImpl.java
  28. 5 5
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MemberRankSettingServiceImpl.java
  29. 33 6
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderDetailServiceImpl.java
  30. 23 14
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderServiceImpl.java
  31. 8 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentStudentCourseDetailServiceImpl.java
  32. 111 11
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupSchoolTermCourseDetailServiceImpl.java
  33. 24 7
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java
  34. 58 87
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentServiceImpl.java
  35. 12 3
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java
  36. 2 1
      mec-biz/src/main/resources/config/mybatis/ClassGroupMapper.xml
  37. 11 10
      mec-biz/src/main/resources/config/mybatis/CloudTeacherOrderMapper.xml
  38. 1 0
      mec-biz/src/main/resources/config/mybatis/ExtracurricularExercisesReplyMapper.xml
  39. 6 3
      mec-biz/src/main/resources/config/mybatis/IndexBaseMonthDataMapper.xml
  40. 2 1
      mec-biz/src/main/resources/config/mybatis/MusicGroupMapper.xml
  41. 11 5
      mec-biz/src/main/resources/config/mybatis/MusicGroupPaymentCalenderDetailMapper.xml
  42. 2 1
      mec-biz/src/main/resources/config/mybatis/MusicGroupQuitMapper.xml
  43. 1 0
      mec-biz/src/main/resources/config/mybatis/StudentCourseHomeworkMapper.xml
  44. 2 1
      mec-biz/src/main/resources/config/mybatis/StudentManageDao.xml
  45. 16 0
      mec-biz/src/main/resources/config/mybatis/StudentRegistrationMapper.xml
  46. 22 2
      mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml
  47. 3 1
      mec-biz/src/main/resources/config/mybatis/TeacherAttendanceMapper.xml
  48. 3 2
      mec-student/src/main/java/com/ym/mec/student/config/WebSocketConfig.java
  49. 6 1
      mec-student/src/main/java/com/ym/mec/student/controller/MusicGroupRecordController.java
  50. 3 2
      mec-teacher/src/main/java/com/ym/mec/teacher/config/WebSocketConfig.java
  51. 4 4
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/SoundController.java
  52. 41 0
      mec-web/src/main/java/com/ym/mec/web/config/WebSocketConfig.java
  53. 55 0
      mec-web/src/main/java/com/ym/mec/web/controller/ExportController.java
  54. 1 1
      mec-web/src/main/java/com/ym/mec/web/controller/MusicGroupQuitController.java
  55. 7 1
      mec-web/src/main/java/com/ym/mec/web/controller/TaskController.java
  56. 12 0
      mec-web/src/main/java/com/ym/mec/web/controller/education/EduMusicGroupRecordController.java
  57. 28 0
      mec-web/src/main/java/com/ym/mec/web/interceptor/WebSocketHandshakeInterceptor.java

+ 46 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/config/NioAudioInputStream.java

@@ -0,0 +1,46 @@
+package com.ym.mec.biz.dal.config;
+
+import be.tarsos.dsp.io.TarsosDSPAudioFormat;
+import be.tarsos.dsp.io.TarsosDSPAudioInputStream;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/4 0004
+ */
+public class NioAudioInputStream implements TarsosDSPAudioInputStream {
+
+    private final RandomAccessFile randomAccessFile;
+
+    public NioAudioInputStream(RandomAccessFile randomAccessFile) {
+        this.randomAccessFile = randomAccessFile;
+    }
+
+    @Override
+    public long skip(long bytesToSkip) throws IOException {
+        return randomAccessFile.skipBytes((int) bytesToSkip);
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        return randomAccessFile.read(b, off, len);
+    }
+
+    @Override
+    public void close() throws IOException {
+        randomAccessFile.close();
+    }
+
+    @Override
+    public TarsosDSPAudioFormat getFormat() {
+        TarsosDSPAudioFormat tarsosDSPFormat = new TarsosDSPAudioFormat(44100, 16, 1, false, true);
+        return tarsosDSPFormat;
+    }
+
+    @Override
+    public long getFrameLength() {
+        return 0;
+    }
+}

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

@@ -0,0 +1,56 @@
+package com.ym.mec.biz.dal.config;
+
+import be.tarsos.dsp.SilenceDetector;
+import be.tarsos.dsp.pitch.PitchProcessor;
+
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/4 0004
+ */
+public class SoundCompareConfig {
+
+    /**
+     * @describe 采样率
+     */
+    public float simpleRate = 44100;
+    /**
+     * @describe 采样大小
+     */
+    public int simpleSize = 1024;
+    /**
+     * @describe 帧覆盖大小
+     */
+    public int overlap = 256;
+
+    /**
+     * @describe 音频解析格式
+     */
+    public AudioFormat audioFormat = new AudioFormat(simpleRate, 16, 1, true, false);
+    /**
+     * @describe 音频解析算法
+     */
+    public PitchProcessor.PitchEstimationAlgorithm algo = PitchProcessor.PitchEstimationAlgorithm.FFT_YIN;
+
+    /**
+     * @describe 有效分贝大小
+     */
+    public int validDb = -70;
+    /**
+     * @describe 有效频率
+     */
+    public int validFrequency = 20;
+    /**
+     * @describe 音准前后音分误差范围
+     */
+    public int intonationCentsRange = 3;
+    /**
+     * @describe 节奏有效阈值
+     */
+    public float cadenceValidDuty = 0.09f;
+    /**
+     * @describe 完整性有效频率误差范围
+     */
+    public int integrityFrequencyRange = 30;
+}

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

@@ -463,7 +463,8 @@ public interface ClassGroupDao extends BaseDAO<Integer, ClassGroup> {
      * @param studentId
      * @return
      */
-    List<ClassGroup> queryStudentClassGroups(@Param("musicGroupId") String musicGroupId, @Param("studentId") Integer studentId);
+    List<ClassGroup> queryStudentClassGroups(@Param("musicGroupId") String musicGroupId,
+                                             @Param("studentId") Integer studentId);
 
     /**
      * 批量新增班级上的课次数

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

@@ -36,10 +36,9 @@ public interface CloudTeacherOrderDao extends BaseDAO<Long, CloudTeacherOrder> {
     /**
      * 获取乐团报名的云教练订单
      * @param studentId
-     * @param musicGroupId
      * @return
      */
-    List<CloudTeacherOrder> getStudentCloudTeacherOrder(@Param("studentId") Integer studentId, @Param("musicGroupId") String musicGroupId);
+    List<CloudTeacherOrder> getStudentCloudTeacherOrder(@Param("studentId") Integer studentId);
     
     /**
      * 根据订单编号查询订单详情

+ 9 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentRegistrationDao.java

@@ -657,4 +657,13 @@ public interface StudentRegistrationDao extends BaseDAO<Long, StudentRegistratio
     int queryStudentRegisterInstrumentsDetailCount(Map<String, Object> params);
 	
 	List<SubjectApplyDetailDto> queryStudentApplyDetail(@Param("musicGroupId") String musicGroupId);
+
+    void cleanMusicMember(@Param("userId") Integer userId, @Param("musicGroupId") String musicGroupId);
+
+    /**
+     * 会员结束前15天自动创建乐团缴费
+     * @param pushMemberRenew
+     * @return
+     */
+    List<Map<String,String>> queryAutoCreateStudentMap(@Param("pushMemberRenew") String pushMemberRenew);
 }

+ 10 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/EduHomeworkCardDto.java

@@ -26,6 +26,8 @@ public class EduHomeworkCardDto {
 
     private String teacherName;
 
+    private String teacherAvatar;
+
     private Integer exceptStudentNum;
 
     private Integer submitStudentNum;
@@ -34,6 +36,14 @@ public class EduHomeworkCardDto {
 
     private Date createTime;
 
+    public String getTeacherAvatar() {
+        return teacherAvatar;
+    }
+
+    public void setTeacherAvatar(String teacherAvatar) {
+        this.teacherAvatar = teacherAvatar;
+    }
+
     public String getContent() {
         return content;
     }

+ 10 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/Mapper.java

@@ -8,6 +8,16 @@ public class Mapper {
 
 	private Integer courseScheduleId;
 
+	private String type;
+
+	public String getType() {
+		return type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
 	public Integer getCourseScheduleId() {
 		return courseScheduleId;
 	}

+ 10 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupPaymentCalenderDto.java

@@ -52,6 +52,16 @@ public class MusicGroupPaymentCalenderDto {
 	//会员等级编号
 	private Integer memberRankSettingId;
 
+	private Boolean autoCreate = false;
+
+	public Boolean getAutoCreate() {
+		return autoCreate;
+	}
+
+	public void setAutoCreate(Boolean autoCreate) {
+		this.autoCreate = autoCreate;
+	}
+
 	public Integer getMemberValidDate() {
 		return memberValidDate;
 	}

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupStudentsDto.java

@@ -118,6 +118,17 @@ public class MusicGroupStudentsDto{
     @ApiModelProperty(value = "声部更换详情",required = false)
     private SubjectChange subjectChange;
 
+    @ApiModelProperty(value = "会员截止时间",required = false)
+    private Date membershipEndTime;
+
+    public Date getMembershipEndTime() {
+        return membershipEndTime;
+    }
+
+    public void setMembershipEndTime(Date membershipEndTime) {
+        this.membershipEndTime = membershipEndTime;
+    }
+
     public String getCarePackageStr() {
         return carePackageStr;
     }

+ 65 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicPitchDetailDto.java

@@ -11,15 +11,69 @@ public class MusicPitchDetailDto {
     @ApiModelProperty("时间戳ms")
     private int timeStamp;
 
+    @ApiModelProperty("结束时间戳")
+    private int endTimeStamp;
+
     @ApiModelProperty("持续时长ms")
     private int duration;
 
     @ApiModelProperty("频率Hz")
     private float frequency;
 
+    private float avgFrequency;
+
+    @ApiModelProperty("分贝")
+    private float decibel;
+
     @ApiModelProperty("小节数")
     private int measureIndex;
 
+    @ApiModelProperty("音符数")
+    private int musicalNotesIndex;
+
+    @ApiModelProperty("不需要评分")
+    private Boolean dontEvaluating;
+
+    public float getDecibel() {
+        return decibel;
+    }
+
+    public void setDecibel(float decibel) {
+        this.decibel = decibel;
+    }
+
+    public float getAvgFrequency() {
+        return avgFrequency;
+    }
+
+    public void setAvgFrequency(float avgFrequency) {
+        this.avgFrequency = avgFrequency;
+    }
+
+    public Boolean getDontEvaluating() {
+        return dontEvaluating;
+    }
+
+    public void setDontEvaluating(Boolean dontEvaluating) {
+        this.dontEvaluating = dontEvaluating;
+    }
+
+    public int getMusicalNotesIndex() {
+        return musicalNotesIndex;
+    }
+
+    public void setMusicalNotesIndex(int musicalNotesIndex) {
+        this.musicalNotesIndex = musicalNotesIndex;
+    }
+
+    public int getEndTimeStamp() {
+        return endTimeStamp;
+    }
+
+    public void setEndTimeStamp(int endTimeStamp) {
+        this.endTimeStamp = endTimeStamp;
+    }
+
     public MusicPitchDetailDto() {
     }
 
@@ -28,12 +82,23 @@ public class MusicPitchDetailDto {
         this.frequency = frequency;
     }
 
+    public MusicPitchDetailDto(int timeStamp, int endTimeStamp) {
+        this.timeStamp = timeStamp;
+        this.endTimeStamp = endTimeStamp;
+    }
+
     public MusicPitchDetailDto(int timeStamp, int duration, float frequency) {
         this.timeStamp = timeStamp;
         this.duration = duration;
         this.frequency = frequency;
     }
 
+    public MusicPitchDetailDto(int timeStamp, float frequency, double decibel) {
+        this.timeStamp = timeStamp;
+        this.frequency = frequency;
+        this.decibel = (float) decibel;
+    }
+
     public int getTimeStamp() {
         return timeStamp;
     }

+ 55 - 8
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/SoundCompareHelper.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.dal.dto;
 
+import be.tarsos.dsp.SilenceDetector;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.RandomAccessFile;
@@ -16,16 +17,19 @@ public class SoundCompareHelper {
     private Integer musicScoreId;
 
     @ApiModelProperty(value = "小节开始时间")
-    private double measureStartTime;
+    private double measureStartTime = 0;
 
     @ApiModelProperty
     private RandomAccessFile accessFile;
 
+    @ApiModelProperty(value = "录音文件地址")
+    private String recordFilePath;
+
     @ApiModelProperty(value = "小节xml信息字典")
     private Map<Integer, List<MusicPitchDetailDto>> measureXmlInfoMap = new HashMap<>();
 
     @ApiModelProperty(value = "小节结束时间字典")
-    private Map<Integer, Integer> measureEndTime = new HashMap<>();
+    private Map<Integer, MusicPitchDetailDto> measureEndTime = new HashMap<>();
 
     @ApiModelProperty(value = "录音音频信息")
     private List<MusicPitchDetailDto> recordMeasurePithInfo = new ArrayList<>();
@@ -33,10 +37,45 @@ public class SoundCompareHelper {
     @ApiModelProperty(value = "小节分数记录")
     private Map<String, BigDecimal> userScoreMap = new HashMap<>();
 
-    private Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap = new HashMap<>();
+    private Map<Integer, Map<String, Object>> userMeasureScoreMap = new HashMap<>();
+
+    @ApiModelProperty(value = "音符频率字典")
+    private Map<Integer, Float> musicalNotePitchMap = new HashMap<>();
 
     @ApiModelProperty(value = "偏移时间量,解决客户端录音播放不同步导致的声音留白")
-    private int offsetTime;
+    private int offsetTime = -1;
+
+    private List<MusicPitchDetailDto> musicXmlInfos;
+
+    private byte[] preDataArray = new byte[0];
+    /**
+     * @describe 分贝检测器
+     */
+    public SilenceDetector silenceDetector = new SilenceDetector();
+
+    public List<MusicPitchDetailDto> getMusicXmlInfos() {
+        return musicXmlInfos;
+    }
+
+    public void setMusicXmlInfos(List<MusicPitchDetailDto> musicXmlInfos) {
+        this.musicXmlInfos = musicXmlInfos;
+    }
+
+    public Map<Integer, Float> getMusicalNotePitchMap() {
+        return musicalNotePitchMap;
+    }
+
+    public void setMusicalNotePitchMap(Map<Integer, Float> musicalNotePitchMap) {
+        this.musicalNotePitchMap = musicalNotePitchMap;
+    }
+
+    public byte[] getPreDataArray() {
+        return preDataArray;
+    }
+
+    public void setPreDataArray(byte[] preDataArray) {
+        this.preDataArray = preDataArray;
+    }
 
     public int getOffsetTime() {
         return offsetTime;
@@ -58,6 +97,14 @@ public class SoundCompareHelper {
         return accessFile;
     }
 
+    public String getRecordFilePath() {
+        return recordFilePath;
+    }
+
+    public void setRecordFilePath(String recordFilePath) {
+        this.recordFilePath = recordFilePath;
+    }
+
     public void setAccessFile(RandomAccessFile accessFile) {
         this.accessFile = accessFile;
     }
@@ -78,11 +125,11 @@ public class SoundCompareHelper {
         this.measureXmlInfoMap = measureXmlInfoMap;
     }
 
-    public Map<Integer, Integer> getMeasureEndTime() {
+    public Map<Integer, MusicPitchDetailDto> getMeasureEndTime() {
         return measureEndTime;
     }
 
-    public void setMeasureEndTime(Map<Integer, Integer> measureEndTime) {
+    public void setMeasureEndTime(Map<Integer, MusicPitchDetailDto> measureEndTime) {
         this.measureEndTime = measureEndTime;
     }
 
@@ -102,11 +149,11 @@ public class SoundCompareHelper {
         this.userScoreMap = userScoreMap;
     }
 
-    public Map<Integer, Map<String, BigDecimal>> getUserMeasureScoreMap() {
+    public Map<Integer, Map<String, Object>> getUserMeasureScoreMap() {
         return userMeasureScoreMap;
     }
 
-    public void setUserMeasureScoreMap(Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap) {
+    public void setUserMeasureScoreMap(Map<Integer, Map<String, Object>> userMeasureScoreMap) {
         this.userMeasureScoreMap = userMeasureScoreMap;
     }
 }

+ 20 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherAttendanceComplaintsDto.java

@@ -45,6 +45,26 @@ public class TeacherAttendanceComplaintsDto{
 
     private String url;
 
+    private String teachMode;
+
+    private String courseType;
+
+    public String getTeachMode() {
+        return teachMode;
+    }
+
+    public void setTeachMode(String teachMode) {
+        this.teachMode = teachMode;
+    }
+
+    public String getCourseType() {
+        return courseType;
+    }
+
+    public void setCourseType(String courseType) {
+        this.courseType = courseType;
+    }
+
     public UpdateAttendanceEnum getComplaintsType() {
         return complaintsType;
     }

+ 53 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/WebSocketClientDetail.java

@@ -0,0 +1,53 @@
+package com.ym.mec.biz.dal.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.springframework.web.socket.WebSocketSession;
+
+import java.util.Date;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/8/4 0004
+ */
+public class WebSocketClientDetail {
+
+    private WebSocketSession session;
+
+    @ApiModelProperty(value = "用户登录时间")
+    private Date loginTime;
+
+    @ApiModelProperty(value = "用户退出或断开时间")
+    private Date logoutTime;
+
+    public WebSocketClientDetail() {
+    }
+
+    public WebSocketClientDetail(WebSocketSession session, Date loginTime) {
+        this.session = session;
+        this.loginTime = loginTime;
+    }
+
+    public WebSocketSession getSession() {
+        return session;
+    }
+
+    public void setSession(WebSocketSession session) {
+        this.session = session;
+    }
+
+    public Date getLoginTime() {
+        return loginTime;
+    }
+
+    public void setLoginTime(Date loginTime) {
+        this.loginTime = loginTime;
+    }
+
+    public Date getLogoutTime() {
+        return logoutTime;
+    }
+
+    public void setLogoutTime(Date logoutTime) {
+        this.logoutTime = logoutTime;
+    }
+}

+ 10 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/MusicMemberDto.java

@@ -23,6 +23,16 @@ public class MusicMemberDto {
 
 	private Date visitTime;
 
+	private Integer courseViewType;
+
+	public Integer getCourseViewType() {
+		return courseViewType;
+	}
+
+	public void setCourseViewType(Integer courseViewType) {
+		this.courseViewType = courseViewType;
+	}
+
 	public String getPhone() {
 		return phone;
 	}

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

@@ -2,6 +2,8 @@ package com.ym.mec.biz.dal.entity;
 
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
+import java.math.BigDecimal;
+
 /**
  * 对应数据库表(sys_music_compare_record):
  */
@@ -18,6 +20,21 @@ public class SysMusicCompareRecord {
 	
 	/** 评分数据 */
 	private String scoreData;
+
+	/** 总分 */
+	private BigDecimal score;
+
+	/** 音准 */
+	private BigDecimal intonation;
+
+	/** 节奏 */
+	private BigDecimal cadence;
+
+	/** 完成度 */
+	private BigDecimal integrity;
+
+	/** 录音文件地址 */
+	private String recordFilePath;
 	
 	/** 创建时间 */
 	private java.util.Date createTime;
@@ -53,7 +70,47 @@ public class SysMusicCompareRecord {
 	public String getScoreData(){
 		return this.scoreData;
 	}
-			
+
+	public BigDecimal getScore() {
+		return score;
+	}
+
+	public void setScore(BigDecimal score) {
+		this.score = score;
+	}
+
+	public BigDecimal getIntonation() {
+		return intonation;
+	}
+
+	public void setIntonation(BigDecimal intonation) {
+		this.intonation = intonation;
+	}
+
+	public BigDecimal getCadence() {
+		return cadence;
+	}
+
+	public void setCadence(BigDecimal cadence) {
+		this.cadence = cadence;
+	}
+
+	public BigDecimal getIntegrity() {
+		return integrity;
+	}
+
+	public void setIntegrity(BigDecimal integrity) {
+		this.integrity = integrity;
+	}
+
+	public String getRecordFilePath() {
+		return recordFilePath;
+	}
+
+	public void setRecordFilePath(String recordFilePath) {
+		this.recordFilePath = recordFilePath;
+	}
+
 	public void setCreateTime(java.util.Date createTime){
 		this.createTime = createTime;
 	}

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/MessageTypeEnum.java

@@ -6,6 +6,8 @@ public enum MessageTypeEnum implements BaseEnum<String, MessageTypeEnum> {
     SMS_APPLY_MESSAGE("SMS_APPLY_MESSAGE", "报名通知"),
     SYSTEM_REMIND_EDUCATION_COURSE_TIME("SYSTEM_REMIND_EDUCATION_COURSE_TIME", "排课提醒"),
     STUDENT_MEMBER_RENEW_MESSAGE("STUDENT_MEMBER_RENEW_MESSAGE", "会员续费提醒"),
+    SMS_AUTO_STUDENT_MEMBER_RENEW_MESSAGE("SMS_AUTO_STUDENT_MEMBER_RENEW_MESSAGE", "会员续费提醒"),
+    PUSH_AUTO_STUDENT_MEMBER_RENEW_MESSAGE("PUSH_AUTO_STUDENT_MEMBER_RENEW_MESSAGE", "会员续费提醒"),
     STUDENT_MEMBER_RENEW_QUIT_MESSAGE("STUDENT_MEMBER_RENEW_QUIT_MESSAGE", "会员续费提醒"),
     SMS_VERIFY_CODE_LOGIN("SMS_VERIFY_CODE_LOGIN", "验证码登录"),
     KAPTCHA_SESSION_KEY("KAPTCHA_SESSION_KEY", "登录图形验证码"),

+ 10 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/ArrearageStudentsQueryInfo.java

@@ -21,6 +21,16 @@ public class ArrearageStudentsQueryInfo extends QueryInfo {
     @ApiModelProperty(value = "未缴费类型:0历史,1进行中")
     private Integer noPaymentType;
 
+    private Integer courseViewType;
+
+    public Integer getCourseViewType() {
+        return courseViewType;
+    }
+
+    public void setCourseViewType(Integer courseViewType) {
+        this.courseViewType = courseViewType;
+    }
+
     public String getOrganIds() {
         return organIds;
     }

+ 213 - 125
mec-biz/src/main/java/com/ym/mec/biz/handler/WebSocketHandler.java

@@ -3,12 +3,11 @@ 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.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.config.SoundCompareConfig;
+import com.ym.mec.biz.dal.dto.*;
 import com.ym.mec.biz.service.SoundSocketService;
 import com.ym.mec.biz.service.SysMusicCompareRecordService;
 import com.ym.mec.common.constant.CommonConstants;
@@ -21,7 +20,6 @@ import org.springframework.util.CollectionUtils;
 import org.springframework.web.socket.*;
 import org.springframework.web.socket.handler.AbstractWebSocketHandler;
 
-import javax.sound.sampled.AudioFormat;
 import java.io.File;
 import java.io.IOException;
 import java.io.RandomAccessFile;
@@ -41,24 +39,23 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class);
 
-    //存储客户端链接
-    public static final Map<String, WebSocketSession> WS_CLIENTS = new ConcurrentHashMap<>();
-
-    private final BigDecimal oneHundred = new BigDecimal(100);
-
-    //检测偏移时长的最终时间
-    private final int endCheckOffsetTime = 500;
-
-    private final float simpleRate = 44100;
-    private int simpleSize = 1024;
+    /**
+     * @describe 存储客户端链接
+     */
+    public static final Map<String, WebSocketClientDetail> WS_CLIENTS = new ConcurrentHashMap<>();
 
-    private final AudioFormat audioFormat = new AudioFormat(simpleRate, 16, 1, true, false);
-    private static final PitchProcessor.PitchEstimationAlgorithm algo = PitchProcessor.PitchEstimationAlgorithm.FFT_YIN;
+    private BigDecimal oneHundred = new BigDecimal(100);
 
-    private static final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/";
+    private final String tmpDir = FileUtils.getTempDirectoryPath() + "/soundCompare/";
 
-    //用户对应评分信息
+    /**
+     * @describe 用户对应评分信息
+     */
     private Map<String, SoundCompareHelper> userSoundInfoMap = new ConcurrentHashMap<>();
+    /**
+     * @describe 音频处理参数
+     */
+    private SoundCompareConfig soundCompareConfig = new SoundCompareConfig();
 
     @Autowired
     private SysMusicCompareRecordService sysMusicCompareRecordService;
@@ -75,7 +72,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
     public void afterConnectionEstablished(WebSocketSession session) throws Exception {
         String phone = session.getPrincipal().getName().split(":")[1];
         LOGGER.info("{}上线", phone);
-        WS_CLIENTS.put(phone, session);
+        WS_CLIENTS.put(phone, new WebSocketClientDetail(session, new Date()));
         super.afterConnectionEstablished(session);
     }
 
@@ -99,11 +96,19 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
             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 musicPitchDetailDto = userMeasureXmlInfoEntry.getValue().stream().max(Comparator.comparing(MusicPitchDetailDto::getTimeStamp)).get();
-                    userSoundInfoMap.get(phone).getMeasureEndTime().put(userMeasureXmlInfoEntry.getKey(), musicPitchDetailDto.getTimeStamp()+musicPitchDetailDto.getDuration());
+                    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:
@@ -112,6 +117,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
                 }
                 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)){
@@ -119,9 +125,9 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
                 }
                 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()/(audioFormat.getFrameSize()*audioFormat.getFrameRate())*1000;
+                    double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
                     //如果结束时时长大于某小节,则此小节需要评分
-                    if(recordTime>userSoundInfoMap.get(phone).getMeasureEndTime().get(lastMeasureIndex)){
+                    if(recordTime>userSoundInfoMap.get(phone).getMeasureEndTime().get(lastMeasureIndex).getEndTimeStamp()){
                         measureCompare(phone, lastMeasureIndex);
                         userSoundInfoMap.get(phone).getMeasureEndTime().remove(lastMeasureIndex);
                     }
@@ -132,6 +138,12 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
             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;
         }
@@ -146,52 +158,36 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
             userSoundInfoMap.get(phone).getAccessFile().write(message.getPayload().array());
         }
-        List<MusicPitchDetailDto> recordInfo = new ArrayList<>();
-        AudioDispatcher dispatcher = AudioDispatcherFactory.fromByteArray(message.getPayload().array(), audioFormat, simpleSize, 128);
-        dispatcher.addAudioProcessor(new PitchProcessor(algo, simpleRate, simpleSize, (pitchDetectionResult, audioEvent) -> {
+
+        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();
-//            LOGGER.info("频率:{}, {}", timeStamp, pitch);
-            recordInfo.add(new MusicPitchDetailDto(timeStamp, pitch));
+            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()/(audioFormat.getFrameSize()*audioFormat.getFrameRate())*1000;
-
+        double recordTime = userSoundInfoMap.get(phone).getAccessFile().length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000;
         userSoundInfoMap.get(phone).setMeasureStartTime(recordTime);
-        userSoundInfoMap.get(phone).getRecordMeasurePithInfo().addAll(recordInfo);
-
-        //如果是第一小节,需要计算出录音与播放不同步导致的空白时间偏移量
-        if(userSoundInfoMap.get(phone).getOffsetTime()<=0&&recordTime<endCheckOffsetTime){
-            int hasPitchNum = 0;
-            for (MusicPitchDetailDto ri : userSoundInfoMap.get(phone).getRecordMeasurePithInfo()) {
-                if(hasPitchNum<=0){
-                    userSoundInfoMap.get(phone).setOffsetTime(ri.getTimeStamp());
-                }
-                if(ri.getFrequency()>0){
-                    hasPitchNum++;
+        for (Map.Entry<Integer, MusicPitchDetailDto> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
+            if(recordTime>(userMeasureEndTimeMapEntry.getValue().getEndTimeStamp())){
+                if(userMeasureEndTimeMapEntry.getValue().getDontEvaluating()){
+                    continue;
                 }else{
-                    hasPitchNum=0;
+                    measureCompare(phone, userMeasureEndTimeMapEntry.getKey());
                 }
-                if(hasPitchNum>=3){
-                    LOGGER.info("偏移时间:{}", userSoundInfoMap.get(phone).getOffsetTime());
-                    break;
-                }
-            }
-            if(hasPitchNum<3){
-                userSoundInfoMap.get(phone).setOffsetTime(0);
-            }
-        }
-
-        if(userSoundInfoMap.get(phone).getOffsetTime()<=0&&recordTime<endCheckOffsetTime){
-            return;
-        }
-        for (Map.Entry<Integer, Integer> userMeasureEndTimeMapEntry : userSoundInfoMap.get(phone).getMeasureEndTime().entrySet()) {
-            if((recordTime - userSoundInfoMap.get(phone).getOffsetTime())>userMeasureEndTimeMapEntry.getValue()){
-                measureCompare(phone, userMeasureEndTimeMapEntry.getKey());
                 userSoundInfoMap.get(phone).getMeasureEndTime().remove(userMeasureEndTimeMapEntry.getKey());
                 break;
             }
@@ -214,6 +210,7 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         exception.printStackTrace();
         LOGGER.info("发生了错误,移除客户端: {}", phone);
         WS_CLIENTS.remove(phone);
+        userSoundInfoMap.remove(phone);
         createHeader(phone);
     }
 
@@ -222,8 +219,9 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         super.afterConnectionClosed(session, status);
         String phone = session.getPrincipal().getName().split(":")[1];
         LOGGER.info("{}离线", phone);
-        WS_CLIENTS.remove(phone);
         createHeader(phone);
+        WS_CLIENTS.remove(phone);
+        userSoundInfoMap.remove(phone);
     }
 
     @Override
@@ -232,6 +230,22 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
     }
 
     /**
+     * @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
@@ -244,14 +258,13 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         }
         if(Objects.nonNull(userSoundInfoMap.get(phone).getAccessFile())){
             RandomAccessFile randomAccessFile = userSoundInfoMap.get(phone).getAccessFile();
-            LOGGER.info("音频时长:{}", randomAccessFile.length()/(audioFormat.getFrameSize()*audioFormat.getFrameRate())*1000);
+            LOGGER.info("音频时长:{}", randomAccessFile.length()/(soundCompareConfig.audioFormat.getFrameSize()*soundCompareConfig.audioFormat.getFrameRate())*1000);
             randomAccessFile.seek(0);
-            randomAccessFile.write(WavHeader.getWaveHeader(randomAccessFile.length(), (long) audioFormat.getFrameRate(), audioFormat.getSampleSizeInBits()));
+            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);
-        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone)));
         userSoundInfoMap.remove(phone);
     }
 
@@ -264,6 +277,10 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
      * @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;
         //节奏
@@ -272,84 +289,151 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         BigDecimal integrity = BigDecimal.ZERO;
 
         try {
-            //最低有效频率
-            float minValidFrequency = 20;
-
-            //有效音频数量
-            float validNum = 0;
-            //音频有效阈值
-            float validDuty = 0.5f;
-
-            //音准匹配数量
-            float intonationNum = 0;
-            //音准匹配误差范围
-            float intonationErrRange = 15;
-            //音准有效阈值
-            float intonationValidDuty = 0.7f;
+            //音准分数
+            float intonationScore = 0;
 
             //节奏匹配数量
             float cadenceNum = 0;
-            //节奏匹配误差范围
-            float cadenceErrRange = 30;
-            //节奏有效阈值
-            float cadenceValidDuty = 0.6f;
+
+            //完整性分数
+            float integrityScore = 0;
 
             int totalCompareNum = userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex).size();
 
-            for (MusicPitchDetailDto musicXmlInfo : userSoundInfoMap.get(phone).getMeasureXmlInfoMap().get(measureIndex)) {
-                int startTimeStamp = musicXmlInfo.getTimeStamp() + userSoundInfoMap.get(phone).getOffsetTime();
-                int endTimeStamp = musicXmlInfo.getTimeStamp()+musicXmlInfo.getDuration() + userSoundInfoMap.get(phone).getOffsetTime();
+            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 recordValidIntonationNum = 0;
                 //时间范围内有效节奏数量
                 float cadenceValidNum = 0;
                 //时间范围内有效音频数量
-                float recordValidNum = 0;
+                float integrityValidNum = 0;
                 //时间范围内匹配次数
                 float compareNum = 0;
-                for (MusicPitchDetailDto recordInfo : userSoundInfoMap.get(phone).getRecordMeasurePithInfo()) {
+
+                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;
                     }
-//                    LOGGER.info("{}频率({}-{}):{}, {}", recordInfo.getTimeStamp(), startTimeStamp, endTimeStamp, musicXmlInfo.getFrequency(), recordInfo.getFrequency());
+                    measureSoundPitchInfos.add(recordInfo);
                     compareNum++;
                     //如果在最低有效频率以下则跳过
-                    if(recordInfo.getFrequency()<minValidFrequency&&musicXmlInfo.getFrequency()!=-1){
+                    if(recordInfo.getFrequency()<soundCompareConfig.validFrequency&&musicXmlInfo.getFrequency()!=-1){
                         continue;
                     }
-                    recordValidNum++;
+                    cadenceValidNum++;
                     //如果频率差值在节奏误差范围内
-                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=cadenceErrRange){
-                        cadenceValidNum++;
-                    }
-                    //如果频率差值在音准误差范围内
-                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=intonationErrRange){
-                        recordValidIntonationNum++;
+                    if(Math.abs(recordInfo.getFrequency()-musicXmlInfo.getFrequency())<=soundCompareConfig.integrityFrequencyRange){
+                        integrityValidNum++;
                     }
                 }
-                //有效音频占比
-                float recordValidDuty = recordValidNum/compareNum;
-                if(recordValidDuty<validDuty){
-                    continue;
+
+                //非正常频率次数
+                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);
                 }
-                validNum++;
-                //有效音高占比
-                float intonationDuty = recordValidIntonationNum/compareNum;
+
                 //有效节奏占比
                 float cadenceDuty = cadenceValidNum/compareNum;
-                if(intonationDuty>=intonationValidDuty){
-                    intonationNum++;
+                //如果频率出现断层或这个音量出现断层,则当前音符节奏无效
+                if(errPitchNum>=2 || decibelChangeNum>1){
+                    cadenceDuty = 0;
                 }
-                if(cadenceDuty>=cadenceValidDuty){
+                //节奏
+                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;
             }
 
-            intonation = new BigDecimal(intonationNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_HALF_UP);
-            cadence = new BigDecimal(cadenceNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_HALF_UP);
-            integrity = new BigDecimal(validNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_HALF_UP);
+            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信息");
         }
@@ -372,14 +456,8 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
             userSoundInfoMap.get(phone).getUserScoreMap().put("integrity", integrity);
         }
 
-        Map<String, BigDecimal> scoreData = new HashMap<>();
-        scoreData.put("intonation", intonation);
-        scoreData.put("cadence", cadence);
-        scoreData.put("integrity", integrity);
-
-        userSoundInfoMap.get(phone).getUserMeasureScoreMap().put(measureIndex, scoreData);
-
-        WS_CLIENTS.get(phone).sendMessage(new TextMessage(JSON.toJSONString(createPushInfo("measureScore", measureIndex, intonation, cadence, integrity))));
+        //计算分数并推送
+        createPushInfo(phone, "measureScore", measureIndex, intonation, cadence, integrity);
     }
 
     /**
@@ -399,13 +477,16 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
         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 = new BigDecimal(currentCompareNum).divide(new BigDecimal(totalCompareNum), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(oneHundred).setScale(0, BigDecimal.ROUND_DOWN);
+            integrity = userSoundInfoMap.get(phone).getUserScoreMap().get("integrity").divide(new BigDecimal(currentCompareNum), 0, BigDecimal.ROUND_DOWN);
         }
 
-        WS_CLIENTS.get(phone).sendMessage(new TextMessage(JSON.toJSONString(createPushInfo("overall", -1, intonation, cadence, integrity))));
+        //计算分数并推送
+        createPushInfo(phone, "overall", -1, intonation, cadence, integrity);
 
         //存储评分数据
-        sysMusicCompareRecordService.saveMusicCompareData(phone, userSoundInfoMap.get(phone).getMusicScoreId(), userSoundInfoMap.get(phone).getUserMeasureScoreMap());
+        sysMusicCompareRecordService.saveMusicCompareData(phone, userSoundInfoMap.get(phone));
+
+        LOGGER.info("评分数据:{}", JSON.toJSONString(userSoundInfoMap.get(phone)));
     }
 
     /**
@@ -419,22 +500,29 @@ public class WebSocketHandler extends AbstractWebSocketHandler {
      * @param integrity:
      * @return com.ym.mec.biz.dal.dto.WebSocketInfo
      */
-    private WebSocketInfo createPushInfo(String command, Integer measureIndex,
-                                         BigDecimal intonation, BigDecimal cadence, BigDecimal integrity){
+    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 = cadence.setScale(0, BigDecimal.ROUND_HALF_UP);
+//        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;
     }
 }

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

@@ -50,10 +50,9 @@ public interface CloudTeacherOrderService extends BaseService<Long, CloudTeacher
      * 获取乐团报名的云教练订单
      *
      * @param studentId
-     * @param musicGroupId
      * @return
      */
-    List<CloudTeacherOrder> getStudentCloudTeacherOrder(Integer studentId, String musicGroupId);
+    List<CloudTeacherOrder> getStudentCloudTeacherOrder(Integer studentId);
 
     /**
      * 退云教练

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

@@ -51,7 +51,7 @@ public interface MusicGroupPaymentCalenderDetailService extends BaseService<Long
      * @param musicGroupPaymentCalenderId
      * @param userIdList
      */
-    void batchAdd(Long musicGroupPaymentCalenderId, Set<Integer> userIdList,MusicGroup musicGroup);
+    void batchAdd(Long musicGroupPaymentCalenderId, Set<Integer> userIdList,MusicGroup musicGroup,Boolean autoCreate);
 
     /**
      * 跨团合班新增学员

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupPaymentCalenderService.java

@@ -174,4 +174,6 @@ public interface MusicGroupPaymentCalenderService extends BaseService<Long, Musi
 	 * @param batchNo
 	 */
 	void revoke(String batchNo);
+
+	List<MusicGroupPaymentCalender> findByBatchNo(String batchNo);
 }

+ 5 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupPaymentStudentCourseDetailService.java

@@ -1,8 +1,13 @@
 package com.ym.mec.biz.service;
 
+import com.ym.mec.biz.dal.entity.CourseSchedule;
 import com.ym.mec.biz.dal.entity.MusicGroupPaymentStudentCourseDetail;
 import com.ym.mec.common.service.BaseService;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 public interface MusicGroupPaymentStudentCourseDetailService extends BaseService<Long, MusicGroupPaymentStudentCourseDetail> {
 
+    String getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(String musicGroupId,Integer studentId,CourseSchedule.CourseScheduleType courseType,List<String> batchNos);
 }

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

@@ -11,5 +11,7 @@ public interface SoundSocketService {
     String RECORD_START = "recordStart";
     String RECORD_END = "recordEnd";
     String RECORD_CANCEL = "recordCancel";
+    String PROXY_MESSAGE = "proxyMessage";
+    String OFFSET_TIME = "offsetTime";
 
 }

+ 2 - 6
mec-biz/src/main/java/com/ym/mec/biz/service/StudentService.java

@@ -3,6 +3,7 @@ package com.ym.mec.biz.service;
 import java.text.ParseException;
 import java.util.List;
 
+import com.ym.mec.biz.dal.entity.CloudTeacherOrder;
 import com.ym.mec.biz.dal.entity.CooperationOrgan;
 import com.ym.mec.biz.dal.entity.Student;
 import com.ym.mec.biz.dal.enums.GradeTypeEnum;
@@ -70,12 +71,7 @@ public interface StudentService extends BaseService<Integer, Student> {
     /**
      * 更新学员会员信息
      */
-    void updateMemberRank(Integer userId, Integer rankSettingId, PeriodEnum periodEnum, int quantityPerPeriod);
-
-    /**
-     * 更新学员会员信息
-     */
-    void batchUpdateMemberRank(List<Integer> studentIds, Integer rankSettingId, PeriodEnum periodEnum, int quantityPerPeriod);
+    void updateMemberRank(CloudTeacherOrder cloudTeacherOrder, PeriodEnum periodEnum);
 
     /**
      * 更新服务指标

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

@@ -218,6 +218,10 @@ public interface SysConfigService extends BaseService<Long, SysConfig> {
 
     //会员结束前15天提醒学员续费(默认提前15天)
     String PUSH_MEMBER_RENEW = "push_member_renew";
+
+    //会员结束前15天自动创建乐团续费(默认提前15天)
+    String AUTO_CREATE_MEMBER_RENEW = "auto_create_member_renew";
+
     //会员结束前15天提醒学员续费(默认提前5天)
     String PUSH_MEMBER_RENEW_AGAIN = "push_member_renew_again";
 

+ 3 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/SysMusicCompareRecordService.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.service;
 
+import com.ym.mec.biz.dal.dto.SoundCompareHelper;
 import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
 import com.ym.mec.common.service.BaseService;
 
@@ -13,9 +14,9 @@ public interface SysMusicCompareRecordService extends BaseService<Long, SysMusic
      * @author Joburgess
      * @date 2021/6/25 0025
      * @param phone:
-     * @param userMeasureScoreMap:
+     * @param soundCompareInfo:
      * @return void
      */
-    void saveMusicCompareData(String phone, Integer sysMusicScoreId, Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap);
+    void saveMusicCompareData(String phone, SoundCompareHelper soundCompareInfo);
 
 }

+ 13 - 17
mec-biz/src/main/java/com/ym/mec/biz/service/impl/CloudTeacherOrderServiceImpl.java

@@ -1,19 +1,8 @@
 package com.ym.mec.biz.service.impl;
 
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
 import com.ym.mec.biz.dal.dao.CloudTeacherDao;
 import com.ym.mec.biz.dal.dao.CloudTeacherOrderDao;
 import com.ym.mec.biz.dal.dao.CourseScheduleDao;
-import com.ym.mec.biz.dal.dao.StudentPaymentOrderDetailDao;
 import com.ym.mec.biz.dal.dto.CloudTeacherOrderDto;
 import com.ym.mec.biz.dal.entity.CloudTeacher;
 import com.ym.mec.biz.dal.entity.CloudTeacherOrder;
@@ -26,6 +15,15 @@ import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.exception.BizException;
 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 org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 @Service
 public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTeacherOrder> implements CloudTeacherOrderService {
@@ -33,8 +31,6 @@ public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTea
     @Autowired
     private CloudTeacherOrderDao cloudTeacherOrderDao;
     @Autowired
-    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
-    @Autowired
     private CourseScheduleDao courseScheduleDao;
     @Autowired
     private CloudTeacherDao cloudTeacherDao;
@@ -104,7 +100,7 @@ public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTea
 			break;
 		}
         //更新student表信息
-        studentService.updateMemberRank(cloudTeacherOrder.getStudentId(), cloudTeacherOrder.getLevel(), periodEnum, cloudTeacherOrder.getTime());
+        studentService.updateMemberRank(cloudTeacherOrder,periodEnum);
         
         if (cloudTeacher == null) {
             cloudTeacher = new CloudTeacher();
@@ -158,8 +154,8 @@ public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTea
     }
 
     @Override
-    public List<CloudTeacherOrder> getStudentCloudTeacherOrder(Integer studentId, String musicGroupId) {
-        return cloudTeacherOrderDao.getStudentCloudTeacherOrder(studentId, musicGroupId);
+    public List<CloudTeacherOrder> getStudentCloudTeacherOrder(Integer studentId) {
+        return cloudTeacherOrderDao.getStudentCloudTeacherOrder(studentId);
     }
 
     @Override
@@ -188,7 +184,7 @@ public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTea
             }
 
             if (oldStatus.equals(1)) {
-                return true;
+                continue;
             }
             int days = DateUtil.daysBetween(DateUtil.trunc(nowDate), cloudTeacherOrder.getEndTime());
             CloudTeacher cloudTeacher = cloudTeacherDao.getByStudentId(cloudTeacherOrder.getStudentId());

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

@@ -156,22 +156,22 @@ public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, Membe
 
 		switch (periodEnum) {
 		case DAY:
-			actualAmount = memberFeeSetting.getCurrentDayFee();
+			actualAmount = memberFeeSetting.getOriginalDayFee();
 			cloudTeacherOrder.setType(1);
 			cloudTeacherOrder.setTime(1);
 			break;
 		case MONTH:
-			actualAmount = memberFeeSetting.getCurrentMonthFee();
+			actualAmount = memberFeeSetting.getOriginalMonthFee();
 			cloudTeacherOrder.setType(2);
 			cloudTeacherOrder.setTime(1);
 			break;
 		case YEAR_HALF:
-			actualAmount = memberFeeSetting.getCurrentHalfYearFee();
+			actualAmount = memberFeeSetting.getOriginalHalfYearFee();
 			cloudTeacherOrder.setType(2);
 			cloudTeacherOrder.setTime(6);
 			break;
 		case YEAR:
-			actualAmount = memberFeeSetting.getCurrentYearFee();
+			actualAmount = memberFeeSetting.getOriginalYearFee();
 			cloudTeacherOrder.setType(3);
 			cloudTeacherOrder.setTime(1);
 			break;
@@ -332,7 +332,7 @@ public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, Membe
 
 			cloudTeacherOrderService.update(cloudTeacherOrder);
 			// 添加会员有效时长
-			studentService.updateMemberRank(userId,cloudTeacherOrder.getLevel(), periodEnum, cloudTeacherOrder.getTime());
+			studentService.updateMemberRank(cloudTeacherOrder, periodEnum);
 
 			// 插入交易明细
 			BigDecimal amount = studentPaymentOrder.getActualAmount();

+ 33 - 6
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderDetailServiceImpl.java

@@ -176,9 +176,14 @@ public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<
 					cloudTeacherOrder.setStatus(2);
 					cloudTeacherOrder.setStartTime(date);
 					cloudTeacherOrder.setEndTime(DateUtil.addMonths(date,calender.getMemberValidDate()));
-					cloudTeacherOrder.setRemark("进行中乐团加学生,缴费金额改为0元");
+					if(calender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.ADD_STUDENT){
+						cloudTeacherOrder.setRemark("进行中乐团加学生,缴费金额改为0元");
+					}else {
+						cloudTeacherOrder.setRemark("乐团续费,缴费金额改为0元");
+					}
+					cloudTeacherOrder.setMusicGroupId(calender.getMusicGroupId());
 					cloudTeacherOrderDao.insert(cloudTeacherOrder);
-					studentService.updateMemberRank(e.getUserId(),calender.getMemberRankSettingId(),PeriodEnum.MONTH,calender.getMemberValidDate());
+					studentService.updateMemberRank(cloudTeacherOrder,PeriodEnum.MONTH);
 				}
 				calender.setActualNum((calender.getActualNum()==null?0:calender.getActualNum()) + 1);
 				e.setPaymentStatus(PAID_COMPLETED);
@@ -286,7 +291,7 @@ public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<
 
 	@Override
 	@Transactional(rollbackFor = Exception.class)
-	public void batchAdd(Long musicGroupPaymentCalenderId, Set<Integer> userIdList,MusicGroup musicGroup) {
+	public void batchAdd(Long musicGroupPaymentCalenderId, Set<Integer> userIdList,MusicGroup musicGroup,Boolean autoCreate) {
 		
 		MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderService.get(musicGroupPaymentCalenderId);
 		if(musicGroupPaymentCalender == null){
@@ -391,9 +396,11 @@ public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<
 		if(musicGroupPaymentStudentCourseDetailList.size() > 0){
 			musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetailList);
 		}
-		//给学员推送缴费通知
-		if(musicGroupPaymentCalender.getPayUserType() == STUDENT && musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.OPEN){
-			musicGroupPaymentCalenderService.pushWaitRenewMessage(musicGroupPaymentCalenderId,musicGroupDao.get(musicGroupPaymentCalender.getMusicGroupId()),userIdList);
+		if(!autoCreate){
+			//给学员推送缴费通知
+			if(musicGroupPaymentCalender.getPayUserType() == STUDENT && musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.OPEN){
+				musicGroupPaymentCalenderService.pushWaitRenewMessage(musicGroupPaymentCalenderId,musicGroupDao.get(musicGroupPaymentCalender.getMusicGroupId()),userIdList);
+			}
 		}
 	}
 
@@ -501,6 +508,7 @@ public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<
 			Map<Integer,MusicGroupPaymentCalenderDetail> userMap = new HashMap<Integer, MusicGroupPaymentCalenderDetail>();
 			List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = new ArrayList<MusicGroupPaymentCalenderDetail>();
 			//创建缴费明细
+			MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
 			for(Integer studentId : userIdList){
 				musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
 				musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
@@ -519,6 +527,25 @@ public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<
 				musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
 				
 				musicGroupPaymentCalenderDetailList.add(musicGroupPaymentCalenderDetail);
+				if (expectAmount.doubleValue() == 0d && expectMemberAmount.doubleValue() == 0d) {
+					// 添加会员有效时长
+					if(musicGroupPaymentCalender.getMemberRankSettingId() != null){
+						CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
+						cloudTeacherOrder.setOrganId(musicGroup.getOrganId());
+						cloudTeacherOrder.setType(2);
+						cloudTeacherOrder.setTime(musicGroupPaymentCalender.getMemberValidDate());
+						cloudTeacherOrder.setAmount(expectMemberAmount);
+						cloudTeacherOrder.setStudentId(studentId);
+						cloudTeacherOrder.setLevel(musicGroupPaymentCalender.getMemberRankSettingId());
+						cloudTeacherOrder.setStatus(2);
+						cloudTeacherOrder.setStartTime(date);
+						cloudTeacherOrder.setEndTime(DateUtil.addMonths(date,musicGroupPaymentCalender.getMemberValidDate()));
+						cloudTeacherOrder.setRemark("缴费项目0元新增学员");
+						cloudTeacherOrder.setMusicGroupId(musicGroupId);
+						cloudTeacherOrderDao.insert(cloudTeacherOrder);
+						studentService.updateMemberRank(cloudTeacherOrder,PeriodEnum.MONTH);
+					}
+				}
 			}
 
 			if (musicGroupPaymentCalenderDetailList.size() > 0) {

+ 23 - 14
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupPaymentCalenderServiceImpl.java

@@ -156,7 +156,7 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 		List<MusicGroupPaymentDateRange> musicGroupPaymentDateRangeList = musicGroupPaymentCalenderDto.getMusicGroupPaymentDateRangeList();
 
 		if(musicGroupPaymentCalenderDto.getMemberRankSettingId() != null){
-			if(paymentType != ADD_STUDENT && paymentType != MUSIC_APPLY){
+			if(paymentType != ADD_STUDENT && paymentType != MUSIC_APPLY && paymentType != MUSIC_RENEW){
 				throw new BizException("操作失败:{} 不支持会员收费",paymentType.getDesc());
 			}
 		}
@@ -204,11 +204,14 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 		if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE && musicGroupPaymentDateRangeList.size() > 1) {
 			throw new BizException("创建缴费失败:会员收费乐团不支持多周期缴费");
 		}
-		// 所有缴费项目已完成排课才能创建下一个缴费项目
-		String orignBatchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, null, null,musicGroupPaymentCalenderDto.getIgnoreBatchNoList());
-		if (StringUtils.isNoneBlank(orignBatchNo)) {
-			if(StringUtils.isEmpty(musicGroupPaymentCalenderDto.getBatchNo()) || !musicGroupPaymentCalenderDto.getBatchNo().equals(orignBatchNo)){
-				throw new BizException("当前乐团存在未排课的缴费项目,请先完成排课再操作");
+		//是否自动创建
+		if(!musicGroupPaymentCalenderDto.getAutoCreate()){
+			// 所有缴费项目已完成排课才能创建下一个缴费项目
+			String orignBatchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, null, null,musicGroupPaymentCalenderDto.getIgnoreBatchNoList());
+			if (StringUtils.isNoneBlank(orignBatchNo)) {
+				if(StringUtils.isEmpty(musicGroupPaymentCalenderDto.getBatchNo()) || !musicGroupPaymentCalenderDto.getBatchNo().equals(orignBatchNo)){
+					throw new BizException("当前乐团存在未排课的缴费项目,请先完成排课再操作");
+				}
 			}
 		}
 
@@ -490,7 +493,7 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 					//缴费项目添加学员
 					int[] ints = Arrays.stream(musicGroupPaymentCalenderDto.getStudentIds().split(",")).mapToInt(Integer::parseInt).toArray();
 					Set<Integer> list2 = Arrays.stream(ints).boxed().collect(Collectors.toSet());
-					musicGroupPaymentCalenderDetailService.batchAdd(musicGroupPaymentCalender.getId(),list2,musicGroup);
+					musicGroupPaymentCalenderDetailService.batchAdd(musicGroupPaymentCalender.getId(),list2,musicGroup,false);
 				}
 				//将0元未缴费学员缴费状态更新为已缴费
 				int j = musicGroupPaymentCalenderDetailDao.updateNoPaymentAndZeroPaymentStatus(musicGroupPaymentCalender.getId());
@@ -582,7 +585,7 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 		List<MusicGroupPaymentDateRange> musicGroupPaymentDateRangeList = musicGroupPaymentCalenderDto.getMusicGroupPaymentDateRangeList();
 
 		if(musicGroupPaymentCalenderDto.getMemberRankSettingId() != null){
-			if(paymentType != ADD_STUDENT && paymentType != MUSIC_APPLY){
+			if(paymentType != ADD_STUDENT && paymentType != MUSIC_APPLY && paymentType != MUSIC_RENEW){
 				throw new BizException("操作失败:{} 不支持会员收费",paymentType.getDesc());
 			}
 		}
@@ -1035,8 +1038,9 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 						cloudTeacherOrder.setStartTime(date);
 						cloudTeacherOrder.setEndTime(DateUtil.addMonths(date,musicGroupPaymentCalender.getMemberValidDate()));
 						cloudTeacherOrder.setRemark("进行中乐团0元加学生");
+						cloudTeacherOrder.setMusicGroupId(musicGroup.getId());
 						cloudTeacherOrderDao.insert(cloudTeacherOrder);
-						studentService.updateMemberRank(Integer.parseInt(studentId),musicGroupPaymentCalender.getMemberRankSettingId(),PeriodEnum.MONTH,musicGroupPaymentCalender.getMemberValidDate());
+						studentService.updateMemberRank(cloudTeacherOrder,PeriodEnum.MONTH);
 					}
 					MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(Integer.parseInt(studentId), musicGroupPaymentCalender.getMusicGroupId());
 					if (musicGroupStudentFee != null) {
@@ -1224,7 +1228,7 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 			//缴费项目添加学员
 			int[] ints = Arrays.stream(calender.getStudentIds().split(",")).mapToInt(Integer::parseInt).toArray();
 			Set<Integer> list2 = Arrays.stream(ints).boxed().collect(Collectors.toSet());
-			musicGroupPaymentCalenderDetailService.batchAdd(calender.getId(),list2,musicGroup);
+			musicGroupPaymentCalenderDetailService.batchAdd(calender.getId(),list2,musicGroup,false);
 		}
 		//每种课程类型单独排课
 		ClassGroup classGroup = null;
@@ -1473,6 +1477,11 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 	}
 
 	@Override
+	public List<MusicGroupPaymentCalender> findByBatchNo(String batchNo) {
+		return musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
+	}
+
+	@Override
 	@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
 	public boolean autoUpdateMusicGroupPaymentCalenderStatus() {
 		Date date = new Date();
@@ -1550,10 +1559,10 @@ public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long,
 		if (musicGroupPaymentCalenderDetailList != null && musicGroupPaymentCalenderDetailList.size() > 0) {
 			throw new BizException("缴费项目中已存在学员,不能删除");
 		}
-		if (calender.getStatus() != PaymentCalenderStatusEnum.AUDITING && calender.getStatus() != PaymentCalenderStatusEnum.NO
-				&& calender.getStatus() != PaymentCalenderStatusEnum.REJECT && calender.getStatus() != DRAFT) {
-			throw new BizException("删除失败,{} 的缴费项目不允许删除");
-		}
+//		if (calender.getStatus() != PaymentCalenderStatusEnum.AUDITING && calender.getStatus() != PaymentCalenderStatusEnum.NO
+//				&& calender.getStatus() != PaymentCalenderStatusEnum.REJECT && calender.getStatus() != DRAFT) {
+//			throw new BizException("删除失败,{} 的缴费项目不允许删除",calender.getStatus().getDesc());
+//		}
 		MusicGroupStudentClassAdjust byBatchNo = musicGroupStudentClassAdjustDao.findByBatchNo(calender.getBatchNo());
 		if(byBatchNo != null){
 			throw new BizException("删除失败,班级调整的缴费项目不允许删除");

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

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.service.impl;
 
+import com.ym.mec.biz.dal.entity.CourseSchedule;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -9,6 +10,8 @@ import com.ym.mec.biz.service.MusicGroupPaymentStudentCourseDetailService;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
 
+import java.util.List;
+
 @Service
 public class MusicGroupPaymentStudentCourseDetailServiceImpl extends BaseServiceImpl<Long, MusicGroupPaymentStudentCourseDetail>  implements MusicGroupPaymentStudentCourseDetailService {
 	
@@ -19,5 +22,9 @@ public class MusicGroupPaymentStudentCourseDetailServiceImpl extends BaseService
 	public BaseDAO<Long, MusicGroupPaymentStudentCourseDetail> getDAO() {
 		return musicGroupPaymentStudentCourseDetailDao;
 	}
-	
+
+    @Override
+    public String getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(String musicGroupId, Integer studentId, CourseSchedule.CourseScheduleType courseType, List<String> batchNos) {
+        return musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, studentId, courseType, batchNos);
+    }
 }

+ 111 - 11
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupSchoolTermCourseDetailServiceImpl.java

@@ -1,31 +1,32 @@
 package com.ym.mec.biz.service.impl;
 
-import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.biz.dal.dao.*;
+import com.ym.mec.biz.dal.dto.MusicGroupPaymentCalenderDto;
 import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
 import com.ym.mec.biz.dal.enums.MessageTypeEnum;
-import com.ym.mec.biz.service.MusicGroupSchoolTermCourseDetailService;
-import com.ym.mec.biz.service.SysConfigService;
-import com.ym.mec.biz.service.SysMessageService;
+import com.ym.mec.biz.service.*;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.entity.HttpResponseResult;
 import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.redis.service.RedisCache;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
 import com.ym.mec.util.collection.MapUtil;
 import com.ym.mec.util.date.DateUtil;
+import com.ym.mec.util.http.HttpUtil;
 import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 @Service
@@ -55,6 +56,18 @@ public class MusicGroupSchoolTermCourseDetailServiceImpl extends BaseServiceImpl
 	private StudentDao studentDao;
 	@Autowired
 	private MemberRankSettingDao memberRankSettingDao;
+	@Autowired
+	private MemberFeeSettingDao memberFeeSettingDao;
+	@Autowired
+	private OrganizationDao organizationDao;
+	@Autowired
+	private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
+	@Autowired
+	private MusicGroupPaymentCalenderDetailService musicGroupPaymentCalenderDetailService;
+	@Autowired
+	private RedisCache<String, Object> redisCache;
+
+	private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
 	@Override
 	public BaseDAO<Integer, MusicGroupSchoolTermCourseDetail> getDAO() {
@@ -152,7 +165,12 @@ public class MusicGroupSchoolTermCourseDetailServiceImpl extends BaseServiceImpl
 	}
 
 	@Override
+	@Transactional(rollbackFor = Exception.class)
 	public void musicSchoolTermPush() {
+		Object o = redisCache.get("musicSchoolTermPush");
+		if(o != null){
+			return;
+		}
 		String remindCourseTime = sysConfigDao.findConfigValue(SysConfigService.REMIND_COURSE_TIME);
 		if(StringUtils.isEmpty(remindCourseTime)){
 			remindCourseTime = "14";
@@ -191,8 +209,9 @@ public class MusicGroupSchoolTermCourseDetailServiceImpl extends BaseServiceImpl
 		if(memberRankSetting != null){
 			memberName = memberRankSetting.getName();
 		}
+		Date date = new Date();
 		//会员结束前15天提醒学员续费
-		String pushMemberRenew = sysConfigDao.findConfigValue(SysConfigService.PUSH_MEMBER_RENEW);
+		/*String pushMemberRenew = sysConfigDao.findConfigValue(SysConfigService.PUSH_MEMBER_RENEW);
 		if(StringUtils.isEmpty(pushMemberRenew)){
 			pushMemberRenew = "15";
 		}
@@ -220,8 +239,8 @@ public class MusicGroupSchoolTermCourseDetailServiceImpl extends BaseServiceImpl
 					0,
 					null,
 					"STUDENT",memberName,pushMemberRenew);
-		}
-		//会员结束前15天提醒学员续费
+		}*/
+		//会员结束前5天提醒学员续费
 		String pushMemberRenewAgain = sysConfigDao.findConfigValue(SysConfigService.PUSH_MEMBER_RENEW_AGAIN);
 		if(StringUtils.isEmpty(pushMemberRenewAgain)){
 			pushMemberRenewAgain = "5";
@@ -251,6 +270,87 @@ public class MusicGroupSchoolTermCourseDetailServiceImpl extends BaseServiceImpl
 					null,
 					"STUDENT",memberName,pushMemberRenewAgain);
 		}
+
+
+		//会员结束前15天自动创建乐团续费(默认提前15天)
+		String autoCreateMemberRenew = sysConfigDao.findConfigValue(SysConfigService.AUTO_CREATE_MEMBER_RENEW);
+		if(StringUtils.isEmpty(autoCreateMemberRenew)){
+			autoCreateMemberRenew = "15";
+		}
+		Map<String,String> studentMusicMap = MapUtil.convertMybatisMap(studentRegistrationDao.queryAutoCreateStudentMap(autoCreateMemberRenew));
+		if(studentMusicMap.size() > 0){
+			for (String musicGroupId : studentMusicMap.keySet()) {
+				MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
+				// 所有缴费项目已完成排课才能创建下一个缴费项目
+//				String orignBatchNo = musicGroupPaymentStudentCourseDetailService.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, null, null,null);
+//				if (StringUtils.isNoneBlank(orignBatchNo)) {
+//					logger.error("自动创建缴费项目失败,{} 乐团存在未排课的缴费项目",musicGroup.getName());
+//					continue;
+//				}
+				MemberFeeSetting memberFee = memberFeeSettingDao.findByRankIdAndOrganId(musicGroup.getOrganId(), memberRankSetting.getId());
+				if(memberFee == null){
+					Organization organization = organizationDao.get(musicGroup.getOrganId());
+					logger.error("自动创建缴费项目失败,{} 分部会员收费标准未配置",organization.getName());
+					continue;
+				}
+				//创建缴费项目
+				MusicGroupPaymentCalenderDto musicGroupPaymentCalenderDto = new MusicGroupPaymentCalenderDto();
+				musicGroupPaymentCalenderDto.setMusicGroupId(musicGroupId);
+				musicGroupPaymentCalenderDto.setMemberValidDate(6);
+				musicGroupPaymentCalenderDto.setMemo("系统自动创建缴费项目");
+				musicGroupPaymentCalenderDto.setMemberRankSettingId(memberRankSetting.getId());
+				musicGroupPaymentCalenderDto.setPayUserType(MusicGroupPaymentCalender.PayUserType.STUDENT);
+				musicGroupPaymentCalenderDto.setPaymentType(MusicGroupPaymentCalender.PaymentType.MUSIC_RENEW);
+				musicGroupPaymentCalenderDto.setPaymentPattern(1);
+				musicGroupPaymentCalenderDto.setMemberPaymentAmount(memberFee.getCurrentHalfYearFee().setScale(0, BigDecimal.ROUND_HALF_UP));
+				musicGroupPaymentCalenderDto.setAutoCreate(true);
+				musicGroupPaymentCalenderDto.setIsGiveMusicNetwork(false);
+				List<MusicGroupPaymentCalenderDto.MusicGroupPaymentDateRange> musicGroupPaymentDateRangeList = new ArrayList<>();
+				MusicGroupPaymentCalenderDto.MusicGroupPaymentDateRange range = new MusicGroupPaymentCalenderDto().new MusicGroupPaymentDateRange();
+				range.setStartPaymentDate(date);
+				range.setDeadlinePaymentDate(DateUtil.addMonths(date,1));
+				musicGroupPaymentDateRangeList.add(range);
+				musicGroupPaymentCalenderDto.setMusicGroupPaymentDateRangeList(musicGroupPaymentDateRangeList);
+				String batchNo = "";
+				try {
+					batchNo = musicGroupPaymentCalenderService.create(musicGroupPaymentCalenderDto);
+				}catch (Exception e){
+					logger.error("{} 乐团自动创建缴费项目失败,失败原因:{}",musicGroup.getName(),e.getMessage());
+					continue;
+				}
+				MusicGroupPaymentCalender calender = musicGroupPaymentCalenderService.findByBatchNo(batchNo).get(0);
+				Set<Integer> userIdList = Arrays.stream(studentMusicMap.get(musicGroupId).split(",")).map(Integer::new).collect(Collectors.toSet());
+				musicGroupPaymentCalenderDetailService.batchAdd(calender.getId(),userIdList,musicGroup,true);
+				Map<Integer, String> studentPhoneMap = MapUtil.convertMybatisMap(teacherDao.queryPhoneByIds(studentMusicMap.get(musicGroupId)));
+				Map<Integer,String> userMap = new HashMap<>(userIdList.size());
+				Map<Integer,String> userMap1 = new HashMap<>(userIdList.size());
+				for (Integer studentId : userIdList) {
+					userMap.put(studentId,studentPhoneMap.get(studentId));
+					userMap1.put(studentId,studentId.toString());
+				}
+				String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");
+				String pushUrl = baseApiUrl + "/#/musicGroupRenew?calenderId=" + calender.getId() + "&id=" + musicGroupId;
+				String sortUrl = HttpUtil.getSortUrl(pushUrl);
+				sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS,
+						MessageTypeEnum.SMS_AUTO_STUDENT_MEMBER_RENEW_MESSAGE,
+						userMap,
+						null,
+						0,
+						sortUrl,
+						null,memberName,autoCreateMemberRenew,sortUrl);
+
+				sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG,
+						MessageTypeEnum.PUSH_AUTO_STUDENT_MEMBER_RENEW_MESSAGE,
+						userMap1,
+						null,
+						0,
+						"4?" + pushUrl,
+						"STUDENT",memberName,autoCreateMemberRenew);
+			}
+		}
+		redisCache.getRedisTemplate().opsForValue().set("musicSchoolTermPush","musicSchoolTermPush",
+		23,
+		TimeUnit.HOURS);
 	}
 
 	private MusicGroupSchoolTermCourseDetail getCourseDetail(MusicGroupSchoolTermCourseDetail courseDetail){

+ 24 - 7
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java

@@ -883,6 +883,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     		cloudTeacherOrder.setLevel(musicGroupRegCalender.getMemberRankSettingId() == null ? 1 : musicGroupRegCalender.getMemberRankSettingId());
     		cloudTeacherOrder.setAmount(cloudTeacherPrice);
     		cloudTeacherOrder.setStatus(0);
+            cloudTeacherOrder.setMusicGroupId(musicGroup.getId());
         }
 
         if (amount.compareTo(orderAmount) != 0) {
@@ -1117,6 +1118,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     		cloudTeacherOrder.setLevel(musicGroupRegCalender.getMemberRankSettingId() == null ? 1 : musicGroupRegCalender.getMemberRankSettingId());
     		cloudTeacherOrder.setAmount(musicGroupRegCalender.getMemberPaymentAmount() == null ? cloudTeacherPrice : musicGroupRegCalender.getMemberPaymentAmount());
     		cloudTeacherOrder.setStatus(0);
+            cloudTeacherOrder.setMusicGroupId(musicGroup.getId());
         }
 
         if (amount.compareTo(orderAmount) != 0) {
@@ -2038,7 +2040,6 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
             studentRegistration.setSurplusCourseFee(BigDecimal.ZERO);
             studentRegistration.setHasCloudTeacher(0);
             studentRegistration.setUpdateTime(date);
-
             studentRegistrationDao.update(studentRegistration);
 
             //更新服务指标、运营指标
@@ -2127,12 +2128,16 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                 groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.QUIT, new ArrayList<>(Arrays.asList(userId)));
 
             }
-
-            if(isRefundMemberFee){
+            if (isRefundMemberFee){
+                if(musicGroup.getCourseViewType() != CourseViewTypeEnum.MEMBER_FEE){
+                    throw new BizException("非会员乐团不允许退云教练");
+                }
+                //删除乐团会员时长
+                studentRegistrationDao.cleanMusicMember(userId,null);
                 //退云教练费用
                 if (cloudTeacherAmount != null) {
                     Date nowDate = new Date();
-                    List<CloudTeacherOrder> cloudTeacherOrders = cloudTeacherOrderService.getStudentCloudTeacherOrder(userId, musicGroupId);
+                    List<CloudTeacherOrder> cloudTeacherOrders = cloudTeacherOrderService.getStudentCloudTeacherOrder(userId);
                     BigDecimal orderAmount = BigDecimal.ZERO;
                     if(cloudTeacherOrders.size() > 0){
                         List<CloudTeacherOrder> quitCloudTeacherOrders = new ArrayList<>();
@@ -2152,6 +2157,9 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                     //清除学员云教练
                     studentService.cleanMember(userId);
                 }
+            }else {
+                //删除乐团会员时长
+                studentRegistrationDao.cleanMusicMember(userId,musicGroupId);
             }
 
             if (isRefundCourseFee) {
@@ -2313,7 +2321,6 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
         studentRegistration.setSurplusCourseFee(BigDecimal.ZERO);
         studentRegistration.setHasCloudTeacher(0);
         studentRegistration.setUpdateTime(date);
-
         studentRegistrationDao.update(studentRegistration);
 
         //更新服务指标、运营指标
@@ -2400,11 +2407,17 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
             //统计变更学员数
             groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.QUIT, new ArrayList<>(Arrays.asList(userId)));
         }
+
         if (isRefundMemberFee){
+            if(musicGroup.getCourseViewType() != CourseViewTypeEnum.MEMBER_FEE){
+                throw new BizException("非会员乐团不允许退云教练");
+            }
+            //删除乐团会员时长
+            studentRegistrationDao.cleanMusicMember(userId,null);
             //退云教练费用
             if (cloudTeacherAmount != null) {
                 Date nowDate = new Date();
-                List<CloudTeacherOrder> cloudTeacherOrders = cloudTeacherOrderService.getStudentCloudTeacherOrder(userId, musicGroupId);
+                List<CloudTeacherOrder> cloudTeacherOrders = cloudTeacherOrderService.getStudentCloudTeacherOrder(userId);
                 BigDecimal orderAmount = BigDecimal.ZERO;
                 if(cloudTeacherOrders.size() > 0){
                     List<CloudTeacherOrder> quitCloudTeacherOrders = new ArrayList<>();
@@ -2424,6 +2437,9 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                 //清除学员云教练
                 studentService.cleanMember(userId);
             }
+        }else {
+            //删除乐团会员时长
+            studentRegistrationDao.cleanMusicMember(userId,musicGroupId);
         }
 
         if (isRefundCourseFee) {
@@ -2568,6 +2584,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     		cloudTeacherOrder.setOrderId(studentPaymentOrder.getId());
     		cloudTeacherOrder.setCreateTime(date);
     		cloudTeacherOrder.setUpdateTime(date);
+            cloudTeacherOrder.setMusicGroupId(calender.getMusicGroupId());
     		cloudTeacherOrderService.insert(cloudTeacherOrder);
         }
 
@@ -2741,7 +2758,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 
 				cloudTeacherOrderService.update(cloudTeacherOrder);
 				// 添加会员有效时长
-				studentService.updateMemberRank(userId,cloudTeacherOrder.getLevel(), periodEnum, cloudTeacherOrder.getTime());
+				studentService.updateMemberRank(cloudTeacherOrder, periodEnum);
 				
 				//添加订单明细
 				StudentPaymentOrderDetail studentPaymentOrderDetail = new StudentPaymentOrderDetail();

+ 58 - 87
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentServiceImpl.java

@@ -1,37 +1,11 @@
 package com.ym.mec.biz.service.impl;
 
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.ibatis.annotations.Param;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-
-import com.ym.mec.biz.dal.dao.CourseScheduleDao;
-import com.ym.mec.biz.dal.dao.CourseScheduleStudentPaymentDao;
-import com.ym.mec.biz.dal.dao.MusicGroupDao;
-import com.ym.mec.biz.dal.dao.PracticeGroupDao;
-import com.ym.mec.biz.dal.dao.StudentDao;
-import com.ym.mec.biz.dal.dao.StudentRegistrationDao;
+import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.dto.StudentClassInfoDto;
 import com.ym.mec.biz.dal.dto.StudentCourseTimesDto;
 import com.ym.mec.biz.dal.dto.StudentTeacherCourseDto;
-import com.ym.mec.biz.dal.entity.CooperationOrgan;
-import com.ym.mec.biz.dal.entity.CourseSchedule;
-import com.ym.mec.biz.dal.entity.Student;
-import com.ym.mec.biz.dal.enums.FivePlusGradeEnum;
-import com.ym.mec.biz.dal.enums.GradeTypeEnum;
-import com.ym.mec.biz.dal.enums.PeriodEnum;
-import com.ym.mec.biz.dal.enums.SixPlusGradeEnum;
+import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.enums.*;
 import com.ym.mec.biz.dal.page.StudentQueryInfo;
 import com.ym.mec.biz.service.StudentService;
 import com.ym.mec.common.dal.BaseDAO;
@@ -40,14 +14,20 @@ import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.util.collection.MapUtil;
 import com.ym.mec.util.date.DateUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 public class StudentServiceImpl extends BaseServiceImpl<Integer, Student> implements StudentService {
 
     @Autowired
     private StudentDao studentDao;
-    @Autowired
-    private CourseScheduleDao courseScheduleDao;
 
     @Autowired
     private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
@@ -279,25 +259,25 @@ public class StudentServiceImpl extends BaseServiceImpl<Integer, Student> implem
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void updateMemberRank(Integer userId, Integer rankSettingId, PeriodEnum periodEnum, int quantityPerPeriod) {
+    public void updateMemberRank(CloudTeacherOrder cloudTeacherOrder, PeriodEnum periodEnum) {
         // 添加会员有效时长
-        Student student = this.get(userId);
+        Student student = this.get(cloudTeacherOrder.getStudentId());
         if (student == null) {
             throw new BizException("学员信息不存在");
         }
-        
+
         Date nowDate = new Date();
         if (student.getMemberRankSettingId() == null || nowDate.after(student.getMembershipEndTime())) {
         	switch (periodEnum) {
     		case DAY:
-                student.setMembershipEndTime(DateUtil.addDays(nowDate, quantityPerPeriod));
+                student.setMembershipEndTime(DateUtil.addDays(nowDate, cloudTeacherOrder.getTime()));
     			break;
     		case MONTH:
     		case YEAR_HALF:
-                student.setMembershipEndTime(DateUtil.addMonths(nowDate, quantityPerPeriod));
+                student.setMembershipEndTime(DateUtil.addMonths(nowDate, cloudTeacherOrder.getTime()));
     			break;
     		case YEAR:
-                student.setMembershipEndTime(DateUtil.addYears(nowDate, quantityPerPeriod));
+                student.setMembershipEndTime(DateUtil.addYears(nowDate, cloudTeacherOrder.getTime()));
     			break;
 
     		default:
@@ -307,69 +287,60 @@ public class StudentServiceImpl extends BaseServiceImpl<Integer, Student> implem
         } else {
         	switch (periodEnum) {
     		case DAY:
-            	student.setMembershipEndTime(DateUtil.addDays(student.getMembershipEndTime(), quantityPerPeriod));
+            	student.setMembershipEndTime(DateUtil.addDays(student.getMembershipEndTime(), cloudTeacherOrder.getTime()));
     			break;
     		case MONTH:
     		case YEAR_HALF:
-            	student.setMembershipEndTime(DateUtil.addMonths(student.getMembershipEndTime(), quantityPerPeriod));
+            	student.setMembershipEndTime(DateUtil.addMonths(student.getMembershipEndTime(), cloudTeacherOrder.getTime()));
     			break;
     		case YEAR:
-            	student.setMembershipEndTime(DateUtil.addYears(student.getMembershipEndTime(), quantityPerPeriod));
+            	student.setMembershipEndTime(DateUtil.addYears(student.getMembershipEndTime(), cloudTeacherOrder.getTime()));
     			break;
-
     		default:
     			break;
     		}
         }
-        student.setMemberRankSettingId(rankSettingId);
-        student.setUpdateTime(nowDate);
-        this.update(student);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void batchUpdateMemberRank(List<Integer> studentIds, Integer rankSettingId, PeriodEnum periodEnum, int quantityPerPeriod) {
-        // 添加会员有效时长
-        List<Student> studentList = studentDao.findByStudentIds(studentIds);
-        Date nowDate = new Date();
-        for (Student student : studentList) {
-            if (student.getMemberRankSettingId() == null || nowDate.after(student.getMembershipEndTime())) {
-                switch (periodEnum) {
-                    case DAY:
-                        student.setMembershipEndTime(DateUtil.addDays(nowDate, quantityPerPeriod));
-                        break;
-                    case MONTH:
-                    case YEAR_HALF:
-                        student.setMembershipEndTime(DateUtil.addMonths(nowDate, quantityPerPeriod));
-                        break;
-                    case YEAR:
-                        student.setMembershipEndTime(DateUtil.addYears(nowDate, quantityPerPeriod));
-                        break;
-                    default:
-                        break;
-                }
-                student.setMembershipStartTime(nowDate);
-            } else {
-                switch (periodEnum) {
-                    case DAY:
-                        student.setMembershipEndTime(DateUtil.addMonths(student.getMembershipEndTime(), quantityPerPeriod));
-                        break;
-                    case MONTH:
-                    case YEAR_HALF:
-                        student.setMembershipEndTime(DateUtil.addMonths(student.getMembershipEndTime(), quantityPerPeriod));
-                        break;
-                    case YEAR:
-                        student.setMembershipEndTime(DateUtil.addMonths(student.getMembershipEndTime(), quantityPerPeriod));
-                        break;
-
-                    default:
-                        break;
+        if(StringUtils.isNotEmpty(cloudTeacherOrder.getMusicGroupId())){
+            StudentRegistration registration = studentRegistrationDao.getByUserIdAndMusicGroupId(cloudTeacherOrder.getMusicGroupId(), cloudTeacherOrder.getStudentId());
+            if(registration != null && (registration.getMusicGroupStatus() == StudentMusicGroupStatusEnum.NORMAL || registration.getMusicGroupStatus() == StudentMusicGroupStatusEnum.APPLY)){
+                if (registration.getMembershipEndTime() == null || nowDate.after(registration.getMembershipEndTime())) {
+                    switch (periodEnum) {
+                        case DAY:
+                            registration.setMembershipEndTime(DateUtil.addDays(nowDate, cloudTeacherOrder.getTime()));
+                            break;
+                        case MONTH:
+                        case YEAR_HALF:
+                            registration.setMembershipEndTime(DateUtil.addMonths(nowDate, cloudTeacherOrder.getTime()));
+                            break;
+                        case YEAR:
+                            registration.setMembershipEndTime(DateUtil.addYears(nowDate, cloudTeacherOrder.getTime()));
+                            break;
+                        default:
+                            break;
+                    }
+                } else {
+                    switch (periodEnum) {
+                        case DAY:
+                            registration.setMembershipEndTime(DateUtil.addDays(registration.getMembershipEndTime(), cloudTeacherOrder.getTime()));
+                            break;
+                        case MONTH:
+                        case YEAR_HALF:
+                            registration.setMembershipEndTime(DateUtil.addMonths(registration.getMembershipEndTime(), cloudTeacherOrder.getTime()));
+                            break;
+                        case YEAR:
+                            registration.setMembershipEndTime(DateUtil.addYears(registration.getMembershipEndTime(), cloudTeacherOrder.getTime()));
+                            break;
+                        default:
+                            break;
+                    }
                 }
+                studentRegistrationDao.update(registration);
             }
-            student.setMemberRankSettingId(rankSettingId);
-            student.setUpdateTime(nowDate);
         }
-        studentDao.batchUpdate(studentList);
+
+        student.setMemberRankSettingId(cloudTeacherOrder.getLevel());
+        student.setUpdateTime(nowDate);
+        this.update(student);
     }
 
     @Override

+ 12 - 3
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java

@@ -3,6 +3,7 @@ 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.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;
@@ -29,15 +30,23 @@ public class SysMusicCompareRecordServiceImpl extends BaseServiceImpl<Long, SysM
 	}
 
 	@Override
-	public void saveMusicCompareData(String phone, Integer sysMusicScoreId, Map<Integer, Map<String, BigDecimal>> userMeasureScoreMap) {
+	public void saveMusicCompareData(String phone, SoundCompareHelper soundCompareInfo) {
 		SysUser user = teacherDao.getUserWithPhone(phone);
 		if(Objects.isNull(user)){
 			return;
 		}
 		SysMusicCompareRecord sysMusicCompareRecord = new SysMusicCompareRecord();
 		sysMusicCompareRecord.setUserId(user.getId());
-		sysMusicCompareRecord.setSysMusicScoreId(sysMusicScoreId);
-		sysMusicCompareRecord.setScoreData(JSON.toJSONString(userMeasureScoreMap));
+		sysMusicCompareRecord.setSysMusicScoreId(soundCompareInfo.getMusicScoreId());
+		sysMusicCompareRecord.setScoreData(JSON.toJSONString(soundCompareInfo.getUserMeasureScoreMap()));
+		if (Objects.nonNull(soundCompareInfo.getUserMeasureScoreMap()) && soundCompareInfo.getUserMeasureScoreMap().containsKey(-1)){
+			Map<String, Object> finalScore = soundCompareInfo.getUserMeasureScoreMap().get(-1);
+			sysMusicCompareRecord.setScore((BigDecimal) finalScore.get("score"));
+			sysMusicCompareRecord.setIntonation((BigDecimal) finalScore.get("intonation"));
+			sysMusicCompareRecord.setCadence((BigDecimal) finalScore.get("cadence"));
+			sysMusicCompareRecord.setIntegrity((BigDecimal) finalScore.get("integrity"));
+		}
+		sysMusicCompareRecord.setRecordFilePath(soundCompareInfo.getRecordFilePath());
 		sysMusicCompareRecordDao.insert(sysMusicCompareRecord);
 	}
 }

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

@@ -44,6 +44,7 @@
         <result column="key_" property="key"/>
         <result column="value_" property="value"/>
         <result column="courseScheduleId_" property="courseScheduleId"/>
+        <result column="type_" property="type"/>
     </resultMap>
 
     <insert id="insert" parameterType="com.ym.mec.biz.dal.entity.ClassGroup" useGeneratedKeys="true" keyColumn="id"
@@ -1535,7 +1536,7 @@
     </select>
     
     <select id="countTeacherByMusicGroupId" resultMap="Mapper">
-		select cg.id_ courseScheduleId_,cg.name_ key_,GROUP_CONCAT(u.real_name_) value_ from class_group cg LEFT JOIN class_group_teacher_mapper cgtm on cg.id_ = cgtm.class_group_id_
+		select cg.id_ courseScheduleId_,cg.type_,cg.name_ key_,GROUP_CONCAT(u.real_name_) value_ from class_group cg LEFT JOIN class_group_teacher_mapper cgtm on cg.id_ = cgtm.class_group_id_
 		LEFT JOIN sys_user u on u.id_ = cgtm.user_id_
 		where cg.del_flag_ = 0 and cg.group_type_ = 'MUSIC' and cg.music_group_id_ = #{musicGroupId}  group by cg.id_ order by cg.type_
     </select>

+ 11 - 10
mec-biz/src/main/resources/config/mybatis/CloudTeacherOrderMapper.xml

@@ -38,8 +38,10 @@
         <result column="order_id_" property="cloudTeacherOrder.orderId"/>
         <result column="trans_status_" property="studentPaymentOrder.status"/>
         <result column="expect_amount_" property="studentPaymentOrder.expectAmount"/>
+        <result column="pay_time_" property="studentPaymentOrder.payTime"/>
         <result column="name_" property="memberRankSetting.name"/>
         <result column="icon_" property="memberRankSetting.icon"/>
+        <result column="music_group_id_" property="studentPaymentOrder.musicGroupId"/>
     </resultMap>
 
     <select id="get" resultMap="CloudTeacherOrder">
@@ -55,15 +57,17 @@
             useGeneratedKeys="true">
         <!--@mbg.generated-->
         insert into cloud_teacher_order (organ_id_,student_id_, type_, level_, time_, amount_, refund_amount_, status_,
-        order_id_,start_time_,end_time_,
-        remark_, create_time_, update_time_)
+        order_id_,start_time_,end_time_,remark_, create_time_, update_time_,music_group_id_)
         values (#{organId},#{studentId}, #{type},#{level}, #{time}, #{amount}, #{refundAmount},
-        #{status},#{orderId},#{startTime},#{endTime}, #{remark}, NOW(), NOW())
+        #{status},#{orderId},#{startTime},#{endTime}, #{remark}, NOW(), NOW(),#{musicGroupId})
     </insert>
     <update id="update" parameterType="com.ym.mec.biz.dal.entity.CloudTeacherOrder">
         <!--@mbg.generated-->
         update cloud_teacher_order
         <set>
+            <if test="musicGroupId != null">
+                music_group_id_ = #{musicGroupId},
+            </if>
             <if test="organId != null">
                 organ_id_ = #{organId},
             </if>
@@ -117,7 +121,7 @@
 
     <!-- 分页查询 -->
     <select id="queryPage" resultMap="CloudTeacherOrderDto" parameterType="map">
-        SELECT cto.*,spo.status_ trans_status_,spo.expect_amount_,mrs.name_,mrs.icon_ FROM cloud_teacher_order cto
+        SELECT cto.*,spo.status_ trans_status_,spo.expect_amount_,spo.pay_time_,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'
@@ -146,12 +150,9 @@
     </select>
 
     <select id="getNoStartCloudTeacherOrder" resultMap="CloudTeacherOrder">
-        SELECT cto.*, spo.music_group_id_
+        SELECT cto.*
         FROM cloud_teacher_order cto
-                 LEFT JOIN student_payment_order spo ON cto.order_id_ = spo.id_
-                 LEFT JOIN music_group mg on spo.music_group_id_ = mg.id_
         WHERE cto.status_ = 1
-        ORDER BY spo.pay_time_ ASC
     </select>
 
     <select id="getStudentCloudTeacherOrders" resultMap="CloudTeacherOrder">
@@ -188,8 +189,8 @@
 
     <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_
+       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>
 </mapper>

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

@@ -534,6 +534,7 @@
 		SELECT
 			ee.id_ homeworkId,
 			su.real_name_ teacherName,
+		    su.avatar_ teacherAvatar,
 			ee.create_time_ createTime,
 			COUNT( eer.user_id_ ) exceptStudentNum,
 			SUM( eer.status_ ) submitStudentNum,

+ 6 - 3
mec-biz/src/main/resources/config/mybatis/IndexBaseMonthDataMapper.xml

@@ -797,15 +797,18 @@
 		music_group_payment_calender_detail mgpcd
 		LEFT JOIN music_group_payment_calender mgpc ON mgpcd.music_group_payment_calender_id_ = mgpc.id_
 		LEFT JOIN music_group mg ON mgpc.music_group_id_ = mg.id_
+		LEFT JOIN student_registration sr ON sr.music_group_id_ = mgpc.music_group_id_ AND mgpcd.user_id_ = sr.user_id_
 		WHERE
 		mg.status_ = 'PROGRESS'
+		AND ((mgpc.member_rank_setting_id_ IS NOT NULL AND (DATEDIFF(sr.membership_end_time_,NOW()) &lt; 0 OR sr.membership_end_time_ IS NULL)) OR mgpc.member_rank_setting_id_ IS NULL)
 		<if test="noPaymentType==null or noPaymentType==0">
-			AND DATE_FORMAT(NOW(),'%Y-%m-%d') > mgpc.deadline_payment_date_
+			AND DATE_FORMAT(NOW(),'%Y-%m-%d') > DATE_FORMAT(mgpc.deadline_payment_date_,'%Y-%m-%d')
 		</if>
 		<if test="noPaymentType!=null and noPaymentType==1">
-			AND DATE_FORMAT(NOW(),'%Y-%m-%d') BETWEEN mgpc.start_payment_date_ AND mgpc.deadline_payment_date_
+			AND DATE_FORMAT(NOW(),'%Y-%m-%d') BETWEEN DATE_FORMAT(mgpc.start_payment_date_,'%Y-%m-%d') AND DATE_FORMAT(mgpc.deadline_payment_date_,'%Y-%m-%d')
 		</if>
-		AND mgpcd.payment_status_ = 'NON_PAYMENT' AND mgpcd.expect_amount_ > 0 AND mgpc.batch_no_ IS NOT NULL AND mgpc.pay_user_type_ = 'STUDENT'
+		AND mgpcd.payment_status_ = 'NON_PAYMENT' AND mgpc.batch_no_ IS NOT NULL AND mgpc.pay_user_type_ = 'STUDENT'
+		AND (mgpcd.expect_amount_ + mgpcd.expect_member_amount_) > 0
 		<if test="educationUserId != null">
 			AND mg.educational_teacher_id_ = #{educationUserId}
 		</if>

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

@@ -898,9 +898,10 @@
         <result property="memberDay" column="member_day_"/>
         <result property="visitTime" column="visit_time_"/>
         <result property="phone" column="phone_"/>
+        <result property="courseViewType" column="course_view_type_"/>
     </resultMap>
     <select id="queryMusicMemberList" resultMap="MusicMemberDto">
-        SELECT sr.user_id_,su.username_,su.phone_,o.name_ organ_name_,mg.name_ music_group_name_,
+        SELECT sr.user_id_,su.username_,su.phone_,o.name_ organ_name_,mg.name_ music_group_name_,mg.course_view_type_,
         DATEDIFF(MAX(cto.end_time_),NOW()) + 1 member_day_,sr.music_group_id_,MAX(sv.visit_time_) visit_time_ FROM student_registration sr
         LEFT JOIN music_group mg ON mg.id_ = sr.music_group_id_
         LEFT JOIN cloud_teacher_order cto ON cto.student_id_ = sr.user_id_ AND cto.status_ IN (1,2)

+ 11 - 5
mec-biz/src/main/resources/config/mybatis/MusicGroupPaymentCalenderDetailMapper.xml

@@ -400,8 +400,10 @@
 	<select id="queryNoPaymentTotalAmount" resultType="java.util.Map">
 		SELECT mgpcd.user_id_ 'key',SUM(mgpcd.expect_amount_ + mgpcd.expect_member_amount_) 'value' FROM music_group_payment_calender_detail mgpcd
 		LEFT JOIN music_group_payment_calender mgpc ON mgpcd.music_group_payment_calender_id_ = mgpc.id_
+		LEFT JOIN student_registration sr ON sr.user_id_ = mgpcd.user_id_ AND sr.music_group_id_ = mgpc.music_group_id_
 		WHERE mgpc.batch_no_ IS NOT NULL AND mgpcd.payment_status_ = 'NON_PAYMENT' AND (mgpcd.expect_amount_ + mgpcd.expect_member_amount_) > 0
-		AND mgpc.music_group_id_ = #{musicGroupId} AND mgpc.status_ IN ('OPEN','OVER','PAID') AND mgpc.pay_user_type_ = 'STUDENT'
+		  AND mgpc.music_group_id_ = #{musicGroupId} AND mgpc.status_ IN ('OPEN','OVER','PAID') AND mgpc.pay_user_type_ = 'STUDENT'
+		  AND ((mgpc.member_rank_setting_id_ IS NOT NULL AND (DATEDIFF(sr.membership_end_time_,NOW()) &lt; 0 OR sr.membership_end_time_ IS NULL)) OR mgpc.member_rank_setting_id_ IS NULL)
 		GROUP BY mgpcd.user_id_
 	</select>
 
@@ -437,11 +439,12 @@
 	<sql id="queryArrearageStudentsCondition">
 		<where>
 			mg.status_ = 'PROGRESS'
+			AND ((mgpc.member_rank_setting_id_ IS NOT NULL AND (DATEDIFF(sr.membership_end_time_,NOW()) &lt; 0 OR sr.membership_end_time_ IS NULL)) OR mgpc.member_rank_setting_id_ IS NULL)
 			<if test="noPaymentType==null or noPaymentType==0">
-				AND DATE_FORMAT(NOW(),'%Y-%m-%d') > mgpc.deadline_payment_date_
+				AND DATE_FORMAT(NOW(),'%Y-%m-%d') > DATE_FORMAT(mgpc.deadline_payment_date_,'%Y-%m-%d')
 			</if>
 			<if test="noPaymentType!=null and noPaymentType==1">
-				AND DATE_FORMAT(NOW(),'%Y-%m-%d') BETWEEN mgpc.start_payment_date_ AND mgpc.deadline_payment_date_
+				AND DATE_FORMAT(NOW(),'%Y-%m-%d') BETWEEN DATE_FORMAT(mgpc.start_payment_date_,'%Y-%m-%d') AND DATE_FORMAT(mgpc.deadline_payment_date_,'%Y-%m-%d')
 			</if>
 			AND mgpcd.payment_status_ = 'NON_PAYMENT' AND mgpc.batch_no_ IS NOT NULL AND mgpc.pay_user_type_ = 'STUDENT'
 			AND (mgpcd.expect_amount_ + mgpcd.expect_member_amount_) > 0
@@ -454,6 +457,9 @@
 			<if test="musicGroupId!=null and musicGroupId!=''">
 				AND mgpc.music_group_id_ = #{musicGroupId}
 			</if>
+			<if test="courseViewType != null">
+				AND mg.course_view_type_ = #{courseViewType}
+			</if>
 			<if test="cooperationOrganId!=null">
 				AND mg.cooperation_organ_id_ = #{cooperationOrganId}
 			</if>
@@ -484,8 +490,7 @@
 			music_group_payment_calender_detail mgpcd
 			LEFT JOIN music_group_payment_calender mgpc ON mgpcd.music_group_payment_calender_id_ = mgpc.id_
 			LEFT JOIN music_group mg ON mgpc.music_group_id_ = mg.id_
-			LEFT JOIN student_registration sr ON sr.music_group_id_ = mgpc.music_group_id_
-			AND mgpcd.user_id_ = sr.user_id_
+			LEFT JOIN student_registration sr ON sr.music_group_id_ = mgpc.music_group_id_ AND mgpcd.user_id_ = sr.user_id_
 			LEFT JOIN sys_user su ON mgpcd.user_id_ = su.id_
 			LEFT JOIN sys_user_tsign sut ON sut.user_id_ = su.id_
 			LEFT JOIN sys_user edu ON edu.id_ = mg.educational_teacher_id_
@@ -505,6 +510,7 @@
 			music_group_payment_calender_detail mgpcd
 			LEFT JOIN music_group_payment_calender mgpc ON mgpcd.music_group_payment_calender_id_ = mgpc.id_
 			LEFT JOIN music_group mg ON mgpc.music_group_id_ = mg.id_
+			LEFT JOIN student_registration sr ON sr.music_group_id_ = mgpc.music_group_id_ AND mgpcd.user_id_ = sr.user_id_
 			<if test="search!=null and search!=''">
 				LEFT JOIN sys_user su ON mgpcd.user_id_ = su.id_
 			</if>

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

@@ -16,6 +16,7 @@
         <result column="status_" property="status" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
         <association property="musicGroup" javaType="com.ym.mec.biz.dal.entity.MusicGroup">
             <result column="music_group_name_" property="name"/>
+            <result column="course_view_type_" property="courseViewType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
         </association>
         <association property="user" javaType="com.ym.mec.auth.api.entity.SysUser">
             <result column="username_" property="username"/>
@@ -90,7 +91,7 @@
 
     <!-- 分页查询 -->
     <select id="queryPage" resultMap="MusicGroupQuit" parameterType="map">
-        SELECT mgq.*,mg.name_ music_group_name_,su.username_
+        SELECT mgq.*,mg.name_ music_group_name_,su.username_,mg.course_view_type_
         FROM music_group_quit mgq
         LEFT JOIN sys_user su ON su.id_ = mgq.user_id_
         LEFT JOIN music_group mg ON mg.id_ = mgq.music_group_id_

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

@@ -514,6 +514,7 @@
             CONCAT( cs.class_date_, ' ', cs.start_class_time_ ) courseStartTime,
             cs.actual_teacher_id_ teacherId,
             su.real_name_ teacherName,
+            su.avatar_ teacherAvatar,
             COUNT( sch.user_id_ ) exceptStudentNum,
             SUM( sch.status_ ) submitStudentNum,
             SUM( sch.is_replied_ ) repliedStudentNum

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

@@ -533,13 +533,14 @@
         <result column="come_on_package_" property="comeOnPackage"/>
         <result column="registerTime" property="registerTime"/>
         <result column="remark_" property="remark"/>
+        <result column="membership_end_time_" property="membershipEndTime"/>
     </resultMap>
     <select id="queryMusicGroupStudent" resultMap="MusicGroupStudentsDto">
         SELECT sr.id_ student_registration_id_,sr.user_id_,su.username_ real_name_,su.gender_,su.phone_ parents_phone_,sr.current_grade_,sr.current_grade_date_,
         sr.current_class_,sr.music_group_status_ student_status_,sr.payment_status_,sr.subject_id_ reg_subject_id_,rs.name_ regSubjectName,sr.remark_,
         sr.actual_subject_id_ subject_id_,s.name_ subject_name_,sr.music_group_id_,CASE WHEN su.password_ IS NULL THEN 0 ELSE 1 END isActive_,
         IF(DATE_FORMAT(sr.create_time_,'%Y-%m-%d') > DATE_FORMAT(mg.payment_expire_date_,'%Y-%m-%d'),1,0) is_new_student_,
-        stu.care_package_,stu.come_on_package_,sr.create_time_ registerTime
+        stu.care_package_,stu.come_on_package_,sr.create_time_ registerTime,sr.membership_end_time_
         FROM student_registration sr
         LEFT JOIN sys_user su ON sr.user_id_ = su.id_
         LEFT JOIN subject s ON s.id_ = sr.actual_subject_id_

+ 16 - 0
mec-biz/src/main/resources/config/mybatis/StudentRegistrationMapper.xml

@@ -50,6 +50,7 @@
         <result column="none_need_cloud_teacher_" property="noneNeedCloudTeacher"/>
         <result column="membership_end_time_" property="membershipEndTime"/>
         <result column="music_group_payment_calender_id_" property="musicGroupPaymentCalenderId"/>
+        <result column="membership_end_time_" property="membershipEndTime"/>
     </resultMap>
 
     <resultMap type="com.ym.mec.biz.dal.dto.StudentMusicGroupDto" id="StudentMusicGroupDto"
@@ -365,6 +366,9 @@
             <if test="noneNeedCloudTeacher != null">
                 none_need_cloud_teacher_ =#{noneNeedCloudTeacher},
             </if>
+            <if test="membershipEndTime != null">
+                membership_end_time_ =#{membershipEndTime},
+            </if>
                 music_group_payment_calender_id_ =#{musicGroupPaymentCalenderId}
         </set>
         WHERE id_ = #{id}
@@ -1360,6 +1364,13 @@
         WHERE music_group_id_ = #{musicGroupId}
         AND music_group_status_ IN ('APPLY', 'NORMAL')
     </update>
+    <update id="cleanMusicMember">
+        UPDATE student_registration SET membership_end_time_ = NULL
+        WHERE user_id_ = #{userId}
+        <if test="musicGroupId != null and musicGroupId != ''">
+            AND music_group_id_ = #{musicGroupId}
+        </if>
+    </update>
 
     <select id="countPayingNum" resultType="map">
         SELECT COUNT(DISTINCT user_id_) `value`, actual_subject_id_ `key`
@@ -1658,4 +1669,9 @@
         AND music_group_status_ != 'QUIT'
         GROUP BY music_group_id_,actual_subject_id_
     </select>
+    <select id="queryAutoCreateStudentMap" resultType="java.util.Map">
+        SELECT GROUP_CONCAT(sr.user_id_) 'value',sr.music_group_id_ 'key' FROM student_registration sr
+        WHERE sr.membership_end_time_ IS NOT NULL AND DATEDIFF(sr.membership_end_time_,NOW()) + 1 = #{pushMemberRenew}
+        GROUP BY sr.music_group_id_
+    </select>
 </mapper>

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

@@ -11,6 +11,11 @@
 		<result column="user_id_" property="userId" />
 		<result column="sys_music_score_id_" property="sysMusicScoreId" />
 		<result column="score_data_" property="scoreData" />
+		<result column="score_" property="score" />
+		<result column="intonation_" property="intonation" />
+		<result column="cadence_" property="cadence" />
+		<result column="integrity_" property="integrity" />
+		<result column="record_file_path_" property="recordFilePath" />
 		<result column="create_time_" property="createTime" />
 	</resultMap>
 
@@ -31,8 +36,8 @@
 		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_,create_time_)
-		VALUES(#{id},#{userId},#{sysMusicScoreId},#{scoreData},NOW())
+		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>
 
 	<!-- 根据主键查询一条记录 -->
@@ -50,6 +55,21 @@
 		<if test="scoreData != null">
 			score_data_ = #{scoreData},
 		</if>
+		<if test="score != null">
+			score_ = #{score},
+		</if>
+		<if test="integrity != null">
+			integrity_ = #{integrity},
+		</if>
+		<if test="cadence != null">
+			cadence_ = #{cadence},
+		</if>
+		<if test="sysMusicScoreId != null">
+			sys_music_score_id_ = #{sysMusicScoreId},
+		</if>
+		<if test="recordFilePath != null">
+			record_file_path_ = #{recordFilePath},
+		</if>
 		<if test="createTime != null">
 			create_time_ = #{createTime},
 		</if>

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

@@ -549,6 +549,8 @@
         <result property="disposeContent" column="dispose_content_"/>
         <result property="teacherAttendanceId" column="teacher_attendance_id_"/>
         <result property="url" column="url_"/>
+        <result property="teachMode" column="teach_mode_"/>
+        <result property="courseType" column="course_type_"/>
         <result property="updateAttendanceEnum" column="update_attendance_type_" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
     </resultMap>
     <select id="queryTeacherAttendanceComplaints" resultMap="TeacherAttendanceComplaintsDtoMap">
@@ -557,7 +559,7 @@
         IF(ta.sign_out_status_ IS NULL,3,ta.sign_out_status_) sign_out_status_,
         suo.real_name_ operator_name_,su.real_name_ teacher_name_,ta.complaints_status_,ta.sign_in_time_,ta.sign_out_time_
         ,ta.complaints_content_,ta.dispose_content_,cs.end_class_time_,cs.start_class_time_,
-        ta.id_ teacher_attendance_id_,ta.update_attendance_type_,ta.url_,ta.complaints_type_
+        ta.id_ teacher_attendance_id_,ta.update_attendance_type_,ta.url_,ta.complaints_type_,cs.teach_mode_,cs.type_ course_type_
         FROM teacher_attendance ta
         LEFT JOIN sys_user su ON ta.teacher_id_ = su.id_
         LEFT JOIN teacher t ON t.id_ = su.id_

+ 3 - 2
mec-student/src/main/java/com/ym/mec/student/config/WebSocketConfig.java

@@ -25,8 +25,9 @@ public class WebSocketConfig implements WebSocketConfigurer {
 
     @Override
     public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
-        webSocketHandlerRegistry.addHandler(webSocketHandler, "/ws")
-                .addInterceptors(webSocketHandshakeInterceptor);
+        webSocketHandlerRegistry.addHandler(webSocketHandler, "/audioEvaluate")
+                .addInterceptors(webSocketHandshakeInterceptor)
+                .setAllowedOrigins("*");
     }
 
     @Bean

+ 6 - 1
mec-student/src/main/java/com/ym/mec/student/controller/MusicGroupRecordController.java

@@ -4,7 +4,6 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -78,4 +77,10 @@ public class MusicGroupRecordController extends BaseController {
 		return succeed(model);
 	}
 
+	@ApiOperation(value = "学员列表")
+	@GetMapping("/queryStudentInfo")
+	public Object queryStudentInfo(MusicGroupRecordStudentQueryInfo queryInfo) {
+		return succeed(studentRegistrationService.queryStudentRegisterInstrumentsDetailList(queryInfo));
+	}
+
 }

+ 3 - 2
mec-teacher/src/main/java/com/ym/mec/teacher/config/WebSocketConfig.java

@@ -25,8 +25,9 @@ public class WebSocketConfig implements WebSocketConfigurer {
 
     @Override
     public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
-        webSocketHandlerRegistry.addHandler(webSocketHandler, "/ws")
-                .addInterceptors(webSocketHandshakeInterceptor);
+        webSocketHandlerRegistry.addHandler(webSocketHandler, "/audioEvaluate", "/ws")
+                .addInterceptors(webSocketHandshakeInterceptor)
+                .setAllowedOrigins("*");
     }
 
     @Bean

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

@@ -54,10 +54,10 @@ public class SoundController extends BaseController {
         if(!WebSocketHandler.WS_CLIENTS.containsKey(phone)){
             return failed("未上线");
         }
-        if(!WebSocketHandler.WS_CLIENTS.get(phone).isOpen()){
+        if(!WebSocketHandler.WS_CLIENTS.get(phone).getSession().isOpen()){
             return failed("已离线");
         }
-        WebSocketHandler.WS_CLIENTS.get(phone).sendMessage(new TextMessage(message));
+        WebSocketHandler.WS_CLIENTS.get(phone).getSession().sendMessage(new TextMessage(message));
         return succeed();
     }
 
@@ -66,10 +66,10 @@ public class SoundController extends BaseController {
         if(!WebSocketHandler.WS_CLIENTS.containsKey(phone)){
             return failed("未上线");
         }
-        if(!WebSocketHandler.WS_CLIENTS.get(phone).isOpen()){
+        if(!WebSocketHandler.WS_CLIENTS.get(phone).getSession().isOpen()){
             return failed("已离线");
         }
-        WebSocketHandler.WS_CLIENTS.get(phone).close();
+        WebSocketHandler.WS_CLIENTS.get(phone).getSession().close();
         return succeed();
     }
 

+ 41 - 0
mec-web/src/main/java/com/ym/mec/web/config/WebSocketConfig.java

@@ -0,0 +1,41 @@
+package com.ym.mec.web.config;
+
+import com.ym.mec.biz.handler.WebSocketHandler;
+import com.ym.mec.web.interceptor.WebSocketHandshakeInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/6/8 0008
+ */
+@Configuration
+@EnableWebSocket
+public class WebSocketConfig implements WebSocketConfigurer {
+
+    @Autowired
+    private WebSocketHandler webSocketHandler;
+    @Autowired
+    private WebSocketHandshakeInterceptor webSocketHandshakeInterceptor;
+
+    @Override
+    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
+        webSocketHandlerRegistry.addHandler(webSocketHandler, "/audioEvaluate")
+                .addInterceptors(webSocketHandshakeInterceptor)
+                .setAllowedOrigins("*");
+    }
+
+    @Bean
+    public ServletServerContainerFactoryBean createWebSocketContainer() {
+        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
+        container.setMaxTextMessageBufferSize(8192*4);
+        container.setMaxBinaryMessageBufferSize(8192*4);
+        return container;
+    }
+
+}

+ 55 - 0
mec-web/src/main/java/com/ym/mec/web/controller/ExportController.java

@@ -2995,4 +2995,59 @@ public class ExportController extends BaseController {
             }
         }
     }
+
+    @ApiOperation(value = "老师列表导出")
+    @RequestMapping("export/teacherList")
+    @PreAuthorize("@pcs.hasPermissions('export/teacherList')")
+    public void exportTeacherList(TeacherQueryInfo queryInfo,HttpServletResponse response) throws IOException {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            throw new BizException("用户信息获取失败");
+        }
+        Employee employee = employeeDao.get(sysUser.getId());
+        if (StringUtils.isEmpty(queryInfo.getOrganId())) {
+            queryInfo.setOrganId(employee.getOrganIdList());
+        }else if(StringUtils.isEmpty(employee.getOrganIdList())){
+            throw new BizException("用户所在分部异常");
+        }else {
+            List<String> list = Arrays.asList(employee.getOrganIdList().split(","));
+            if(!list.containsAll(Arrays.asList(queryInfo.getOrganId().split(",")))){
+                throw new BizException("非法请求");
+            }
+        }
+        queryInfo.setPage(1);
+        queryInfo.setRows(49999);
+        List<Teacher> rows = teacherService.queryPageDetail(queryInfo).getRows();
+        if (CollectionUtils.isEmpty(rows)) {
+            response.setStatus(200);
+            response.setContentType("Content-Type: application/json;charset=UTF-8");
+            response.getOutputStream().write("{\"data\": null, \"code\": 500, \"status\": false, \"msg\": \"没有可导出的记录\"}".getBytes());
+            response.flushBuffer();
+            return;
+        }
+        OutputStream outputStream = response.getOutputStream();
+        try {
+            String[] header = {"老师编号", "老师名称", "所属分部", "老师状态", "专业技能", "联系电话", "工作类型",
+                    "员工状态", "已开小课", "试听课安排", "开放网管课","转正日期","离职日期"};
+            String[] body = {"id", "realName", "organName", "lockFlag == 0?'正常':lockFlag == 1?'冻结':'锁定'", "splitSubjectName", "phone", "jobNature.msg",
+                    "isProbationPeriod.msg", "vipNum", "demoNum", "isSupportExtraPracticeLesson?'是':'否'","formalStaffDate","demissionDate"};
+            HSSFWorkbook workbook = POIUtil.exportExcel(header, body, rows);
+            response.setContentType("application/octet-stream");
+            response.setHeader("Content-Disposition", "attachment;filename=teacherPage-" + DateUtil.getDate(new Date()) + ".xls");
+            response.flushBuffer();
+            outputStream = response.getOutputStream();
+            workbook.write(outputStream);
+            outputStream.flush();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
 }

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

@@ -91,7 +91,7 @@ public class MusicGroupQuitController extends BaseController {
                 if (studentMaintenance != null) {
                     row.setHasMaintenance(true);
                 }
-                List<CloudTeacherOrder> cloudTeacherOrders = cloudTeacherOrderDao.getStudentCloudTeacherOrder(row.getUserId(), row.getMusicGroupId());
+                List<CloudTeacherOrder> cloudTeacherOrders = cloudTeacherOrderDao.getStudentCloudTeacherOrder(row.getUserId());
                 if(cloudTeacherOrders.size() > 0){
                     BigDecimal orderAmount = BigDecimal.ZERO;
                     for (CloudTeacherOrder cloudTeacherOrder : cloudTeacherOrders) {

+ 7 - 1
mec-web/src/main/java/com/ym/mec/web/controller/TaskController.java

@@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
 import java.io.File;
 import java.net.URL;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 @RequestMapping("task")
@@ -471,7 +472,12 @@ public class TaskController extends BaseController {
 	@ApiOperation("每天10点推送排课、续费提醒")
 	@GetMapping(value = "/musicSchoolTermPush")
 	public void musicSchoolTermPush() {
-		musicGroupSchoolTermCourseDetailService.musicSchoolTermPush();
+//		Boolean success = redisCache.getRedisTemplate().opsForValue().setIfAbsent("musicSchoolTermPush","musicSchoolTermPush",
+//				23,
+//				TimeUnit.HOURS);
+//		if(success){
+			musicGroupSchoolTermCourseDetailService.musicSchoolTermPush();
+//		}
 	}
 
 	@ApiOperation("会员到期后清空会员信息")

+ 12 - 0
mec-web/src/main/java/com/ym/mec/web/controller/education/EduMusicGroupRecordController.java

@@ -4,6 +4,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -13,9 +14,11 @@ import com.ym.mec.biz.dal.dao.ClassGroupDao;
 import com.ym.mec.biz.dal.dao.StudentRegistrationDao;
 import com.ym.mec.biz.dal.dto.MusicGroupBasicDto;
 import com.ym.mec.biz.dal.entity.MusicGroup;
+import com.ym.mec.biz.dal.page.MusicGroupRecordStudentQueryInfo;
 import com.ym.mec.biz.service.CooperationOrganLinkmanService;
 import com.ym.mec.biz.service.MusicGroupService;
 import com.ym.mec.biz.service.OrganizationService;
+import com.ym.mec.biz.service.StudentRegistrationService;
 import com.ym.mec.common.controller.BaseController;
 
 @RequestMapping("eduMusicGroupRecord")
@@ -37,6 +40,9 @@ public class EduMusicGroupRecordController extends BaseController {
 	
 	@Autowired
 	private ClassGroupDao classGroupDao;
+	
+	@Autowired
+	private StudentRegistrationService studentRegistrationService;
 
 	@ApiOperation(value = "查询基本信息")
 	@GetMapping("/queryBasicInfo")
@@ -71,4 +77,10 @@ public class EduMusicGroupRecordController extends BaseController {
 		
 		return succeed(model);
 	}
+
+	@ApiOperation(value = "学员列表")
+	@GetMapping("/queryStudentInfo")
+	public Object queryStudentInfo(MusicGroupRecordStudentQueryInfo queryInfo) {
+		return succeed(studentRegistrationService.queryStudentRegisterInstrumentsDetailList(queryInfo));
+	}
 }

+ 28 - 0
mec-web/src/main/java/com/ym/mec/web/interceptor/WebSocketHandshakeInterceptor.java

@@ -0,0 +1,28 @@
+package com.ym.mec.web.interceptor;
+
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.server.HandshakeInterceptor;
+
+import java.util.Map;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/6/9 0009
+ */
+@Component
+public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
+
+    @Override
+    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
+        return true;
+    }
+
+    @Override
+    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
+
+    }
+
+}