shangke 2 سال پیش
والد
کامیت
5de5bdcb13
31فایلهای تغییر یافته به همراه1202 افزوده شده و 790 حذف شده
  1. 239 354
      .idea/httpRequests/http-requests-log.http
  2. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CourseScheduleStudentPaymentDao.java
  3. 13 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/BasicUserDto.java
  4. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/CourseScheduleDto.java
  5. 23 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherClassCourseSchudeleDto.java
  6. 3 177
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/CourseScheduleStudentPayment.java
  7. 13 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentAttendance.java
  8. 8 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/mapper/LiveGroupPlusMapper.java
  9. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/CourseDetailQueryInfo.java
  10. 7 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/LiveGroupWrapper.java
  11. 8 0
      mec-biz/src/main/java/com/ym/mec/biz/service/CourseScheduleService.java
  12. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/service/CourseShareService.java
  13. 4 2
      mec-biz/src/main/java/com/ym/mec/biz/service/SysConfigService.java
  14. 396 51
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/CourseScheduleServiceImpl.java
  15. 59 37
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/CourseShareServiceImpl.java
  16. 10 14
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java
  17. 158 39
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/VipGroupServiceImpl.java
  18. 2 1
      mec-biz/src/main/resources/config/mybatis/ClassGroupStudentMapperMapper.xml
  19. 48 5
      mec-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml
  20. 9 3
      mec-biz/src/main/resources/config/mybatis/CourseScheduleStudentPaymentMapper.xml
  21. 2 2
      mec-biz/src/main/resources/config/mybatis/CourseShareMapper.xml
  22. 25 2
      mec-biz/src/main/resources/config/mybatis/LiveGroupPlusMapper.xml
  23. 3 1
      mec-biz/src/main/resources/config/mybatis/StudentAttendanceMapper.xml
  24. 7 10
      mec-biz/src/main/resources/config/mybatis/VipGroupMapper.xml
  25. 86 86
      mec-common/common-core/src/main/java/com/ym/mec/common/service/impl/BaseServiceImpl.java
  26. 17 1
      mec-im/src/main/java/com/ym/service/Impl/RoomServiceImpl.java
  27. 5 0
      mec-student/src/main/java/com/ym/mec/student/controller/StudentCourseScheduleController.java
  28. 22 0
      mec-web/src/main/java/com/ym/mec/web/controller/CourseScheduleController.java
  29. 8 0
      mec-web/src/main/java/com/ym/mec/web/controller/CourseShareController.java
  30. 2 2
      mec-web/src/main/java/com/ym/mec/web/controller/ExportController.java
  31. 0 1
      mec-web/src/main/java/com/ym/mec/web/controller/VipGroupManageController.java

+ 239 - 354
.idea/httpRequests/http-requests-log.http

@@ -1,183 +1,170 @@
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T163044.200.json
+<> 2023-06-15T221721.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T095605.200.json
+<> 2023-06-15T221523.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T095427.200.json
+<> 2023-06-15T221236.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T095323.200.json
+<> 2023-06-15T220649.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/getCourseSchedulesWithDate?date=2023-06-05 00:00:00
+Content-Type: application/json
+Authorization: bearer 4d8e23a1-3acd-42e4-a1ca-b4d595506d98
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T095238.200.json
+<> 2023-06-15T220555.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T095217.200.json
+<> 2023-06-15T220546.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T095045.200.json
+<> 2023-06-15T220439.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T094907.200.json
+<> 2023-06-15T220236.200.json
 
 ###
 
-GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
-Authorization: bearer 81d0c352-fcc8-4812-87f5-0f7a68d10451
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-12T094734.200.json
+<> 2023-06-15T215903.200.json
 
 ###
 
-POST http://localhost:8005/imSendGroupMessage/send
-Content-Type: application/json
-tenantId: 1
-Authorization: bearer 9b756b90-f27a-4ca9-99b1-da854c72eb3f
-Content-Length: 99
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{"postType":"0","messageContent":"3の3","messageType":"TXT","targetIds":"232","isIncludeSender":0}
-
-<> 2023-06-09T174838.200.json
+<> 2023-06-15T215426.200.json
 
 ###
 
-GET http://127.0.0.1:8005/task/closeLiveCourseRoom
-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2548
+Authorization: bearer e70c68c9-05e3-4502-aed4-f7001a0e2766
+Proxy-Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T214126.200.json
+<> 2023-06-15T215131.200.json
 
 ###
 
-GET http://127.0.0.1:8005/task/closeLiveCourseRoom
+POST https://online.lexiaoya.cn/api-backend/open/schoolTeacherStudent/importPlan?fileUrl=https://polestar-oss.oss-cn-shenzhen.aliyuncs.com/assets/excel/0614/0614单簧管导入表.xlsx
+Content-Length: 0
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T210807.200.json
+<> 2023-06-15T100514.200.json
 
 ###
 
-GET http://127.0.0.1:9002/teacherCourseSchedule/findCourseAttendanceDetailHeadInfo?courseScheduleId=1701
-authorization: bearer b33a3aed-ca44-4537-b3ae-1fba38c2560a
+POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
+authorization: bearer 0071d90f-5623-4ee9-a88e-c7adb09efb1c
 Content-Type: application/json
+Content-Length: 149
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T194906.200.json
-
-###
-
-GET http://127.0.0.1:9002/teacherCourseSchedule/findCourseAttendanceDetailHeadInfo?courseScheduleId=1701
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
-Content-Type: application/json
-Connection: Keep-Alive
-User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
-Accept-Encoding: br,deflate,gzip,x-gzip
+{
+  "page": 1,
+  "rows": 10,
+//  "startTime": "2023-06-06 10:14:57",
+//  "endTime": "2023-06-08 10:14:57",
+//  "search": "",
+  "status": "UNDERWAY"
+}
 
-<> 2023-06-08T194556.200.json
+<> 2023-06-14T173156.200.json
 
 ###
 
-GET http://127.0.0.1:9002/teacherCourseSchedule/findCourseAttendanceDetailHeadInfo?courseScheduleId=1701
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
+authorization: bearer 0071d90f-5623-4ee9-a88e-c7adb09efb1c
 Content-Type: application/json
+Content-Length: 150
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T171149.200.json
-
-###
-
-GET http://127.0.0.1:8005/task/closeLiveCourseRoom
-Connection: Keep-Alive
-User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
-Accept-Encoding: br,deflate,gzip,x-gzip
-
-<> 2023-06-08T163756.200.json
-
-###
-
-GET http://127.0.0.1:9002/teacherCourseSchedule/findCourseAttendanceDetailHeadInfo?courseScheduleId=2002
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
-Content-Type: application/json
-Connection: Keep-Alive
-User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
-Accept-Encoding: br,deflate,gzip,x-gzip
+{
+  "page": 1,
+  "rows": 10,
+//  "startTime": "2023-06-06 10:14:57",
+//  "endTime": "2023-06-08 10:14:57",
+//  "search": "",
+  "status": "NOT_START"
+}
 
-<> 2023-06-08T162615.200.json
+<> 2023-06-14T173111.200.json
 
 ###
 
 POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer fe63240c-4f7d-4b67-90f8-7d51eaafdfb7
+authorization: bearer a9b023c1-f525-4b95-8723-0ca14b038624
 Content-Type: application/json
-Content-Length: 152
+Content-Length: 150
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
@@ -188,174 +175,173 @@ Accept-Encoding: br,deflate,gzip,x-gzip
 //  "startTime": "2023-06-06 10:14:57",
 //  "endTime": "2023-06-08 10:14:57",
 //  "search": "",
-//  "status": "NOT_START"
+  "status": "NOT_START"
 }
 
-<> 2023-06-08T162147.200.json
+<> 2023-06-14T173045.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
-Content-Type: application/json
-Content-Length: 70
+GET http://127.0.0.1:9001/studentCourseSchedule/queryCourseId?courseId=2162
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "courseScheduleId": 2001,
-  "status": "PURCHASE",
-  "search": ""
-}
-
-<> 2023-06-08T162015.200.json
+<> 2023-06-14T154028.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
-Content-Type: application/json
-Content-Length: 67
+GET http://127.0.0.1:9001/studentCourseSchedule/queryCourseId?courseId=2162
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "courseScheduleId": 2001,
-  "status": "SHARE",
-  "search": ""
-}
+<> 2023-06-14T145629.200.json
 
-<> 2023-06-08T161954.200.json
+###
+
+GET http://127.0.0.1:9001/studentCourseSchedule/queryCourseId?courseId=1374
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
+Connection: Keep-Alive
+User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
+Accept-Encoding: br,deflate,gzip,x-gzip
+
+<> 2023-06-14T145450.200.json
 
 ###
 
-GET http://127.0.0.1:8005/task/closeLiveCourseRoom
+GET http://127.0.0.1:8005/courseSchedule/getCurrentCourseDetail/1374
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T161900.200.json
+<> 2023-06-14T143343.200.json
 
 ###
 
-GET http://127.0.0.1:8005/task/closeLiveCourseRoom
+GET http://127.0.0.1:8005/courseSchedule/query?courseScheduleId=1374
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T161723.200.json
+<> 2023-06-14T143049.200.json
 
 ###
 
-GET http://127.0.0.1:8005/task/closeLiveCourseRoom
+POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
+authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
+Content-Type: application/json
+Content-Length: 69
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T161420.200.json
+{
+  "courseScheduleId": "2328",
+  "status": "SHARE",
+  "search": ""
+}
+
+<> 2023-06-14T124937.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
+POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
+authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 152
+Content-Length: 69
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "page": 1,
-  "rows": 10,
-//  "startTime": "2023-06-06 10:14:57",
-//  "endTime": "2023-06-08 10:14:57",
-//  "search": "",
-//  "status": "NOT_START"
+  "courseScheduleId": "2328",
+  "status": "SHARE",
+  "search": ""
 }
 
-<> 2023-06-08T155851.200.json
+<> 2023-06-14T124615.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
+POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
+authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 152
+Content-Length: 69
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "page": 1,
-  "rows": 10,
-//  "startTime": "2023-06-06 10:14:57",
-//  "endTime": "2023-06-08 10:14:57",
-//  "search": "",
-//  "status": "NOT_START"
+  "courseScheduleId": "2328",
+  "status": "SHARE",
+  "search": ""
 }
 
-<> 2023-06-08T155845.200.json
+<> 2023-06-14T124548.200.json
 
 ###
 
 POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 70
+Content-Length: 69
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "courseScheduleId": 2001,
-//  "status": "NORMAL",
+  "courseScheduleId": "2328",
+  "status": "SHARE",
   "search": ""
 }
 
-<> 2023-06-08T155815.200.json
+<> 2023-06-14T124526.200.json
 
 ###
 
 POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 70
+Content-Length: 69
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "courseScheduleId": 2001,
-//  "status": "NORMAL",
+  "courseScheduleId": "2328",
+  "status": "SHARE",
   "search": ""
 }
 
-<> 2023-06-08T155623.200.json
+<> 2023-06-14T124513.200.json
 
 ###
 
 POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 70
+Content-Length: 69
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "courseScheduleId": 2001,
-//  "status": "NORMAL",
+  "courseScheduleId": "2328",
+  "status": "SHARE",
   "search": ""
 }
 
-<> 2023-06-08T155544.200.json
+<> 2023-06-14T124441.200.json
 
 ###
 
 POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
+authorization: bearer a9b023c1-f525-4b95-8723-0ca14b038624
 Content-Type: application/json
 Content-Length: 152
 Connection: Keep-Alive
@@ -371,365 +357,264 @@ Accept-Encoding: br,deflate,gzip,x-gzip
 //  "status": "NOT_START"
 }
 
-<> 2023-06-08T155515.200.json
+<> 2023-06-14T111123.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+POST http://127.0.0.1:8005/vipGroupManage/liveStudentList
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 70
+Content-Length: 78
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "courseScheduleId": 2001,
-//  "status": "NORMAL",
-  "search": ""
+  "page": 1,
+  "rows": 10,
+  "liveGroupId": 102,
+  "search": "测试59611"
 }
 
-<> 2023-06-08T141058.200.json
+<> 2023-06-14T105403.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherAttendance/getLiveCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+POST http://127.0.0.1:8005/vipGroupManage/liveStudentList
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 68
+Content-Length: 77
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "courseScheduleId": 2001,
-  "status": "NORMAL",
-  "search": ""
+  "page": 1,
+  "rows": 10,
+  "liveGroupId": 102,
+  "search": "测试5961"
 }
 
-<> 2023-06-08T141049.200.json
+<> 2023-06-14T105355.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherAttendance/getCurrentCourseStudents
-authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+POST http://127.0.0.1:8005/vipGroupManage/liveStudentList
+Authorization: bearer b2d082f2-2e51-4880-8119-5471c5287bf9
 Content-Type: application/json
-Content-Length: 68
+Content-Length: 51
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
 {
-  "courseScheduleId": 2001,
-  "status": "NORMAL",
-  "search": ""
+  "page": 1,
+  "rows": 10,
+  "liveGroupId": 102
 }
 
-<> 2023-06-08T140909.200.json
+<> 2023-06-14T105332.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherAttendance/getCurrentCourseStudents
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
-Content-Type: application/json
-Content-Length: 68
+GET http://127.0.0.1:8005/task/liveCourseRemind
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "courseScheduleId": 2001,
-  "status": "NORMAL",
-  "search": ""
-}
-
-<> 2023-06-08T140848.200.json
+<> 2023-06-13T183554.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
-Content-Type: application/json
-Content-Length: 152
+GET http://127.0.0.1:8005/task/liveCourseRemind
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-//  "startTime": "2023-06-06 10:14:57",
-//  "endTime": "2023-06-08 10:14:57",
-//  "search": "",
-//  "status": "NOT_START"
-}
-
-<> 2023-06-08T112258.200.json
+<> 2023-06-13T183425.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
-Content-Type: application/json
-Content-Length: 152
+GET http://127.0.0.1:8005/task/liveCourseRemind
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-//  "startTime": "2023-06-06 10:14:57",
-//  "endTime": "2023-06-08 10:14:57",
-//  "search": "",
-//  "status": "NOT_START"
-}
-
-<> 2023-06-08T111901.200.json
+<> 2023-06-13T183308.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
-Content-Type: application/json
-Content-Length: 152
+GET http://127.0.0.1:8005/task/liveCourseRemind
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-//  "startTime": "2023-06-06 10:14:57",
-//  "endTime": "2023-06-08 10:14:57",
-//  "search": "",
-//  "status": "NOT_START"
-}
-
-<> 2023-06-08T111651.200.json
+<> 2023-06-13T182452.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
-Content-Type: application/json
-Content-Length: 152
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-//  "startTime": "2023-06-06 10:14:57",
-//  "endTime": "2023-06-08 10:14:57",
-//  "search": "",
-//  "status": "NOT_START"
-}
-
-<> 2023-06-08T111624.200.json
+<> 2023-06-12T163044.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-authorization: bearer 1238347b-3b06-444e-9d35-d122639121ad
-Content-Type: application/json
-Content-Length: 146
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-  "startTime": "2023-06-06 10:14:57",
-  "endTime": "2023-06-08 10:14:57",
-  "search": "",
-//  "status": "NOT_START"
-}
-
-<> 2023-06-08T111544.200.json
+<> 2023-06-12T095605.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-Authorization: bearer 3c1eec84-6ee9-4c70-a4a8-d857d57338f6
-Content-Type: application/json
-Content-Length: 146
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-  "startTime": "2023-06-06 10:14:57",
-  "endTime": "2023-06-08 10:14:57",
-  "search": "",
-//  "status": "NOT_START"
-}
-
-<> 2023-06-08T110339.200.json
+<> 2023-06-12T095427.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-Authorization: bearer 3c1eec84-6ee9-4c70-a4a8-d857d57338f6
-Content-Type: application/json
-Content-Length: 146
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-  "startTime": "2023-06-08 10:14:57",
-  "endTime": "2023-06-08 10:14:57",
-  "search": "",
-//  "status": "NOT_START"
-}
-
-<> 2023-06-08T110325.200.json
+<> 2023-06-12T095323.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-Authorization: bearer 3c1eec84-6ee9-4c70-a4a8-d857d57338f6
-Content-Type: application/json
-Content-Length: 144
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-  "startTime": "2023-06-08 10:14:57",
-  "endTime": "2023-06-08 10:14:57",
-  "search": "",
-  "status": "NOT_START"
-}
-
-<> 2023-06-08T110304.200.json
+<> 2023-06-12T095238.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-Authorization: bearer 3c1eec84-6ee9-4c70-a4a8-d857d57338f6
-Content-Type: application/json
-Content-Length: 144
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-  "startTime": "2023-06-08 10:14:57",
-  "endTime": "2023-06-08 10:14:57",
-  "search": "",
-  "status": "NOT_START"
-}
+<> 2023-06-12T095217.200.json
+
+###
+
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
+Connection: Keep-Alive
+User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
+Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T102617.200.json
+<> 2023-06-12T095045.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-Authorization: bearer 6dbea593-df93-4bf4-9f75-538c1bcc231e
-Content-Type: application/json
-Content-Length: 145
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 093517b0-c9a4-407b-b558-0d71bf157b16
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10,
-  "startTime": "2023-06-08 10:14:57",
-  "endTime": "2023-06-08 10:14:57",
-  "search": "",
-  "status": "NOT_START",
-}
+<> 2023-06-12T094907.200.json
+
+###
+
+GET http://127.0.0.1:9001/studentVipGroup/joinLiveRoomByShare?courseScheduleId=2179
+Authorization: bearer 81d0c352-fcc8-4812-87f5-0f7a68d10451
+Connection: Keep-Alive
+User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
+Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-08T101549.200.json
+<> 2023-06-12T094734.200.json
 
 ###
 
-POST http://127.0.0.1:9002/teacherCourseSchedule/liveCoursePage
-Authorization: bearer 6dbea593-df93-4bf4-9f75-538c1bcc231e
-Content-Length: 29
-Content-Type: */*; charset=UTF-8
+POST http://localhost:8005/imSendGroupMessage/send
+Content-Type: application/json
+tenantId: 1
+Authorization: bearer 9b756b90-f27a-4ca9-99b1-da854c72eb3f
+Content-Length: 99
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-{
-  "page": 1,
-  "rows": 10
-}
+{"postType":"0","messageContent":"3の3","messageType":"TXT","targetIds":"232","isIncludeSender":0}
 
-<> 2023-06-08T100117.200.json
+<> 2023-06-09T174838.200.json
 
 ###
 
-GET http://127.0.0.1:8005/task/liveCourseRemind
+GET http://127.0.0.1:8005/task/closeLiveCourseRoom
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-07T141437.200.json
+<> 2023-06-08T214126.200.json
 
 ###
 
-GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2030
-Authorization: bearer 2cd308e9-0b8b-4b08-b3cd-f34dc50a8dfd
-Proxy-Connection: Keep-Alive
+GET http://127.0.0.1:8005/task/closeLiveCourseRoom
+Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-07T155507.200.json
+<> 2023-06-08T210807.200.json
 
 ###
 
-GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2030
-Authorization: bearer 2cd308e9-0b8b-4b08-b3cd-f34dc50a8dfd
-Proxy-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/findCourseAttendanceDetailHeadInfo?courseScheduleId=1701
+authorization: bearer b33a3aed-ca44-4537-b3ae-1fba38c2560a
+Content-Type: application/json
+Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-07T155111.200.json
+<> 2023-06-08T194906.200.json
 
 ###
 
-GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2030
-Authorization: bearer 2cd308e9-0b8b-4b08-b3cd-f34dc50a8dfd
-Proxy-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/findCourseAttendanceDetailHeadInfo?courseScheduleId=1701
+authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+Content-Type: application/json
+Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-07T155043.200.json
+<> 2023-06-08T194556.200.json
 
 ###
 
-GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2030
-Authorization: bearer 2cd308e9-0b8b-4b08-b3cd-f34dc50a8dfd
-Proxy-Connection: Keep-Alive
+GET http://127.0.0.1:9002/teacherCourseSchedule/findCourseAttendanceDetailHeadInfo?courseScheduleId=1701
+authorization: bearer 97fd8e85-bb3c-4967-8a07-47c44957f94a
+Content-Type: application/json
+Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-07T154917.200.json
+<> 2023-06-08T171149.200.json
 
 ###
 
-GET http://127.0.0.1:9002/teacherCourseSchedule/liveCourseScheduleTime?courseScheduleId=2030
-Authorization: bearer 2cd308e9-0b8b-4b08-b3cd-f34dc50a8dfd
-Proxy-Connection: Keep-Alive
+GET http://127.0.0.1:8005/task/closeLiveCourseRoom
+Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.6)
 Accept-Encoding: br,deflate,gzip,x-gzip
 
-<> 2023-06-07T154631.200.json
+<> 2023-06-08T163756.200.json
 
 ###
 

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

@@ -619,4 +619,6 @@ public interface CourseScheduleStudentPaymentDao extends BaseDAO<Long, CourseSch
     List<StudentOrganDto> queryRemainCourseStudent(@Param("organIds") List<Integer> organIds);
 
     List<Map> statCourseFee(@Param("cutFirstDayOfMonth") String cutFirstDayOfMonth, @Param("cutLastDayOfMonth") String cutLastDayOfMonth);
+
+    CourseScheduleStudentPayment getByUserIdAndCourseId(@Param("userId") Integer userId, @Param("courseScheduleId") Long courseScheduleId);
 }

+ 13 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/BasicUserDto.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.dal.dto;
 
+import com.ym.mec.biz.dal.enums.JoinCourseType;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.util.Objects;
@@ -46,6 +47,18 @@ public class BasicUserDto {
     @ApiModelProperty(value = "是否需要乐器维修")
     private Boolean repairFlag = false;
 
+
+    @ApiModelProperty(value = "加入课程类型 PURCHASE:购买 SHARE:分享")
+    private String joinCourseType;
+
+    public String getJoinCourseType() {
+        return joinCourseType;
+    }
+
+    public void setJoinCourseType(String joinCourseType) {
+        this.joinCourseType = joinCourseType;
+    }
+
     public String getTeacherType() {
         return teacherType;
     }

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

@@ -116,6 +116,17 @@ public class CourseScheduleDto extends CourseSchedule {
     @ApiModelProperty("视频数量")
     private Integer videoNum;
 
+    @ApiModelProperty(value = "预热模版")
+    private String preTemplate;
+
+    public String getPreTemplate() {
+        return preTemplate;
+    }
+
+    public void setPreTemplate(String preTemplate) {
+        this.preTemplate = preTemplate;
+    }
+
     public Integer getVideoNum() {
         return videoNum;
     }

+ 23 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherClassCourseSchudeleDto.java

@@ -90,6 +90,29 @@ public class TeacherClassCourseSchudeleDto {
     @ApiModelProperty("课程组编号")
     private String musicGroupId;
 
+
+    @ApiModelProperty("直播房间号")
+    private String  liveRoomId;
+
+    @ApiModelProperty("直播课回放记录")
+    private Boolean hasVideoRecord;
+
+    public String getLiveRoomId() {
+        return liveRoomId;
+    }
+
+    public void setLiveRoomId(String liveRoomId) {
+        this.liveRoomId = liveRoomId;
+    }
+
+    public Boolean getHasVideoRecord() {
+        return hasVideoRecord;
+    }
+
+    public void setHasVideoRecord(Boolean hasVideoRecord) {
+        this.hasVideoRecord = hasVideoRecord;
+    }
+
     public Date getExpiryDate() {
         return expiryDate;
     }

+ 3 - 177
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/CourseScheduleStudentPayment.java

@@ -4,6 +4,7 @@ import com.ym.mec.biz.dal.enums.GroupType;
 import com.ym.mec.biz.dal.enums.JoinCourseType;
 import com.ym.mec.common.entity.BaseEntity;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
 import java.math.BigDecimal;
@@ -11,6 +12,7 @@ import java.math.BigDecimal;
 /**
  * 对应数据库表(course_schedule_student_payment):
  */
+@Data
 public class CourseScheduleStudentPayment extends BaseEntity implements Comparable<CourseScheduleStudentPayment> {
 
 	/**  */
@@ -69,49 +71,9 @@ public class CourseScheduleStudentPayment extends BaseEntity implements Comparab
 	@ApiModelProperty(value = "关联的云教练缴费项目编号",required = false)
 	private Long calenderId;
 
-	@ApiModelProperty(value = "加入课程类型")
+	@ApiModelProperty(value = "加入课程类型 PURCHASE:购买 SHARE:分享")
 	private JoinCourseType joinCourseType;
 
-	public BigDecimal getExpectPriceBak() {
-		return expectPriceBak;
-	}
-
-	public void setExpectPriceBak(BigDecimal expectPriceBak) {
-		this.expectPriceBak = expectPriceBak;
-	}
-
-	public BigDecimal getActualPriceBak() {
-		return actualPriceBak;
-	}
-
-	public void setActualPriceBak(BigDecimal actualPriceBak) {
-		this.actualPriceBak = actualPriceBak;
-	}
-
-	public Long getCalenderId() {
-		return calenderId;
-	}
-
-	public void setCalenderId(Long calenderId) {
-		this.calenderId = calenderId;
-	}
-
-	public Integer getActivityUserMapperId() {
-		return activityUserMapperId;
-	}
-
-	public void setActivityUserMapperId(Integer activityUserMapperId) {
-		this.activityUserMapperId = activityUserMapperId;
-	}
-
-	public Boolean getBeMerged() {
-		return beMerged;
-	}
-
-	public void setBeMerged(Boolean beMerged) {
-		this.beMerged = beMerged;
-	}
-
 	public CourseScheduleStudentPayment() {
 	}
 
@@ -127,142 +89,6 @@ public class CourseScheduleStudentPayment extends BaseEntity implements Comparab
 		this.courseScheduleId = courseScheduleId;
 	}
 
-	public String getExamSongDownloadJson() {
-		return examSongDownloadJson;
-	}
-
-	public void setExamSongDownloadJson(String examSongDownloadJson) {
-		this.examSongDownloadJson = examSongDownloadJson;
-	}
-
-	public String getOpenPlayMidi() {
-		return openPlayMidi;
-	}
-
-	public void setOpenPlayMidi(String openPlayMidi) {
-		this.openPlayMidi = openPlayMidi;
-	}
-
-	public void setId(Long id){
-		this.id = id;
-	}
-	
-	public Long getId(){
-		return this.id;
-	}
-			
-	public GroupType getGroupType() {
-		return groupType;
-	}
-
-	public void setGroupType(GroupType groupType) {
-		this.groupType = groupType;
-	}
-
-	public String getMusicGroupId() {
-		return musicGroupId;
-	}
-
-	public void setMusicGroupId(String musicGroupId) {
-		this.musicGroupId = musicGroupId;
-	}
-
-	public void setCourseScheduleId(Long courseScheduleId){
-		this.courseScheduleId = courseScheduleId;
-	}
-	
-	public Long getCourseScheduleId(){
-		return this.courseScheduleId;
-	}
-			
-	public void setUserId(Integer userId){
-		this.userId = userId;
-	}
-	
-	public Integer getUserId(){
-		return this.userId;
-	}
-
-	public BigDecimal getOriginalPrice() {
-		return originalPrice;
-	}
-
-	public void setOriginalPrice(BigDecimal originalPrice) {
-		this.originalPrice = originalPrice;
-	}
-
-	public void setExpectPrice(java.math.BigDecimal expectPrice){
-		this.expectPrice = expectPrice;
-	}
-	
-	public java.math.BigDecimal getExpectPrice(){
-		return this.expectPrice;
-	}
-			
-	public void setActualPrice(java.math.BigDecimal actualPrice){
-		this.actualPrice = actualPrice;
-	}
-	
-	public java.math.BigDecimal getActualPrice(){
-		return this.actualPrice;
-	}
-			
-	public void setCreateTime(java.util.Date createTime){
-		this.createTime = createTime;
-	}
-	
-	public java.util.Date getCreateTime(){
-		return this.createTime;
-	}
-			
-	public void setUpdateTime(java.util.Date updateTime){
-		this.updateTime = updateTime;
-	}
-	
-	public java.util.Date getUpdateTime(){
-		return this.updateTime;
-	}
-			
-	public void setSettlementTime(java.util.Date settlementTime){
-		this.settlementTime = settlementTime;
-	}
-	
-	public java.util.Date getSettlementTime(){
-		return this.settlementTime;
-	}
-			
-	public Integer getClassGroupId() {
-		return classGroupId;
-	}
-
-	public void setClassGroupId(Integer classGroupId) {
-		this.classGroupId = classGroupId;
-	}
-
-	public String getBatchNo() {
-		return batchNo;
-	}
-
-	public void setBatchNo(String batchNo) {
-		this.batchNo = batchNo;
-	}
-
-	public CourseSchedule getCourseSchedule() {
-		return courseSchedule;
-	}
-
-	public void setCourseSchedule(CourseSchedule courseSchedule) {
-		this.courseSchedule = courseSchedule;
-	}
-
-	public JoinCourseType getJoinCourseType() {
-		return joinCourseType;
-	}
-
-	public void setJoinCourseType(JoinCourseType joinCourseType) {
-		this.joinCourseType = joinCourseType;
-	}
-
 	@Override
 	public String toString() {
 		return ToStringBuilder.reflectionToString(this);

+ 13 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentAttendance.java

@@ -1,6 +1,7 @@
 package com.ym.mec.biz.dal.entity;
 
 import com.ym.mec.biz.dal.enums.GroupType;
+import com.ym.mec.biz.dal.enums.JoinCourseType;
 import com.ym.mec.biz.dal.enums.StudentAttendanceStatusEnum;
 import com.ym.mec.biz.dal.enums.YesOrNoEnum;
 import com.ym.mec.common.entity.BaseEntity;
@@ -107,7 +108,18 @@ public class StudentAttendance extends BaseEntity {
 	@ApiModelProperty(value = "是否达标1是0否")
 	private Integer qualifiedFlag;
 
-	public String getClassTimeStr() {
+    @ApiModelProperty(value = "加入课程类型 PURCHASE:购买 SHARE:分享")
+    private JoinCourseType joinCourseType;
+
+    public JoinCourseType getJoinCourseType() {
+        return joinCourseType;
+    }
+
+    public void setJoinCourseType(JoinCourseType joinCourseType) {
+        this.joinCourseType = joinCourseType;
+    }
+
+    public String getClassTimeStr() {
 		return classTimeStr;
 	}
 

+ 8 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/mapper/LiveGroupPlusMapper.java

@@ -21,4 +21,12 @@ public interface LiveGroupPlusMapper extends BaseMapper<Object> {
      * 直播课课表
      */
     List<CourseScheduleDto> liveCoursePage(@Param("page") IPage<CourseScheduleDto> page, @Param("param") LiveGroupWrapper.LiveCoursePageQuery queryInfo);
+
+    /**
+     * 直播课详情
+     *
+     * @param courseScheduleId 课表id
+     * @return
+     */
+    CourseScheduleDto detailLiveCourse(@Param("courseScheduleId") Long courseScheduleId);
 }

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

@@ -22,6 +22,16 @@ public class CourseDetailQueryInfo{
     @ApiModelProperty(value = "课程组编号")
     private String groupId;
 
+    public Integer notStartCourseTime;
+
+    public Integer getNotStartCourseTime() {
+        return notStartCourseTime;
+    }
+
+    public void setNotStartCourseTime(Integer notStartCourseTime) {
+        this.notStartCourseTime = notStartCourseTime;
+    }
+
     public String getGroupType() {
         return groupType;
     }

+ 7 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/LiveGroupWrapper.java

@@ -38,6 +38,9 @@ public class LiveGroupWrapper {
 
         @ApiModelProperty("共享方式,NO_SHARE:未共享,OPEN:公开,PRIVATE:私密")
         private ShareModeEnum shareMode;
+
+        @ApiModelProperty("模糊查询")
+        private String search;
     }
 
 
@@ -106,12 +109,15 @@ public class LiveGroupWrapper {
         private String search;
 
         @ApiModelProperty("课程状态")
-        private CourseStatusEnum status;
+        private String status;
 
         private Integer teacherId;
 
         private Integer tenantId;
 
+        //未开始直播课,提前开始时间
+        private Integer notStartCourseTime;
+
     }
 
 

+ 8 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/CourseScheduleService.java

@@ -801,4 +801,12 @@ public interface CourseScheduleService extends BaseService<Long, CourseSchedule>
     IPage<CourseScheduleDto> liveCoursePage(LiveGroupWrapper.LiveCoursePageQuery queryInfo);
 
 	void updateCourseScheduleShareMode(UpdateCourseShareModeDto updateCourseShareModeDto);
+
+
+    /**
+     * 查询课程信息
+     * @param courseScheduleId
+     * @return
+     */
+    CourseScheduleDto detailLiveCourse(Long courseScheduleId);
 }

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

@@ -12,6 +12,8 @@ public interface CourseShareService extends BaseService<Integer, CourseShare> {
 
     Boolean saveCourseShare(CourseShareDto courseShareDto);
 
+    Boolean saveCourseShareByOne(CourseShareDto courseShareDto);
+
     PageInfo<StudentManageListDto> queryCourseSharedStudent(CourseShareQueryInfo shareQueryInfo);
 
     boolean createPaymentRecord(Long courseId, Integer userId);

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

@@ -420,9 +420,11 @@ public interface SysConfigService extends BaseService<Long, SysConfig> {
     // 微信公众号secret
     String SCHOOL_IM_GROUP_IMG = "school_im_group_img";
     // 直播课通知学生退出直播间时间
-    String liveClassStudentRemindTime = "live_class_student_remind_time";
+    String LIVE_CLASS_STUDENT_REMIND_TIME = "live_class_student_remind_time";
     // 关闭直播间时间
-    String closeClassStudentRemindTime = "close_class_student_remind_time";
+    String CLOSE_CLASS_STUDENT_REMIND_TIME = "close_class_student_remind_time";
+    // 直播课程开始前XX分钟,发送通知
+    String LIVE_CLASS_START_REMIND_TIME = "live_class_start_remind_time";
 
     static void checkActivityDate(String startTimeStr, String endTimeStr) {
         if(StringUtils.isEmpty(startTimeStr) || StringUtils.isEmpty(startTimeStr)){

+ 396 - 51
mec-biz/src/main/java/com/ym/mec/biz/service/impl/CourseScheduleServiceImpl.java

@@ -5,6 +5,9 @@ import com.alibaba.fastjson.JSONObject;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.microsvc.toolkit.middleware.live.LivePluginContext;
+import com.microsvc.toolkit.middleware.live.LivePluginService;
+import com.microsvc.toolkit.middleware.live.message.LiveRoomMessage;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.dto.*;
@@ -195,7 +198,10 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
     private LessonExaminationService lessonExaminationService;
 	@Autowired
 	private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
-
+	@Autowired
+	private LivePluginContext livePluginContext;
+    @Autowired
+    private ImLiveRoomVideoService imLiveRoomVideoService;
 
     @Autowired
     private ImLiveRoomVideoDao imLiveRoomVideoDao;
@@ -1170,6 +1176,18 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 				courseScheduleDto.setOs(courseScheduleDto.getLiveBroadcastRoom().getOs());
 			}
         }
+
+        // 直播课判断时间,提前30分钟将课程改为进行中
+
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+        for (CourseScheduleDto record : studentCourseSchedulesWithDate) {
+            if (CourseScheduleType.LIVE.equals(record.getType()) && CourseStatusEnum.NOT_START.equals(record.getStatus())) {
+                Date date = DateUtil.addMinutes(new Date(), studentRemindTime);
+                if (date.after(record.getStartClassTime())) {
+                    record.setStatus(CourseStatusEnum.UNDERWAY);
+                }
+            }
+        }
     }
 
     private Map<String, List<ImLiveRoomVideoVo>> getLiveRecord(List<String> roomIds) {
@@ -1282,6 +1300,18 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
         if (count == 0) {
             dataList = new ArrayList<>();
         }
+
+        // 直播课判断时间,提前30分钟将课程改为进行中
+
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+        for (CourseScheduleDto record : dataList) {
+            if (CourseScheduleType.LIVE.equals(record.getType()) && CourseStatusEnum.NOT_START.equals(record.getStatus())) {
+                Date date = DateUtil.addMinutes(new Date(), studentRemindTime);
+                if (date.after(record.getStartClassTime())) {
+                    record.setStatus(CourseStatusEnum.UNDERWAY);
+                }
+            }
+        }
         pageInfo.setRows(dataList);
         return pageInfo;
     }
@@ -1302,16 +1332,15 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 						cs.getType().equals(CourseScheduleType.COMM))
                 .map(CourseScheduleDto::getId).collect(Collectors.toList());
 
-        List<CourseScheduleDto> teacherCourseSchedulesWithDate1 = getTeacherCourseFormat(userId, classDate, tenantId, now,
+        return getTeacherCourseFormat(userId, classDate, tenantId,
                 teacherCourseSchedulesWithDate, allCourseScheduleIds, courseScheduleIds);
-        if (teacherCourseSchedulesWithDate1 != null) return teacherCourseSchedulesWithDate1;
-        return teacherCourseSchedulesWithDate;
     }
 
     // 数据整理
     @Nullable
-    private List<CourseScheduleDto> getTeacherCourseFormat(Integer userId, Date classDate, Integer tenantId, Date now,
-                                                         List<CourseScheduleDto> teacherCourseSchedulesWithDate, List<Long> allCourseScheduleIds, List<Long> courseScheduleIds) {
+    private List<CourseScheduleDto> getTeacherCourseFormat(Integer userId, Date classDate, Integer tenantId,
+                                                           List<CourseScheduleDto> teacherCourseSchedulesWithDate, List<Long> allCourseScheduleIds,
+                                                           List<Long> courseScheduleIds) {
         // 直播课设置直播间信息
         Map<String, ImLiveBroadcastRoomDto> liveRoomMap = getLiveRoomMap(teacherCourseSchedulesWithDate);
 
@@ -1406,6 +1435,46 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
                 courseScheduleDto.setOs(courseScheduleDto.getLiveBroadcastRoom().getOs());
             }
         }
+
+        // roomId
+        List<String> roomIdList = teacherCourseSchedulesWithDate.stream().map(CourseScheduleDto::getLiveRoomId).collect(Collectors.toList());
+
+
+        Map<String, List<ImLiveRoomVideoVo>> imLiveRoomVideoVoMap = getLiveRecord(roomIdList);
+
+        for (CourseScheduleDto courseScheduleDto : teacherCourseSchedulesWithDate) {
+            if (StringUtils.isNotEmpty(courseScheduleDto.getLiveRoomId())) {
+                List<ImLiveRoomVideoVo> imLiveRoomVideoVoList = imLiveRoomVideoVoMap.get(courseScheduleDto.getLiveRoomId());
+                if (CollectionUtils.isNotEmpty(imLiveRoomVideoVoList)) {
+                    courseScheduleDto.setHasVideoRecord(true);
+                    continue;
+                }
+                courseScheduleDto.setHasVideoRecord(false);
+            }
+        }
+
+        // 查询直播间视频数
+        Map<String, Integer> uidCountMap = imLiveRoomVideoService.queryRoomUidCountMap(roomIdList);
+        for (CourseScheduleDto record : teacherCourseSchedulesWithDate) {
+            if (Objects.isNull(record.getLiveRoomId())) {
+                continue;
+            }
+            Integer count = uidCountMap.get(record.getLiveRoomId());
+            if (count == null) {
+                record.setVideoNum(0);
+            }
+            record.setVideoNum(count);
+        }
+        // 直播课判断时间,提前30分钟将课程改为进行中
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+        for (CourseScheduleDto record : teacherCourseSchedulesWithDate) {
+            if (CourseScheduleType.LIVE.equals(record.getType()) && CourseStatusEnum.NOT_START.equals(record.getStatus())) {
+                Date date = DateUtil.addMinutes(new Date(), studentRemindTime);
+                if (date.after(record.getStartClassTime())) {
+                    record.setStatus(CourseStatusEnum.UNDERWAY);
+                }
+            }
+        }
         return teacherCourseSchedulesWithDate;
     }
 
@@ -2425,6 +2494,17 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 
 //			courseScheduleTeacherSalaryDao.batchUpdateCourseSalarys(courseScheduleIds, teacherSalary);
 
+			// 直播课数据清除
+			for (CourseSchedule item : courseSchedules) {
+				if (LIVE == item.getGroupType()) {
+					// 消息提醒
+					item.setLiveRemind(0);
+					// 直播间关联
+					item.setLiveRoomId("");
+					// 连堂课标识
+					item.setContinuousCourse(false);
+				}
+			}
 		}
 
         courseScheduleDao.batchUpdate(courseSchedules);
@@ -2967,6 +3047,7 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 
 		Map<Long, CourseSchedule> oldCourseScheduleMap = oldCourseScheduleList.stream().collect(Collectors.toMap(CourseSchedule::getId, c -> c));
 
+		List<CourseSchedule> liveCourseSchedules = Lists.newArrayList();
         for(CourseSchedule newCourseSchedule : newCourseSchedules){
 
         	//获取数据库中的记录
@@ -3022,6 +3103,17 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 				}
 			}
 
+			// 直播课发送推送消息
+			if (LIVE.equals(oldCourseSchedule.getGroupType())) {
+				// 日期,时间,时长,主教老师不一致时,发送消息
+				if (newCourseSchedule.getClassDate() != oldCourseSchedule.getClassDate()
+						|| newCourseSchedule.getStartClassTime() != oldCourseSchedule.getStartClassTime()
+						|| newCourseSchedule.getEndClassTime() != oldCourseSchedule.getEndClassTime()
+						|| newCourseSchedule.getActualTeacherId() != oldCourseSchedule.getActualTeacherId().intValue()) {
+					liveCourseSchedules.add(oldCourseSchedule);
+				}
+			}
+
             if(!CollectionUtils.isEmpty(newCourseSchedule.getTeachingTeacherIdList())){
                 if (newCourseSchedule.getTeachingTeacherIdList().contains(newCourseSchedule.getActualTeacherId())){
                     throw new BizException("主教和助教不可重复");
@@ -3083,7 +3175,7 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 
             //课程结束时间必须在21:00之前
             if(DateUtil.getHour(newCourseSchedule.getEndClassTime()) > 20 && DateUtil.getMinute(newCourseSchedule.getEndClassTime()) > 0){
-            	throw new BizException("课程结束时间不能超过21:00,请重新调整上课时间");
+				throw new BizException("课程结束时间不能超过21:00,请重新调整上课时间");
             }
 
             //判断上课时间是否跨天
@@ -3464,9 +3556,75 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
+
+		// 直播课消息推送
+		if (CollectionUtils.isNotEmpty(liveCourseSchedules)) {
+
+			liveCourseSchedules.parallelStream().forEach(item -> {
+
+				// 是否是连堂课
+				String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, item.getTenantId());
+				if (StringUtils.isEmpty(continueCourseTime)) {
+					continueCourseTime = "5";
+				}
+
+				// 查询最新课程信息
+				CourseSchedule newCourseSchedule = courseScheduleDao.get(item.getId());
+				// 连堂课更新标识
+				boolean updateFlag = true;
+				// 新课时间
+				Date newCourseScheduleDate = getDateTime(newCourseSchedule.getClassDate(), newCourseSchedule.getStartClassTime()).toDate();
+				Date oldCourseScheduleDate = getDateTime(item.getClassDate(), item.getStartClassTime()).toDate();
+				if (newCourseScheduleDate.getTime() > oldCourseScheduleDate.getTime()) {
+					newCourseSchedule = item;
+					// 更新标识
+					updateFlag = false;
+				}
+
+				// 直播课关联直播间编号
+				String liveRoomId = getCourseScheduleLiveRoomId(newCourseSchedule, continueCourseTime, Lists.newArrayList(), Lists.newArrayList(), updateFlag);
+
+				if (StringUtils.isBlank(liveRoomId)) {
+					liveRoomId = item.getLiveRoomId();
+				}
+
+				ImLiveBroadcastRoom liveRoom = imLiveBroadcastRoomService.getByRoomUid(liveRoomId);
+				if (Objects.isNull(liveRoom)) {
+					log.warn("liveRoom sendChatRoomMessage is null, liveRoomId:{}", liveRoomId);
+					return;
+				}
+
+				try {
+					LivePluginService pluginService = livePluginContext.getPluginService(liveRoom.getServiceProvider());
+
+					LiveRoomMessage message = new LiveRoomMessage();
+					message.setIsIncludeSender(1);
+					message.setFromUserId(newCourseSchedule.getActualTeacherId().toString());
+					message.setToChatRoomId(liveRoom.getRoomUid());
+					message.setObjectName(LiveRoomMessage.LIVE_STATUS_CHANGE);
+
+					// 发送用户信息
+					LiveRoomMessage.MessageUser messageUser = LiveRoomMessage.MessageUser.builder()
+							.sendUserId("")
+							.sendUserName("")
+							.avatarUrl("")
+							.build();
+
+					message.setContent(LiveRoomMessage.MessageContent.builder()
+							.sendUserInfo(messageUser).build());
+
+					pluginService.sendChatRoomMessage(message);
+					log.info("liveRoom sendChatRoomMessage success, liveRoomId:{}", liveRoomId);
+				} catch (Exception e) {
+					log.error("liveRoom sendChatRoomMessage error", e);
+				}
+			});
+
+		}
 		return BaseController.succeed();
     }
 
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void courseSwap(Long courseScheduleId1, Long courseScheduleId2) {
@@ -3819,8 +3977,16 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 			queryInfo.setDate(new Date());
 		}
 
+        // 直播课判断时间,提前30分钟将课程改为进行中
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+
 		Map<String, Object> params = new HashMap<>();
 		MapUtil.populateMap(params, queryInfo);
+        params.put("notStartCourseTime", studentRemindTime);
+        if (queryInfo.getClassGroupId() != null) {
+            ClassGroup classGroup = classGroupDao.get(queryInfo.getClassGroupId().intValue());
+            params.put("groupType", classGroup.getGroupType().name());
+        }
 
 		List<TeacherClassCourseSchudeleDto> dataList = null;
 		int count = 0;
@@ -3885,7 +4051,30 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 		if (count == 0) {
 			dataList = new ArrayList<>();
 		}
-		pageInfo.setRows(dataList);
+
+
+        // 直播房间号ID
+        List<String> liveRoomIds = dataList.stream().map(e -> e.getLiveRoomId()).filter(Objects::nonNull).collect(Collectors.toList());
+
+        Map<String, List<ImLiveRoomVideoVo>> imLiveRoomVideoVoMap = getLiveRecord(liveRoomIds);
+        dataList.forEach(e -> {
+            if (imLiveRoomVideoVoMap != null && imLiveRoomVideoVoMap.containsKey(e.getLiveRoomId())) {
+                e.setHasVideoRecord(true);
+            } else {
+                e.setHasVideoRecord(false);
+            }
+        });
+
+        for (TeacherClassCourseSchudeleDto record : dataList) {
+            if (CourseScheduleType.LIVE.equals(record.getType()) && CourseStatusEnum.NOT_START.equals(record.getStatus())) {
+                Date date = DateUtil.addMinutes(new Date(), studentRemindTime);
+                if (date.after(record.getStartClassTime())) {
+                    record.setStatus(CourseStatusEnum.UNDERWAY);
+                }
+            }
+        }
+
+        pageInfo.setRows(dataList);
 		return pageInfo;
 	}
 
@@ -3925,6 +4114,7 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
         }
         CourseAttendanceDetailHeadInfoDto courseAttendanceDetailHeadInfoDto = courseScheduleDao.findByCourse(courseScheduleId);
         courseAttendanceDetailHeadInfoDto.setLatestAttendanceTime(studentAttendanceDao.findLatestAttendanceDate(courseScheduleId));
+        courseAttendanceDetailHeadInfoDto.setStudentNum(studentAttendanceDao.getStudentNumByStatus(courseScheduleId, StudentAttendanceStatusEnum.NORMAL));
         courseAttendanceDetailHeadInfoDto.setLeaveStudentNum(studentAttendanceDao.getStudentNumByStatus(courseScheduleId, StudentAttendanceStatusEnum.LEAVE));
         courseAttendanceDetailHeadInfoDto.setTruantStudentNum(studentAttendanceDao.getStudentNumByStatus(courseScheduleId, StudentAttendanceStatusEnum.TRUANT));
         courseAttendanceDetailHeadInfoDto.setLateStudentNum(studentAttendanceDao.getStudentNumByStatus(courseScheduleId, StudentAttendanceStatusEnum.LATE));
@@ -5879,7 +6069,54 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 	}
 
     @Override
+    public CourseScheduleDto detailLiveCourse(Long courseScheduleId) {
+        CourseScheduleDto courseSchedule = liveGroupPlusMapper.detailLiveCourse(courseScheduleId);
+
+
+
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+
+        Date startDate = DateUtil.startDateAndEndTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime());
+        courseSchedule.setStartClassTime(startDate);
+        Date endDate = DateUtil.startDateAndEndTime(courseSchedule.getClassDate(), courseSchedule.getEndClassTime());
+        courseSchedule.setEndClassTime(endDate);
+        startDate = DateUtil.addMinutes(startDate, -studentRemindTime);
+        // 课程是否开始
+        if(CourseStatusEnum.NOT_START.equals(courseSchedule.getStatus()) && startDate.before(new Date())) {
+            courseSchedule.setStatus(CourseStatusEnum.UNDERWAY);
+        }
+        // 设置老师信息
+        Teacher teacher = teacherService.get(courseSchedule.getActualTeacherId());
+        if (teacher != null) {
+            courseSchedule.setTeacherId(teacher.getId());
+            courseSchedule.setTeacherName(teacher.getRealName());
+            courseSchedule.setHeadUrl(teacher.getAvatar());
+        }
+
+        // 查询直播课程组
+        VipGroup vipGroup = vipGroupDao.findByCourseSchedule(courseScheduleId);
+        if (vipGroup != null) {
+            ImLiveBroadcastRoomDto imLiveBroadcastRoomDto = JSON.parseObject(vipGroup.getLiveConfigJson(), ImLiveBroadcastRoomDto.class);
+            if (imLiveBroadcastRoomDto != null) {
+                courseSchedule.setPreTemplate(imLiveBroadcastRoomDto.getPreTemplate());
+            }
+        }
+
+        return courseSchedule;
+
+    }
+
+    @Override
     public List<CourseScheduleStudentDto> queryDetailList(CourseDetailQueryInfo courseDetailQueryInfo) {
+
+
+        // 直播课判断时间,提前30分钟将课程改为进行中
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+
+        if (StringUtils.isNotBlank(courseDetailQueryInfo.getGroupType())) {
+            courseDetailQueryInfo.setGroupType(courseDetailQueryInfo.getGroupType().toUpperCase());
+        }
+        courseDetailQueryInfo.setNotStartCourseTime(studentRemindTime);
         List<CourseScheduleStudentDto> courseScheduleStudentDtos = courseScheduleDao.queryDetailList(courseDetailQueryInfo);
 
 
@@ -5895,12 +6132,29 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
             }
         });
 
+
+        // 直播课判断时间,提前30分钟将课程改为进行中
+        for (CourseScheduleStudentDto record : courseScheduleStudentDtos) {
+            if (CourseStatusEnum.NOT_START.equals(record.getCourseStatus())
+                    && courseDetailQueryInfo.getGroupType().toUpperCase(Locale.ROOT).equals(GroupType.LIVE.getCode())) {
+                Date date = DateUtil.addMinutes(new Date(), studentRemindTime);
+                if (date.after(DateUtil.toDateTime(record.getStartClassTime()))) {
+                    record.setCourseStatus(CourseStatusEnum.UNDERWAY);
+                }
+            }
+        }
+
         return courseScheduleStudentDtos;
     }
 
     @Override
     public IPage<CourseScheduleDto> liveCoursePage(LiveGroupWrapper.LiveCoursePageQuery queryInfo) {
         IPage<CourseScheduleDto> page = com.microsvc.toolkit.common.response.paging.QueryInfo.getPage(queryInfo);
+
+        // 直播课判断时间,提前30分钟将课程改为进行中
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+
+        queryInfo.setNotStartCourseTime(studentRemindTime);
         List<CourseScheduleDto> courseScheduleDtos = liveGroupPlusMapper.liveCoursePage(page, queryInfo);
         if (CollectionUtils.isEmpty(courseScheduleDtos)) {
             return page;
@@ -5908,8 +6162,17 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
         // id 集合
         List<Long> courseIds = courseScheduleDtos.stream().map(CourseScheduleDto::getId).collect(Collectors.toList());
         List<CourseScheduleDto> teacherCourseFormat = getTeacherCourseFormat(queryInfo.getTeacherId(), new Date(),
-                queryInfo.getTenantId(), new Date(), courseScheduleDtos, courseIds, courseIds);
+                queryInfo.getTenantId(), courseScheduleDtos, courseIds, courseIds);
 
+
+        for (CourseScheduleDto record : teacherCourseFormat) {
+            if (CourseScheduleType.LIVE.equals(record.getType()) && CourseStatusEnum.NOT_START.equals(record.getStatus())) {
+                Date date = DateUtil.addMinutes(new Date(), studentRemindTime);
+                if (date.after(record.getStartClassTime())) {
+                    record.setStatus(CourseStatusEnum.UNDERWAY);
+                }
+            }
+        }
         return page.setRecords(teacherCourseFormat);
     }
 
@@ -6008,16 +6271,83 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 		if (courseSchedule.getTeachMode() == TeachModeEnum.OFFLINE) {
 			throw new BizException("请前往线下教室");
 		}
+
+		// 是否是连堂课
+		String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, courseSchedule.getTenantId());
+		if (StringUtils.isEmpty(continueCourseTime)) {
+			continueCourseTime = "5";
+		}
+
+		// 直播课关联直播间
+		List<CourseSchedule> newCourseSchedules = Lists.newArrayList();
+		// 课程时间长计算
+		List<CourseScheduleWrapper.CourseScheduleTime> courseScheduleTimes = Lists.newArrayList();
+		// 直播课关联直播间编号
+		String liveRoomId = getCourseScheduleLiveRoomId(courseSchedule, continueCourseTime, newCourseSchedules, courseScheduleTimes, true);
+
+		// 定时任务更新课程状态为进行中,判断当前课程状态是否匹配
+		/*int studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+
+		Date date = DateUtil.startDateAndEndTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime());
+		date = DateUtil.addMinutes(date, -studentRemindTime);
+		// 课程是否开始
+		if(CourseStatusEnum.NOT_START.equals(courseSchedule.getStatus()) && date.after(new Date())) {
+			throw new BizException("直播课暂未开启,请稍后重试");
+		}
+		if (CourseStatusEnum.OVER == courseSchedule.getStatus()) {
+			throw new BizException("直播课已结束");
+		}*/
+
+		// 直播间配置
+		ImLiveBroadcastRoom liveBroadcastRoom = imLiveBroadcastRoomService.lambdaQuery()
+				.eq(ImLiveBroadcastRoom::getRoomUid, liveRoomId)
+				.last("LIMIT 1")
+				.one();
+		if (Objects.isNull(liveBroadcastRoom)) {
+			throw new BizException("请先进入直播课教室");
+		}
+
+		String autoCloseNetworkRoomTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.COURSE_AFTER_BUFFER_TIME, courseSchedule.getTenantId());
+		if (StringUtils.isEmpty(autoCloseNetworkRoomTime)) {
+			autoCloseNetworkRoomTime = "15";
+		}
+
+		return CourseScheduleWrapper.LiveCourseSchedule.builder()
+				.liveRoomId(liveRoomId)
+				.subjectId(liveBroadcastRoom.getSubjectId())
+				.autoCloseFlag(true)
+				//.autoCloseNetworkRoomTime(getCloseNetworkRoomTime(courseSchedule, continueCourseTime))
+				.autoCloseNetworkRoomTime(autoCloseNetworkRoomTime)
+				.surplusTime(DateUtil.secondsBetween(new Date(), courseSchedule.getEndClassTime()))
+				.timestamp(DateTime.now().getMillis())
+				.courseScheduleTimes(courseScheduleTimes)
+				.build();
+	}
+
+	/**
+	 * 同步连堂课状态,获取直播间编号
+	 * @param courseSchedule CourseSchedule
+	 * @param continueCourseTime 连堂课时长
+	 * @param newCourseSchedules List<CourseSchedule>
+	 * @param courseScheduleTimes List<CourseScheduleWrapper.CourseScheduleTime>
+	 * @return String
+	 */
+	private String getCourseScheduleLiveRoomId(CourseSchedule courseSchedule,
+											   String continueCourseTime,
+											   List<CourseSchedule> newCourseSchedules,
+											   List<CourseScheduleWrapper.CourseScheduleTime> courseScheduleTimes,
+											   Boolean updateFlag) {
+		String liveRoomId;
 		// 课程开始时间
 		courseSchedule.setStartClassTime(getDateTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime()).toDate());
 		// 课程结束时间
 		courseSchedule.setEndClassTime(getDateTime(courseSchedule.getClassDate(), courseSchedule.getEndClassTime()).toDate());
 
 		// 是否是连堂课
-		String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, courseSchedule.getTenantId());
+		/*String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, courseSchedule.getTenantId());
 		if (StringUtils.isEmpty(continueCourseTime)) {
 			continueCourseTime = "5";
-		}
+		}*/
 
 		// 连堂课标准:同一个老师,同一天,同一课程组,连续上课
 		List<CourseSchedule> continuousCourse = courseScheduleDao.getTeacherContinuousCourse(courseSchedule.getClassGroupId(),
@@ -6043,6 +6373,8 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 			if (item.getId().longValue() == courseSchedule.getId()) {
 				continue;
 			}
+			// 重置连堂状态
+			item.setContinuousCourse(false);
 
 			schedule = JSON.parseObject(JSON.toJSONString(item), CourseSchedule.class);
 			if (item.getEndClassTime().getTime() <= courseSchedule.getStartClassTime().getTime()) {
@@ -6054,6 +6386,7 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 			}
 		}
 
+		courseSchedule.setContinuousCourse(false);
 		// 当前课程之前连堂课
 		beforeCourse.add(JSON.parseObject(JSON.toJSONString(courseSchedule), CourseSchedule.class));
 		// 当前课程之后连堂课
@@ -6062,7 +6395,6 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 		// 课程前连堂状态
 		updateContinuousCourseStatus(continueCourseTime, beforeCourse);
 
-		List<CourseSchedule> newCourseSchedules = Lists.newArrayList();
 		// 课程连堂状态
 		if (beforeCourse.get(beforeCourse.size() - 1).getContinuousCourse()) {
 			List<CourseSchedule> collect = beforeCourse.stream()
@@ -6089,10 +6421,6 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 			}
 		}
 
-		// 直播课关联直播间编号
-		String liveRoomId = courseSchedule.getLiveRoomId();
-
-		List<CourseScheduleWrapper.CourseScheduleTime> courseScheduleTimes = Lists.newArrayList();
 		if (CollectionUtils.isNotEmpty(newCourseSchedules)) {
 
 			// 连党课程信息
@@ -6105,27 +6433,65 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 
 			// 获取连堂课第一节信息
 			CourseSchedule finalCourseSchedule = newCourseSchedules.get(0);
-			CompletableFuture.runAsync(() -> {
 
-				List<Long> collect = newCourseSchedules.stream()
-						.map(CourseSchedule::getId)
-						.distinct().collect(Collectors.toList());
-				try {
+			List<Long> collect = newCourseSchedules.stream()
+					.map(CourseSchedule::getId)
+					.distinct().collect(Collectors.toList());
+			try {
 
+				if (Optional.ofNullable(updateFlag).orElse(true)) {
 					// 关联直播间编号
 					courseScheduleDao.batchUpdateLiveRoomId(collect, finalCourseSchedule.getLiveRoomId());
+				}
 
+				if (CollectionUtils.size(collect) > 1) {
 					collect = newCourseSchedules.subList(0, newCourseSchedules.size() - 1).stream()
 							.map(CourseSchedule::getId)
 							.distinct().collect(Collectors.toList());
+
 					// 更新连堂课状态
 					courseScheduleDao.batchUpdateContinuousCourse(collect, true);
+				}
 
-				} catch (Exception e) {
-				    log.error("getLiveCourseScheduleTime courseScheduleIds={}", collect, e);
+				if (!Optional.ofNullable(updateFlag).orElse(true)) {
+
+					// 课程连堂状态
+					if (beforeCourse.get(beforeCourse.size() - 1).getContinuousCourse()) {
+
+						int size = beforeCourse.size();
+						collect = beforeCourse.subList(size - 2, size).stream()
+								.map(CourseSchedule::getId)
+								.distinct().collect(Collectors.toList());
+						if (CollectionUtils.isNotEmpty(collect)) {
+							// 更新连堂课状态
+							courseScheduleDao.batchUpdateContinuousCourse(collect, false);
+						}
+					}
+
+					// 课程后连堂状态
+					if (afterCourse.get(0).getContinuousCourse()) {
+						collect = afterCourse.subList(1, afterCourse.size()).stream()
+								.map(CourseSchedule::getId)
+								.distinct().collect(Collectors.toList());
+
+						if (CollectionUtils.isNotEmpty(collect)) {
+							// 关联直播间编号
+							courseScheduleDao.batchUpdateLiveRoomId(collect, "");
+							// 更新连堂课状态
+							courseScheduleDao.batchUpdateContinuousCourse(collect, false);
+						}
+					}
 				}
 
-			});
+				// 更新连堂课状态,最后一节课重置
+				CourseSchedule lastCourseSchedule = newCourseSchedules.get(newCourseSchedules.size() - 1);
+				if (Objects.nonNull(lastCourseSchedule)) {
+					courseScheduleDao.batchUpdateContinuousCourse(Lists.newArrayList(lastCourseSchedule.getId()), false);
+				}
+
+			} catch (Exception e) {
+				log.error("getLiveCourseScheduleTime courseScheduleIds={}", collect, e);
+			}
 			// 连堂课直播间编号
 			liveRoomId = finalCourseSchedule.getLiveRoomId();
 		} else {
@@ -6135,34 +6501,13 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 					.startTime(courseSchedule.getStartClassTime().getTime())
 					.endTime(courseSchedule.getEndClassTime().getTime())
 					.build());
-		}
 
-		// 定时任务更新课程状态为进行中,判断当前课程状态是否匹配
-		if (CourseStatusEnum.NOT_START == courseSchedule.getStatus()) {
-			throw new BizException("直播课暂未开启,请稍后重试");
-		}
-		if (CourseStatusEnum.OVER == courseSchedule.getStatus()) {
-			throw new BizException("直播课已结束");
-		}
+			// 更新连堂课状态
+			courseScheduleDao.batchUpdateContinuousCourse(Lists.newArrayList(courseSchedule.getId()), false);
 
-		// 直播间配置
-		ImLiveBroadcastRoom liveBroadcastRoom = imLiveBroadcastRoomService.lambdaQuery()
-				.eq(ImLiveBroadcastRoom::getRoomUid, liveRoomId)
-				.last("LIMIT 1")
-				.one();
-		if (Objects.isNull(liveBroadcastRoom)) {
-			throw new BizException("请先进入直播课教室");
+			liveRoomId = courseSchedule.getLiveRoomId();
 		}
-
-		return CourseScheduleWrapper.LiveCourseSchedule.builder()
-				.liveRoomId(liveRoomId)
-				.subjectId(liveBroadcastRoom.getSubjectId())
-				.autoCloseFlag(true)
-				.autoCloseNetworkRoomTime(getCloseNetworkRoomTime(courseSchedule, continueCourseTime))
-				.surplusTime(DateUtil.secondsBetween(new Date(), courseSchedule.getEndClassTime()))
-				.timestamp(DateTime.now().getMillis())
-				.courseScheduleTimes(courseScheduleTimes)
-				.build();
+		return liveRoomId;
 	}
 
 	/**
@@ -6185,8 +6530,8 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 
 				startTime = getDateTime(current.getClassDate(), current.getEndClassTime());
 				endTime = getDateTime(next.getClassDate(), next.getStartClassTime());
-				// 如果当前课程结束时间和下一节课开始时间间隔小于5分钟,那么合并时间
-				if (startTime.isBefore(endTime)
+				// 如果当前课程结束时间和下一节课开始时间间隔小于5分钟,那么合并时间(修复代码合并)
+				if ((startTime.isBefore(endTime) || startTime.isEqual(endTime))
 						&& startTime.plusMinutes(Integer.parseInt(continueCourseTime) + 1).isAfter(endTime)) {
 					// 上节连堂状态
 					current.setContinuousCourse(true);

+ 59 - 37
mec-biz/src/main/java/com/ym/mec/biz/service/impl/CourseShareServiceImpl.java

@@ -28,6 +28,7 @@ import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.util.collection.MapUtil;
 import com.ym.mec.util.excel.POIUtil;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -92,49 +93,32 @@ public class CourseShareServiceImpl extends BaseServiceImpl<Integer, CourseShare
     public Boolean saveCourseShare(CourseShareDto courseShareDto) {
         CourseSchedule courseSchedule = getCourseScheduleById(courseShareDto.getCourseId());
 
-        HashMap<String, Object> params = new HashMap<>();
-        MapUtil.populateMap(params, courseShareDto);
-        List<Integer> userIds = courseShareDto.getUserIds();
-        if (params.keySet().isEmpty() && CollectionUtils.isEmpty(userIds)) {
+        List<Integer> userIdList = courseShareDto.getUserIds();
+        if (CollectionUtils.isEmpty(userIdList)) {
+            throw new BizException("未选择学员");
+        }
+        saveCourseShareStudent(courseShareDto.getCourseId(), courseSchedule.getTenantId(), userIdList);
+        return true;
+    }
+
+    @Override
+    public Boolean saveCourseShareByOne(CourseShareDto courseShareDto) {
+        CourseSchedule courseSchedule = getCourseScheduleById(courseShareDto.getCourseId());
+
+        if (StringUtils.isEmpty(courseShareDto.getSearch()) &&
+                StringUtils.isEmpty(courseShareDto.getSubjectId()) &&
+                StringUtils.isEmpty(courseShareDto.getOrganIds()) &&
+                StringUtils.isEmpty(courseShareDto.getGroupIds()) &&
+                StringUtils.isEmpty(courseShareDto.getSchoolIds())) {
             throw new BizException("未选择搜索条件");
         }
+        HashMap<String, Object> params = new HashMap<>();
+        MapUtil.populateMap(params, courseShareDto);
         List<StudentManageListDto> studentList = courseShareDao.selectStudentByParam(params);
         List<Integer> userIdList = studentList.stream()
                 .map(StudentManageListDto::getUserId).distinct().collect(Collectors.toList());
-        if (CollectionUtils.isNotEmpty(userIds)) {
-            userIds.forEach(next -> {
-                if (!userIdList.contains(next)) {
-                    userIdList.add(next);
-                }
-            });
-        }
         // 处理已经分享过的数据
-        List<CourseShare> existShares = courseShareDao.selectByCourseId(courseShareDto.getCourseId());
-        if (CollectionUtils.isNotEmpty(existShares)) {
-            List<Integer> sharedHistoryRecords = existShares.stream()
-                    .map(CourseShare::getUserId)
-                    .collect(Collectors.toList());
-            // 已经存在的数据不需要重复录入
-            userIdList.removeIf(sharedHistoryRecords::contains);
-        }
-        if (CollectionUtils.isEmpty(userIdList)) {
-            // 没有新加入的数据
-            return true;
-        }
-
-        Integer userId = userService.getUserId();
-        List<CourseShare> courseShares = userIdList.stream().map(next -> {
-            CourseShare courseShare = new CourseShare();
-            courseShare.setCourseId(courseShareDto.getCourseId());
-            courseShare.setTenantId(courseSchedule.getTenantId());
-            courseShare.setUserId(next);
-            courseShare.setCreateTime(new Date());
-            courseShare.setCreateBy(userId);
-            return courseShare;
-        }).collect(Collectors.toList());
-
-        // 数据入库
-        batchInsert(courseShares);
+        saveCourseShareStudent(courseShareDto.getCourseId(), courseSchedule.getTenantId(), userIdList);
         return true;
     }
 
@@ -173,6 +157,7 @@ public class CourseShareServiceImpl extends BaseServiceImpl<Integer, CourseShare
             CourseSchedule schedule = schedules.get(0);
             CourseScheduleStudentPayment payment = new CourseScheduleStudentPayment();
             payment.setGroupType(schedule.getGroupType());
+            payment.setCourseScheduleId(courseId);
             payment.setMusicGroupId(schedule.getMusicGroupId());
             payment.setUserId(userId);
             // 分享方式下,价格为0
@@ -364,6 +349,43 @@ public class CourseShareServiceImpl extends BaseServiceImpl<Integer, CourseShare
     }
 
     /**
+     * // 保存课程分享的学生
+     *
+     * @param courseId   课程ID
+     * @param tenantId   租户ID
+     * @param userIdList 用户ID列表
+     */
+    private void saveCourseShareStudent(Long courseId, Integer tenantId, List<Integer> userIdList) {
+        // 处理已经分享过的数据
+        List<CourseShare> existShares = courseShareDao.selectByCourseId(courseId);
+        if (CollectionUtils.isNotEmpty(existShares)) {
+            List<Integer> sharedHistoryRecords = existShares.stream()
+                    .map(CourseShare::getUserId)
+                    .collect(Collectors.toList());
+            // 已经存在的数据不需要重复录入
+            userIdList.removeIf(sharedHistoryRecords::contains);
+        }
+        if (CollectionUtils.isEmpty(userIdList)) {
+            // 没有新加入的数据
+            throw new BizException("学员已经在分享名单中");
+        }
+
+        Integer userId = userService.getUserId();
+        List<CourseShare> courseShares = userIdList.stream().map(next -> {
+            CourseShare courseShare = new CourseShare();
+            courseShare.setCourseId(courseId);
+            courseShare.setTenantId(tenantId);
+            courseShare.setUserId(next);
+            courseShare.setCreateTime(new Date());
+            courseShare.setCreateBy(userId);
+            return courseShare;
+        }).collect(Collectors.toList());
+
+        // 数据入库
+        batchInsert(courseShares);
+    }
+
+    /**
      * 根据用户id和课程id查询是否已经私有分享当前课程
      *
      * @param studentId        用户id

+ 10 - 14
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java

@@ -1891,22 +1891,18 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         roomMember.setLiveRoomStatus(1);
         roomMember.setMicrophoneFlag(microphoneFlag);
 
-        // 保存直播间用户信息
-        liveBroadcastRoomMemberService.save(roomMember);
+        ImLiveBroadcastRoomMember liveRoomMember = liveBroadcastRoomMemberService.lambdaQuery()
+                .eq(ImLiveBroadcastRoomMember::getTenantId, userInfo.getTenantId())
+                .eq(ImLiveBroadcastRoomMember::getRoomUid, imLiveBroadcastRoomVo.getRoomUid())
+                .eq(ImLiveBroadcastRoomMember::getUserId, userInfo.getUserId())
+                .list().stream().findFirst().orElse(null);
+        if (Objects.nonNull(liveRoomMember)) {
+           return userInfo;
+        }
 
-        if ("LIVE".equals(imLiveBroadcastRoomVo.getGroupType())) {
 
-            // 课程ID
-            CourseSchedule courseSchedule = courseScheduleDao.findByRoomUid(imLiveBroadcastRoomVo.getRoomUid(), GroupType.LIVE);
-            if (Objects.isNull(courseSchedule)) {
-                return userInfo;
-            }
-            try {
-                courseShareService.createPaymentRecord(courseSchedule.getId(),userId);
-            } catch (Exception e) {
-                log.error("getLiveRoomUserInfo>>>> createPaymentRecord error", e);
-            }
-        }
+        // 保存直播间用户信息
+        liveBroadcastRoomMemberService.save(roomMember);
 
         return userInfo;
     }

+ 158 - 39
mec-biz/src/main/java/com/ym/mec/biz/service/impl/VipGroupServiceImpl.java

@@ -6,6 +6,9 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.microsvc.toolkit.middleware.live.LivePluginContext;
+import com.microsvc.toolkit.middleware.live.LivePluginService;
+import com.microsvc.toolkit.middleware.live.message.LiveRoomMessage;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.dto.VipGroupClassGroupMapper;
@@ -16,6 +19,7 @@ import com.ym.mec.biz.dal.enums.*;
 import com.ym.mec.biz.dal.mapper.LiveGroupPlusMapper;
 import com.ym.mec.biz.dal.page.*;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
+import com.ym.mec.biz.dal.vo.ImLiveRoomVideoVo;
 import com.ym.mec.biz.dal.wrapper.LiveGroupWrapper;
 import com.ym.mec.biz.event.source.SendSeoMessageSource;
 import com.ym.mec.biz.service.*;
@@ -186,6 +190,8 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
 
     @Autowired
     private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
+    @Autowired
+    private LivePluginContext livePluginContext;
 
     @Autowired
     private StudentService studentService;
@@ -211,6 +217,9 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
     @Autowired
     private VipGroupService vipGroupService;
 
+    @Autowired
+    private ImLiveRoomVideoService imLiveRoomVideoService;
+
     private static final Logger LOGGER = LoggerFactory.getLogger(VipGroup.class);
 
     @Override
@@ -3192,31 +3201,76 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
             classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT);
             classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);
             studentPauseInfoDao.deleteUserPauseInfoWithGroup(groupType, vipGroupId.toString(), studentId);
-
-            classGroup.setStudentNum(classGroup.getStudentNum() - 1);
-            classGroupDao.update(classGroup);
+            classGroupDao.modifyStudentNum(classGroup.getId(),-1);
             return;
         }
 
-
         classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT);
         classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);
-
-        courseScheduleService.batchDeleteMusicGroupCourseWithStudent(vipGroupId.toString(), studentId, groupType);
-
-        List<Integer> studentPaymentIds = courseScheduleStudentPaymentDao.findNotStartCourseStudentPaymentIdsWithClassGroupAndStudent(classGroup.getId(), studentId);
-        if (!CollectionUtils.isEmpty(studentPaymentIds)) {
-            courseScheduleStudentPaymentDao.batchDeleteWithID(studentPaymentIds);
+        List<CourseSchedule> musicGroupCourseSchedules = courseScheduleDao.findMusicGroupCourseSchedulesWithStudent(vipGroupId.toString(), groupType.getCode(), CourseStatusEnum.NOT_START.getCode(), studentId);
+        if (!org.apache.commons.collections.CollectionUtils.isEmpty(musicGroupCourseSchedules)) {
+            List<Long> courseScheduleIds = musicGroupCourseSchedules.stream()
+                    .map(courseSchedule -> courseSchedule.getId())
+                    .collect(Collectors.toList());
+            courseScheduleDao.deleteMusicGroupCourseSchedulesWithStudent(courseScheduleIds, studentId);
+            studentAttendanceDao.deleteByCourseAndUser(courseScheduleIds,studentId);
+            /*if(groupType == LIVE){
+                List<CourseScheduleStudentPayment> studentPayments = courseScheduleStudentPaymentDao.findByCourseScheduleIds(courseScheduleIds);
+                Map<Long, Integer> courseStudentNumMap = studentPayments.stream().filter(e -> e.getJoinCourseType() == JoinCourseType.PURCHASE)
+                        .collect(Collectors.groupingBy(e -> e.getCourseScheduleId(), Collectors.collectingAndThen(Collectors.toList(), v -> v.size())));
+                for (CourseSchedule schedule : musicGroupCourseSchedules) {
+                    if(StringUtils.isEmpty(schedule.getLiveRoomId())){
+                        continue;
+                    }
+                    ImLiveBroadcastRoom liveRoom = imLiveBroadcastRoomService.getByRoomUid(schedule.getLiveRoomId());
+                    if (Objects.isNull(liveRoom)) {
+                        continue;
+                    }
+                    Integer studentNum = courseStudentNumMap.get(schedule.getId());
+                    //如果还有学生,那么之发送给退学学员
+                    try {
+                        LivePluginService pluginService = livePluginContext.getPluginService(liveRoom.getServiceProvider());
+                        // 发送用户信息
+                        LiveRoomMessage.MessageUser messageUser = LiveRoomMessage.MessageUser.builder()
+                                .sendUserId("")
+                                .sendUserName("")
+                                .avatarUrl("")
+                                .build();
+
+                        LiveRoomMessage message = new LiveRoomMessage();
+                        message.setIsIncludeSender(1);
+                        message.setFromUserId(studentId.toString());
+                        message.setToChatRoomId(schedule.getLiveRoomId());
+                        message.setObjectName(LiveRoomMessage.LIVE_STATUS_CHANGE);
+                        message.setContent(LiveRoomMessage.MessageContent.builder()
+                                .reason("您的退学申请已处理,点击退出直播间")
+                                .targetIds(Lists.newArrayList())
+                                .sendUserInfo(messageUser).build());
+                        if(studentNum == null || studentNum == 0){
+                            LiveRoomMessage message1 = new LiveRoomMessage();
+                            message1.setIsIncludeSender(1);
+                            message1.setFromUserId(schedule.getActualTeacherId().toString());
+                            message1.setToChatRoomId(schedule.getLiveRoomId());
+                            message1.setObjectName(LiveRoomMessage.LIVE_STATUS_CHANGE);
+                            message1.setContent(LiveRoomMessage.MessageContent.builder()
+                                    .reason("课程信息已变更")
+                                    .targetIds(Lists.newArrayList())
+                                    .sendUserInfo(messageUser).build());
+                            pluginService.sendChatRoomMessage(message1);
+                        }
+                        pluginService.sendChatRoomMessage(message);
+                    } catch (Exception e) {
+                        log.error("liveRoom error", e);
+                    }
+                }
+            }*/
         }
 
         if (!vipGroup.getStatus().equals(VipGroupStatusEnum.APPLYING) || (Objects.nonNull(vipGroupCategory) && vipGroupCategory.getMusicTheory())) {
             courseScheduleTeacherSalaryService.updateVipGroupCourseTeacherSalary(vipGroupId.intValue(), vipGroup.getUserId());
         }
 
-        classGroup.setStudentNum(classGroup.getStudentNum() - 1);
-
-        classGroupDao.update(classGroup);
-
+        classGroupDao.modifyStudentNum(classGroup.getId(),-1);
         //学员退出班级群
         imGroupMemberService.quit(classGroup.getId().toString(), studentId);
     }
@@ -4737,10 +4791,12 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
         MapUtil.populateMap(params, queryInfo);
         // VIP小课
         List<StudentVipGroupShowListDto> vipGroups = vipGroupDao.findVipGroups(params);
-        // 直播课
-        vipGroups.addAll(vipGroupDao.findLiveGroups(params));
         // 网课
         vipGroups.addAll(practiceGroupService.findPracticeGroups(params));
+        Student student = studentDao.get(queryInfo.getUserId());
+        // 直播课
+        params.put("subjectId",student.getSubjectIdList());
+        vipGroups.addAll(vipGroupDao.findLiveGroups(params));
         // 删除返回null值数据
         vipGroups.removeAll(Collections.singleton(null));
         // 按照创建时间倒序
@@ -4882,7 +4938,7 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
         Map<Integer, List<StudentApplyRefunds>> studentApplyRefundsMap = applyRefunds.stream()
                 .collect(Collectors.groupingBy(StudentApplyRefunds::getUserId));
         records.forEach(data -> {
-            ClassGroupStudentMapper classGroupStudentMapper = studentMapperMap.get(data.getStudentId().intValue());
+            ClassGroupStudentMapper classGroupStudentMapper = studentMapperMap.get(data.getStudentId());
             if (Objects.isNull(classGroupStudentMapper)) {
                 data.setStudentStatus(0);
                 return;
@@ -4895,7 +4951,7 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
                 return;
             }
 
-            List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsMap.get(data.getStudentId().intValue());
+            List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsMap.get(data.getStudentId());
             if (!CollectionUtils.isEmpty(studentApplyRefunds)) {
                 StudentApplyRefunds studentApplyRefund = studentApplyRefunds.get(0);
                 if (data.getStudentStatus() == 0 && studentApplyRefund.getStatus().equals(StudentApplyRefundsStatus.ING)) {
@@ -4922,7 +4978,7 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
         }
         // 报名中的课程直接返回json数据
         List<CourseSchedule> courseSchedules;
-        if (vipGroup.getStatus().equals(VipGroupStatusEnum.APPLYING)) {
+        if (VipGroupStatusEnum.APPLYING.equals(vipGroup.getStatus()) ||VipGroupStatusEnum.NOT_START.equals(vipGroup.getStatus())) {
             courseSchedules =  JSON.parseArray(vipGroup.getCourseSchedulesJson(), CourseSchedule.class);
             // 报名中的课程默认未分享,不能修改
             courseSchedules.forEach(next->next.setShareMode(ShareModeEnum.NO_SHARE));
@@ -4935,9 +4991,28 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
             courseSchedules.removeIf(next -> !shareMode.equals(next.getShareMode()));
         }
 
+        List<CourseScheduleDto> courseScheduleDtos = JSON.parseArray(JSON.toJSONString(courseSchedules), CourseScheduleDto.class);
+
+        // roomId
+        List<String> roomIdList = courseScheduleDtos.stream().map(CourseScheduleDto::getLiveRoomId).collect(Collectors.toList());
+
+        // 查询直播间视频数
+        Map<String, Integer> uidCountMap = imLiveRoomVideoService.queryRoomUidCountMap(roomIdList);
+        for (CourseScheduleDto record : courseScheduleDtos) {
+            if (Objects.isNull(record.getLiveRoomId())) {
+                continue;
+            }
+            Integer count = uidCountMap.get(record.getLiveRoomId());
+            if (count == null) {
+                record.setVideoNum(0);
+            }
+            record.setVideoNum(count);
+        }
+
+
 
         Map<String, Object> result = new HashMap<>();
-        result.put("list", courseSchedules);
+        result.put("list", courseScheduleDtos);
         result.put("singleClassMinutes", vipGroup.getSingleClassMinutes());
         return result;
     }
@@ -4947,8 +5022,10 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
      */
     @Override
     public void liveCourseRemind() {
+
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
         // 查询30分钟内要开始的并且没有直播通知的直播课
-        List<CourseSchedule> courseSchedules = courseScheduleDao.liveCourseRemind(30);
+        List<CourseSchedule> courseSchedules = courseScheduleDao.liveCourseRemind(studentRemindTime);
 
         if (CollectionUtils.isEmpty(courseSchedules)) {
             return;
@@ -5079,6 +5156,8 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
         } catch (Exception e) {
             log.error("创建直播间失败", e);
             imLiveBroadcastRoomService.removeById(liveRoom.getId());
+            roomUid = null;
+//            throw new BizException("创建直播间失败");
         }
 
         // 更新课程关联直播间
@@ -5086,7 +5165,13 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
         schedule.setId(courseSchedule.getId());
         schedule.setTenantId(courseSchedule.getTenantId());
         schedule.setLiveRoomId(roomUid);
-        courseScheduleDao.update(schedule);
+        CourseSchedule courseSchedule1 = courseScheduleDao.get(courseSchedule.getId());
+        if (StringUtils.isBlank(courseSchedule1.getLiveRoomId())) {
+            courseSchedule.setLiveRoomId(roomUid);
+            courseScheduleDao.update(schedule);
+        } else {
+            courseSchedule.setLiveRoomId(courseSchedule1.getLiveRoomId());
+        }
 
     }
 
@@ -5102,7 +5187,10 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
         if (!vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
             throw new BizException("课程组不是取消状态");
         }
-
+        List<CourseSchedule> schedules = courseScheduleDao.findGroupCourseSchedules(id.toString(), vipGroup.getGroupType());
+        if(!CollectionUtils.isEmpty(schedules)){
+            throw new BizException("当前课程组已排课");
+        }
         vipGroupDao.del(id);
         return true;
     }
@@ -5112,9 +5200,9 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
 
         List<TenantInfo> list = tenantInfoService.list();
 
-        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.liveClassStudentRemindTime).getParanValue());
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_STUDENT_REMIND_TIME).getParanValue());
 
-        Integer closeTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.closeClassStudentRemindTime).getParanValue());
+        Integer closeTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.CLOSE_CLASS_STUDENT_REMIND_TIME).getParanValue());
 
         for (TenantInfo tenantInfo : list) {
             // 是否是连堂课
@@ -5138,13 +5226,13 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
                         try {
                             imLiveBroadcastRoomService.sendForcedOffline(imLiveBroadcastRoomVo);
 
-                            courseScheduleDao.updateLiveRemind(data.getId(), 1);
+                            courseScheduleDao.updateLiveRemind(data.getId(), 2);
                         } catch (Exception e) {
                             log.error("发送直播间退出消息失败", e);
                         }
                     } else if (imLiveBroadcastRoomVo.getLiveState() == 2) {
                         // 直播未开始 设置通知状态
-                        courseScheduleDao.updateLiveRemind(data.getId(), 2);
+                        courseScheduleDao.updateLiveRemind(data.getId(), 3);
                     }
                 }
             });
@@ -5163,14 +5251,14 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
                         boolean b = imLiveBroadcastRoomService.tryDestroyLiveRoom(imLiveBroadcastRoomVo);
                         if (b) {
                             // 直播已关闭 设置通知状态
-                            courseScheduleDao.updateLiveRemind(data.getId(), 2);
+                            courseScheduleDao.updateLiveRemind(data.getId(), 3);
                         }
                     } catch (Exception e) {
                         log.error("关闭直播间失败", e);
                     }
                 } else if (imLiveBroadcastRoomVo.getLiveState() == 2) {
                     // 直播已关闭 设置通知状态
-                    courseScheduleDao.updateLiveRemind(data.getId(), 2);
+                    courseScheduleDao.updateLiveRemind(data.getId(), 3);
                 }
             }
 
@@ -5178,6 +5266,7 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public LiveGroupWrapper.LiveCourseInfo joinLiveRoomByShare(Integer courseScheduleId,Integer studentId) {
 
         //  判断课程类型
@@ -5186,22 +5275,40 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
             throw new BizException("课程不存在");
         }
 
+        // 购买用户可以直接进入
+        CourseScheduleStudentPayment payment = courseScheduleStudentPaymentDao.getByUserIdAndCourseId(studentId, courseScheduleId.longValue());
+        if (!Objects.isNull(payment) && JoinCourseType.PURCHASE.equals(payment.getJoinCourseType())) {
 
-        // 分享类型  是否能进入
-        if (ShareModeEnum.NO_SHARE.equals(courseSchedule.getShareMode())) {
-            throw new BizException("课程不允许分享");
-        }
-        if (ShareModeEnum.PRIVATE.equals(courseSchedule.getShareMode())) {
-            // 查询
-            CourseShare courseShare = courseShareService.getByUserIdAndCourseId(studentId, courseScheduleId);
-            if (Objects.isNull(courseShare)) {
-                throw new BizException("非分享用户,不可进入");
+        } else {
+
+
+            // 分享类型  是否能进入
+            if (ShareModeEnum.NO_SHARE.equals(courseSchedule.getShareMode())) {
+                throw new BizException("课程不允许分享");
+            }
+            if (ShareModeEnum.PRIVATE.equals(courseSchedule.getShareMode())) {
+                // 查询
+                CourseShare courseShare = courseShareService.getByUserIdAndCourseId(studentId, courseScheduleId);
+                if (Objects.isNull(courseShare)) {
+                    throw new BizException("非分享用户,不可进入");
+                }
+            }
+
+            SysUser sysUser = sysUserService.queryUserById(studentId);
+            if (Objects.isNull(sysUser)) {
+                throw new BizException("用户不存在");
+            }
+            if (!courseSchedule.getTenantId().equals(sysUser.getTenantId())) {
+                throw new BizException("用户不属于此机构");
             }
         }
 
+        Integer studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
 
+        Date date = DateUtil.startDateAndEndTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime());
+        date = DateUtil.addMinutes(date, -studentRemindTime);
         // 课程是否开始
-        if(CourseStatusEnum.NOT_START.equals(courseSchedule.getStatus())) {
+        if(CourseStatusEnum.NOT_START.equals(courseSchedule.getStatus()) && date.after(new Date())) {
             throw new BizException("课程未开始");
         }
 
@@ -5209,6 +5316,18 @@ public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> impleme
         if (CourseStatusEnum.OVER.equals(courseSchedule.getStatus())) {
             throw new BizException("课程已结束");
         }
+        if (StringUtils.isBlank(courseSchedule.getLiveRoomId())) {
+
+            createVipGroupLiveRoom(courseSchedule.getId().toString(), courseSchedule);
+
+        }
+
+        try {
+            courseShareService.createPaymentRecord(courseSchedule.getId(),studentId);
+        } catch (Exception e) {
+            log.error("getLiveRoomUserInfo>>>> createPaymentRecord error", e);
+        }
+
 
         return LiveGroupWrapper.LiveCourseInfo.builder()
                 .studentId(studentId)

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

@@ -205,7 +205,8 @@
             cssp.be_merged_,
             st.current_grade_num_,
             st.current_class_,
-            IF(sa.status_ IS NULL,'TRUANT',sa.status_) status_
+            IF(sa.status_ IS NULL,'TRUANT',sa.status_) status_,
+        cssp.join_course_type_ as joinCourseType
         FROM
             course_schedule_student_payment cssp
             LEFT JOIN sys_user su ON cssp.user_id_ = su.id_

+ 48 - 5
mec-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

@@ -1290,6 +1290,7 @@
                cs.student_num_,
                cs.leave_student_num_,
                cs.schoole_id_,
+        cs.live_room_id_,
                cs.share_mode_,
                s.name_                                           schoole_name_
         FROM course_schedule cs
@@ -1426,6 +1427,15 @@
                 <if test="item.shareMode != null">
                     share_mode_ = #{item.shareMode},
                 </if>
+                <if test="item.liveRoomId != null">
+                    live_room_id_ = #{item.liveRoomId},
+                </if>
+                <if test="item.continuousCourse != null">
+                    continuous_course_ = #{item.continuousCourse},
+                </if>
+                <if test="item.liveRemind != null">
+                    live_remind_ = #{item.liveRemind},
+                </if>
                 update_time_ = NOW()
             </set>
             WHERE id_ = #{item.id} and tenant_id_ = #{item.tenantId}
@@ -1517,6 +1527,7 @@
         <result column="teaching_content_" property="teachingContent" />
         <result column="teaching_point_" property="teachingPoint" />
         <result column="music_group_id_" property="musicGroupId" />
+        <result column="live_room_id_" property="liveRoomId" />
     </resultMap>
 
     <sql id="teacherClassCourseScheduleQueryCondition">
@@ -1531,7 +1542,22 @@
                 AND CONCAT( cs.class_date_, ' ', cs.end_class_time_ )&lt;now()
             </if>
             <if test="status!=null">
-                AND cs.status_ = #{status,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+                <if test=" groupType == 'LIVE'">
+                    <if test="status.code == 'UNDERWAY'">
+                        AND (cs.status_  = 'UNDERWAY'
+                        or (cs.status_ = 'NOT_START' and  CONCAT(cs.class_date_,' ',cs.start_class_time_) &lt; date_add(now(), interval #{notStartCourseTime} minute))
+                        )
+                    </if>
+                    <if test="status.code == 'NOT_START'">
+                        AND cs.status_ = 'NOT_START' and CONCAT(cs.class_date_,' ',cs.start_class_time_) &gt; date_add(now(), interval #{notStartCourseTime} minute)
+                    </if>
+                    <if test="status.code == 'OVER'">
+                        AND cs.status_ = #{status,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+                    </if>
+                </if>
+                <if test="groupType != 'LIVE'">
+                    AND cs.status_ = #{status,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+                </if>
             </if>
             <if test="startClassDate!=null and startClassDate!=''">
                 AND cs.class_date_ &gt;= #{startClassDate}
@@ -1562,6 +1588,7 @@
         cs.teaching_content_,
         cs.teaching_point_,
         cs.music_group_id_,
+        cs.live_room_id_,
         s.name_ school_name_,
         ch.expiry_date_
         FROM
@@ -4191,7 +4218,22 @@
         left join student_attendance sa ON sa.course_schedule_id_ = cs.id_ AND sa.user_id_ = cssp.user_id_
         where cssp.music_group_id_ = #{queryInfo.groupId} AND cssp.user_id_ = #{queryInfo.userId} AND cssp.group_type_ = #{queryInfo.groupType}
         <if test="queryInfo.courseStatus != null and queryInfo.courseStatus != ''">
-            AND cs.status_ = #{queryInfo.courseStatus}
+            <if test=" queryInfo.groupType == 'LIVE'">
+                <if test="queryInfo.courseStatus == 'UNDERWAY'">
+                    AND (cs.status_  = 'UNDERWAY'
+                    or (cs.status_ = 'NOT_START' and  CONCAT(cs.class_date_,' ',cs.start_class_time_) &lt; date_add(now(), interval #{queryInfo.notStartCourseTime} minute))
+                    )
+                </if>
+                <if test="queryInfo.courseStatus == 'NOT_START'">
+                    AND cs.status_ = 'NOT_START' and CONCAT(cs.class_date_,' ',cs.start_class_time_) &gt; date_add(now(), interval #{queryInfo.notStartCourseTime} minute)
+                </if>
+                <if test="queryInfo.courseStatus == 'OVER'">
+                    AND cs.status_ = 'OVER'
+                </if>
+            </if>
+            <if test="queryInfo.groupType != 'LIVE'">
+                AND cs.status_ = #{queryInfo.courseStatus}
+            </if>
         </if>
         <if test="queryInfo.teachMode != null and queryInfo.teachMode != ''">
             AND cs.teach_mode_ = #{queryInfo.teachMode}
@@ -4374,6 +4416,7 @@
         from course_schedule cs
         where cs.status_ = 'NOT_START'
           and cs.type_ = 'LIVE'
+        and cs.live_remind_ = 0
           and cs.class_date_ = date_format(now(),'%Y-%m-%d')
           and CONCAT(class_date_,' ',start_class_time_)  &lt;= date_format(date_add(now(),interval #{minutes} minute),'%Y-%m-%d %H:%i:%s')
           and CONCAT(class_date_,' ',start_class_time_)  &gt;= date_format(now(),'%Y-%m-%d %H:%i:%s')
@@ -4381,7 +4424,7 @@
 
     <update id="updateRemindStatus">
         update course_schedule
-        set status_ = 'UNDERWAY'
+        set live_remind_ = 1
         where id_  in
         <foreach collection="ids" item="id" open="(" separator="," close=")">
             #{id}
@@ -4393,11 +4436,11 @@
         where status_ = 'OVER' and type_ = 'LIVE'  and  continuous_course_ = 0
         <if test="studentRemindTime != null" >
             and CONCAT(class_date_,' ',end_class_time_) &lt;= date_format(date_add(now(),interval -#{studentRemindTime} minute),'%Y-%m-%d %H:%i:%s')
-            and live_remind_ = 0
+            and live_remind_ = 1
         </if>
         <if test="closeTime != null" >
             and CONCAT(class_date_,' ',end_class_time_) &lt;= date_format(date_add(now(),interval -#{closeTime} minute),'%Y-%m-%d %H:%i:%s')
-            and live_remind_ = 1
+            and live_remind_ = 2
         </if>
         <if test="tenantId != null">
             and tenant_id_ = #{tenantId}

+ 9 - 3
mec-biz/src/main/resources/config/mybatis/CourseScheduleStudentPaymentMapper.xml

@@ -25,6 +25,7 @@
 		<result column="be_merged_" property="beMerged"/>
 		<result column="tenant_id_" property="tenantId" />
 		<result column="activity_user_mapper_id_" property="activityUserMapperId" />
+		<result column="join_course_type_" property="joinCourseType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
 	</resultMap>
 
 	<resultMap type="com.ym.mec.biz.dal.dto.StudentCourseTimesDto" id="studentCourseTimesDto">
@@ -59,10 +60,11 @@
 	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.CourseScheduleStudentPayment" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
 		INSERT INTO course_schedule_student_payment (id_,group_type_,music_group_id_,course_schedule_id_,user_id_,
 			original_price_,expect_price_,actual_price_,expect_price_bak_,actual_price_bak_,create_time_,update_time_,
-		settlement_time_,class_group_id_,batch_no_,be_merged_,tenant_id_,activity_user_mapper_id_)
+		settlement_time_,class_group_id_,batch_no_,be_merged_,tenant_id_,activity_user_mapper_id_,join_course_type_)
 		VALUES(#{id},#{groupType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{musicGroupId},#{courseScheduleId},#{userId},
 			#{originalPrice},#{expectPrice},#{actualPrice},#{expectPriceBak},#{actualPriceBak},NOW(),NOW()
-			,#{settlementTime},#{classGroupId},#{batchNo},#{beMerged},#{tenantId},#{activityUserMapperId})
+			,#{settlementTime},#{classGroupId},#{batchNo},#{beMerged},#{tenantId},#{activityUserMapperId}
+        ,#{joinCourseType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler})
 	</insert>
     <insert id="batchInsert" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id_">
 		INSERT INTO course_schedule_student_payment (id_,group_type_,music_group_id_,course_schedule_id_,user_id_,
@@ -834,7 +836,7 @@
     <select id="getCourseStudents" resultType="com.ym.mec.biz.dal.dto.BasicUserDto">
 		SELECT cssp.user_id_ userId,st.member_rank_setting_id_ memberRankSettingId,
 		       s.name_ subjectName,su.avatar_ headUrl,su.username_ name,
-                s.id_ subjectIdList,st.repair_flag_ repairFlag
+                s.id_ subjectIdList,st.repair_flag_ repairFlag,cssp.join_course_type_ as joinCourseType
 		FROM course_schedule_student_payment cssp
 		LEFT JOIN sys_user su ON su.id_ = cssp.user_id_
 		LEFT JOIN student st ON st.user_id_ = cssp.user_id_
@@ -1118,4 +1120,8 @@
 		AND cs.del_flag_ = 0 AND cs.is_lock_ = 0 and cs.pre_course_flag_ = 0 AND t.is_settlement_salary_ = 1 AND csts.settlement_time_ IS NOT NULL AND cs.tenant_id_ = 1
 		group by cs.organ_id_
 	</select>
+
+	<select id="getByUserIdAndCourseId" resultMap="CourseScheduleStudentPayment">
+        SELECT * FROM `course_schedule_student_payment` WHERE `user_id_` = #{userId} AND `course_schedule_id_` = #{courseScheduleId} limit 1
+    </select>
 </mapper>

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

@@ -85,7 +85,7 @@
         SELECT distinct
         s.user_id_ userId,
         su.username_ username,
-        su.phone_ phone,
+        su.phone_ parentsPhone,
         o.name_ organName,
         co.name_ cooperationOrganName,
         sb.name_ subjectName
@@ -197,6 +197,6 @@
     <select id="getByUserIdAndCourseId" resultMap="courseShare">
         SELECT *
         FROM course_share
-        WHERE user_id_ = #{studentId} AND course_id_ = #{courseScheduleId}
+        WHERE user_id_ = #{studentId} AND course_id_ = #{courseScheduleId} limit 1
     </select>
 </mapper>

+ 25 - 2
mec-biz/src/main/resources/config/mybatis/LiveGroupPlusMapper.xml

@@ -8,12 +8,19 @@
     t.create_time_ as createTime,
     t.order_no_ as orderNo
     from student_payment_order t
+    left join sys_user su on su.id_ = t.user_id_
     <where>
         <if test="param.liveGroupId != null">
             and t.music_group_id_ = #{param.liveGroupId}
             and t.type_ = 'LIVE_GROUP_BUY'
             and t.status_ = 'SUCCESS'
         </if>
+        <if test="param.search != null and param.search != ''">
+            and (su.id_ = #{param.search}
+                or su.username_ like concat('%',#{param.search},'%')
+                or su.phone_ like concat('%',#{param.search},'%')
+            )
+        </if>
     </where>
 
     </select>
@@ -30,7 +37,7 @@
     cs.class_date_,
     CONCAT(cs.class_date_,' ',cs.start_class_time_) start_class_time_,
     CONCAT(cs.class_date_,' ',cs.end_class_time_) end_class_time_,
-    cs.status_,
+    cs.status_ as status_,
     csts.user_id_ actual_teacher_id_,
     csts.teacher_role_,
     cg.expect_student_num_,
@@ -64,11 +71,27 @@
     </if>
     AND csts.user_id_ = #{param.teacherId} AND cs.pre_course_flag_ = 0
     <if test="param.status != null">
-        AND cs.status_ = #{param.status}
+        <if test="param.status == 'UNDERWAY'">
+            AND (cs.status_  = 'UNDERWAY'
+                or (cs.status_ = 'NOT_START' and  CONCAT(cs.class_date_,' ',cs.start_class_time_) &lt; date_add(now(), interval #{param.notStartCourseTime} minute))
+            )
+        </if>
+        <if test="param.status == 'NOT_START'">
+            AND cs.status_ = 'NOT_START' and CONCAT(cs.class_date_,' ',cs.start_class_time_) &gt; date_add(now(), interval #{param.notStartCourseTime} minute)
+        </if>
+        <if test="param.status == 'OVER'">
+            AND cs.status_ = 'OVER'
+        </if>
     </if>
     <if test="param.search != null and param.search != ''">
         AND (cs.name_ LIKE CONCAT('%',#{param.search},'%'))
     </if>
     order by field(cs.status_, 'UNDERWAY', 'NOT_START', 'OVER') asc, cs.class_date_,cs.start_class_time_
     </select>
+
+<select id="detailLiveCourse" resultType="com.ym.mec.biz.dal.dto.CourseScheduleDto">
+    SELECT *
+    FROM course_schedule cs
+    where id_ = #{courseScheduleId}
+    </select>
 </mapper>

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

@@ -44,6 +44,7 @@
         <result column="new_course_id_" property="courseSchedule.newCourseId"/>
         <result column="tenant_id_" property="tenantId"/>
         <result column="qualified_flag_" property="qualifiedFlag"/>
+        <result column="join_course_type_" property="joinCourseType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
     </resultMap>
 
     <!-- 根据主键查询一条记录 -->
@@ -192,6 +193,7 @@
         <result property="avatar" column="avatar_"/>
         <result property="phone" column="phone_"/>
         <result property="beMerged" column="be_merged_"/>
+        <result property="joinCourseType" column="joinCourseType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
         <result property="status" column="status_" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
     </resultMap>
 
@@ -475,7 +477,7 @@
                CASE WHEN sa.status_ IS NULL and cs.status_ = 'OVER' THEN 'TRUANT' ELSE sa.status_ END status_,
         su.username_,su.phone_,su.avatar_,cs.teach_mode_,cs.type_ course_type_,o.name_ organ_name_,tu.real_name_ teacher_name_,tu.avatar_ teacher_avatar_,
         cs.name_ course_schedule_name_,cs.status_ course_status_,
-        cs.actual_teacher_id_ teacher_id_,
+        cs.actual_teacher_id_ teacher_id_,cssp.join_course_type_ as join_course_type_,
         CONCAT(cs.class_date_,' ',cs.start_class_time_,'-',cs.end_class_time_) classTimeStr,
         cs.class_date_ ,cs.start_class_time_,cs.end_class_time_ ,cs.new_course_id_,
         CASE WHEN sa.visit_flag_ IS NULL THEN 0 ELSE sa.visit_flag_ END visitFlag,

+ 7 - 10
mec-biz/src/main/resources/config/mybatis/VipGroupMapper.xml

@@ -432,20 +432,17 @@
             <if test="organId != null">
                 AND FIND_IN_SET(#{organId},vg.organ_id_list_)
             </if>
-            <if test="subjectId!=null">
-                AND FIND_IN_SET(#{subjectId},cg.subject_id_list_)
-            </if>
-            <if test="subjectId!=null">
-                AND FIND_IN_SET(#{subjectId},cg.subject_id_list_)
+            <if test="subjectId != null and subjectId != ''">
+                AND (JSON_EXTRACT(live_config_json_, '$.subjectId') = "31" OR FIND_IN_SET(#{subjectId},cg.subject_id_list_))
             </if>
             <if test="categoryId!=null">
                 AND FIND_IN_SET(vg.vip_group_category_id_,#{categoryId})
             </if>
             <if test="classType!=null and classType.toString()=='0'.toString()">
-                AND vg.offline_classes_num_>0
+                AND vg.offline_classes_num_ > 0
             </if>
             <if test="classType!=null and classType.toString()=='1'.toString()">
-                AND vg.online_classes_num_>0
+                AND vg.online_classes_num_ > 0
             </if>
             <if test="search != null and search != ''">
                 AND vg.name_ like concat('%',#{search},'%')
@@ -478,9 +475,9 @@
         vg.group_type_
         FROM
         vip_group vg
-        LEFT JOIN class_group cg ON vg.id_=cg.music_group_id_ AND cg.group_type_ = vg.group_type_
-        LEFT JOIN teacher t ON vg.user_id_=t.id_
-        LEFT JOIN sys_user su ON vg.user_id_=su.id_
+        LEFT JOIN class_group cg ON vg.id_ = cg.music_group_id_ AND cg.group_type_ = vg.group_type_
+        LEFT JOIN teacher t ON vg.user_id_ = t.id_
+        LEFT JOIN sys_user su ON vg.user_id_ = su.id_
         LEFT JOIN vip_group_activity vga ON vg.vip_group_activity_id_=vga.id_
         LEFT JOIN vip_group_category vgc ON vg.vip_group_category_id_=vgc.id_
         <include refid="studentVipGroupQueryCondition"/>

+ 86 - 86
mec-common/common-core/src/main/java/com/ym/mec/common/service/impl/BaseServiceImpl.java

@@ -35,94 +35,94 @@ import java.util.*;
  */
 public abstract class BaseServiceImpl<PK extends Serializable, T> implements BaseService<PK, T> {
 
-	@Autowired
-	protected SqlSessionFactory sqlSessionFactory;
+    @Autowired
+    protected SqlSessionFactory sqlSessionFactory;
 
-	public abstract BaseDAO<PK, T> getDAO();
+    public abstract BaseDAO<PK, T> getDAO();
 
-	/**
-	 * 通过主键id加载对象
-	 * @param id
-	 * @return
-	 */
-	public T get(final PK id) {
-		return this.getDAO().get(id);
-	}
+    /**
+     * 通过主键id加载对象
+     * @param id
+     * @return
+     */
+    public T get(final PK id) {
+        return this.getDAO().get(id);
+    }
 
-	/**
-	 * 更新实体对象
-	 * @param bean
-	 * @return int
-	 */
-	public int update(T bean) {
-		return this.getDAO().update(bean);
-	}
+    /**
+     * 更新实体对象
+     * @param bean
+     * @return int
+     */
+    public int update(T bean) {
+        return this.getDAO().update(bean);
+    }
 
-	/**
-	 * 通过主键id删除对象
-	 * @param id
-	 * @return int
-	 */
-	public int delete(final PK id) {
-		return this.getDAO().delete(id);
-	}
+    /**
+     * 通过主键id删除对象
+     * @param id
+     * @return int
+     */
+    public int delete(final PK id) {
+        return this.getDAO().delete(id);
+    }
 
-	/**
-	 * 写入实体对象
-	 * @param bean
-	 * @return int
-	 */
-	public long insert(T bean) {
-		return this.getDAO().insert(bean);
-	}
+    /**
+     * 写入实体对象
+     * @param bean
+     * @return int
+     */
+    public long insert(T bean) {
+        return this.getDAO().insert(bean);
+    }
 
-	/**
-	 * 通过参数查找所有结果集
-	 * @param params
-	 * @return
-	 */
-	public List<T> findAll(Map<String, Object> params) {
-		final String TENANT_ID = "tenantId";
-		
-		if(!params.containsKey(TENANT_ID)){
-			params.put(TENANT_ID, TenantContextHolder.getTenantId());
-		}
-		return this.getDAO().findAll(params);
-	}
+    /**
+     * 通过参数查找所有结果集
+     * @param params
+     * @return
+     */
+    public List<T> findAll(Map<String, Object> params) {
+        final String TENANT_ID = "tenantId";
 
-	/**
-	 * 通过参数查找结果集,适合分页场景
-	 * @param queryInfo
-	 * @return
-	 */
-	public PageInfo<T> queryPage(QueryInfo queryInfo) {
-		PageInfo<T> pageInfo = new PageInfo<T>(queryInfo.getPage(), queryInfo.getRows());
-		Map<String, Object> params = new HashMap<String, Object>();
-		MapUtil.populateMap(params, queryInfo);
-		
-		List<T> dataList = null;
-		int count = this.findCount(params);
-		if (count > 0) {
-			pageInfo.setTotal(count);
-			params.put("offset", pageInfo.getOffset());
-			dataList = this.getDAO().queryPage(params);
-		}
-		if (count == 0) {
-			dataList = new ArrayList<T>();
-		}
-		pageInfo.setRows(dataList);
-		return pageInfo;
-	}
+        if(!params.containsKey(TENANT_ID)){
+            params.put(TENANT_ID, TenantContextHolder.getTenantId());
+        }
+        return this.getDAO().findAll(params);
+    }
+
+    /**
+     * 通过参数查找结果集,适合分页场景
+     * @param queryInfo
+     * @return
+     */
+    public PageInfo<T> queryPage(QueryInfo queryInfo) {
+        PageInfo<T> pageInfo = new PageInfo<T>(queryInfo.getPage(), queryInfo.getRows());
+        Map<String, Object> params = new HashMap<String, Object>();
+        MapUtil.populateMap(params, queryInfo);
+
+        List<T> dataList = null;
+        int count = this.findCount(params);
+        if (count > 0) {
+            pageInfo.setTotal(count);
+            params.put("offset", pageInfo.getOffset());
+            dataList = this.getDAO().queryPage(params);
+        }
+        if (count == 0) {
+            dataList = new ArrayList<T>();
+        }
+        pageInfo.setRows(dataList);
+        return pageInfo;
+    }
 
-	/**
-	 * 通过参数查找结果集数目
-	 * @author pengdc
-	 * @param params
-	 * @return
-	 */
-	public int findCount(Map<String, Object> params) {
-		return this.getDAO().queryCount(params);
-	}
+    /**
+     * 通过参数查找结果集数目
+     * @author pengdc
+     * @param params
+     * @return
+     */
+    public int findCount(Map<String, Object> params) {
+        return this.getDAO().queryCount(params);
+    }
 
 
 	@Override
@@ -186,8 +186,8 @@ public abstract class BaseServiceImpl<PK extends Serializable, T> implements Bas
 			}
 		}
 
-		return result;
-	}
+            return result;
+        }
 
 	@Override
 	public <K extends List, Y, Z> Map<Y,Z> getMap(String tableName, String columnKey, String columnValue, String ids, Class<Y> keyType, Class<Z> valueType){
@@ -247,8 +247,8 @@ public abstract class BaseServiceImpl<PK extends Serializable, T> implements Bas
 			}
 		}
 
-		return result;
-	}
+            return result;
+        }
 
 
 	@Override
@@ -312,6 +312,6 @@ public abstract class BaseServiceImpl<PK extends Serializable, T> implements Bas
 			}
 		}
 
-		return result;
-	}
+            return result;
+        }
 }

+ 17 - 1
mec-im/src/main/java/com/ym/service/Impl/RoomServiceImpl.java

@@ -130,6 +130,8 @@ public class RoomServiceImpl implements RoomService {
     private VipGroupDao vipGroupDao;
     @Autowired
     private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
+    @Autowired
+    private SysConfigService sysConfigService;
 
     @Override
     public Integer getCurrentCourseId(String roomId) {
@@ -267,8 +269,22 @@ public class RoomServiceImpl implements RoomService {
         // 网络课形式:RTC房间,直播间
         if (GroupType.LIVE == courseSchedule.getGroupType()) {
 
+            if (sysUser.getId().intValue() != courseSchedule.getActualTeacherId()) {
+                // 学生课程购买记录
+                CourseScheduleStudentPayment studentPayment = courseScheduleStudentPaymentDao.getByUserIdAndCourseId(sysUser.getId(),
+                        courseSchedule.getId());
+                if (Objects.isNull(studentPayment)) {
+                    throw new BizException(MessageFormat.format("{0}你已退学", courseSchedule.getName()));
+                }
+            }
+
             // 直播课已结束
-            if (CourseStatusEnum.NOT_START == courseSchedule.getStatus()) {
+            int studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
+
+            Date date = DateUtil.startDateAndEndTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime());
+            date = DateUtil.addMinutes(date, -studentRemindTime);
+            // 课程是否开始
+            if(CourseStatusEnum.NOT_START.equals(courseSchedule.getStatus()) && date.after(new Date())) {
                 throw new BizException("直播课未开始");
             }
 

+ 5 - 0
mec-student/src/main/java/com/ym/mec/student/controller/StudentCourseScheduleController.java

@@ -102,4 +102,9 @@ public class StudentCourseScheduleController extends BaseController {
 		return succeed(scheduleService.queryMusicCoursePlan(sysUserService.getUserId(), startDate, endDate));
 	}
 
+    @ApiOperation(value = "获取课程信息")
+    @GetMapping("/queryCourseId")
+    public Object queryCourseId(Long courseId){
+        return succeed(scheduleService.detailLiveCourse(courseId));
+    }
 }

+ 22 - 0
mec-web/src/main/java/com/ym/mec/web/controller/CourseScheduleController.java

@@ -3,6 +3,7 @@ package com.ym.mec.web.controller;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.ClassGroupDao;
 import com.ym.mec.biz.dal.dao.ClassGroupTeacherMapperDao;
+import com.ym.mec.biz.dal.dao.SysConfigDao;
 import com.ym.mec.biz.dal.dao.VipGroupDao;
 import com.ym.mec.biz.dal.dto.*;
 import com.ym.mec.biz.dal.entity.*;
@@ -15,6 +16,7 @@ import com.ym.mec.biz.service.*;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.entity.HttpResponseResult;
 import com.ym.mec.common.exception.BizException;
+import com.ym.mec.util.date.DateUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -59,6 +61,8 @@ public class CourseScheduleController extends BaseController {
     private OrganizationService organizationService;
     @Autowired
     private VipGroupDao vipGroupDao;
+    @Autowired
+    private SysConfigDao sysConfigDao;
 
     @ApiOperation(value = "课表详情")
     @GetMapping("/query")
@@ -186,6 +190,24 @@ public class CourseScheduleController extends BaseController {
                     &&!VipGroupStatusEnum.FINISHED.equals(vipGroup.getStatus())){
                 throw new BizException("非进行中课程组不允许进行此操作");
             }
+
+            // 直播课
+            if (GroupType.LIVE.equals(oldCourseSchedule.getGroupType())){
+                if(org.apache.commons.lang3.StringUtils.isNotBlank(oldCourseSchedule.getLiveRoomId())){
+                    // 重置连堂课,关联直播间,消息推送状态
+                    courseSchedule.setLiveRemind(0);
+                    courseSchedule.setContinuousCourse(false);
+                    courseSchedule.setLiveRoomId("");
+                }
+                String startRemindTime = sysConfigDao.findConfigValue("live_class_start_remind_time");
+                if(StringUtils.isEmpty(startRemindTime)){
+                    startRemindTime = "30";
+                }
+                if(DateUtil.minutesBetween(new Date(),oldCourseSchedule.getStartClassTime()) < Integer.parseInt(startRemindTime)
+                 && DateUtil.minutesBetween(new Date(),oldCourseSchedule.getEndClassTime()) >= 0){
+                    throw new BizException("直播课课程开始前{}分钟不允许调整",startRemindTime);
+                }
+            }
         }
         if(Objects.isNull(courseSchedule.getClassGroupId())){
             courseSchedule.setClassGroupId(oldCourseSchedule.getClassGroupId());

+ 8 - 0
mec-web/src/main/java/com/ym/mec/web/controller/CourseShareController.java

@@ -45,6 +45,14 @@ public class CourseShareController extends BaseController {
         return succeed();
     }
 
+    @ApiOperation(value = "一键添加保存分享列表")
+    @PostMapping("/saveCourseShareByOne")
+    @PreAuthorize("@pcs.hasPermissions('courseShare/saveCourseShareByOne')")
+    public HttpResponseResult<List<CourseShare>> saveCourseShareByOne(@Validated @RequestBody CourseShareDto courseShareDto) {
+        courseShareService.saveCourseShareByOne(courseShareDto);
+        return succeed();
+    }
+
     @ApiOperation(value = "查询已经分享过的学生")
     @GetMapping("/queryCourseSharedStudent")
     @PreAuthorize("@pcs.hasPermissions('courseShare/queryCourseSharedStudent')")

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

@@ -2800,10 +2800,10 @@ public class ExportController extends BaseController {
         OutputStream outputStream = response.getOutputStream();
         try {
             HSSFWorkbook workbook = POIUtil.exportExcel(new String[]{"分部", "学员姓名", "学员编号", "老师姓名", "老师编号",
-                    "课程组编号", "课程编号", "课程名称", "课程组类型", "课程类型", "上课时间","签到时间", "签退时间", "考勤状态"}, new String[]{
+                    "课程组编号", "课程编号", "课程名称", "课程组类型", "课程类型", "上课时间","签到时间", "签退时间", "考勤状态","来源"}, new String[]{
                     "courseSchedule.organization.name", "username", "userId", "courseSchedule.teacherName", "teacherId", "musicGroupId", "courseScheduleId",
                     "courseSchedule.name", "groupType.desc", "courseSchedule.type.msg", "classTimeStr", "signInTime",
-                    "signOutTime", "status.msg"}, rows);
+                    "signOutTime", "status.msg","joinCourseType.msg"}, rows);
             response.setContentType("application/octet-stream");
             response.setHeader("Content-Disposition", "attac:wq" +
                     "hment;filename=courseAttendance-" + DateUtil.getDate(new Date()) + ".xls");

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

@@ -449,7 +449,6 @@ public class VipGroupManageController extends BaseController {
     @ApiOperation(value = "删除直播课")
     @GetMapping(value = "/delLiveGroup/{id}")
     public HttpResponseResult<Object> delLiveGroup(@PathVariable Integer id){
-
         return succeed(vipGroupService.del(id));
     }
 }