Selaa lähdekoodia

课表日历+课表列表

Steven 3 vuotta sitten
vanhempi
commit
da7b479b4a
100 muutettua tiedostoa jossa 4291 lisäystä ja 6 poistoa
  1. 196 0
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. BIN
      KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/UserInterfaceState.xcuserstate
  3. 32 0
      KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  4. 6 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/Contents.json
  5. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/accompany_edit.imageset/Contents.json
  6. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/accompany_edit.imageset/accompany_edit@2x.png
  7. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/accompany_edit.imageset/accompany_edit@3x.png
  8. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrangement_homework.imageset/Contents.json
  9. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrangement_homework.imageset/arrangement_homework@2x.png
  10. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrangement_homework.imageset/arrangement_homework@3x.png
  11. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_down.imageset/Contents.json
  12. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_down.imageset/arrow_down@2x.png
  13. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_down.imageset/arrow_down@3x.png
  14. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_up.imageset/Contents.json
  15. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_up.imageset/arrow_up@2x.png
  16. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_up.imageset/arrow_up@3x.png
  17. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_chat.imageset/Contents.json
  18. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_chat.imageset/course_chat@2x.png
  19. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_chat.imageset/course_chat@3x.png
  20. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_nav.imageset/Contents.json
  21. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_nav.imageset/course_nav@2x.png
  22. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_nav.imageset/course_nav@3x.png
  23. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_time.imageset/Contents.json
  24. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_time.imageset/course_time@2x.png
  25. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_time.imageset/course_time@3x.png
  26. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/down_arrow.imageset/Contents.json
  27. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/down_arrow.imageset/down_arrow@2x.png
  28. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/down_arrow.imageset/down_arrow@3x.png
  29. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homeworkVideo_placeholder.imageset/Contents.json
  30. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homeworkVideo_placeholder.imageset/homeworkVideo_placeholder@2x.png
  31. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homeworkVideo_placeholder.imageset/homeworkVideo_placeholder@3x.png
  32. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_eva.imageset/Contents.json
  33. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_eva.imageset/homework_eva@2x.png
  34. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_eva.imageset/homework_eva@3x.png
  35. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_placeholder.imageset/Contents.json
  36. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_placeholder.imageset/homework_placeholder@2x.png
  37. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_placeholder.imageset/homework_placeholder@3x.png
  38. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/Contents.json
  39. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/lesson_Live@2x.png
  40. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/lesson_Live@3x.png
  41. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/student_eva_placeholder.imageset/Contents.json
  42. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/student_eva_placeholder.imageset/student_eva_placeholder@2x.png
  43. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/student_eva_placeholder.imageset/student_eva_placeholder@3x.png
  44. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/teacher_eva_placeholder.imageset/Contents.json
  45. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/teacher_eva_placeholder.imageset/teacher_eva_placeholder@2x.png
  46. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/teacher_eva_placeholder.imageset/teacher_eva_placeholder@3x.png
  47. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/up_arrow.imageset/Contents.json
  48. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/up_arrow.imageset/up_arrow@2x.png
  49. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/up_arrow.imageset/up_arrow@3x.png
  50. 6 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/Contents.json
  51. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alertTips.imageset/Contents.json
  52. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alertTips.imageset/image_alertTips@2x.png
  53. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alertTips.imageset/image_alertTips@3x.png
  54. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_camera.imageset/Contents.json
  55. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_camera.imageset/image_alert_camera@2x.png
  56. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_camera.imageset/image_alert_camera@3x.png
  57. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_mic.imageset/Contents.json
  58. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_mic.imageset/image_alert_mic@2x.png
  59. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_mic.imageset/image_alert_mic@3x.png
  60. 18 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h
  61. 29 1
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m
  62. 29 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/kSJXCollectionView.h
  63. 48 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/kSJXCollectionView.m
  64. 1 0
      KulexiuForStudent/KulexiuForStudent/Common/Define/PrefixHeader.pch
  65. 4 1
      KulexiuForStudent/KulexiuForStudent/Common/ThirdPart/FSCalendar/FSCalendarAppearance.h
  66. 15 0
      KulexiuForStudent/KulexiuForStudent/Common/ThirdPart/FSCalendar/FSCalendarAppearance.m
  67. 3 3
      KulexiuForStudent/KulexiuForStudent/Common/ThirdPart/FSCalendar/FSCalendarCell.m
  68. 20 0
      KulexiuForStudent/KulexiuForStudent/Common/Tools/Category/NSObject+KSDateFormatter.h
  69. 20 0
      KulexiuForStudent/KulexiuForStudent/Common/Tools/Category/NSObject+KSDateFormatter.m
  70. 26 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.h
  71. 31 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.m
  72. 545 1
      KulexiuForStudent/KulexiuForStudent/Module/Course/Controller/CourseViewController.m
  73. 32 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/Model/TableCourseModel.h
  74. 183 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/Model/TableCourseModel.m
  75. 32 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/AccompanyCourseCell.h
  76. 220 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/AccompanyCourseCell.m
  77. 196 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/AccompanyCourseCell.xib
  78. 26 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.h
  79. 95 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.m
  80. 215 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.xib
  81. 28 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseNavView.h
  82. 50 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseNavView.m
  83. 76 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseNavView.xib
  84. 25 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/LTSCalendarBottomView.h
  85. 45 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/LTSCalendarBottomView.m
  86. 73 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/LTSCalendarBottomView.xib
  87. 22 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Controller/MyCourseViewController.h
  88. 32 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Controller/MyCourseViewController.m
  89. 29 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/AccompanyLessonModel.h
  90. 162 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/AccompanyLessonModel.m
  91. 27 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/LiveLessonModel.h
  92. 148 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/LiveLessonModel.m
  93. 20 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonBodyView.h
  94. 515 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonBodyView.m
  95. 40 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonSearchView.h
  96. 98 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonSearchView.m
  97. 168 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonSearchView.xib
  98. 21 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLiveCourseCell.h
  99. 90 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLiveCourseCell.m
  100. 198 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLiveCourseCell.xib

+ 196 - 0
KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj

@@ -361,6 +361,29 @@
 		BC0212FB27FC61D30040569F /* KSSegmentControl.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0212FA27FC61D30040569F /* KSSegmentControl.m */; };
 		BC0212FE27FC66AA0040569F /* InstrumentMessageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0212FD27FC66AA0040569F /* InstrumentMessageModel.m */; };
 		BC02130127FC6ADD0040569F /* UIView+SubViewExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02130027FC6ADD0040569F /* UIView+SubViewExtension.m */; };
+		BC1191FF280ED64E00A716F7 /* MyCourseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1191FE280ED64E00A716F7 /* MyCourseViewController.m */; };
+		BC119213280ED6A900A716F7 /* MyLessonBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119200280ED6A600A716F7 /* MyLessonBodyView.m */; };
+		BC119215280ED6A900A716F7 /* MyLiveCourseCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC119203280ED6A700A716F7 /* MyLiveCourseCell.xib */; };
+		BC119216280ED6A900A716F7 /* MyLiveCourseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119204280ED6A700A716F7 /* MyLiveCourseCell.m */; };
+		BC119217280ED6A900A716F7 /* MyLessonSearchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC119206280ED6A700A716F7 /* MyLessonSearchView.xib */; };
+		BC119218280ED6A900A716F7 /* MyLessonSearchView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119209280ED6A800A716F7 /* MyLessonSearchView.m */; };
+		BC11921B280ED6A900A716F7 /* NewClassPopCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC11920F280ED6A900A716F7 /* NewClassPopCell.xib */; };
+		BC11921C280ED6A900A716F7 /* NewClassPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119211280ED6A900A716F7 /* NewClassPopView.m */; };
+		BC11921D280ED6A900A716F7 /* NewClassPopCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119212280ED6A900A716F7 /* NewClassPopCell.m */; };
+		BC119222280ED6F500A716F7 /* LiveLessonModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC11921E280ED6F400A716F7 /* LiveLessonModel.m */; };
+		BC119223280ED6F500A716F7 /* AccompanyLessonModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC11921F280ED6F400A716F7 /* AccompanyLessonModel.m */; };
+		BC11922A280ED8E800A716F7 /* LTSCalendarBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119224280ED8E700A716F7 /* LTSCalendarBottomView.m */; };
+		BC11922B280ED8E800A716F7 /* CourseNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119226280ED8E800A716F7 /* CourseNavView.m */; };
+		BC11922C280ED8E800A716F7 /* LTSCalendarBottomView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC119227280ED8E800A716F7 /* LTSCalendarBottomView.xib */; };
+		BC11922D280ED8E800A716F7 /* CourseNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC119229280ED8E800A716F7 /* CourseNavView.xib */; };
+		BC119230280ED8F900A716F7 /* TableCourseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC11922F280ED8F900A716F7 /* TableCourseModel.m */; };
+		BC119234280ED97C00A716F7 /* CourseForLiveCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119231280ED97B00A716F7 /* CourseForLiveCell.m */; };
+		BC119235280ED97C00A716F7 /* CourseForLiveCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC119232280ED97C00A716F7 /* CourseForLiveCell.xib */; };
+		BC119239280ED98E00A716F7 /* AccompanyCourseCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC119237280ED98E00A716F7 /* AccompanyCourseCell.xib */; };
+		BC11923A280ED98E00A716F7 /* AccompanyCourseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119238280ED98E00A716F7 /* AccompanyCourseCell.m */; };
+		BC119241280ED9E000A716F7 /* AccompanyDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119240280ED9E000A716F7 /* AccompanyDetailViewController.m */; };
+		BC119244280EDA2400A716F7 /* NSObject+KSDateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119243280EDA2400A716F7 /* NSObject+KSDateFormatter.m */; };
+		BC119247280EDA5800A716F7 /* kSJXCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC119245280EDA5800A716F7 /* kSJXCollectionView.m */; };
 		BC28582B2809036D0024697C /* StudentInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC28582A2809036D0024697C /* StudentInfoModel.m */; };
 		BC50171227FC0D5600F8BCBC /* SubjectChooseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC50171127FC0D5600F8BCBC /* SubjectChooseViewController.m */; };
 		BC50171527FC0D8300F8BCBC /* SubjectChooseBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC50171427FC0D8300F8BCBC /* SubjectChooseBodyView.m */; };
@@ -1174,6 +1197,45 @@
 		BC0212FD27FC66AA0040569F /* InstrumentMessageModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstrumentMessageModel.m; sourceTree = "<group>"; };
 		BC0212FF27FC6ADD0040569F /* UIView+SubViewExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+SubViewExtension.h"; sourceTree = "<group>"; };
 		BC02130027FC6ADD0040569F /* UIView+SubViewExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+SubViewExtension.m"; sourceTree = "<group>"; };
+		BC1191FD280ED64E00A716F7 /* MyCourseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyCourseViewController.h; sourceTree = "<group>"; };
+		BC1191FE280ED64E00A716F7 /* MyCourseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyCourseViewController.m; sourceTree = "<group>"; };
+		BC119200280ED6A600A716F7 /* MyLessonBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLessonBodyView.m; sourceTree = "<group>"; };
+		BC119202280ED6A600A716F7 /* MyLessonBodyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLessonBodyView.h; sourceTree = "<group>"; };
+		BC119203280ED6A700A716F7 /* MyLiveCourseCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyLiveCourseCell.xib; sourceTree = "<group>"; };
+		BC119204280ED6A700A716F7 /* MyLiveCourseCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLiveCourseCell.m; sourceTree = "<group>"; };
+		BC119205280ED6A700A716F7 /* MyLiveCourseCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLiveCourseCell.h; sourceTree = "<group>"; };
+		BC119206280ED6A700A716F7 /* MyLessonSearchView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyLessonSearchView.xib; sourceTree = "<group>"; };
+		BC119208280ED6A800A716F7 /* MyLessonSearchView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyLessonSearchView.h; sourceTree = "<group>"; };
+		BC119209280ED6A800A716F7 /* MyLessonSearchView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyLessonSearchView.m; sourceTree = "<group>"; };
+		BC11920E280ED6A900A716F7 /* NewClassPopView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewClassPopView.h; sourceTree = "<group>"; };
+		BC11920F280ED6A900A716F7 /* NewClassPopCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NewClassPopCell.xib; sourceTree = "<group>"; };
+		BC119210280ED6A900A716F7 /* NewClassPopCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewClassPopCell.h; sourceTree = "<group>"; };
+		BC119211280ED6A900A716F7 /* NewClassPopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewClassPopView.m; sourceTree = "<group>"; };
+		BC119212280ED6A900A716F7 /* NewClassPopCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewClassPopCell.m; sourceTree = "<group>"; };
+		BC11921E280ED6F400A716F7 /* LiveLessonModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveLessonModel.m; sourceTree = "<group>"; };
+		BC11921F280ED6F400A716F7 /* AccompanyLessonModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AccompanyLessonModel.m; sourceTree = "<group>"; };
+		BC119220280ED6F500A716F7 /* AccompanyLessonModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccompanyLessonModel.h; sourceTree = "<group>"; };
+		BC119221280ED6F500A716F7 /* LiveLessonModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveLessonModel.h; sourceTree = "<group>"; };
+		BC119224280ED8E700A716F7 /* LTSCalendarBottomView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LTSCalendarBottomView.m; sourceTree = "<group>"; };
+		BC119225280ED8E800A716F7 /* CourseNavView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CourseNavView.h; sourceTree = "<group>"; };
+		BC119226280ED8E800A716F7 /* CourseNavView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CourseNavView.m; sourceTree = "<group>"; };
+		BC119227280ED8E800A716F7 /* LTSCalendarBottomView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LTSCalendarBottomView.xib; sourceTree = "<group>"; };
+		BC119228280ED8E800A716F7 /* LTSCalendarBottomView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LTSCalendarBottomView.h; sourceTree = "<group>"; };
+		BC119229280ED8E800A716F7 /* CourseNavView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CourseNavView.xib; sourceTree = "<group>"; };
+		BC11922E280ED8F800A716F7 /* TableCourseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableCourseModel.h; sourceTree = "<group>"; };
+		BC11922F280ED8F900A716F7 /* TableCourseModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableCourseModel.m; sourceTree = "<group>"; };
+		BC119231280ED97B00A716F7 /* CourseForLiveCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CourseForLiveCell.m; sourceTree = "<group>"; };
+		BC119232280ED97C00A716F7 /* CourseForLiveCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CourseForLiveCell.xib; sourceTree = "<group>"; };
+		BC119233280ED97C00A716F7 /* CourseForLiveCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CourseForLiveCell.h; sourceTree = "<group>"; };
+		BC119236280ED98D00A716F7 /* AccompanyCourseCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccompanyCourseCell.h; sourceTree = "<group>"; };
+		BC119237280ED98E00A716F7 /* AccompanyCourseCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccompanyCourseCell.xib; sourceTree = "<group>"; };
+		BC119238280ED98E00A716F7 /* AccompanyCourseCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AccompanyCourseCell.m; sourceTree = "<group>"; };
+		BC11923F280ED9E000A716F7 /* AccompanyDetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AccompanyDetailViewController.h; sourceTree = "<group>"; };
+		BC119240280ED9E000A716F7 /* AccompanyDetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AccompanyDetailViewController.m; sourceTree = "<group>"; };
+		BC119242280EDA2400A716F7 /* NSObject+KSDateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+KSDateFormatter.h"; sourceTree = "<group>"; };
+		BC119243280EDA2400A716F7 /* NSObject+KSDateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+KSDateFormatter.m"; sourceTree = "<group>"; };
+		BC119245280EDA5800A716F7 /* kSJXCollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kSJXCollectionView.m; sourceTree = "<group>"; };
+		BC119246280EDA5800A716F7 /* kSJXCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kSJXCollectionView.h; sourceTree = "<group>"; };
 		BC2858292809036C0024697C /* StudentInfoModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StudentInfoModel.h; sourceTree = "<group>"; };
 		BC28582A2809036D0024697C /* StudentInfoModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StudentInfoModel.m; sourceTree = "<group>"; };
 		BC50171027FC0D5600F8BCBC /* SubjectChooseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SubjectChooseViewController.h; sourceTree = "<group>"; };
@@ -1739,6 +1801,7 @@
 		275FA1F727E7356A00CFEA2E /* Course */ = {
 			isa = PBXGroup;
 			children = (
+				BC11923B280ED9CC00A716F7 /* AccompanyCourse */,
 				275FA1F827E7356A00CFEA2E /* Controller */,
 				275FA1FB27E7356B00CFEA2E /* Model */,
 				275FA1FC27E7356B00CFEA2E /* View */,
@@ -1758,6 +1821,8 @@
 		275FA1FB27E7356B00CFEA2E /* Model */ = {
 			isa = PBXGroup;
 			children = (
+				BC11922E280ED8F800A716F7 /* TableCourseModel.h */,
+				BC11922F280ED8F900A716F7 /* TableCourseModel.m */,
 			);
 			path = Model;
 			sourceTree = "<group>";
@@ -1765,6 +1830,18 @@
 		275FA1FC27E7356B00CFEA2E /* View */ = {
 			isa = PBXGroup;
 			children = (
+				BC119225280ED8E800A716F7 /* CourseNavView.h */,
+				BC119226280ED8E800A716F7 /* CourseNavView.m */,
+				BC119229280ED8E800A716F7 /* CourseNavView.xib */,
+				BC119228280ED8E800A716F7 /* LTSCalendarBottomView.h */,
+				BC119224280ED8E700A716F7 /* LTSCalendarBottomView.m */,
+				BC119227280ED8E800A716F7 /* LTSCalendarBottomView.xib */,
+				BC119233280ED97C00A716F7 /* CourseForLiveCell.h */,
+				BC119231280ED97B00A716F7 /* CourseForLiveCell.m */,
+				BC119232280ED97C00A716F7 /* CourseForLiveCell.xib */,
+				BC119236280ED98D00A716F7 /* AccompanyCourseCell.h */,
+				BC119238280ED98E00A716F7 /* AccompanyCourseCell.m */,
+				BC119237280ED98E00A716F7 /* AccompanyCourseCell.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -1842,6 +1919,7 @@
 		275FA20327E7356B00CFEA2E /* Mine */ = {
 			isa = PBXGroup;
 			children = (
+				BC1191F9280ED63C00A716F7 /* MineCourse */,
 				27F9031B27E87C2D00C08A19 /* DeviceCheck */,
 				27F9030F27E87C2C00C08A19 /* Networking */,
 				27F9032327E87C2E00C08A19 /* Setting */,
@@ -2135,6 +2213,8 @@
 		277933B627E3249E0010E277 /* Category */ = {
 			isa = PBXGroup;
 			children = (
+				BC119242280EDA2400A716F7 /* NSObject+KSDateFormatter.h */,
+				BC119243280EDA2400A716F7 /* NSObject+KSDateFormatter.m */,
 				277933BD27E3249E0010E277 /* MBProgressHUD+KSShow.h */,
 				277933D727E3249E0010E277 /* MBProgressHUD+KSShow.m */,
 				277933D027E3249E0010E277 /* NSObject+AutoProperty.h */,
@@ -2657,6 +2737,8 @@
 		2779350B27E324A40010E277 /* Base */ = {
 			isa = PBXGroup;
 			children = (
+				BC119246280EDA5800A716F7 /* kSJXCollectionView.h */,
+				BC119245280EDA5800A716F7 /* kSJXCollectionView.m */,
 				2723B64727F15BDB00E0B90B /* KSJXBodyView.h */,
 				2723B64827F15BDC00E0B90B /* KSJXBodyView.m */,
 				2723B63B27F159BA00E0B90B /* KSBaseTableViewController.h */,
@@ -2833,6 +2915,97 @@
 			name = Frameworks;
 			sourceTree = "<group>";
 		};
+		BC1191F9280ED63C00A716F7 /* MineCourse */ = {
+			isa = PBXGroup;
+			children = (
+				BC1191FA280ED63C00A716F7 /* Controller */,
+				BC1191FB280ED63C00A716F7 /* Model */,
+				BC1191FC280ED63C00A716F7 /* View */,
+			);
+			path = MineCourse;
+			sourceTree = "<group>";
+		};
+		BC1191FA280ED63C00A716F7 /* Controller */ = {
+			isa = PBXGroup;
+			children = (
+				BC1191FD280ED64E00A716F7 /* MyCourseViewController.h */,
+				BC1191FE280ED64E00A716F7 /* MyCourseViewController.m */,
+			);
+			path = Controller;
+			sourceTree = "<group>";
+		};
+		BC1191FB280ED63C00A716F7 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+				BC119220280ED6F500A716F7 /* AccompanyLessonModel.h */,
+				BC11921F280ED6F400A716F7 /* AccompanyLessonModel.m */,
+				BC119221280ED6F500A716F7 /* LiveLessonModel.h */,
+				BC11921E280ED6F400A716F7 /* LiveLessonModel.m */,
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		BC1191FC280ED63C00A716F7 /* View */ = {
+			isa = PBXGroup;
+			children = (
+				BC119202280ED6A600A716F7 /* MyLessonBodyView.h */,
+				BC119200280ED6A600A716F7 /* MyLessonBodyView.m */,
+				BC119208280ED6A800A716F7 /* MyLessonSearchView.h */,
+				BC119209280ED6A800A716F7 /* MyLessonSearchView.m */,
+				BC119206280ED6A700A716F7 /* MyLessonSearchView.xib */,
+				BC119205280ED6A700A716F7 /* MyLiveCourseCell.h */,
+				BC119204280ED6A700A716F7 /* MyLiveCourseCell.m */,
+				BC119203280ED6A700A716F7 /* MyLiveCourseCell.xib */,
+				BC11920D280ED6A900A716F7 /* PopView */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		BC11920D280ED6A900A716F7 /* PopView */ = {
+			isa = PBXGroup;
+			children = (
+				BC11920E280ED6A900A716F7 /* NewClassPopView.h */,
+				BC11920F280ED6A900A716F7 /* NewClassPopCell.xib */,
+				BC119210280ED6A900A716F7 /* NewClassPopCell.h */,
+				BC119211280ED6A900A716F7 /* NewClassPopView.m */,
+				BC119212280ED6A900A716F7 /* NewClassPopCell.m */,
+			);
+			path = PopView;
+			sourceTree = "<group>";
+		};
+		BC11923B280ED9CC00A716F7 /* AccompanyCourse */ = {
+			isa = PBXGroup;
+			children = (
+				BC11923C280ED9CC00A716F7 /* Controller */,
+				BC11923D280ED9CC00A716F7 /* Model */,
+				BC11923E280ED9CC00A716F7 /* View */,
+			);
+			path = AccompanyCourse;
+			sourceTree = "<group>";
+		};
+		BC11923C280ED9CC00A716F7 /* Controller */ = {
+			isa = PBXGroup;
+			children = (
+				BC11923F280ED9E000A716F7 /* AccompanyDetailViewController.h */,
+				BC119240280ED9E000A716F7 /* AccompanyDetailViewController.m */,
+			);
+			path = Controller;
+			sourceTree = "<group>";
+		};
+		BC11923D280ED9CC00A716F7 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		BC11923E280ED9CC00A716F7 /* View */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
 		BCB6340A27F6D29500ACFDCF /* Live */ = {
 			isa = PBXGroup;
 			children = (
@@ -3558,6 +3731,7 @@
 				2779355727E324A70010E277 /* KSPremissionAlert.xib in Resources */,
 				2723B5C327F157B100E0B90B /* ChatNavView.xib in Resources */,
 				2723B5BA27F157B100E0B90B /* ChatAddressHeaderView.xib in Resources */,
+				BC119235280ED97C00A716F7 /* CourseForLiveCell.xib in Resources */,
 				2723B62E27F157D500E0B90B /* GroupApplyChooseAllCell.xib in Resources */,
 				275FA23A27E7356B00CFEA2E /* VefiBodyView.xib in Resources */,
 				2723B63227F157D500E0B90B /* GroupSettingBodyView.xib in Resources */,
@@ -3586,12 +3760,14 @@
 				2723B66A27F15CFC00E0B90B /* PhoneChangeBodyView.xib in Resources */,
 				27F9032D27E87C2E00C08A19 /* KSNetworkAlert.xib in Resources */,
 				275FA24527E73E0100CFEA2E /* InstrumentDescView.xib in Resources */,
+				BC11922D280ED8E800A716F7 /* CourseNavView.xib in Resources */,
 				BCB6348127F6D29600ACFDCF /* LiveSeatApplyCell.xib in Resources */,
 				2723B62D27F157D500E0B90B /* GroupApplyMemberCell.xib in Resources */,
 				BCB6347427F6D29600ACFDCF /* BaseEmoji.plist in Resources */,
 				27F9032E27E87C2E00C08A19 /* DeviceCheckView.xib in Resources */,
 				275FA23727E7356B00CFEA2E /* LoginBodyView.xib in Resources */,
 				BCB6355927F6D2A300ACFDCF /* class_stop.mp3 in Resources */,
+				BC119239280ED98E00A716F7 /* AccompanyCourseCell.xib in Resources */,
 				27F9033C27E87FE100C08A19 /* MineBodyView.xib in Resources */,
 				27F9032B27E87C2E00C08A19 /* NetworkBodyView.xib in Resources */,
 				2779358F27E324A80010E277 /* WMPlayer.bundle in Resources */,
@@ -3599,13 +3775,17 @@
 				275FA23827E7356B00CFEA2E /* FirstSettingBodyView.xib in Resources */,
 				2723B63927F157D500E0B90B /* GroupMemberListCell.xib in Resources */,
 				BC0212F827FC4A080040569F /* SubjectImageCell.xib in Resources */,
+				BC11921B280ED6A900A716F7 /* NewClassPopCell.xib in Resources */,
 				2723B66E27F15CFC00E0B90B /* PhoneCheckBodyView.xib in Resources */,
+				BC119217280ED6A900A716F7 /* MyLessonSearchView.xib in Resources */,
 				2723B5C527F157B100E0B90B /* ContractListCell.xib in Resources */,
 				27F9033727E87C8B00C08A19 /* MineNavView.xib in Resources */,
+				BC119215280ED6A900A716F7 /* MyLiveCourseCell.xib in Resources */,
 				BC50171727FC0D8E00F8BCBC /* SubjectChooseBodyView.xib in Resources */,
 				BCB6359D27F6D2AB00ACFDCF /* tock.wav in Resources */,
 				275E8AB327E18F8800DD3F6E /* Main.storyboard in Resources */,
 				277935B127E324A90010E277 /* mss_browseLoading@2x.png in Resources */,
+				BC11922C280ED8E800A716F7 /* LTSCalendarBottomView.xib in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3862,13 +4042,16 @@
 				BCB6347327F6D29600ACFDCF /* KSChatEmojiCollectionCell.m in Sources */,
 				2723B62327F157D500E0B90B /* LFPopupMenuDefaultConfig.m in Sources */,
 				2779351627E324A60010E277 /* NSMutableArray+KSSafe.m in Sources */,
+				BC119247280EDA5800A716F7 /* kSJXCollectionView.m in Sources */,
 				2779358927E324A80010E277 /* CoinModel.m in Sources */,
 				275FA1EA27E7351900CFEA2E /* KSRCIMDataSource.m in Sources */,
+				BC119241280ED9E000A716F7 /* AccompanyDetailViewController.m in Sources */,
 				BCB6346F27F6D29600ACFDCF /* LiveroomTimeManager.m in Sources */,
 				2779359C27E324A80010E277 /* TZProgressView.m in Sources */,
 				27F9033627E87C8B00C08A19 /* MineNavView.m in Sources */,
 				BC50171527FC0D8300F8BCBC /* SubjectChooseBodyView.m in Sources */,
 				2723B62727F157D500E0B90B /* GroupMemberViewController.m in Sources */,
+				BC119216280ED6A900A716F7 /* MyLiveCourseCell.m in Sources */,
 				2779353727E324A60010E277 /* UIImage+Color.m in Sources */,
 				2779353127E324A60010E277 /* NSString+Extension.m in Sources */,
 				2779353F27E324A60010E277 /* UIView+KSLayer.m in Sources */,
@@ -3914,10 +4097,12 @@
 				2779353327E324A60010E277 /* UIScreen+Extend.m in Sources */,
 				2723B67E27F15D3D00E0B90B /* ModifyPhoneCheckController.m in Sources */,
 				2779353A27E324A60010E277 /* UILabel+QWTopLeftLabel.m in Sources */,
+				BC119213280ED6A900A716F7 /* MyLessonBodyView.m in Sources */,
 				BCB6354227F6D2A300ACFDCF /* VideoListView.m in Sources */,
 				2779359A27E324A80010E277 /* TZPhotoPreviewController.m in Sources */,
 				2779355E27E324A70010E277 /* KSAudioRecordFileManager.m in Sources */,
 				2779357A27E324A70010E277 /* PIckView.m in Sources */,
+				BC119234280ED97C00A716F7 /* CourseForLiveCell.m in Sources */,
 				BCB6346027F6D29600ACFDCF /* KSLiveChatroomKickOut.m in Sources */,
 				2779354127E324A60010E277 /* UIView+ShowProgress.m in Sources */,
 				BCB6346627F6D29600ACFDCF /* KSLiveChatroomUserQuit.m in Sources */,
@@ -3928,6 +4113,7 @@
 				277935A927E324A80010E277 /* MSSBrowseActionSheet.m in Sources */,
 				275FA1E027E7351900CFEA2E /* RecordCheckManager.m in Sources */,
 				2779355627E324A70010E277 /* KSPremissionAlert.m in Sources */,
+				BC119230280ED8F900A716F7 /* TableCourseModel.m in Sources */,
 				BCB6353827F6D2A300ACFDCF /* TipMessageCell.m in Sources */,
 				2779352827E324A60010E277 /* UIColor+Extend.m in Sources */,
 				2779357627E324A70010E277 /* ShoppCatView.m in Sources */,
@@ -3982,6 +4168,7 @@
 				2723B5CF27F157BE00E0B90B /* GroupMemberModel.m in Sources */,
 				2723B62A27F157D500E0B90B /* GroupSettingViewController.m in Sources */,
 				2779359127E324A80010E277 /* FastForwardView.m in Sources */,
+				BC119222280ED6F500A716F7 /* LiveLessonModel.m in Sources */,
 				2723B63C27F159BA00E0B90B /* KSBaseTableViewController.m in Sources */,
 				2779358B27E324A80010E277 /* KLTNavigationController.m in Sources */,
 				27F9033127E87C2E00C08A19 /* DeviceCheckView.m in Sources */,
@@ -4010,6 +4197,7 @@
 				275FA1ED27E7351900CFEA2E /* KSUpdateManager.m in Sources */,
 				BCB6355727F6D2A300ACFDCF /* HTTPResult.m in Sources */,
 				BC0212FB27FC61D30040569F /* KSSegmentControl.m in Sources */,
+				BC119223280ED6F500A716F7 /* AccompanyLessonModel.m in Sources */,
 				277935B227E324A90010E277 /* UIView+MSSLayout.m in Sources */,
 				275FA1E427E7351900CFEA2E /* KSWebNavView.m in Sources */,
 				2779356D27E324A70010E277 /* StoreShopCaterview.m in Sources */,
@@ -4023,6 +4211,7 @@
 				275FA1E727E7351900CFEA2E /* KSWebSocketManager.m in Sources */,
 				277935AE27E324A80010E277 /* MSSBrowseRemindView.m in Sources */,
 				2779356A27E324A70010E277 /* YKNodeModel.m in Sources */,
+				BC119244280EDA2400A716F7 /* NSObject+KSDateFormatter.m in Sources */,
 				277935CE27E324A90010E277 /* ALCalendarConfig.m in Sources */,
 				2779354327E324A60010E277 /* UIButton+HasChooseImage.m in Sources */,
 				2779355927E324A70010E277 /* GRCreateManager.m in Sources */,
@@ -4032,6 +4221,7 @@
 				BCB6348227F6D29600ACFDCF /* SeatContentView.m in Sources */,
 				2723B68227F15D3D00E0B90B /* ModifyPhoneChangeController.m in Sources */,
 				277935C827E324A90010E277 /* TADotView.m in Sources */,
+				BC1191FF280ED64E00A716F7 /* MyCourseViewController.m in Sources */,
 				BCB635A927F6D93300ACFDCF /* KSChatVideoView.m in Sources */,
 				2779353027E324A60010E277 /* NSDate+Extension.m in Sources */,
 				BCB6356627F6D2A300ACFDCF /* DeviceMessage.m in Sources */,
@@ -4069,6 +4259,7 @@
 				2779351827E324A60010E277 /* NSObject+KSImpChangeTool.m in Sources */,
 				2779359D27E324A80010E277 /* TZImageManager.m in Sources */,
 				2723B5BE27F157B100E0B90B /* ChatNavView.m in Sources */,
+				BC119218280ED6A900A716F7 /* MyLessonSearchView.m in Sources */,
 				BCB6354C27F6D2A300ACFDCF /* VideoMaskView.m in Sources */,
 				2723B66D27F15CFC00E0B90B /* ModifyNameBodyView.m in Sources */,
 				275FA23327E7356B00CFEA2E /* VefiCodeLoginController.m in Sources */,
@@ -4084,6 +4275,7 @@
 				27F9033A27E87FD500C08A19 /* MineBodyView.m in Sources */,
 				275FA1EC27E7351900CFEA2E /* BaseViewController.m in Sources */,
 				BCB6353427F6D2A300ACFDCF /* InputBarControl.m in Sources */,
+				BC11922B280ED8E800A716F7 /* CourseNavView.m in Sources */,
 				275FA1DB27E7351900CFEA2E /* UINavigationController+KSNavigationBar.m in Sources */,
 				2779352127E324A60010E277 /* NSMutableAttributedString+CZHExtention.m in Sources */,
 				277935C727E324A90010E277 /* SDCollectionViewCell.m in Sources */,
@@ -4092,9 +4284,11 @@
 				275FA23127E7356B00CFEA2E /* FirstSettingViewController.m in Sources */,
 				BCB6355827F6D2A300ACFDCF /* NormalAlertView.m in Sources */,
 				275FA1DD27E7351900CFEA2E /* KSBaseModel.m in Sources */,
+				BC11922A280ED8E800A716F7 /* LTSCalendarBottomView.m in Sources */,
 				BCB6353E27F6D2A300ACFDCF /* TimeStampMessage.m in Sources */,
 				2779354027E324A60010E277 /* UIImage+Property.m in Sources */,
 				2779356627E324A70010E277 /* ShopMessBtn.m in Sources */,
+				BC11921D280ED6A900A716F7 /* NewClassPopCell.m in Sources */,
 				277935B727E324A90010E277 /* FSCalendarStickyHeader.m in Sources */,
 				2779356927E324A70010E277 /* YKMultiLevelTableView.m in Sources */,
 				BCB6354B27F6D2A300ACFDCF /* MainContainerView.m in Sources */,
@@ -4138,6 +4332,7 @@
 				BCB6355127F6D2A300ACFDCF /* LoginHelper.m in Sources */,
 				2723B5C127F157B100E0B90B /* ContractListCell.m in Sources */,
 				275FA1E527E7351900CFEA2E /* KSAccompanyWebViewController.m in Sources */,
+				BC11923A280ED98E00A716F7 /* AccompanyCourseCell.m in Sources */,
 				2779354A27E324A60010E277 /* UIImage+Resize.m in Sources */,
 				2723B5A327F1578300E0B90B /* KSChatListViewController.m in Sources */,
 				2723B68427F15D3D00E0B90B /* AddressViewController.m in Sources */,
@@ -4179,6 +4374,7 @@
 				277935B527E324A90010E277 /* FSCalendarDelegationFactory.m in Sources */,
 				BCB6353927F6D2A300ACFDCF /* MessageCell.m in Sources */,
 				BCB6354027F6D2A300ACFDCF /* ClassroomTitleView.m in Sources */,
+				BC11921C280ED6A900A716F7 /* NewClassPopView.m in Sources */,
 				BCB6359627F6D2AB00ACFDCF /* LocalRenderManager.m in Sources */,
 				2723B66927F15CFC00E0B90B /* PhoneChangeBodyView.m in Sources */,
 				27F9033227E87C2E00C08A19 /* SettingViewController.m in Sources */,

BIN
KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/UserInterfaceState.xcuserstate


+ 32 - 0
KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -52,5 +52,37 @@
             landmarkType = "7">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "717EAF05-8918-413E-9C75-56859D0E716D"
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "KulexiuForStudent/Module/Course/Controller/CourseViewController.m"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "290"
+            endingLineNumber = "290"
+            landmarkName = "-loadMonthCourse:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "AC09EF7E-D41B-4CB1-8763-5BA5699C3941"
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "KulexiuForStudent/Module/Course/Controller/CourseViewController.m"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "304"
+            endingLineNumber = "304"
+            landmarkName = "-loadMonthCourse:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 6 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/accompany_edit.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "accompany_edit@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "accompany_edit@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/accompany_edit.imageset/accompany_edit@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/accompany_edit.imageset/accompany_edit@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrangement_homework.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "arrangement_homework@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "arrangement_homework@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrangement_homework.imageset/arrangement_homework@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrangement_homework.imageset/arrangement_homework@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_down.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "arrow_down@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "arrow_down@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_down.imageset/arrow_down@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_down.imageset/arrow_down@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_up.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "arrow_up@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "arrow_up@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_up.imageset/arrow_up@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/arrow_up.imageset/arrow_up@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_chat.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "course_chat@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "course_chat@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_chat.imageset/course_chat@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_chat.imageset/course_chat@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_nav.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "course_nav@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "course_nav@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_nav.imageset/course_nav@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_nav.imageset/course_nav@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_time.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "course_time@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "course_time@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_time.imageset/course_time@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_time.imageset/course_time@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/down_arrow.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "down_arrow@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "down_arrow@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/down_arrow.imageset/down_arrow@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/down_arrow.imageset/down_arrow@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homeworkVideo_placeholder.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "homeworkVideo_placeholder@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "homeworkVideo_placeholder@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homeworkVideo_placeholder.imageset/homeworkVideo_placeholder@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homeworkVideo_placeholder.imageset/homeworkVideo_placeholder@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_eva.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "homework_eva@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "homework_eva@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_eva.imageset/homework_eva@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_eva.imageset/homework_eva@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_placeholder.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "homework_placeholder@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "homework_placeholder@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_placeholder.imageset/homework_placeholder@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/homework_placeholder.imageset/homework_placeholder@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "lesson_Live@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "lesson_Live@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/lesson_Live@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/lesson_Live@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/student_eva_placeholder.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "student_eva_placeholder@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "student_eva_placeholder@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/student_eva_placeholder.imageset/student_eva_placeholder@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/student_eva_placeholder.imageset/student_eva_placeholder@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/teacher_eva_placeholder.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "teacher_eva_placeholder@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "teacher_eva_placeholder@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/teacher_eva_placeholder.imageset/teacher_eva_placeholder@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/teacher_eva_placeholder.imageset/teacher_eva_placeholder@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/up_arrow.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "up_arrow@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "up_arrow@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/up_arrow.imageset/up_arrow@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/up_arrow.imageset/up_arrow@3x.png


+ 6 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alertTips.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "image_alertTips@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "image_alertTips@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alertTips.imageset/image_alertTips@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alertTips.imageset/image_alertTips@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_camera.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "image_alert_camera@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "image_alert_camera@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_camera.imageset/image_alert_camera@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_camera.imageset/image_alert_camera@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_mic.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "image_alert_mic@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "image_alert_mic@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_mic.imageset/image_alert_mic@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/CustomAlert/image_alert_mic.imageset/image_alert_mic@3x.png


+ 18 - 0
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h

@@ -344,6 +344,24 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param success 成功
 /// @param faliure 失败
 + (void)LiveroomQuit:(NSString *)post success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+#pragma mark ----- 课表
+// /api-student/courseSchedule/queryCourseScheduleStudent
+/// 课表日历
+/// @param post post
+/// @param classMonth 月份
+/// @param success 成功
+/// @param faliure 失败
++ (void)queryCourseSchedule:(NSString *)post classMonth:(NSString *)classMonth success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+// /api-student/courseSchedule/queryCourseUser
+/// 查询日期课程
+/// @param post post
+/// @param classDate 日期
+/// @param success 成功
+/// @param faliure 失败
++ (void)queryCourseForDay:(NSString *)post classDate:(NSString *)classDate success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 29 - 1
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m

@@ -781,7 +781,6 @@
 /// @param faliure 失败
 + (void)LiveroomQuit:(NSString *)post success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
-    
     NSString *url = [NSString stringWithFormat:@"%@%@", SEALCLASSHOST, @"/api-student/liveRoom/syncUserStatus"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:@"iOS" forKey:@"os"];
@@ -789,4 +788,33 @@
     [parm setValue:UserDefault(UIDKey) forKey:@"userid"];
     [self request:post andWithUrl:url and:@[parm] success:success faliure:faliure];
 }
+
+#pragma mark ----- 课表
+// /api-student/courseSchedule/queryCourseScheduleStudent
+/// 课表日历
+/// @param post post
+/// @param classMonth 月份
+/// @param success 成功
+/// @param faliure 失败
++ (void)queryCourseSchedule:(NSString *)post classMonth:(NSString *)classMonth success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-student/courseSchedule/queryCourseScheduleStudent"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:classMonth forKey:@"classMonth"];
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
+
+// /api-student/courseSchedule/queryCourseUser
+/// 查询日期课程
+/// @param post post
+/// @param classDate 日期
+/// @param success 成功
+/// @param faliure 失败
++ (void)queryCourseForDay:(NSString *)post classDate:(NSString *)classDate success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-student/courseSchedule/queryCourseUser"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:classDate forKey:@"classDate"];
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
 @end

+ 29 - 0
KulexiuForStudent/KulexiuForStudent/Common/Base/kSJXCollectionView.h

@@ -0,0 +1,29 @@
+//
+//  kSJXCollectionView.h
+//  KulexiuForTeacher
+//
+//  Created by Kyle on 2022/3/29.
+//
+
+#import <UIKit/UIKit.h>
+#import "JXPagerView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface kSJXCollectionView : UIView <JXPagerViewListViewDelegate>
+
+@property (nonatomic, weak) UINavigationController *naviController;
+
+@property (nonatomic, strong) UICollectionView *collectionView;
+
+@property (nonatomic, assign) NSInteger selectIndex;
+
+@property (nonatomic, assign) BOOL isHeaderRefreshed;   //默认为YES
+
+@property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView);
+@property (nonatomic, strong) NSIndexPath *lastSelectedIndexPath;
+- (void)beginFirstRefresh;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 48 - 0
KulexiuForStudent/KulexiuForStudent/Common/Base/kSJXCollectionView.m

@@ -0,0 +1,48 @@
+//
+//  kSJXCollectionView.m
+//  KulexiuForTeacher
+//
+//  Created by Kyle on 2022/3/29.
+//
+
+#import "kSJXCollectionView.h"
+
+@implementation kSJXCollectionView
+
+- (void)beginFirstRefresh {
+    
+}
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+    !self.scrollCallback ?: self.scrollCallback(scrollView);
+}
+#pragma mark - JXPagingViewListViewDelegate
+
+- (UIView *)listView {
+    return self;
+}
+
+- (UIScrollView *)listScrollView {
+    return self.collectionView;
+}
+
+- (void)listViewDidScrollCallback:(void (^)(UIScrollView *))callback {
+    self.scrollCallback = callback;
+}
+
+- (void)listDidAppear {
+    NSLog(@"listDidAppear");
+}
+
+- (void)listDidDisappear {
+    NSLog(@"listDidDisappear");
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Common/Define/PrefixHeader.pch

@@ -32,6 +32,7 @@
 #import "KSGifRefreshFooter.h"
 
 #import "UIView+SubViewExtension.h"
+#import "NSObject+KSDateFormatter.h"
 
 // 加密使用 NSString+MD5
 #define DEFAULT_SALT (@"D5sIlPU2")

+ 4 - 1
KulexiuForStudent/KulexiuForStudent/Common/ThirdPart/FSCalendar/FSCalendarAppearance.h

@@ -127,7 +127,10 @@ typedef NS_OPTIONS(NSUInteger, FSCalendarCaseOptions) {
  * highlight day text color
  */
 @property (strong, nonatomic) UIColor *titleHightlightColor;
-
+/**
+ * highlight background  color
+ */
+@property (strong, nonatomic) UIColor *backgoundHightlightColor;
 /**
  * The day text color for today in the calendar.
  */

+ 15 - 0
KulexiuForStudent/KulexiuForStudent/Common/ThirdPart/FSCalendar/FSCalendarAppearance.m

@@ -47,6 +47,7 @@
         _backgroundColors[@(FSCalendarCellStateDisabled)]    = [UIColor clearColor];
         _backgroundColors[@(FSCalendarCellStatePlaceholder)] = [UIColor clearColor];
         _backgroundColors[@(FSCalendarCellStateToday)]       = FSCalendarStandardTodayColor;
+        _backgroundColors[@(FSCalendarCellStateHightlight)] = [UIColor clearColor];
         
         _titleColors = [NSMutableDictionary dictionaryWithCapacity:5];
         _titleColors[@(FSCalendarCellStateNormal)]      = [UIColor blackColor];
@@ -54,6 +55,7 @@
         _titleColors[@(FSCalendarCellStateDisabled)]    = [UIColor grayColor];
         _titleColors[@(FSCalendarCellStatePlaceholder)] = [UIColor lightGrayColor];
         _titleColors[@(FSCalendarCellStateToday)]       = [UIColor whiteColor];
+        _titleColors[@(FSCalendarCellStateHightlight)]  = [UIColor whiteColor];
         
         _subtitleColors = [NSMutableDictionary dictionaryWithCapacity:5];
         _subtitleColors[@(FSCalendarCellStateNormal)]      = [UIColor darkGrayColor];
@@ -186,6 +188,19 @@
     return _titleColors[@(FSCalendarCellStateHightlight)];
 }
 
+- (void)setBackgoundHightlightColor:(UIColor *)backgoundHightlightColor {
+    if (backgoundHightlightColor) {
+        _backgroundColors[@(FSCalendarCellStateHightlight)] = backgoundHightlightColor;
+    } else {
+        [_backgroundColors removeObjectForKey:@(FSCalendarCellStateHightlight)];
+    }
+    [self.calendar configureAppearance];
+}
+
+- (UIColor *)backgoundHightlightColor {
+    return _backgroundColors[@(FSCalendarCellStateHightlight)];
+}
+
 - (void)setTitleTodayColor:(UIColor *)color
 {
     if (color) {

+ 3 - 3
KulexiuForStudent/KulexiuForStudent/Common/ThirdPart/FSCalendar/FSCalendarCell.m

@@ -285,6 +285,9 @@
     if (self.selected) {
         return self.preferredFillSelectionColor ?: [self colorForCurrentStateInDictionary:_appearance.backgroundColors];
     }
+    if (!self.dateIsToday && _isHightlight) {
+        return _appearance.backgroundColors[@(FSCalendarCellStateHightlight)];
+    }
     return self.preferredFillDefaultColor ?: [self colorForCurrentStateInDictionary:_appearance.backgroundColors];
 }
 
@@ -296,9 +299,6 @@
     if (!self.dateIsToday && _isHightlight) {
         return _appearance.titleColors[@(FSCalendarCellStateHightlight)];
     }
-    else if (!self.dateIsToday && _isHightlight == NO) {
-        return _appearance.titleColors[@(FSCalendarCellStateNormal)];
-    }
     else {
         return self.preferredTitleDefaultColor ?: [self colorForCurrentStateInDictionary:_appearance.titleColors];
 

+ 20 - 0
KulexiuForStudent/KulexiuForStudent/Common/Tools/Category/NSObject+KSDateFormatter.h

@@ -0,0 +1,20 @@
+//
+//  NSObject+KSDateFormatter.h
+//  TeacherDaya
+//
+//  Created by 王智 on 2022/4/7.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NSObject (KSDateFormatter)
+
+/// 获取NSDateFormatter shanghai
++ (NSDateFormatter *)getDateformatter;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 20 - 0
KulexiuForStudent/KulexiuForStudent/Common/Tools/Category/NSObject+KSDateFormatter.m

@@ -0,0 +1,20 @@
+//
+//  NSObject+KSDateFormatter.m
+//  TeacherDaya
+//
+//  Created by 王智 on 2022/4/7.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "NSObject+KSDateFormatter.h"
+
+@implementation NSObject (KSDateFormatter)
+
++ (NSDateFormatter *)getDateformatter {
+    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+    dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
+    [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"zh_CN"]];
+    return dateFormatter;
+}
+
+@end

+ 26 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.h

@@ -0,0 +1,26 @@
+//
+//  AccompanyDetailViewController.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/4/19.
+//
+
+#import "KSBaseViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+/// 陪练课详情
+@interface AccompanyDetailViewController : KSBaseViewController
+
+@property (nonatomic, strong) NSString *courseId;
+
+@property (nonatomic, strong) NSString *courseGroupId;
+
+@property (nonatomic, strong) NSString *studentId;
+
+@property (nonatomic, assign) NSInteger joinRoomBeforeTime; // 上课开始时间
+
+@property (nonatomic, assign) NSInteger quitRomeEndTime;    // 下课截止时间
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 31 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.m

@@ -0,0 +1,31 @@
+//
+//  AccompanyDetailViewController.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/4/19.
+//
+
+#import "AccompanyDetailViewController.h"
+
+@interface AccompanyDetailViewController ()
+
+@end
+
+@implementation AccompanyDetailViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+    // Get the new view controller using [segue destinationViewController].
+    // Pass the selected object to the new view controller.
+}
+*/
+
+@end

+ 545 - 1
KulexiuForStudent/KulexiuForStudent/Module/Course/Controller/CourseViewController.m

@@ -6,8 +6,53 @@
 //
 
 #import "CourseViewController.h"
+#import "FSCalendar.h"
+#import "CourseNavView.h"
+#import "LTSCalendarBottomView.h"
+#import "KSFullDatePicker.h"
+#import "TableCourseModel.h"
+#import "KSChatConversationViewController.h"
+#import "KSEnterLiveroomManager.h"
+#import "KSBaseWKWebViewController.h"
+#import "AccompanyCourseCell.h"
+#import "CourseForLiveCell.h"
+#import "AccompanyDetailViewController.h"
 
-@interface CourseViewController ()
+@interface CourseViewController ()<UITableViewDataSource,UITableViewDelegate,FSCalendarDataSource,FSCalendarDelegate,UIGestureRecognizerDelegate>
+{
+    void * _KVOContext;
+}
+@property (nonatomic, strong) CourseNavView *navHeadView;
+
+@property (nonatomic, strong) NSString *chooseMonth;
+
+@property (nonatomic, strong) NSString *chooseDay;
+
+@property (nonatomic,strong) FSCalendar *calendar;
+
+@property (strong, nonatomic) NSCalendar *gregorian;
+
+@property (nonatomic, strong) UITableView *tableView;
+
+@property (strong, nonatomic) UIPanGestureRecognizer *scopeGesture;
+
+@property (strong, nonatomic) NSDateFormatter *dateFormatter;
+
+@property (nonatomic, strong) LTSCalendarBottomView *calendarBottom;
+
+@property (nonatomic, assign) BOOL cancleRequest;
+
+@property (nonatomic, strong) KSFullDatePicker *datePicker;
+
+@property (nonatomic, assign) BOOL isPickerChoose; // 是否选择的月份
+
+@property (nonatomic, assign) NSInteger practiceStartTime;  // 陪练课开课前可进入时间配置(分钟)
+
+@property (nonatomic, assign) NSInteger practiceEndTime;    // 陪练课结束后退出时间配置(分钟)
+
+@property (nonatomic, assign) NSInteger liveStartTime;      // 直播课开课前可进入时间配置(分钟)
+
+@property (nonatomic, assign) NSInteger liveEndTime;        // 直播课结束后退出时间配置(分钟)
 
 @end
 
@@ -16,8 +61,507 @@
 - (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
+    self.ks_prefersNavigationBarHidden = YES;
+    [self configUI];
+    [self loadCalendarInfo];
 }
 
+- (void)loadCalendarInfo {
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM"];
+    NSDate *date = [NSDate date];
+    self.chooseMonth = [formatter stringFromDate:date];
+    [formatter setDateFormat:@"yyyy-MM-dd"];
+    self.chooseDay = [NSString stringWithFormat:@"%@ 00:00:00", [formatter stringFromDate:date]];
+    [self.calendar selectDate:date];
+    
+    // title  显示
+    [formatter setDateFormat:@"yyyy年MM月"];
+    [self.navHeadView.navTitle setText:[formatter stringFromDate:date]];
+    
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    [self loadMonthCourse:self.chooseMonth];
+    if (![NSString isEmptyString:self.chooseDay]) {
+        [self getCourseByDate:self.chooseDay];
+    }
+}
+
+- (void)configUI {
+    [self.view addSubview:self.navHeadView];
+    [self.navHeadView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.mas_equalTo(self.view);
+        make.height.mas_equalTo(kNaviBarHeight);
+    }];
+    
+    [self.scrollView mas_remakeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.navHeadView.mas_bottom);
+        make.bottom.mas_equalTo(self.view.mas_bottom);
+    }];
+    
+    UIView *containerView = [[UIView alloc] initWithFrame:CGRectZero];
+    containerView.backgroundColor = [UIColor clearColor];
+    [self.scrollView addSubview:containerView];
+    [containerView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.edges.mas_equalTo(self.scrollView);
+        make.width.mas_equalTo(self.scrollView);
+    }];
+    
+    self.calendar = [[FSCalendar alloc] init];
+    [self configCalendar];
+    [containerView addSubview:self.calendar];
+    [self.calendar mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(containerView);
+        make.top.mas_equalTo(containerView.mas_top);
+        make.height.mas_equalTo(300);
+    }];
+    self.calendarBottom = [LTSCalendarBottomView shareInstance];
+    MJWeakSelf;
+    [self.calendarBottom changeDisplay:^{
+        [weakSelf changeDisplay];
+    }];
+    [containerView addSubview:self.calendarBottom];
+    [self.calendarBottom mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(containerView);
+        make.top.mas_equalTo(self.calendar.mas_bottom);
+        make.height.mas_equalTo(40);
+    }];
+    
+    [containerView addSubview:self.tableView];
+    CGFloat tableHeight = kScreenHeight - kNaviBarHeight - kTabBarHeight - 300 - 40;
+    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.calendarBottom.mas_bottom);
+        make.height.mas_equalTo(tableHeight);
+    }];
+    [containerView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.bottom.mas_equalTo(self.tableView.mas_bottom);
+    }];
+    
+    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self.calendar action:@selector(handleScopeGesture:)];
+    panGesture.delegate = self;
+    panGesture.minimumNumberOfTouches = 1;
+    panGesture.maximumNumberOfTouches = 2;
+    [self.scrollView addGestureRecognizer:panGesture];
+    self.scopeGesture = panGesture;
+    [self.tableView.panGestureRecognizer requireGestureRecognizerToFail:panGesture];
+    self.scrollView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+        [weakSelf.calendar setToday:[NSDate date]];
+        [weakSelf loadMonthCourse:weakSelf.chooseMonth];
+        if (![NSString isEmptyString:weakSelf.chooseDay]) {
+            [weakSelf getCourseByDate:weakSelf.chooseDay];
+        }
+    }];
+    if (@available(iOS 11.0, *)) {
+        self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+    } else {
+        // Fallback on earlier versions
+        self.automaticallyAdjustsScrollViewInsets = NO;
+    }
+}
+
+- (void)endRefresh {
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        [self.scrollView.mj_header endRefreshing];
+    });
+}
+
+
+#pragma mark ---- calender action
+
+// 收起或展开日历
+- (void)changeDisplay {
+    FSCalendarScope selectedScope = self.calendar.scope ==  FSCalendarScopeMonth ?  FSCalendarScopeWeek : FSCalendarScopeMonth;
+    [self.calendar setScope:selectedScope animated:YES];
+    NSString *imgName = selectedScope == FSCalendarScopeWeek ? @"arrow_down" : @"arrow_up";
+    [self.calendarBottom.arrowImage setImage:[UIImage imageNamed:imgName]];
+    [self.calendar reloadData];
+}
+
+- (void)configCalendar {
+    self.calendar.backgroundColor = [UIColor whiteColor];
+    self.calendar.appearance.titleFont = [UIFont systemFontOfSize:14.0f weight:UIFontWeightMedium];
+    self.calendar.appearance.titleDefaultColor = HexRGB(0x444444);
+    self.calendar.appearance.titleTodayColor = HexRGB(0x444444);
+    self.calendar.appearance.titleSelectionColor = [UIColor whiteColor];
+    self.calendar.appearance.selectionColor = THEMECOLOR;
+    self.calendar.appearance.weekdayFont = [UIFont systemFontOfSize:14.0f];
+    self.calendar.appearance.weekdayTextColor = HexRGB(0x777777);
+    self.calendar.appearance.titleWeekendColor = THEMECOLOR;
+    self.calendar.appearance.todaySelectionColor = THEMECOLOR;
+    self.calendar.appearance.todayColor = [UIColor whiteColor];
+    self.calendar.appearance.todayBorderColor = [UIColor whiteColor];
+    self.calendar.appearance.borderRadius = 0.2f;
+    self.calendar.appearance.borderDefaultColor = [UIColor whiteColor];
+    self.calendar.appearance.titleHightlightColor = HexRGB(0x444444);
+    self.calendar.appearance.backgoundHightlightColor = HexRGBAlpha(0xffd7a6, 0.21);
+    self.calendar.appearance.subtitleFont = [UIFont systemFontOfSize:10.0f];
+    self.calendar.appearance.subtitleOffset = CGPointMake(0, 3);
+    self.calendar.appearance.subtitleTodayColor = HexRGB(0xff6363);
+    self.calendar.appearance.subtitleDefaultColor = HexRGB(0xff6363);
+    self.calendar.appearance.subtitleSelectionColor = [UIColor whiteColor];
+    self.calendar.dataSource = self;
+    self.calendar.delegate = self;
+    //    self.calendar.firstWeekday = 2;
+    self.calendar.appearance.caseOptions = FSCalendarCaseOptionsWeekdayUsesSingleUpperCase|FSCalendarCaseOptionsHeaderUsesUpperCase;
+    self.calendar.calendarHeaderView.hidden = YES;
+    self.calendar.locale = [NSLocale localeWithLocaleIdentifier:@"zh_CN"];
+    [self.calendar addObserver:self forKeyPath:@"scope" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:_KVOContext];
+    self.calendar.placeholderType = FSCalendarPlaceholderTypeNone;
+    self.calendar.scope = FSCalendarScopeMonth;
+    [self.calendar selectDate:[NSDate date] scrollToDate:YES];
+    [self.calendar reloadData];
+}
+#pragma mark - FSCalendarDataSource
+- (NSString *)calendar:(FSCalendar *)calendar subtitleForDate:(NSDate *)date {
+    
+    // 判断有课的日期显示subtitle
+    if ([calendar.highlightDates containsObject:date]) {
+        return @"有课";
+    }
+    return nil;
+    
+    
+}
+
+#pragma mark - FSCalendarDelegate
+- (void)calendar:(FSCalendar *)calendar boundingRectWillChange:(CGRect)bounds animated:(BOOL)animated
+{
+    [calendar mas_updateConstraints:^(MASConstraintMaker *make) {
+        make.height.mas_equalTo(bounds.size.height);
+        // Do other updates
+    }];
+    [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
+        make.height.mas_equalTo(kScreenHeight - kTabBarHeight - bounds.size.height - kNaviBarHeight - 40);
+    }];
+    [self.view layoutIfNeeded];
+}
+- (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition
+{
+    NSLog(@"did select date %@",[self.dateFormatter stringFromDate:date]);
+    
+    NSMutableArray *selectedDates = [NSMutableArray arrayWithCapacity:calendar.selectedDates.count];
+    [calendar.selectedDates enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        [selectedDates addObject:[self.dateFormatter stringFromDate:obj]];
+    }];
+    self.navHeadView.navTitle.text = [self.dateFormatter stringFromDate:date];
+    NSLog(@"selected dates is %@",selectedDates);
+    if (monthPosition == FSCalendarMonthPositionNext || monthPosition == FSCalendarMonthPositionPrevious) {
+        [calendar setCurrentPage:date animated:YES];
+    }
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM-dd"];
+    NSString *dateStr = [formatter stringFromDate:date];
+    dateStr = [NSString stringWithFormat:@"%@ 00:00:00", dateStr];
+    self.chooseDay = dateStr;
+    [self getCourseByDate:dateStr];
+}
+
+
+
+- (void)calendarCurrentPageDidChange:(FSCalendar *)calendar {
+    if (_isPickerChoose) {
+        _isPickerChoose = NO;
+        return;
+    }
+    self.navHeadView.navTitle.text = [self.dateFormatter stringFromDate:calendar.currentPage];
+    NSLog(@"%s %@", __FUNCTION__, [self.dateFormatter stringFromDate:calendar.currentPage]);
+    // 获取当前月份信息
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM"];
+    NSString *month = [formatter stringFromDate:calendar.currentPage];
+    if (![_chooseMonth isEqualToString:month]) {
+        _chooseMonth = month;
+        [self loadMonthCourse:month];
+    }
+    [formatter setDateFormat:@"yyyy-MM-dd"];
+    NSString *chooseDay = [formatter stringFromDate:calendar.currentPage];
+    self.chooseDay = chooseDay;
+    [self.calendar selectDate:calendar.currentPage];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSString *currentDate = [formatter stringFromDate:calendar.currentPage];
+    [self getCourseByDate:currentDate];
+}
+
+#pragma mark --- 获取当前月份有课日期
+- (void)loadMonthCourse:(NSString *)month {
+    [KSNetworkingManager queryCourseSchedule:KS_POST classMonth:month success:^(NSDictionary * _Nonnull dic) {
+        [self endRefresh];
+        if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+            NSArray *courseArray = [dic arrayValueForKey:@"data"];
+            NSMutableArray *courseDateArray = [NSMutableArray array];
+            for (NSString *dateString in courseArray) {
+                NSString *dateStr = [NSString stringWithFormat:@"%@ %@", dateString, @"00:00:00"];
+                [courseDateArray addObject:dateStr];
+            }
+            self.calendar.highlightDates = courseDateArray;
+            [self.calendar reloadData];
+        }
+        else {
+            [self MBPShow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        [self endRefresh];
+    }];
+}
+
+#pragma mark --- 获取当日课程
+- (void)getCourseByDate:(NSString *)date {
+    [self showhud];
+    [KSNetworkingManager queryCourseForDay:KS_POST classDate:date success:^(NSDictionary * _Nonnull dic) {
+        [self removehub];
+        if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+            // 配置信息
+            NSDictionary *config = [[dic dictionaryValueForKey:@"data"] dictionaryValueForKey:@"sysConfig"];
+            self.practiceStartTime = [config integerValueForKey:@"practiceStartTime"];
+            self.practiceEndTime = [config integerValueForKey:@"practiceEndTime"];
+            self.liveStartTime = [config integerValueForKey:@"liveStartTime"];
+            self.liveEndTime = [config integerValueForKey:@"liveEndTime"];
+            
+            NSArray *courseArray = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"studentList"];
+            NSMutableArray *lessonArray = [NSMutableArray array];
+            for (NSDictionary *parm in courseArray) {
+                TableCourseModel *model = [[TableCourseModel alloc] initWithDictionary:parm];
+                [lessonArray addObject:model];
+            }
+            self.dataArray = [lessonArray mutableCopy];
+        }
+        else {
+            [self MBPShow:MESSAGEKEY];
+        }
+        [self.tableView reloadData];
+    } faliure:^(NSError * _Nonnull error) {
+        [self removehub];
+    }];
+}
+
+#pragma mark - <UIGestureRecognizerDelegate>
+
+// Whether scope gesture should begin
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
+{
+    BOOL shouldBegin = self.tableView.contentOffset.y <= -self.tableView.contentInset.top;
+    if (shouldBegin) {
+        CGPoint velocity = [self.scopeGesture velocityInView:self.view];
+        switch (self.calendar.scope) {
+            case FSCalendarScopeMonth:
+                return velocity.y < 0;
+            case FSCalendarScopeWeek:
+                return velocity.y > 0;
+        }
+    }
+    return shouldBegin;
+}
+
+#pragma mark - KVO
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
+{
+    if (context == _KVOContext) {
+        FSCalendarScope oldScope = [change[NSKeyValueChangeOldKey] unsignedIntegerValue];
+        FSCalendarScope newScope = [change[NSKeyValueChangeNewKey] unsignedIntegerValue];
+        NSLog(@"From %@ to %@",(oldScope==FSCalendarScopeWeek?@"week":@"month"),(newScope==FSCalendarScopeWeek?@"week":@"month"));
+    } else {
+        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+    }
+}
+
+#pragma mark --- table data source
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
+    return 1;
+}
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
+    return  self.dataArray.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    TableCourseModel *model = self.dataArray[indexPath.row];
+    if ([model.courseType isEqualToString:@"PRACTICE"]) { // 陪练课
+        AccompanyCourseCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AccompanyCourseCell"];
+        MJWeakSelf;
+        [cell configWithCourseMessage:model beforeTime:self.practiceStartTime actionCallback:^(ACCOMPANY_TYPE type, TableCourseModel * _Nonnull courseModel) {
+            [weakSelf accompanyLessonAction:type source:courseModel];
+        }];
+        return cell;
+    }
+    else { // 直播课
+        CourseForLiveCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CourseForLiveCell"];
+        MJWeakSelf;
+        [cell configWithSource:model beforeTime:self.liveStartTime callback:^(LIVECOURSEACTION action, TableCourseModel *sourceModel) {
+            [weakSelf liveCourseAction:action source:sourceModel];
+        }];
+        return cell;
+    }
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    TableCourseModel *model = self.dataArray[indexPath.row];
+    if ([model.courseType isEqualToString:@"PRACTICE"]) { // 陪练课
+        [self showAccompanyDetailAction:model];
+    }
+    else { // 直播课详情
+        [self liveCourseDetail:model.courseId courseGroupId:model.courseGoupId];
+    }
+}
+
+- (void)accompanyLessonAction:(ACCOMPANY_TYPE)action source:(TableCourseModel *)source {
+    switch (action) {
+        case ACCOMPANY_TYPE_CHAT:
+        {
+            [self chatAction:source.userId groupName:source.name isGroup:NO];
+        }
+            break;
+        case ACCOMPANY_TYPE_ADJUST:
+        {
+            [self adjustCourseAction:source];
+        }
+            break;
+        case ACCOMPANY_DETAIL:
+        {
+            [self showAccompanyDetailAction:source];
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)adjustCourseAction:(TableCourseModel *)source {
+    KSFullDatePicker *adjustPicker = [[KSFullDatePicker alloc] initWithTitle:@"课程调整" date:[NSDate date] pickMode:KSDATEPICKER_MODE_DAY_TIME selectDateBlock:^(NSString *date) {
+        
+    } cancleBlock:^{
+        
+    }];
+    [adjustPicker show];
+}
+
+- (void)showAccompanyDetailAction:(TableCourseModel *)source {
+    AccompanyDetailViewController *detailVC = [[AccompanyDetailViewController alloc] init];
+    detailVC.courseId = source.courseId;
+    detailVC.courseGroupId = source.courseGoupId;
+    detailVC.studentId = source.userId;
+    [self.navigationController pushViewController:detailVC animated:YES];
+}
+
+- (void)liveCourseAction:(LIVECOURSEACTION)action source:(TableCourseModel *)source {
+    switch (action) {
+        case LIVECOURSEACTION_CHAT:  // 聊天
+        {
+            [self chatAction:source.courseGoupId groupName:source.name isGroup:YES];
+        }
+            break;
+        case LIVECOURSEACTION_LIVEROOM: // 直播课上课
+        {
+            [self liveCourseDetail:source.courseId courseGroupId:source.courseGoupId];
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)chatAction:(NSString *)targetId groupName:(NSString *)targetName isGroup:(BOOL)isGroup {
+    KSChatConversationViewController *conversationVC = [[KSChatConversationViewController alloc] init];
+    conversationVC.targetId = targetId;
+    conversationVC.title = targetName;
+    conversationVC.conversationType = isGroup ? ConversationType_GROUP : ConversationType_PRIVATE;
+    [self.navigationController pushViewController:conversationVC animated:YES];
+}
+
+- (void)liveCourseDetail:(NSString *)courseId courseGroupId:(NSString *)courseGroupId {
+    KSBaseWKWebViewController *ctrl = [[KSBaseWKWebViewController alloc] init];
+    ctrl.url = [NSString stringWithFormat:@"%@%@",WEBHOST,@"/#/openLive"];
+    [self.navigationController pushViewController:ctrl animated:YES];
+}
+
+#pragma mark --- lazying
+- (CourseNavView *)navHeadView {
+    if (!_navHeadView) {
+        _navHeadView = [CourseNavView shareInstance];
+        MJWeakSelf;
+        [_navHeadView chooseNavCallback:^{
+            [weakSelf displayMounthPicker];
+        }];
+        
+    }
+    return _navHeadView;
+}
+
+- (KSFullDatePicker *)datePicker {
+    if (!_datePicker) {
+        _datePicker = [[KSFullDatePicker alloc] initWithTitle:@"" date:[NSDate date] pickMode:KSDATEPICKER_MODE_YEAR_MONTH selectDateBlock:^(NSString *date) {
+            self.navHeadView.navTitle.text = [self getTimeDisplay:date];
+            self.chooseMonth = date;
+            [self resetPickerStatus];
+            [self scrollCalendarToChooseMonth];
+            
+        } cancleBlock:^{
+            [self resetPickerStatus];
+        }];
+    }
+    return _datePicker;
+}
+
+- (void)scrollCalendarToChooseMonth {
+    self.isPickerChoose = YES;
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM"];
+    NSDate *chooseDate = [formatter dateFromString:self.chooseMonth];
+    [formatter setDateFormat:@"yyyy-MM-dd"];
+    self.chooseDay = [NSString stringWithFormat:@"%@ 00:00:00", [formatter stringFromDate:chooseDate]];
+    [self.calendar setCurrentPage:chooseDate animated:YES];
+    [self loadMonthCourse:self.chooseMonth];
+    if (![NSString isEmptyString:self.chooseDay]) {
+        [self.calendar selectDate:chooseDate];
+        [self getCourseByDate:self.chooseDay];
+    }
+}
+
+- (NSString *)getTimeDisplay:(NSString *)chooseMonth {
+    [self.dateFormatter setDateFormat:@"yyyy-MM"];
+    NSDate *chooseDate = [self.dateFormatter dateFromString:chooseMonth];
+    [self.dateFormatter setDateFormat:@"yyyy年MM月"];
+    NSString *displayTime = [self.dateFormatter stringFromDate:chooseDate];
+    return displayTime;
+}
+
+- (void)resetPickerStatus {
+    self.navHeadView.arrowUp = NO;
+}
+
+- (void)displayMounthPicker {
+    [self.datePicker show];
+}
+
+- (NSDateFormatter *)dateFormatter {
+    if (!_dateFormatter) {
+        _dateFormatter = [NSObject getDateformatter];
+        _dateFormatter.dateFormat = @"yyyy年MM月";
+    }
+    return _dateFormatter;
+}
+- (UITableView *)tableView {
+    if (!_tableView) {
+        _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
+        _tableView.delegate = self;
+        _tableView.dataSource = self;
+        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        _tableView.backgroundColor = [UIColor clearColor];
+        _tableView.showsVerticalScrollIndicator = NO;
+        _tableView.showsHorizontalScrollIndicator = NO;
+//        _tableView.rowHeight = UITableViewAutomaticDimension;
+        _tableView.rowHeight = 127.0f;
+        [_tableView registerNib:[UINib nibWithNibName:@"AccompanyCourseCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"AccompanyCourseCell"];
+        [_tableView registerNib:[UINib nibWithNibName:@"CourseForLiveCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CourseForLiveCell"];
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 15)];
+        bottomView.backgroundColor = [UIColor clearColor];
+        _tableView.tableFooterView = bottomView;
+        
+    }
+    return _tableView;
+}
+
+
 /*
 #pragma mark - Navigation
 

+ 32 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/Model/TableCourseModel.h

@@ -0,0 +1,32 @@
+//
+//  TableCourseModel.h
+//
+//  Created by Steven  on 2022/4/19
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface TableCourseModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, strong) NSString *classDate;
+@property (nonatomic, strong) NSString *status;
+@property (nonatomic, strong) NSString *subjectId;
+@property (nonatomic, strong) NSString *courseId;
+@property (nonatomic, strong) NSString *userId;
+@property (nonatomic, strong) NSString *courseGoupId;
+@property (nonatomic, strong) NSString *endTime;
+@property (nonatomic, strong) NSString *subjectName;
+@property (nonatomic, strong) NSString *cover;
+@property (nonatomic, strong) NSString *payCount;
+@property (nonatomic, strong) NSString *courseType;
+@property (nonatomic, strong) NSString *name;
+@property (nonatomic, strong) NSString *startTime;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 183 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/Model/TableCourseModel.m

@@ -0,0 +1,183 @@
+//
+//  TableCourseModel.m
+//
+//  Created by Steven  on 2022/4/19
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import "TableCourseModel.h"
+
+
+NSString *const kTableCourseModelClassDate = @"classDate";
+NSString *const kTableCourseModelStatus = @"status";
+NSString *const kTableCourseModelSubjectId = @"subjectId";
+NSString *const kTableCourseModelCourseId = @"courseId";
+NSString *const kTableCourseModelUserId = @"userId";
+NSString *const kTableCourseModelCourseGoupId = @"courseGoupId";
+NSString *const kTableCourseModelEndTime = @"endTime";
+NSString *const kTableCourseModelSubjectName = @"subjectName";
+NSString *const kTableCourseModelCover = @"cover";
+NSString *const kTableCourseModelPayCount = @"payCount";
+NSString *const kTableCourseModelCourseType = @"courseType";
+NSString *const kTableCourseModelName = @"name";
+NSString *const kTableCourseModelStartTime = @"startTime";
+
+
+@interface TableCourseModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation TableCourseModel
+
+@synthesize classDate = _classDate;
+@synthesize status = _status;
+@synthesize subjectId = _subjectId;
+@synthesize courseId = _courseId;
+@synthesize userId = _userId;
+@synthesize courseGoupId = _courseGoupId;
+@synthesize endTime = _endTime;
+@synthesize subjectName = _subjectName;
+@synthesize cover = _cover;
+@synthesize payCount = _payCount;
+@synthesize courseType = _courseType;
+@synthesize name = _name;
+@synthesize startTime = _startTime;
+
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
+{
+    return [[self alloc] initWithDictionary:dict];
+}
+
+- (instancetype)initWithDictionary:(NSDictionary *)dict
+{
+    self = [super init];
+    
+    // This check serves to make sure that a non-NSDictionary object
+    // passed into the model class doesn't break the parsing.
+    if(self && [dict isKindOfClass:[NSDictionary class]]) {
+            self.classDate = [self objectOrNilForKey:kTableCourseModelClassDate fromDictionary:dict];
+            self.status = [self objectOrNilForKey:kTableCourseModelStatus fromDictionary:dict];
+            self.subjectId = [self objectOrNilForKey:kTableCourseModelSubjectId fromDictionary:dict];
+            self.courseId = [self objectOrNilForKey:kTableCourseModelCourseId fromDictionary:dict];
+            self.userId = [self objectOrNilForKey:kTableCourseModelUserId fromDictionary:dict];
+            self.courseGoupId = [self objectOrNilForKey:kTableCourseModelCourseGoupId fromDictionary:dict];
+            self.endTime = [self objectOrNilForKey:kTableCourseModelEndTime fromDictionary:dict];
+            self.subjectName = [self objectOrNilForKey:kTableCourseModelSubjectName fromDictionary:dict];
+            self.cover = [self objectOrNilForKey:kTableCourseModelCover fromDictionary:dict];
+            self.payCount = [self objectOrNilForKey:kTableCourseModelPayCount fromDictionary:dict];
+            self.courseType = [self objectOrNilForKey:kTableCourseModelCourseType fromDictionary:dict];
+            self.name = [self objectOrNilForKey:kTableCourseModelName fromDictionary:dict];
+            self.startTime = [self objectOrNilForKey:kTableCourseModelStartTime fromDictionary:dict];
+
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:self.classDate forKey:kTableCourseModelClassDate];
+    [mutableDict setValue:self.status forKey:kTableCourseModelStatus];
+    [mutableDict setValue:self.subjectId forKey:kTableCourseModelSubjectId];
+    [mutableDict setValue:self.courseId forKey:kTableCourseModelCourseId];
+    [mutableDict setValue:self.userId forKey:kTableCourseModelUserId];
+    [mutableDict setValue:self.courseGoupId forKey:kTableCourseModelCourseGoupId];
+    [mutableDict setValue:self.endTime forKey:kTableCourseModelEndTime];
+    [mutableDict setValue:self.subjectName forKey:kTableCourseModelSubjectName];
+    [mutableDict setValue:self.cover forKey:kTableCourseModelCover];
+    [mutableDict setValue:self.payCount forKey:kTableCourseModelPayCount];
+    [mutableDict setValue:self.courseType forKey:kTableCourseModelCourseType];
+    [mutableDict setValue:self.name forKey:kTableCourseModelName];
+    [mutableDict setValue:self.startTime forKey:kTableCourseModelStartTime];
+
+    return [NSDictionary dictionaryWithDictionary:mutableDict];
+}
+
+- (NSString *)description 
+{
+    return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]];
+}
+
+#pragma mark - Helper Method
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict
+{
+    id object = [dict objectForKey:aKey];
+    if ([object isKindOfClass:[NSNumber class]]) {
+        NSNumber *number = object;
+        object = [number stringValue];
+    }
+    return [object isEqual:[NSNull null]] ? nil : object;
+}
+
+
+#pragma mark - NSCoding Methods
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super init];
+
+    self.classDate = [aDecoder decodeObjectForKey:kTableCourseModelClassDate];
+    self.status = [aDecoder decodeObjectForKey:kTableCourseModelStatus];
+    self.subjectId = [aDecoder decodeObjectForKey:kTableCourseModelSubjectId];
+    self.courseId = [aDecoder decodeObjectForKey:kTableCourseModelCourseId];
+    self.userId = [aDecoder decodeObjectForKey:kTableCourseModelUserId];
+    self.courseGoupId = [aDecoder decodeObjectForKey:kTableCourseModelCourseGoupId];
+    self.endTime = [aDecoder decodeObjectForKey:kTableCourseModelEndTime];
+    self.subjectName = [aDecoder decodeObjectForKey:kTableCourseModelSubjectName];
+    self.cover = [aDecoder decodeObjectForKey:kTableCourseModelCover];
+    self.payCount = [aDecoder decodeObjectForKey:kTableCourseModelPayCount];
+    self.courseType = [aDecoder decodeObjectForKey:kTableCourseModelCourseType];
+    self.name = [aDecoder decodeObjectForKey:kTableCourseModelName];
+    self.startTime = [aDecoder decodeObjectForKey:kTableCourseModelStartTime];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeObject:_classDate forKey:kTableCourseModelClassDate];
+    [aCoder encodeObject:_status forKey:kTableCourseModelStatus];
+    [aCoder encodeObject:_subjectId forKey:kTableCourseModelSubjectId];
+    [aCoder encodeObject:_courseId forKey:kTableCourseModelCourseId];
+    [aCoder encodeObject:_userId forKey:kTableCourseModelUserId];
+    [aCoder encodeObject:_courseGoupId forKey:kTableCourseModelCourseGoupId];
+    [aCoder encodeObject:_endTime forKey:kTableCourseModelEndTime];
+    [aCoder encodeObject:_subjectName forKey:kTableCourseModelSubjectName];
+    [aCoder encodeObject:_cover forKey:kTableCourseModelCover];
+    [aCoder encodeObject:_payCount forKey:kTableCourseModelPayCount];
+    [aCoder encodeObject:_courseType forKey:kTableCourseModelCourseType];
+    [aCoder encodeObject:_name forKey:kTableCourseModelName];
+    [aCoder encodeObject:_startTime forKey:kTableCourseModelStartTime];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    TableCourseModel *copy = [[TableCourseModel alloc] init];
+    
+    if (copy) {
+
+        copy.classDate = [self.classDate copyWithZone:zone];
+        copy.status = [self.status copyWithZone:zone];
+        copy.subjectId = [self.subjectId copyWithZone:zone];
+        copy.courseId = [self.courseId copyWithZone:zone];
+        copy.userId = [self.userId copyWithZone:zone];
+        copy.courseGoupId = [self.courseGoupId copyWithZone:zone];
+        copy.endTime = [self.endTime copyWithZone:zone];
+        copy.subjectName = [self.subjectName copyWithZone:zone];
+        copy.cover = [self.cover copyWithZone:zone];
+        copy.payCount = [self.payCount copyWithZone:zone];
+        copy.courseType = [self.courseType copyWithZone:zone];
+        copy.name = [self.name copyWithZone:zone];
+        copy.startTime = [self.startTime copyWithZone:zone];
+    }
+    
+    return copy;
+}
+
+
+@end

+ 32 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/AccompanyCourseCell.h

@@ -0,0 +1,32 @@
+//
+//  AccompanyCourseCell.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/2.
+//
+
+#import <UIKit/UIKit.h>
+#import "AccompanyLessonModel.h"
+#import "TableCourseModel.h"
+
+typedef NS_ENUM(NSInteger, ACCOMPANY_TYPE) {
+    ACCOMPANY_TYPE_CHAT,
+    ACCOMPANY_DETAIL,
+    ACCOMPANY_TYPE_ADJUST,
+};
+
+typedef void(^AccompanyCourseCallback)(ACCOMPANY_TYPE type, AccompanyLessonModel * _Nonnull source);
+
+typedef void(^AccompanyLessonCallback)(ACCOMPANY_TYPE type, TableCourseModel * _Nonnull courseModel);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AccompanyCourseCell : UITableViewCell
+
+- (void)configWithSource:(AccompanyLessonModel *)model actionCallback:(AccompanyCourseCallback)callback;
+/// 课表使用
+- (void)configWithCourseMessage:(TableCourseModel *)model beforeTime:(NSInteger)beforeTime actionCallback:(AccompanyLessonCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 220 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/AccompanyCourseCell.m

@@ -0,0 +1,220 @@
+//
+//  AccompanyCourseCell.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/2.
+//
+
+#import "AccompanyCourseCell.h"
+
+@interface AccompanyCourseCell ()
+@property (weak, nonatomic) IBOutlet UILabel *courseTime;
+@property (weak, nonatomic) IBOutlet UILabel *courseStatus;
+@property (weak, nonatomic) IBOutlet UIImageView *studentAvatar;
+@property (weak, nonatomic) IBOutlet UILabel *studentName;
+@property (weak, nonatomic) IBOutlet UILabel *studentSubject;
+
+@property (weak, nonatomic) IBOutlet UIButton *opreationButton;
+
+@property (nonatomic, copy) AccompanyCourseCallback callback;
+
+@property (nonatomic, strong) AccompanyLessonModel *sourceModel;
+
+@property (nonatomic, assign) ACCOMPANY_TYPE type;
+
+/// 课表使用
+@property (nonatomic, copy) AccompanyLessonCallback lessonCallback;
+
+@property (nonatomic, strong) TableCourseModel *lessonModel;
+
+@end
+
+@interface AccompanyCourseCell ()
+
+@end
+
+@implementation AccompanyCourseCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+- (void)configWithSource:(AccompanyLessonModel *)model actionCallback:(AccompanyCourseCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    self.sourceModel = model;
+    [self.studentAvatar sd_setImageWithURL:[NSURL URLWithString:model.avatar] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
+    self.studentName.text = [NSString returnNoNullStringWithString:model.userName];
+    self.studentSubject.text = [NSString returnNoNullStringWithString:model.subjectName];
+    // time
+    [self evaluateTimeLabelWithBeginTime:model.startTime endTime:model.endTime];
+    
+    if ([model.status isEqualToString:@"NOT_START"]) { // 未开始
+        self.courseStatus.text = @"未开始";
+        self.courseStatus.textColor = HexRGB(0xff802C);
+        // 判断按钮显示调课还是进入教室
+        BOOL canChange = NO;
+        if (canChange) {
+            self.type = ACCOMPANY_TYPE_ADJUST;
+            self.opreationButton.userInteractionEnabled = YES;
+            [self.opreationButton setTitle:@"调课" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:HexRGB(0xffffff)];
+        }
+        else {
+            self.type = ACCOMPANY_DETAIL;
+            self.opreationButton.userInteractionEnabled = YES;
+            [self.opreationButton setTitle:@"进入教室" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:HexRGB(0xffffff) forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:THEMECOLOR];
+        }
+    }
+    else if ([model.status isEqualToString:@"ING"]) { // 进行中
+        self.courseStatus.text = @"进行中";
+        self.courseStatus.textColor = THEMECOLOR;
+        self.type = ACCOMPANY_DETAIL;
+        self.opreationButton.userInteractionEnabled = YES;
+        [self.opreationButton setTitle:@"进入教室" forState:UIControlStateNormal];
+        [self.opreationButton setTitleColor:HexRGB(0xffffff) forState:UIControlStateNormal];
+        [self.opreationButton setBackgroundColor:THEMECOLOR];
+    }
+    else if ([model.status isEqualToString:@"COMPLETE"]) { // 已结束
+        self.courseStatus.text = @"已结束";
+        self.courseStatus.textColor = HexRGB(0x999999);
+        // 判断显示评价还是已评价
+        BOOL hasEvaluate = NO;
+        if (hasEvaluate) {
+            self.type = ACCOMPANY_DETAIL;
+            self.opreationButton.userInteractionEnabled = YES;
+            [self.opreationButton setTitle:@"评价" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:HexRGB(0xffffff)];
+        }
+        else {
+            self.opreationButton.userInteractionEnabled = NO;
+            [self.opreationButton setTitle:@"已评价" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:HexRGB(0xffffff)];
+        }
+    }
+}
+
+/// 课表使用
+- (void)configWithCourseMessage:(TableCourseModel *)model beforeTime:(NSInteger)beforeTime actionCallback:(AccompanyLessonCallback)callback {
+    if (callback) {
+        self.lessonCallback = callback;
+    }
+    self.lessonModel = model;
+    
+    [self.studentAvatar sd_setImageWithURL:[NSURL URLWithString:model.cover] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
+    self.studentName.text = [NSString returnNoNullStringWithString:model.name];
+    self.studentSubject.text = [NSString returnNoNullStringWithString:model.subjectName];
+    
+    // time
+    [self evaluateTimeLabelWithBeginTime:model.startTime endTime:model.endTime];
+    
+    if ([model.status isEqualToString:@"NOT_START"]) { // 未开始
+        self.courseStatus.text = @"未开始";
+        self.courseStatus.textColor = HexRGB(0xff802C);
+        
+        // 判断按钮显示调课还是进入教室
+        NSDate *currentDate = [NSDate date];
+        NSDate *beginDate = [self getCourseBeginDate:model.startTime];
+        NSTimeInterval beginTimeInterval = [beginDate timeIntervalSinceDate:currentDate];
+        BOOL canChange = NO;
+        if (beginTimeInterval > beforeTime * 60) {
+            canChange = YES;
+        }
+        if (canChange) {
+            self.type = ACCOMPANY_TYPE_ADJUST;
+            self.opreationButton.userInteractionEnabled = YES;
+            [self.opreationButton setTitle:@"调课" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:HexRGB(0xffffff)];
+        }
+        else {
+            self.type = ACCOMPANY_DETAIL;
+            self.opreationButton.userInteractionEnabled = YES;
+            [self.opreationButton setTitle:@"进入教室" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:HexRGB(0xffffff) forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:THEMECOLOR];
+        }
+    }
+    else if ([model.status isEqualToString:@"ING"]) { // 进行中
+        self.courseStatus.text = @"进行中";
+        self.courseStatus.textColor = THEMECOLOR;
+        self.type = ACCOMPANY_DETAIL;
+        self.opreationButton.userInteractionEnabled = YES;
+        [self.opreationButton setTitle:@"进入教室" forState:UIControlStateNormal];
+        [self.opreationButton setTitleColor:HexRGB(0xffffff) forState:UIControlStateNormal];
+        [self.opreationButton setBackgroundColor:THEMECOLOR];
+    }
+    else if ([model.status isEqualToString:@"COMPLETE"]) { // 已结束
+        self.courseStatus.text = @"已结束";
+        self.courseStatus.textColor = HexRGB(0x999999);
+        // 判断显示评价还是已评价
+        BOOL hasEvaluate = NO;
+        if (hasEvaluate) {
+            self.type = ACCOMPANY_DETAIL;
+            self.opreationButton.userInteractionEnabled = YES;
+            [self.opreationButton setTitle:@"评价" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:HexRGB(0xffffff)];
+        }
+        else {
+            self.opreationButton.userInteractionEnabled = NO;
+            [self.opreationButton setTitle:@"已评价" forState:UIControlStateNormal];
+            [self.opreationButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
+            [self.opreationButton setBackgroundColor:HexRGB(0xffffff)];
+        }
+    }
+}
+
+- (NSDate *)getCourseBeginDate:(NSString *)beginTime {
+    NSDateFormatter *dateFormatter = [NSObject getDateformatter];
+    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *beginDate = [dateFormatter dateFromString:beginTime];
+    return beginDate;
+}
+
+- (void)evaluateTimeLabelWithBeginTime:(NSString *)beginTime endTime:(NSString *)endTime {
+    // 时间
+    NSDateFormatter *dateFormatter = [NSObject getDateformatter];
+    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *beginDate = [dateFormatter dateFromString:beginTime];
+    NSDate *endDate = [dateFormatter dateFromString:endTime];
+    [dateFormatter setDateFormat:@"yyyy/MM/dd HH:mm"];
+    NSString *beginStr = [NSString returnNoNullStringWithString:[dateFormatter stringFromDate:beginDate]];
+    [dateFormatter setDateFormat:@"HH:mm"];
+    NSString *endStr = [NSString returnNoNullStringWithString:[dateFormatter stringFromDate:endDate]];
+    self.courseTime.text = [NSString stringWithFormat:@"%@~%@", beginStr, endStr];    
+}
+
+- (IBAction)chatAction:(id)sender {
+    if (self.callback) {
+        self.callback(ACCOMPANY_TYPE_CHAT, self.sourceModel);
+    }
+    else if (self.lessonCallback) {
+        self.lessonCallback(ACCOMPANY_TYPE_CHAT, self.lessonModel);
+    }
+}
+
+- (IBAction)courseAction:(UIButton *)sender {
+    if (self.callback) {
+        self.callback(self.type, self.sourceModel);
+    }
+    else if (self.lessonCallback) {
+        self.lessonCallback(self.type, self.lessonModel);
+    }
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 196 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/AccompanyCourseCell.xib

@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="AccompanyCourseCell">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="127"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
+                <rect key="frame" x="0.0" y="0.0" width="414" height="127"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hEp-yz-qU7">
+                        <rect key="frame" x="14" y="0.0" width="386" height="115"/>
+                        <subviews>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wXs-1T-7ew">
+                                <rect key="frame" x="10" y="38" width="366" height="1"/>
+                                <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="1" id="r83-A3-xqW"/>
+                                </constraints>
+                            </view>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="course_time" translatesAutoresizingMaskIntoConstraints="NO" id="3FJ-PP-t5u">
+                                <rect key="frame" x="11" y="12" width="16" height="16"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="16" id="kGT-bb-CIU"/>
+                                    <constraint firstAttribute="height" constant="16" id="tQi-IQ-bdk"/>
+                                </constraints>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2021/09/17 14:00~14:25" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="y3h-K3-zJ8">
+                                <rect key="frame" x="34" y="12" width="147" height="16"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="进行中" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XKr-bP-maa">
+                                <rect key="frame" x="325" y="11.5" width="50" height="17"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="50" id="cYb-s7-ndU"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <color key="textColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="user_default_avatal" translatesAutoresizingMaskIntoConstraints="NO" id="foX-kQ-NZi">
+                                <rect key="frame" x="11" y="56" width="47" height="47"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="47" id="cRs-VR-QQw"/>
+                                    <constraint firstAttribute="width" constant="47" id="t7w-Ui-5tY"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="5"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="张豆豆" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eJa-81-RrN">
+                                <rect key="frame" x="68" y="56" width="49" height="24"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="24" id="u07-aD-Pru"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                                <color key="textColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dGh-TI-XLP">
+                                <rect key="frame" x="68" y="83" width="44" height="20"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="单簧管" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mz9-eT-OVS">
+                                        <rect key="frame" x="5" y="0.0" width="34" height="20"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="11"/>
+                                        <color key="textColor" red="1" green="0.5490196078431373" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="1" green="0.94509803921568625" blue="0.87058823529411766" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="bottom" secondItem="mz9-eT-OVS" secondAttribute="bottom" id="5gk-Fm-zz0"/>
+                                    <constraint firstItem="mz9-eT-OVS" firstAttribute="leading" secondItem="dGh-TI-XLP" secondAttribute="leading" constant="5" id="D7V-i6-966"/>
+                                    <constraint firstItem="mz9-eT-OVS" firstAttribute="top" secondItem="dGh-TI-XLP" secondAttribute="top" id="Hfm-VX-vtc"/>
+                                    <constraint firstAttribute="height" constant="20" id="UmQ-Xh-8WZ"/>
+                                    <constraint firstAttribute="trailing" secondItem="mz9-eT-OVS" secondAttribute="trailing" constant="5" id="z12-0a-6PU"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="4"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NOA-EQ-Fjn">
+                                <rect key="frame" x="117" y="48" width="40" height="40"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="40" id="87u-cE-Y5V"/>
+                                    <constraint firstAttribute="width" constant="40" id="gOV-9c-ibN"/>
+                                </constraints>
+                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                <state key="normal" image="course_chat"/>
+                                <connections>
+                                    <action selector="chatAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="oA7-RL-IvS"/>
+                                </connections>
+                            </button>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="42d-Nb-iRS">
+                                <rect key="frame" x="304" y="67" width="70" height="28"/>
+                                <color key="backgroundColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="70" id="FVJ-kk-We8"/>
+                                    <constraint firstAttribute="height" constant="28" id="Hin-5d-6me"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                <state key="normal" title="进入教室"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="14"/>
+                                    </userDefinedRuntimeAttribute>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                        <real key="value" value="1"/>
+                                    </userDefinedRuntimeAttribute>
+                                    <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                                        <color key="value" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="calibratedRGB"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <action selector="courseAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="Cjj-lv-UXo"/>
+                                </connections>
+                            </button>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstItem="XKr-bP-maa" firstAttribute="centerY" secondItem="y3h-K3-zJ8" secondAttribute="centerY" id="2ud-Y3-DkF"/>
+                            <constraint firstItem="wXs-1T-7ew" firstAttribute="top" secondItem="3FJ-PP-t5u" secondAttribute="bottom" constant="10" id="4AU-q2-JKK"/>
+                            <constraint firstItem="eJa-81-RrN" firstAttribute="top" secondItem="foX-kQ-NZi" secondAttribute="top" id="9f4-fS-Mjm"/>
+                            <constraint firstItem="dGh-TI-XLP" firstAttribute="bottom" secondItem="foX-kQ-NZi" secondAttribute="bottom" id="Azp-AH-Ulo"/>
+                            <constraint firstItem="NOA-EQ-Fjn" firstAttribute="centerY" secondItem="eJa-81-RrN" secondAttribute="centerY" id="Dh1-vS-VH4"/>
+                            <constraint firstItem="y3h-K3-zJ8" firstAttribute="leading" secondItem="3FJ-PP-t5u" secondAttribute="trailing" constant="7" id="HDn-Dn-gXp"/>
+                            <constraint firstItem="wXs-1T-7ew" firstAttribute="leading" secondItem="hEp-yz-qU7" secondAttribute="leading" constant="10" id="MuH-hq-nak"/>
+                            <constraint firstAttribute="bottom" secondItem="42d-Nb-iRS" secondAttribute="bottom" constant="20" id="PRc-Qs-mXb"/>
+                            <constraint firstItem="3FJ-PP-t5u" firstAttribute="leading" secondItem="hEp-yz-qU7" secondAttribute="leading" constant="11" id="SPj-TQ-Naq"/>
+                            <constraint firstItem="eJa-81-RrN" firstAttribute="leading" secondItem="foX-kQ-NZi" secondAttribute="trailing" constant="10" id="XMS-cQ-9qv"/>
+                            <constraint firstItem="3FJ-PP-t5u" firstAttribute="top" secondItem="hEp-yz-qU7" secondAttribute="top" constant="12" id="ZIs-gJ-5ER"/>
+                            <constraint firstItem="42d-Nb-iRS" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="NOA-EQ-Fjn" secondAttribute="trailing" constant="11" id="fQa-VV-TW6"/>
+                            <constraint firstItem="foX-kQ-NZi" firstAttribute="leading" secondItem="hEp-yz-qU7" secondAttribute="leading" constant="11" id="fzi-Jo-dW2"/>
+                            <constraint firstItem="XKr-bP-maa" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="y3h-K3-zJ8" secondAttribute="trailing" constant="10" id="iWy-rf-ocs"/>
+                            <constraint firstItem="foX-kQ-NZi" firstAttribute="top" secondItem="wXs-1T-7ew" secondAttribute="bottom" constant="17" id="jyB-6O-Z10"/>
+                            <constraint firstItem="y3h-K3-zJ8" firstAttribute="centerY" secondItem="3FJ-PP-t5u" secondAttribute="centerY" id="krf-gM-z84"/>
+                            <constraint firstAttribute="trailing" secondItem="XKr-bP-maa" secondAttribute="trailing" constant="11" id="n7L-Ge-hdB"/>
+                            <constraint firstItem="NOA-EQ-Fjn" firstAttribute="leading" secondItem="eJa-81-RrN" secondAttribute="trailing" id="oGP-bV-vh8"/>
+                            <constraint firstItem="dGh-TI-XLP" firstAttribute="leading" secondItem="eJa-81-RrN" secondAttribute="leading" id="qFE-Ju-IOj"/>
+                            <constraint firstAttribute="trailing" secondItem="42d-Nb-iRS" secondAttribute="trailing" constant="12" id="tvp-eu-D3U"/>
+                            <constraint firstAttribute="trailing" secondItem="wXs-1T-7ew" secondAttribute="trailing" constant="10" id="yzO-qN-lJn"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="10"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                <constraints>
+                    <constraint firstAttribute="bottom" secondItem="hEp-yz-qU7" secondAttribute="bottom" constant="12" id="1H8-ep-qYi"/>
+                    <constraint firstItem="hEp-yz-qU7" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="14" id="Kid-r9-L7D"/>
+                    <constraint firstItem="hEp-yz-qU7" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="sEC-om-6Mn"/>
+                    <constraint firstAttribute="trailing" secondItem="hEp-yz-qU7" secondAttribute="trailing" constant="14" id="zlt-1I-Jvx"/>
+                </constraints>
+            </tableViewCellContentView>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <connections>
+                <outlet property="courseStatus" destination="XKr-bP-maa" id="lUj-uE-gX6"/>
+                <outlet property="courseTime" destination="y3h-K3-zJ8" id="BQP-Dh-J69"/>
+                <outlet property="opreationButton" destination="42d-Nb-iRS" id="Jez-ID-7gC"/>
+                <outlet property="studentAvatar" destination="foX-kQ-NZi" id="9D9-zE-vdE"/>
+                <outlet property="studentName" destination="eJa-81-RrN" id="Lob-ln-gKG"/>
+                <outlet property="studentSubject" destination="mz9-eT-OVS" id="99G-qb-mJx"/>
+            </connections>
+            <point key="canvasLocation" x="131.8840579710145" y="95.424107142857139"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="course_chat" width="19" height="18"/>
+        <image name="course_time" width="16" height="16"/>
+        <image name="user_default_avatal" width="52" height="52"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 26 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.h

@@ -0,0 +1,26 @@
+//
+//  CourseForLiveCell.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/3.
+//
+
+#import <UIKit/UIKit.h>
+#import "TableCourseModel.h"
+
+typedef NS_ENUM(NSInteger, LIVECOURSEACTION) {
+    LIVECOURSEACTION_CHAT, // 聊天
+    LIVECOURSEACTION_LIVEROOM, // 上课
+};
+
+typedef void(^LiveLessonCallback)(LIVECOURSEACTION action, TableCourseModel * _Nonnull sourceModel);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface CourseForLiveCell : UITableViewCell
+
+- (void)configWithSource:(TableCourseModel *)model beforeTime:(NSInteger)beforeTime callback:(LiveLessonCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 95 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.m

@@ -0,0 +1,95 @@
+//
+//  CourseForLiveCell.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/3.
+//
+
+#import "CourseForLiveCell.h"
+
+@interface CourseForLiveCell ()
+
+@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseStatusLabel;
+@property (weak, nonatomic) IBOutlet UILabel *courseName;
+@property (weak, nonatomic) IBOutlet UILabel *subjectLabel;
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+@property (weak, nonatomic) IBOutlet UIButton *operationButton;
+
+@property (nonatomic, copy) LiveLessonCallback callback;
+
+@property (nonatomic, strong) TableCourseModel *sourceModel;
+
+@end
+
+@implementation CourseForLiveCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+- (void)configWithSource:(TableCourseModel *)model beforeTime:(NSInteger)beforeTime callback:(LiveLessonCallback)callback; {
+    if (callback) {
+        self.callback = callback;
+    }
+    self.sourceModel = model;
+    
+    // time
+    [self evaluateTimeLabelWithBeginTime:model.startTime endTime:model.endTime];
+    
+    self.courseName.text = [NSString returnNoNullStringWithString:model.name];
+    self.subjectLabel.text = [NSString returnNoNullStringWithString:model.subjectName];
+    self.descLabel.text = [NSString stringWithFormat:@"%@人已购买", model.payCount];
+    if ([model.status isEqualToString:@"NOT_START"]) { // 未开始
+        self.courseStatusLabel.text = @"未开始";
+        self.courseStatusLabel.textColor = HexRGB(0xff802C);
+        
+    }
+    else if ([model.status isEqualToString:@"ING"]) { // 进行中
+        self.courseStatusLabel.text = @"进行中";
+        self.courseStatusLabel.textColor = THEMECOLOR;
+        
+    }
+    else if ([model.status isEqualToString:@"COMPLETE"]) { // 已结束
+        self.courseStatusLabel.text = @"已结束";
+        self.courseStatusLabel.textColor = HexRGB(0x999999);
+        
+    }
+}
+
+- (void)evaluateTimeLabelWithBeginTime:(NSString *)beginTime endTime:(NSString *)endTime {
+    // 时间
+    NSDateFormatter *dateFormatter = [NSObject getDateformatter];
+    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *beginDate = [dateFormatter dateFromString:beginTime];
+    NSDate *endDate = [dateFormatter dateFromString:endTime];
+    [dateFormatter setDateFormat:@"yyyy/MM/dd HH:mm"];
+    NSString *beginStr = [NSString returnNoNullStringWithString:[dateFormatter stringFromDate:beginDate]];
+    [dateFormatter setDateFormat:@"HH:mm"];
+    NSString *endStr = [NSString returnNoNullStringWithString:[dateFormatter stringFromDate:endDate]];
+    self.timeLabel.text = [NSString stringWithFormat:@"%@~%@", beginStr, endStr];
+}
+
+
+- (IBAction)chatAction:(id)sender {
+    if (self.callback) {
+        self.callback(LIVECOURSEACTION_CHAT, self.sourceModel);
+    }
+}
+
+- (IBAction)joinLiveroom:(id)sender {
+    if (self.callback) {
+        self.callback(LIVECOURSEACTION_LIVEROOM, self.sourceModel);
+    }
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 215 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.xib

@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="159" id="KGk-i7-Jjw" customClass="CourseForLiveCell">
+            <rect key="frame" x="0.0" y="0.0" width="394" height="159"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
+                <rect key="frame" x="0.0" y="0.0" width="394" height="159"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K4l-Dq-CXi">
+                        <rect key="frame" x="14" y="0.0" width="366" height="147"/>
+                        <subviews>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5Lp-rU-nqx">
+                                <rect key="frame" x="10" y="38" width="346" height="1"/>
+                                <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="1" id="eTt-Xt-i1V"/>
+                                </constraints>
+                            </view>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="course_time" translatesAutoresizingMaskIntoConstraints="NO" id="pTS-nC-xAK">
+                                <rect key="frame" x="11" y="12" width="16" height="16"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="16" id="8mn-T2-CXB"/>
+                                    <constraint firstAttribute="width" constant="16" id="xwh-Vf-z9n"/>
+                                </constraints>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2021/09/17 14:00~14:25" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="T9A-D2-1YE">
+                                <rect key="frame" x="34" y="12" width="147" height="16"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="进行中" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7HA-oy-GhL">
+                                <rect key="frame" x="305" y="11.5" width="50" height="17"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="50" id="Gc8-dU-wiy"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <color key="textColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="lesson_Live" translatesAutoresizingMaskIntoConstraints="NO" id="wA2-zs-RYl">
+                                <rect key="frame" x="11" y="56" width="47" height="47"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="47" id="9Wg-OO-U4i"/>
+                                    <constraint firstAttribute="height" constant="47" id="uww-MX-dub"/>
+                                </constraints>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="单簧管直播课·第三课" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dEp-ou-JBA">
+                                <rect key="frame" x="68" y="56" width="152" height="24"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="24" id="fXZ-Y5-AoA"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                                <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EoV-cQ-MON">
+                                <rect key="frame" x="68" y="83" width="44" height="20"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="单簧管" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EmG-Yo-nbA">
+                                        <rect key="frame" x="5" y="0.0" width="34" height="20"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="11"/>
+                                        <color key="textColor" red="1" green="0.54901960780000003" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="1" green="0.94509803920000002" blue="0.87058823529999996" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstItem="EmG-Yo-nbA" firstAttribute="top" secondItem="EoV-cQ-MON" secondAttribute="top" id="6FH-yM-KLs"/>
+                                    <constraint firstItem="EmG-Yo-nbA" firstAttribute="leading" secondItem="EoV-cQ-MON" secondAttribute="leading" constant="5" id="Jal-Ca-e3Z"/>
+                                    <constraint firstAttribute="bottom" secondItem="EmG-Yo-nbA" secondAttribute="bottom" id="Sb9-A9-sOD"/>
+                                    <constraint firstAttribute="trailing" secondItem="EmG-Yo-nbA" secondAttribute="trailing" constant="5" id="XrD-po-Cbo"/>
+                                    <constraint firstAttribute="height" constant="20" id="jbp-dN-C7f"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="4"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2TM-qv-v7e">
+                                <rect key="frame" x="225" y="53" width="30" height="30"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="30" id="lbN-u0-SFA"/>
+                                    <constraint firstAttribute="height" constant="30" id="x6Y-49-gGY"/>
+                                </constraints>
+                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                <state key="normal" image="course_chat"/>
+                                <connections>
+                                    <action selector="chatAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="58o-ti-5y4"/>
+                                </connections>
+                            </button>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bRl-1p-cZu">
+                                <rect key="frame" x="284" y="99" width="70" height="28"/>
+                                <color key="backgroundColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="28" id="Uge-1g-sLY"/>
+                                    <constraint firstAttribute="width" constant="70" id="laQ-tC-9hL"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                <state key="normal" title="进入教室"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="14"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <action selector="joinLiveroom:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="5Gm-WE-4Mb"/>
+                                </connections>
+                            </button>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MTB-cE-tDv">
+                                <rect key="frame" x="117" y="83" width="157" height="20"/>
+                                <subviews>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nzy-gR-bLh">
+                                        <rect key="frame" x="0.0" y="4.5" width="1" height="11"/>
+                                        <color key="backgroundColor" red="0.82745098039999998" green="0.82745098039999998" blue="0.82745098039999998" alpha="1" colorSpace="calibratedRGB"/>
+                                        <constraints>
+                                            <constraint firstAttribute="width" constant="1" id="aMh-3R-oxO"/>
+                                            <constraint firstAttribute="height" constant="11" id="rQe-eX-5YW"/>
+                                        </constraints>
+                                    </view>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="6人已购买" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="do8-lR-Cg5">
+                                        <rect key="frame" x="7" y="3.5" width="52.5" height="13.5"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="11"/>
+                                        <color key="textColor" red="0.41568627450000001" green="0.41568627450000001" blue="0.41568627450000001" alpha="1" colorSpace="calibratedRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <constraints>
+                                    <constraint firstItem="do8-lR-Cg5" firstAttribute="leading" secondItem="Nzy-gR-bLh" secondAttribute="trailing" constant="6" id="3rt-yE-sdU"/>
+                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="do8-lR-Cg5" secondAttribute="trailing" constant="2" id="67s-lU-r5O"/>
+                                    <constraint firstItem="Nzy-gR-bLh" firstAttribute="centerY" secondItem="MTB-cE-tDv" secondAttribute="centerY" id="PV3-rD-yuv"/>
+                                    <constraint firstItem="do8-lR-Cg5" firstAttribute="centerY" secondItem="MTB-cE-tDv" secondAttribute="centerY" id="Y6P-5i-Xw7"/>
+                                    <constraint firstItem="Nzy-gR-bLh" firstAttribute="leading" secondItem="MTB-cE-tDv" secondAttribute="leading" id="dB5-tY-mrR"/>
+                                    <constraint firstAttribute="height" constant="20" id="qhL-Rb-u4u"/>
+                                </constraints>
+                            </view>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstItem="MTB-cE-tDv" firstAttribute="leading" secondItem="EoV-cQ-MON" secondAttribute="trailing" constant="5" id="1Tg-po-DCR"/>
+                            <constraint firstItem="dEp-ou-JBA" firstAttribute="leading" secondItem="wA2-zs-RYl" secondAttribute="trailing" constant="10" id="2aJ-Aq-JdO"/>
+                            <constraint firstItem="EoV-cQ-MON" firstAttribute="leading" secondItem="dEp-ou-JBA" secondAttribute="leading" id="7Vb-7S-FZM"/>
+                            <constraint firstItem="7HA-oy-GhL" firstAttribute="centerY" secondItem="T9A-D2-1YE" secondAttribute="centerY" id="7cG-kE-7oR"/>
+                            <constraint firstItem="2TM-qv-v7e" firstAttribute="leading" secondItem="dEp-ou-JBA" secondAttribute="trailing" constant="5" id="BMA-h3-EFf"/>
+                            <constraint firstItem="EoV-cQ-MON" firstAttribute="bottom" secondItem="wA2-zs-RYl" secondAttribute="bottom" id="Chd-et-KWm"/>
+                            <constraint firstAttribute="bottom" secondItem="bRl-1p-cZu" secondAttribute="bottom" constant="20" id="DSL-E3-U1J"/>
+                            <constraint firstItem="T9A-D2-1YE" firstAttribute="centerY" secondItem="pTS-nC-xAK" secondAttribute="centerY" id="Hlv-G6-Ihl"/>
+                            <constraint firstAttribute="trailing" secondItem="5Lp-rU-nqx" secondAttribute="trailing" constant="10" id="IrU-1o-C7S"/>
+                            <constraint firstItem="7HA-oy-GhL" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="T9A-D2-1YE" secondAttribute="trailing" constant="10" id="LMB-sX-uzM"/>
+                            <constraint firstItem="wA2-zs-RYl" firstAttribute="leading" secondItem="K4l-Dq-CXi" secondAttribute="leading" constant="11" id="Lc0-sK-oXd"/>
+                            <constraint firstItem="wA2-zs-RYl" firstAttribute="top" secondItem="5Lp-rU-nqx" secondAttribute="bottom" constant="17" id="MsY-pI-vsy"/>
+                            <constraint firstAttribute="trailing" secondItem="bRl-1p-cZu" secondAttribute="trailing" constant="12" id="OK3-7Z-Oyp"/>
+                            <constraint firstItem="T9A-D2-1YE" firstAttribute="leading" secondItem="pTS-nC-xAK" secondAttribute="trailing" constant="7" id="OQD-n7-8U1"/>
+                            <constraint firstItem="dEp-ou-JBA" firstAttribute="top" secondItem="wA2-zs-RYl" secondAttribute="top" id="OSg-qL-j0d"/>
+                            <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="2TM-qv-v7e" secondAttribute="trailing" constant="11" id="RdO-od-8Vv"/>
+                            <constraint firstAttribute="trailing" secondItem="7HA-oy-GhL" secondAttribute="trailing" constant="11" id="Whn-GB-iyS"/>
+                            <constraint firstItem="5Lp-rU-nqx" firstAttribute="top" secondItem="pTS-nC-xAK" secondAttribute="bottom" constant="10" id="ZN2-we-wfB"/>
+                            <constraint firstItem="5Lp-rU-nqx" firstAttribute="leading" secondItem="K4l-Dq-CXi" secondAttribute="leading" constant="10" id="jA3-t4-xid"/>
+                            <constraint firstItem="pTS-nC-xAK" firstAttribute="leading" secondItem="K4l-Dq-CXi" secondAttribute="leading" constant="11" id="kAp-53-8XF"/>
+                            <constraint firstItem="pTS-nC-xAK" firstAttribute="top" secondItem="K4l-Dq-CXi" secondAttribute="top" constant="12" id="o1E-Us-bQ3"/>
+                            <constraint firstItem="bRl-1p-cZu" firstAttribute="leading" secondItem="MTB-cE-tDv" secondAttribute="trailing" constant="10" id="swi-oP-0xd"/>
+                            <constraint firstItem="MTB-cE-tDv" firstAttribute="centerY" secondItem="EoV-cQ-MON" secondAttribute="centerY" id="uTO-Pb-zuG"/>
+                            <constraint firstItem="2TM-qv-v7e" firstAttribute="centerY" secondItem="dEp-ou-JBA" secondAttribute="centerY" id="zPS-Ez-UpN"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="10"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="trailing" secondItem="K4l-Dq-CXi" secondAttribute="trailing" constant="14" id="3Ni-Vy-cdt"/>
+                    <constraint firstItem="K4l-Dq-CXi" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="14" id="4T7-px-9ay"/>
+                    <constraint firstItem="K4l-Dq-CXi" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="FWT-A0-KVM"/>
+                    <constraint firstAttribute="bottom" secondItem="K4l-Dq-CXi" secondAttribute="bottom" constant="12" id="v7e-as-Fu3"/>
+                </constraints>
+            </tableViewCellContentView>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <connections>
+                <outlet property="courseName" destination="dEp-ou-JBA" id="LV9-4Y-wth"/>
+                <outlet property="courseStatusLabel" destination="7HA-oy-GhL" id="oYn-6I-C5g"/>
+                <outlet property="descLabel" destination="do8-lR-Cg5" id="Z6u-4z-HUa"/>
+                <outlet property="operationButton" destination="bRl-1p-cZu" id="vAM-C4-OKI"/>
+                <outlet property="subjectLabel" destination="EmG-Yo-nbA" id="2Fr-ld-btf"/>
+                <outlet property="timeLabel" destination="T9A-D2-1YE" id="s2Z-He-4uC"/>
+            </connections>
+            <point key="canvasLocation" x="185.50724637681162" y="116.18303571428571"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="course_chat" width="19" height="18"/>
+        <image name="course_time" width="16" height="16"/>
+        <image name="lesson_Live" width="47" height="51"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 28 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseNavView.h

@@ -0,0 +1,28 @@
+//
+//  CourseNavView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/3.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^ChooseMouthAction)(void);
+
+@interface CourseNavView : UIView
+
+@property (weak, nonatomic) IBOutlet UIImageView *arrowImage;
+
+@property (weak, nonatomic) IBOutlet UILabel *navTitle;
+
+@property (nonatomic, assign) BOOL arrowUp;
+
++ (instancetype)shareInstance;
+
+- (void)chooseNavCallback:(ChooseMouthAction)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 50 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseNavView.m

@@ -0,0 +1,50 @@
+//
+//  CourseNavView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/3.
+//
+
+#import "CourseNavView.h"
+
+@interface CourseNavView ()
+
+@property (nonatomic, copy) ChooseMouthAction callback;
+
+@end
+
+@implementation CourseNavView
+
++ (instancetype)shareInstance {
+    CourseNavView *view = [[[NSBundle mainBundle] loadNibNamed:@"CourseNavView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)chooseNavCallback:(ChooseMouthAction)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (IBAction)buttonClickAction:(id)sender {
+    self.arrowUp = YES;
+    if (self.callback) {
+        self.callback();
+    }
+}
+
+- (void)setArrowUp:(BOOL)arrowUp {
+    _arrowUp = arrowUp;
+    NSString *imageName = arrowUp ? @"sort_up" : @"sort_down";
+    [self.arrowImage setImage:[UIImage imageNamed:imageName]];
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 76 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseNavView.xib

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CourseNavView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="96"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="39y-6W-6HN">
+                    <rect key="frame" x="0.0" y="95" width="414" height="1"/>
+                    <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="calibratedRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="1" id="ac4-Yf-3QJ"/>
+                    </constraints>
+                </view>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2022年9月" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GTO-1Q-b8D">
+                    <rect key="frame" x="161" y="50" width="92" height="25"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="25" id="TrO-ED-Ma7"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
+                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="down_arrow" translatesAutoresizingMaskIntoConstraints="NO" id="Aty-TD-8f6">
+                    <rect key="frame" x="258" y="59.5" width="8" height="6"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="6" id="FGW-RQ-sze"/>
+                        <constraint firstAttribute="width" constant="8" id="FOk-8J-bnb"/>
+                    </constraints>
+                </imageView>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cUO-Eu-mKa">
+                    <rect key="frame" x="161" y="42.5" width="105" height="40"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="40" id="rgA-0Q-cHA"/>
+                    </constraints>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <connections>
+                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="Of1-Yv-4sa"/>
+                    </connections>
+                </button>
+            </subviews>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="39y-6W-6HN" secondAttribute="trailing" id="0Sc-7V-pPL"/>
+                <constraint firstItem="Aty-TD-8f6" firstAttribute="leading" secondItem="GTO-1Q-b8D" secondAttribute="trailing" constant="5" id="5aF-jm-Cpl"/>
+                <constraint firstItem="Aty-TD-8f6" firstAttribute="centerY" secondItem="GTO-1Q-b8D" secondAttribute="centerY" id="KGA-yE-Id2"/>
+                <constraint firstItem="39y-6W-6HN" firstAttribute="top" secondItem="GTO-1Q-b8D" secondAttribute="bottom" constant="20" id="Um0-5Z-VgP"/>
+                <constraint firstAttribute="bottom" secondItem="39y-6W-6HN" secondAttribute="bottom" id="Wn3-ho-ctn"/>
+                <constraint firstItem="39y-6W-6HN" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="ad9-yT-IV2"/>
+                <constraint firstItem="Aty-TD-8f6" firstAttribute="trailing" secondItem="cUO-Eu-mKa" secondAttribute="trailing" id="deD-vu-Bdf"/>
+                <constraint firstItem="GTO-1Q-b8D" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="fnH-cs-lh8"/>
+                <constraint firstItem="GTO-1Q-b8D" firstAttribute="leading" secondItem="cUO-Eu-mKa" secondAttribute="leading" id="k3o-sg-pI4"/>
+                <constraint firstItem="GTO-1Q-b8D" firstAttribute="centerY" secondItem="cUO-Eu-mKa" secondAttribute="centerY" id="vpg-A7-bif"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="arrowImage" destination="Aty-TD-8f6" id="XvH-NJ-BSR"/>
+                <outlet property="navTitle" destination="GTO-1Q-b8D" id="RMQ-Kd-GIA"/>
+            </connections>
+            <point key="canvasLocation" x="240.57971014492756" y="132.58928571428572"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="down_arrow" width="8" height="6"/>
+    </resources>
+</document>

+ 25 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/LTSCalendarBottomView.h

@@ -0,0 +1,25 @@
+//
+//  LTSCalendarBottomView.h
+//  TeacherDaya
+//
+//  Created by Kyle on 2019/9/20.
+//  Copyright © 2019 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^DisplayCallback)(void);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface LTSCalendarBottomView : UIView
+
+@property (weak, nonatomic) IBOutlet UIImageView *arrowImage;
+
++ (instancetype)shareInstance;
+
+- (void)changeDisplay:(DisplayCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 45 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/LTSCalendarBottomView.m

@@ -0,0 +1,45 @@
+//
+//  LTSCalendarBottomView.m
+//  TeacherDaya
+//
+//  Created by Kyle on 2019/9/20.
+//  Copyright © 2019 DayaMusic. All rights reserved.
+//
+
+#import "LTSCalendarBottomView.h"
+
+@interface LTSCalendarBottomView ()
+
+@property (nonatomic, copy) DisplayCallback callback;
+
+@property (weak, nonatomic) IBOutlet UIView *contentView;
+
+@end
+
+@implementation LTSCalendarBottomView
+
++ (instancetype)shareInstance {
+    LTSCalendarBottomView *view = [[[NSBundle mainBundle] loadNibNamed:@"LTSCalendarBottomView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)changeDisplay:(DisplayCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+- (IBAction)tapAction:(id)sender {
+    if (self.callback) {
+        self.callback();
+    }
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 73 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/LTSCalendarBottomView.xib

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="LTSCalendarBottomView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="94"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zge-3A-nKD">
+                    <rect key="frame" x="0.0" y="0.0" width="414" height="84"/>
+                    <subviews>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TGP-I2-itY">
+                            <rect key="frame" x="177" y="0.0" width="60" height="84"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrow_down" translatesAutoresizingMaskIntoConstraints="NO" id="hQ4-1S-a8X">
+                                    <rect key="frame" x="20" y="37.5" width="20" height="9"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="9" id="enh-ma-vTY"/>
+                                        <constraint firstAttribute="width" constant="20" id="yx1-8C-boD"/>
+                                    </constraints>
+                                </imageView>
+                            </subviews>
+                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            <gestureRecognizers/>
+                            <constraints>
+                                <constraint firstItem="hQ4-1S-a8X" firstAttribute="centerY" secondItem="TGP-I2-itY" secondAttribute="centerY" id="OCb-5I-7z9"/>
+                                <constraint firstItem="hQ4-1S-a8X" firstAttribute="centerX" secondItem="TGP-I2-itY" secondAttribute="centerX" id="mba-6W-6vu"/>
+                                <constraint firstAttribute="width" constant="60" id="yVs-2N-0Uc"/>
+                            </constraints>
+                            <connections>
+                                <outletCollection property="gestureRecognizers" destination="Naj-lG-D6n" appends="YES" id="0Yp-3f-M8g"/>
+                            </connections>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstAttribute="bottom" secondItem="TGP-I2-itY" secondAttribute="bottom" id="87O-vg-Laa"/>
+                        <constraint firstItem="TGP-I2-itY" firstAttribute="top" secondItem="zge-3A-nKD" secondAttribute="top" id="KGI-rO-h7i"/>
+                        <constraint firstItem="TGP-I2-itY" firstAttribute="centerX" secondItem="zge-3A-nKD" secondAttribute="centerX" id="Lkl-r1-dZ4"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstItem="zge-3A-nKD" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="69N-ba-wTi"/>
+                <constraint firstItem="zge-3A-nKD" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="exZ-zP-9fu"/>
+                <constraint firstAttribute="bottom" secondItem="zge-3A-nKD" secondAttribute="bottom" constant="10" id="o72-4j-kf5"/>
+                <constraint firstAttribute="trailing" secondItem="zge-3A-nKD" secondAttribute="trailing" id="zhY-nN-liX"/>
+            </constraints>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="arrowImage" destination="hQ4-1S-a8X" id="qe0-Ph-AvT"/>
+                <outlet property="contentView" destination="zge-3A-nKD" id="gg4-tc-Hnq"/>
+            </connections>
+            <point key="canvasLocation" x="137.68115942028987" y="59.598214285714285"/>
+        </view>
+        <tapGestureRecognizer id="Naj-lG-D6n">
+            <connections>
+                <action selector="tapAction:" destination="iN0-l3-epB" id="2zE-r6-SQj"/>
+            </connections>
+        </tapGestureRecognizer>
+    </objects>
+    <resources>
+        <image name="arrow_down" width="20" height="9"/>
+    </resources>
+</document>

+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Controller/MyCourseViewController.h

@@ -0,0 +1,22 @@
+//
+//  MyCourseViewController.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/4/19.
+//
+
+#import "KSBaseViewController.h"
+#import "JXCategoryView.h"
+#import "JXPagerView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MyCourseViewController : KSBaseViewController
+
+@property (nonatomic, strong) JXPagerView *pagerView;
+@property (nonatomic, strong, readonly) JXCategoryTitleView *categoryView;
+@property (nonatomic, strong) NSArray <NSString *> *titles;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 32 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Controller/MyCourseViewController.m

@@ -0,0 +1,32 @@
+//
+//  MyCourseViewController.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/4/19.
+//
+
+#import "MyCourseViewController.h"
+
+@interface MyCourseViewController ()
+
+@end
+
+@implementation MyCourseViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self allocTitle:@"我的课程"];
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+    // Get the new view controller using [segue destinationViewController].
+    // Pass the selected object to the new view controller.
+}
+*/
+
+@end

+ 29 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/AccompanyLessonModel.h

@@ -0,0 +1,29 @@
+//
+//  AccompanyLessonModel.h
+//
+//  Created by Steven  on 2022/4/12
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface AccompanyLessonModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, strong) NSString *status;
+@property (nonatomic, assign) double userId;
+@property (nonatomic, strong) NSString *classDate;
+@property (nonatomic, strong) NSString *endTime;
+@property (nonatomic, assign) double internalBaseClassIdentifier;
+@property (nonatomic, strong) NSString *userName;
+@property (nonatomic, strong) NSString *avatar;
+@property (nonatomic, assign) double subjectId;
+@property (nonatomic, strong) NSString *subjectName;
+@property (nonatomic, strong) NSString *startTime;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 162 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/AccompanyLessonModel.m

@@ -0,0 +1,162 @@
+//
+//  AccompanyLessonModel.m
+//
+//  Created by Steven  on 2022/4/12
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import "AccompanyLessonModel.h"
+
+
+NSString *const kAccompanyLessonModelStatus = @"status";
+NSString *const kAccompanyLessonModelUserId = @"userId";
+NSString *const kAccompanyLessonModelClassDate = @"classDate";
+NSString *const kAccompanyLessonModelEndTime = @"endTime";
+NSString *const kAccompanyLessonModelId = @"id";
+NSString *const kAccompanyLessonModelUserName = @"userName";
+NSString *const kAccompanyLessonModelAvatar = @"avatar";
+NSString *const kAccompanyLessonModelSubjectId = @"subjectId";
+NSString *const kAccompanyLessonModelSubjectName = @"subjectName";
+NSString *const kAccompanyLessonModelStartTime = @"startTime";
+
+
+@interface AccompanyLessonModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation AccompanyLessonModel
+
+@synthesize status = _status;
+@synthesize userId = _userId;
+@synthesize classDate = _classDate;
+@synthesize endTime = _endTime;
+@synthesize internalBaseClassIdentifier = _internalBaseClassIdentifier;
+@synthesize userName = _userName;
+@synthesize avatar = _avatar;
+@synthesize subjectId = _subjectId;
+@synthesize subjectName = _subjectName;
+@synthesize startTime = _startTime;
+
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
+{
+    return [[self alloc] initWithDictionary:dict];
+}
+
+- (instancetype)initWithDictionary:(NSDictionary *)dict
+{
+    self = [super init];
+    
+    // This check serves to make sure that a non-NSDictionary object
+    // passed into the model class doesn't break the parsing.
+    if(self && [dict isKindOfClass:[NSDictionary class]]) {
+            self.status = [self objectOrNilForKey:kAccompanyLessonModelStatus fromDictionary:dict];
+            self.userId = [[self objectOrNilForKey:kAccompanyLessonModelUserId fromDictionary:dict] doubleValue];
+            self.classDate = [self objectOrNilForKey:kAccompanyLessonModelClassDate fromDictionary:dict];
+            self.endTime = [self objectOrNilForKey:kAccompanyLessonModelEndTime fromDictionary:dict];
+            self.internalBaseClassIdentifier = [[self objectOrNilForKey:kAccompanyLessonModelId fromDictionary:dict] doubleValue];
+            self.userName = [self objectOrNilForKey:kAccompanyLessonModelUserName fromDictionary:dict];
+            self.avatar = [self objectOrNilForKey:kAccompanyLessonModelAvatar fromDictionary:dict];
+            self.subjectId = [[self objectOrNilForKey:kAccompanyLessonModelSubjectId fromDictionary:dict] doubleValue];
+            self.subjectName = [self objectOrNilForKey:kAccompanyLessonModelSubjectName fromDictionary:dict];
+            self.startTime = [self objectOrNilForKey:kAccompanyLessonModelStartTime fromDictionary:dict];
+
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:self.status forKey:kAccompanyLessonModelStatus];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.userId] forKey:kAccompanyLessonModelUserId];
+    [mutableDict setValue:self.classDate forKey:kAccompanyLessonModelClassDate];
+    [mutableDict setValue:self.endTime forKey:kAccompanyLessonModelEndTime];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.internalBaseClassIdentifier] forKey:kAccompanyLessonModelId];
+    [mutableDict setValue:self.userName forKey:kAccompanyLessonModelUserName];
+    [mutableDict setValue:self.avatar forKey:kAccompanyLessonModelAvatar];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.subjectId] forKey:kAccompanyLessonModelSubjectId];
+    [mutableDict setValue:self.subjectName forKey:kAccompanyLessonModelSubjectName];
+    [mutableDict setValue:self.startTime forKey:kAccompanyLessonModelStartTime];
+
+    return [NSDictionary dictionaryWithDictionary:mutableDict];
+}
+
+- (NSString *)description 
+{
+    return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]];
+}
+
+#pragma mark - Helper Method
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict
+{
+    id object = [dict objectForKey:aKey];
+    if ([object isKindOfClass:[NSNumber class]]) {
+        NSNumber *number = object;
+        object = [number stringValue];
+    }
+    return [object isEqual:[NSNull null]] ? nil : object;
+}
+
+
+#pragma mark - NSCoding Methods
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super init];
+
+    self.status = [aDecoder decodeObjectForKey:kAccompanyLessonModelStatus];
+    self.userId = [aDecoder decodeDoubleForKey:kAccompanyLessonModelUserId];
+    self.classDate = [aDecoder decodeObjectForKey:kAccompanyLessonModelClassDate];
+    self.endTime = [aDecoder decodeObjectForKey:kAccompanyLessonModelEndTime];
+    self.internalBaseClassIdentifier = [aDecoder decodeDoubleForKey:kAccompanyLessonModelId];
+    self.userName = [aDecoder decodeObjectForKey:kAccompanyLessonModelUserName];
+    self.avatar = [aDecoder decodeObjectForKey:kAccompanyLessonModelAvatar];
+    self.subjectId = [aDecoder decodeDoubleForKey:kAccompanyLessonModelSubjectId];
+    self.subjectName = [aDecoder decodeObjectForKey:kAccompanyLessonModelSubjectName];
+    self.startTime = [aDecoder decodeObjectForKey:kAccompanyLessonModelStartTime];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeObject:_status forKey:kAccompanyLessonModelStatus];
+    [aCoder encodeDouble:_userId forKey:kAccompanyLessonModelUserId];
+    [aCoder encodeObject:_classDate forKey:kAccompanyLessonModelClassDate];
+    [aCoder encodeObject:_endTime forKey:kAccompanyLessonModelEndTime];
+    [aCoder encodeDouble:_internalBaseClassIdentifier forKey:kAccompanyLessonModelId];
+    [aCoder encodeObject:_userName forKey:kAccompanyLessonModelUserName];
+    [aCoder encodeObject:_avatar forKey:kAccompanyLessonModelAvatar];
+    [aCoder encodeDouble:_subjectId forKey:kAccompanyLessonModelSubjectId];
+    [aCoder encodeObject:_subjectName forKey:kAccompanyLessonModelSubjectName];
+    [aCoder encodeObject:_startTime forKey:kAccompanyLessonModelStartTime];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    AccompanyLessonModel *copy = [[AccompanyLessonModel alloc] init];
+    
+    if (copy) {
+
+        copy.status = [self.status copyWithZone:zone];
+        copy.userId = self.userId;
+        copy.classDate = [self.classDate copyWithZone:zone];
+        copy.endTime = [self.endTime copyWithZone:zone];
+        copy.internalBaseClassIdentifier = self.internalBaseClassIdentifier;
+        copy.userName = [self.userName copyWithZone:zone];
+        copy.avatar = [self.avatar copyWithZone:zone];
+        copy.subjectId = self.subjectId;
+        copy.subjectName = [self.subjectName copyWithZone:zone];
+        copy.startTime = [self.startTime copyWithZone:zone];
+    }
+    
+    return copy;
+}
+
+
+@end

+ 27 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/LiveLessonModel.h

@@ -0,0 +1,27 @@
+//
+//  LiveLessonModel.h
+//
+//  Created by Steven  on 2022/4/12
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface LiveLessonModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, strong) NSString *status;
+@property (nonatomic, assign) double studentCount;
+@property (nonatomic, strong) NSString *courseGroupId;
+@property (nonatomic, strong) NSString *endTime;
+@property (nonatomic, strong) NSString *backgroundPic;
+@property (nonatomic, strong) NSString *subjectName;
+@property (nonatomic, strong) NSString *startTime;
+@property (nonatomic, strong) NSString *courseGroupName;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 148 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/LiveLessonModel.m

@@ -0,0 +1,148 @@
+//
+//  LiveLessonModel.m
+//
+//  Created by Steven  on 2022/4/12
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import "LiveLessonModel.h"
+
+
+NSString *const kLiveLessonModelStatus = @"status";
+NSString *const kLiveLessonModelStudentCount = @"studentCount";
+NSString *const kLiveLessonModelCourseGroupId = @"courseGroupId";
+NSString *const kLiveLessonModelEndTime = @"endTime";
+NSString *const kLiveLessonModelBackgroundPic = @"backgroundPic";
+NSString *const kLiveLessonModelSubjectName = @"subjectName";
+NSString *const kLiveLessonModelStartTime = @"startTime";
+NSString *const kLiveLessonModelCourseGroupName = @"courseGroupName";
+
+
+@interface LiveLessonModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation LiveLessonModel
+
+@synthesize status = _status;
+@synthesize studentCount = _studentCount;
+@synthesize courseGroupId = _courseGroupId;
+@synthesize endTime = _endTime;
+@synthesize backgroundPic = _backgroundPic;
+@synthesize subjectName = _subjectName;
+@synthesize startTime = _startTime;
+@synthesize courseGroupName = _courseGroupName;
+
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
+{
+    return [[self alloc] initWithDictionary:dict];
+}
+
+- (instancetype)initWithDictionary:(NSDictionary *)dict
+{
+    self = [super init];
+    
+    // This check serves to make sure that a non-NSDictionary object
+    // passed into the model class doesn't break the parsing.
+    if(self && [dict isKindOfClass:[NSDictionary class]]) {
+            self.status = [self objectOrNilForKey:kLiveLessonModelStatus fromDictionary:dict];
+            self.studentCount = [[self objectOrNilForKey:kLiveLessonModelStudentCount fromDictionary:dict] doubleValue];
+            self.courseGroupId = [self objectOrNilForKey:kLiveLessonModelCourseGroupId fromDictionary:dict];
+            self.endTime = [self objectOrNilForKey:kLiveLessonModelEndTime fromDictionary:dict];
+            self.backgroundPic = [self objectOrNilForKey:kLiveLessonModelBackgroundPic fromDictionary:dict];
+            self.subjectName = [self objectOrNilForKey:kLiveLessonModelSubjectName fromDictionary:dict];
+            self.startTime = [self objectOrNilForKey:kLiveLessonModelStartTime fromDictionary:dict];
+            self.courseGroupName = [self objectOrNilForKey:kLiveLessonModelCourseGroupName fromDictionary:dict];
+
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:self.status forKey:kLiveLessonModelStatus];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.studentCount] forKey:kLiveLessonModelStudentCount];
+    [mutableDict setValue:self.courseGroupId forKey:kLiveLessonModelCourseGroupId];
+    [mutableDict setValue:self.endTime forKey:kLiveLessonModelEndTime];
+    [mutableDict setValue:self.backgroundPic forKey:kLiveLessonModelBackgroundPic];
+    [mutableDict setValue:self.subjectName forKey:kLiveLessonModelSubjectName];
+    [mutableDict setValue:self.startTime forKey:kLiveLessonModelStartTime];
+    [mutableDict setValue:self.courseGroupName forKey:kLiveLessonModelCourseGroupName];
+
+    return [NSDictionary dictionaryWithDictionary:mutableDict];
+}
+
+- (NSString *)description 
+{
+    return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]];
+}
+
+#pragma mark - Helper Method
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict
+{
+    id object = [dict objectForKey:aKey];
+    if ([object isKindOfClass:[NSNumber class]]) {
+        NSNumber *number = object;
+        object = [number stringValue];
+    }
+    return [object isEqual:[NSNull null]] ? nil : object;
+}
+
+
+#pragma mark - NSCoding Methods
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super init];
+
+    self.status = [aDecoder decodeObjectForKey:kLiveLessonModelStatus];
+    self.studentCount = [aDecoder decodeDoubleForKey:kLiveLessonModelStudentCount];
+    self.courseGroupId = [aDecoder decodeObjectForKey:kLiveLessonModelCourseGroupId];
+    self.endTime = [aDecoder decodeObjectForKey:kLiveLessonModelEndTime];
+    self.backgroundPic = [aDecoder decodeObjectForKey:kLiveLessonModelBackgroundPic];
+    self.subjectName = [aDecoder decodeObjectForKey:kLiveLessonModelSubjectName];
+    self.startTime = [aDecoder decodeObjectForKey:kLiveLessonModelStartTime];
+    self.courseGroupName = [aDecoder decodeObjectForKey:kLiveLessonModelCourseGroupName];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeObject:_status forKey:kLiveLessonModelStatus];
+    [aCoder encodeDouble:_studentCount forKey:kLiveLessonModelStudentCount];
+    [aCoder encodeObject:_courseGroupId forKey:kLiveLessonModelCourseGroupId];
+    [aCoder encodeObject:_endTime forKey:kLiveLessonModelEndTime];
+    [aCoder encodeObject:_backgroundPic forKey:kLiveLessonModelBackgroundPic];
+    [aCoder encodeObject:_subjectName forKey:kLiveLessonModelSubjectName];
+    [aCoder encodeObject:_startTime forKey:kLiveLessonModelStartTime];
+    [aCoder encodeObject:_courseGroupName forKey:kLiveLessonModelCourseGroupName];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    LiveLessonModel *copy = [[LiveLessonModel alloc] init];
+    
+    if (copy) {
+
+        copy.status = [self.status copyWithZone:zone];
+        copy.studentCount = self.studentCount;
+        copy.courseGroupId = [self.courseGroupId copyWithZone:zone];
+        copy.endTime = [self.endTime copyWithZone:zone];
+        copy.backgroundPic = [self.backgroundPic copyWithZone:zone];
+        copy.subjectName = [self.subjectName copyWithZone:zone];
+        copy.startTime = [self.startTime copyWithZone:zone];
+        copy.courseGroupName = [self.courseGroupName copyWithZone:zone];
+    }
+    
+    return copy;
+}
+
+
+@end

+ 20 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonBodyView.h

@@ -0,0 +1,20 @@
+//
+//  MyLessonBodyView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/12.
+//
+
+#import "KSJXBodyView.h"
+#import "StateView.h"
+#import "Reachability.h"
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MyLessonBodyView : KSJXBodyView
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 515 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonBodyView.m

@@ -0,0 +1,515 @@
+//
+//  MyLessonBodyView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/12.
+//
+
+#import "MyLessonBodyView.h"
+#import "KSBaseWKWebViewController.h"
+#import "MyLiveCourseCell.h"
+#import "AccompanyCourseCell.h"
+#import "LiveLessonModel.h"
+#import "AccompanyLessonModel.h"
+#import "KSChatConversationViewController.h"
+#import "MyLessonSearchView.h"
+#import "NewClassPopView.h"
+#import "KSFullDatePicker.h"
+
+
+@interface MyLessonBodyView ()<UITableViewDelegate,UITableViewDataSource>
+
+@property (nonatomic, strong) NSDateFormatter *dateFormatter;
+
+@property (nonatomic, copy) MyLessonSearchView *sortView;
+
+@property (nonatomic, strong) NewClassPopView *popView;
+
+@property (nonatomic, strong) NSMutableArray *dataArray;
+
+@property (nonatomic, strong) StateView *promptView;
+@property (nonatomic, strong) UIView *promptPlaceView;
+
+@property (nonatomic, assign) BOOL networkAvaiable; // 网络是否可用
+
+@property (nonatomic, assign) BOOL isLoadMore;
+@property (nonatomic, assign) NSInteger rows;
+@property (nonatomic, assign) NSInteger pages;
+
+@property (nonatomic, assign) NSInteger secondChooseIndex;
+
+@property (nonatomic, assign) NSInteger thirdChooseIndex;
+
+@property (nonatomic, strong) NSString *classDate;
+
+@property (nonatomic, strong) NSString *status;
+
+@property (nonatomic, strong) NSString *subjectId;
+
+@property (nonatomic, strong) NSMutableArray *subjectMessageArray;
+
+@end
+
+@implementation MyLessonBodyView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        
+        self.backgroundColor = HexRGB(0xf6f8f9);
+        self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) style:UITableViewStylePlain];
+        self.tableView.backgroundColor = HexRGB(0xf6f8f9);
+        self.tableView.showsVerticalScrollIndicator = NO;
+
+        self.tableView.dataSource = self;
+        self.tableView.delegate = self;
+        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        [self addSubview:self.tableView];
+        
+        
+        UIView *headView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 10)];
+        headView.backgroundColor = HexRGB(0xf6f8f9);
+        self.tableView.tableHeaderView = headView;
+        
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 10)];
+        bottomView.backgroundColor = HexRGB(0xf6f8f9);
+        self.tableView.tableFooterView = bottomView;
+        [self.tableView registerNib:[UINib nibWithNibName:@"AccompanyCourseCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"AccompanyCourseCell"];
+        [self.tableView registerNib:[UINib nibWithNibName:@"MyLiveCourseCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MyLiveCourseCell"];
+        
+        [self.dateFormatter setDateFormat:@"yyyy-MM"];
+        NSDate *currentDate = [NSDate date];
+        self.classDate = [self.dateFormatter stringFromDate:currentDate];
+        MJWeakSelf;
+        self.tableView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+            [weakSelf resetParamenter];
+            [weakSelf requestData];
+        }];
+        self.tableView.mj_footer = [KSGifRefreshFooter footerWithRefreshingBlock:^{
+            if (weakSelf.isLoadMore) {
+                weakSelf.pages += 1;
+                [weakSelf requestData];
+            }
+            else {
+                [weakSelf.tableView.mj_footer endRefreshingWithNoMoreData];
+            }
+        }];
+    }
+    return self;
+}
+
+- (void)endRefresh {
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        [self.tableView.mj_header endRefreshing];
+        [self.tableView.mj_footer endRefreshing];
+    });
+}
+
+- (void)refreshAndRequestData {
+    [self resetParamenter];
+    [self requestData];
+}
+
+- (void)resetParamenter {
+    self.isLoadMore = YES;
+    self.pages = 1;
+    self.rows = 10;
+    
+    self.dataArray = [NSMutableArray array];
+    [self.tableView.mj_footer resetNoMoreData];
+    [self setPromptString:@"暂无内容" imageName:@"wd_img_zwsj" inView:self.tableView];
+    [self.tableView reloadData];
+}
+
+- (void)requestData {
+    if (self.selectIndex == 0) { // 陪练课
+//        [KSNetworkingManager accompanyCourseRequest:KS_POST classMonth:self.classDate status:self.status subjectId:self.subjectId page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+//            [self endRefresh];
+//            if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+//                NSArray *sourceArray = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"rows"];
+//                for (NSDictionary *parm in sourceArray) {
+//                    AccompanyLessonModel *model = [[AccompanyLessonModel alloc] initWithDictionary:parm];
+//                    [self.dataArray addObject:model];
+//                }
+//                
+//                if (sourceArray.count < self.rows) {
+//                    self.isLoadMore = NO;
+//                }
+//            }
+//            else {
+//                [self MBPShow:MESSAGEKEY];
+//            }
+//            [self.tableView reloadData];
+//            [self changePromptLabelStateWithArray:self.dataArray];
+//        } faliure:^(NSError * _Nonnull error) {
+//            [self endRefresh];
+//            if (self.networkAvaiable == NO) {
+//                [self setPromptString:@"暂无网络" imageName:@"no_networking" inView:self.tableView];
+//            }
+//            [self.dataArray removeAllObjects];
+//            [self.tableView reloadData];
+//            [self changePromptLabelStateWithArray:self.dataArray];
+//        }];
+    }
+    else { // 直播课
+//        [KSNetworkingManager queryTeacherLiveCourse:KS_POST classDate:self.classDate status:self.status subjectId:self.subjectId page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+//            [self endRefresh];
+//            if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+//                NSArray *sourceArray = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"rows"];
+//                for (NSDictionary *parm in sourceArray) {
+//                    LiveLessonModel *model = [[LiveLessonModel alloc] initWithDictionary:parm];
+//                    [self.dataArray addObject:model];
+//                }
+//
+//                if (sourceArray.count < self.rows) {
+//                    self.isLoadMore = NO;
+//                }
+//            }
+//            else {
+//                [self MBPShow:MESSAGEKEY];
+//            }
+//            [self.tableView reloadData];
+//            [self changePromptLabelStateWithArray:self.dataArray];
+//        } faliure:^(NSError * _Nonnull error) {
+//            [self endRefresh];
+//            if (self.networkAvaiable == NO) {
+//                [self setPromptString:@"暂无网络" imageName:@"no_networking" inView:self.tableView];
+//            }
+//            [self.dataArray removeAllObjects];
+//            [self.tableView reloadData];
+//            [self changePromptLabelStateWithArray:self.dataArray];
+//        }];
+    }
+}
+
+- (void)beginRefreshImmediately {
+    [self.tableView.mj_header beginRefreshing];
+}
+
+- (void)beginFirstRefresh {
+    if (!self.isHeaderRefreshed) {
+        [self beginRefreshImmediately];
+    }
+}
+- (void)selectCellAtIndexPath:(NSIndexPath *)indexPath {
+    
+    if (self.lastSelectedIndexPath == indexPath) {
+        return;
+    }
+    if (self.lastSelectedIndexPath != nil) {
+        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.lastSelectedIndexPath];
+        [cell setSelected:NO animated:NO];
+    }
+    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
+    [cell setSelected:YES animated:NO];
+    self.lastSelectedIndexPath = indexPath;
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    self.tableView.frame = self.bounds;
+    CGFloat topHeight = 55.0f;
+    self.tableView.frame = CGRectMake(0, topHeight, self.bounds.size.width, self.bounds.size.height - topHeight);
+    if (!_sortView) {
+        _sortView = [MyLessonSearchView shareInstance];
+        _sortView.frame = CGRectMake(0, 0, kScreenWidth, 55);
+        MJWeakSelf;
+        [_sortView sortAction:^(SORT_TYPE type) {
+            [weakSelf sortWithType:type];
+        }];
+        [self.dateFormatter setDateFormat:@"yyyy年MM月"];
+        NSDate *currentDate = [NSDate date];
+        [self.sortView.firstButton setTitle:[self.dateFormatter stringFromDate:currentDate] forState:UIControlStateNormal];
+        [self addSubview:self.sortView];
+    }
+}
+
+- (void)sortWithType:(SORT_TYPE)type {
+    
+    if (type == SORT_TYPE_TIME) { // time
+        [self showPickerView];
+    }
+    else if (type == SORT_TYPE_STATUS) { // 状态
+        [self.popView refreshWithSourceArray:@[@"全部",@"未开始",@"进行中",@"已结束"] preChooseIndex:_secondChooseIndex inView:self actionItem:1];
+    }
+    else if (type == SORT_TYPE_SUBJECT) {
+//        [self.popView refreshWithSourceArray:@[@"全部",@"请假",@"旷课",@"迟到",@"正常"] preChooseIndex:_thirdChooseIndex inView:self actionItem:2];
+    }
+    else {
+        [self hiddenPopView];
+    }
+}
+
+- (void)showPickerView {
+    KSFullDatePicker *picker = [[KSFullDatePicker alloc] initWithTitle:@"" date:[NSDate date] pickMode:KSDATEPICKER_MODE_YEAR_MONTH selectDateBlock:^(NSString *date) {
+
+        self.classDate = date;
+        NSString *displayTime = [self getTimeDisplay:date];
+        [self.sortView.firstButton setTitle:displayTime forState:UIControlStateNormal];
+        [self resetPickerStatus];
+        // 请求数据
+        [self refreshAndRequestData];
+    } cancleBlock:^{
+        [self resetPickerStatus];
+    }];
+    [picker show];
+}
+
+
+- (NSString *)getTimeDisplay:(NSString *)chooseMonth {
+    [self.dateFormatter setDateFormat:@"yyyy-MM"];
+    NSDate *chooseDate = [self.dateFormatter dateFromString:chooseMonth];
+    [self.dateFormatter setDateFormat:@"yyyy年MM月"];
+    NSString *displayTime = [self.dateFormatter stringFromDate:chooseDate];
+    return displayTime;
+}
+- (void)resetPickerStatus {
+    self.sortView.firstArrowUp = NO;
+}
+
+- (NewClassPopView *)popView {
+    if (!_popView) {
+        MJWeakSelf;
+        _popView = [[NewClassPopView alloc] initWithFrame:CGRectMake(0, 55, kScreenWidth, kScreenHeight - 55 - kNaviBarHeight - iPhoneXSafeBottomMargin) chooseCallback:^(NSString * _Nonnull sortStr, NSInteger chooseIndex, NSInteger item) {
+            if (chooseIndex != 0) {
+                // 回调
+                [weakSelf sortWithChooseIndex:chooseIndex item:item title:sortStr];
+            }
+            [weakSelf hiddenPopView];
+        }];
+    }
+    return _popView;
+}
+
+- (void)sortWithChooseIndex:(NSInteger)chooseIndex item:(NSInteger)item title:(NSString *)title {
+    if (item == 0) { //
+    }
+    else if (item == 1) { // 课程状态
+        self.secondChooseIndex = chooseIndex;
+        self.thirdChooseIndex = 0;
+        [self.sortView.secondButton setTitle:title forState:UIControlStateNormal];
+        switch (chooseIndex) {
+            case 1:
+            {
+                self.status = nil;
+                [self.sortView.secondButton setTitle:@"课程状态" forState:UIControlStateNormal];
+            }
+                break;
+            case 2:
+            {
+                self.status = @"NOT_START";
+            }
+                break;
+            case 3:
+            {
+                self.status = @"ING";
+            }
+                break;
+            case 4:
+            {
+                self.status = @"COMPLETE";
+            }
+                break;
+                
+            default:
+                break;
+        }
+    }
+    else if (item == 2) { // 声部筛选
+        self.thirdChooseIndex = chooseIndex;
+        [self.sortView.thirdButton setTitle:title forState:UIControlStateNormal];
+        if (chooseIndex == 1) {
+            self.subjectId = nil;
+            [self.sortView.thirdButton setTitle:@"全部声部" forState:UIControlStateNormal];
+        }
+        else {
+            NSDictionary *parm = self.subjectMessageArray[chooseIndex-1];
+            self.subjectId = [parm stringValueForKey:@"subjectId"];
+        }
+    }
+    [self resetParamenter];
+    [self requestData];
+}
+
+
+- (void)hiddenPopView {
+    self.sortView.firstArrowUp = NO;
+    self.sortView.secondArrowUp = NO;
+    self.sortView.thirdArrowUp = NO;
+    [self.popView hiddenView];
+}
+
+#pragma mark - UITableViewDataSource
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return self.dataArray.count;
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+    if (self.selectIndex == 0) {
+        return 127.0f;
+    }
+    else {
+        return 164.0f;
+    }
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    
+    if (self.selectIndex == 0) {
+        AccompanyLessonModel *model = self.dataArray[indexPath.row];
+        AccompanyCourseCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AccompanyCourseCell"];
+        MJWeakSelf;
+        [cell configWithSource:model actionCallback:^(ACCOMPANY_TYPE type, AccompanyLessonModel * _Nonnull source) {
+            [weakSelf courseOperation:type sourceModel:source];
+        }];
+        return cell;
+    }
+    else {
+        LiveLessonModel *model = self.dataArray[indexPath.row];
+        MyLiveCourseCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyLiveCourseCell"];
+        MJWeakSelf;
+        [cell configCellWithSource:model callback:^(NSString *targetId) {
+            [weakSelf chatAction:targetId];
+        }];
+        return cell;
+    }
+}
+
+- (void)courseOperation:(ACCOMPANY_TYPE)type sourceModel:(AccompanyLessonModel *)model {
+    switch (type) {
+        case ACCOMPANY_TYPE_CHAT: // 聊天
+        {
+            KSChatConversationViewController *conversationVC = [[KSChatConversationViewController alloc] init];
+            conversationVC.targetId = [NSString stringWithFormat:@"%.0f",model.userId];
+            conversationVC.conversationType = ConversationType_PRIVATE;
+            [self.naviController pushViewController:conversationVC animated:YES];
+        }
+            break;
+        case ACCOMPANY_TYPE_ADJUST: // 调整
+        {
+            [self showAdjustPicker:model];
+        }
+            break;
+        case ACCOMPANY_DETAIL:  // 陪练课详情
+        {
+            [self showAccompanyDetail:model];
+        }
+            break;
+
+        default:
+            break;
+    }
+}
+
+- (void)showAccompanyDetail:(AccompanyLessonModel *)model {
+    
+}
+
+- (void)showAdjustPicker:(AccompanyLessonModel *)model {
+    
+    KSFullDatePicker *picker = [[KSFullDatePicker alloc] initWithTitle:@"课时调整" date:[NSDate date] pickMode:KSDATEPICKER_MODE_DAY_TIME selectDateBlock:^(NSString *date) {
+        [self courseAdjustAction:model];
+    } cancleBlock:^{
+        
+    }];
+    [picker show];
+}
+
+- (void)courseAdjustAction:(AccompanyLessonModel *)model {
+    
+}
+
+- (void)chatAction:(NSString *)targetId {
+    KSChatConversationViewController *conversationVC = [[KSChatConversationViewController alloc] init];
+    conversationVC.targetId = targetId;
+    conversationVC.conversationType = ConversationType_GROUP;
+    [self.naviController pushViewController:conversationVC animated:YES];
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    if (indexPath.row == 0) { // 进入陪练课详情
+        
+    }
+    else { // 直播课程组详情
+        
+    }
+}
+
+/**
+ 设置没有数据时的显示
+ 
+ @param promptString 提示语
+ @param imgName 图片名称
+ @param view 显示在什么地方
+ */
+- (void)setPromptString:(NSString *)promptString imageName:(NSString *)imgName inView:(UIView *)view {
+    if (self.promptView != nil) {
+        [self.promptView removeFromSuperview];
+    }
+    else {
+        self.promptView = [[StateView alloc]init];
+        self.promptView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight - 300);
+    }
+    _promptPlaceView = view;
+    //当请求不到数据时 ,自定义提示view 将会出现;
+    self.promptView.imageName = imgName;
+    self.promptView.alpha = 0.0f;
+    [self.promptView setText:promptString];
+    [view addSubview:self.promptView];
+}
+
+// 结束刷新后调用方法
+- (void)changePromptLabelStateWithArray:(NSMutableArray *)array {
+    NSInteger count;
+    if (array.count) {
+        count = array.count;
+    } else {
+        count = 0;
+    }
+    
+    [UIView animateWithDuration:0.1 animations:^{
+        [[self promptView] setAlpha:count ? 0.0f :1.0f ] ;
+    }] ;
+    
+}
+
+- (BOOL)networkAvaiable {
+    return [self checkNetworkAvaiable];
+}
+
+- (BOOL)checkNetworkAvaiable {
+    BOOL isExistenceNetwork = YES;
+    Reachability *reach = [Reachability reachabilityWithHostName:@"www.apple.com"];
+    switch ([reach currentReachabilityStatus]) {
+        case NotReachable:
+            isExistenceNetwork = NO;
+            //NSLog(@"notReachable");
+            break;
+        case ReachableViaWiFi:
+            isExistenceNetwork = YES;
+            //NSLog(@"WIFI");
+            break;
+        case ReachableViaWWAN:
+            isExistenceNetwork = YES;
+            //NSLog(@"3G");
+            break;
+    }
+    return isExistenceNetwork;
+}
+#pragma mark ----- lazying
+- (NSDateFormatter *)dateFormatter {
+    if (!_dateFormatter) {
+        _dateFormatter = [NSObject getDateformatter];
+    }
+    return _dateFormatter;
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 40 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonSearchView.h

@@ -0,0 +1,40 @@
+//
+//  MyLessonSearchView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/12.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, SORT_TYPE) {
+    SORT_TYPE_TIME = 1,   // 课程时间
+    SORT_TYPE_STATUS = 2, // 课程状态
+    SORT_TYPE_SUBJECT = 3,  // 声部筛选
+    SORT_TYPE_HIDDEN = 4, // 隐藏
+};
+
+typedef void(^SortActionBlock)(SORT_TYPE type);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MyLessonSearchView : UIView
+
+@property (weak, nonatomic) IBOutlet UIButton *firstButton;
+@property (weak, nonatomic) IBOutlet UIButton *secondButton;
+@property (weak, nonatomic) IBOutlet UIButton *thirdButton;
+
+@property (nonatomic, assign) BOOL firstArrowUp;
+
+@property (nonatomic, assign) BOOL secondArrowUp;
+
+@property (nonatomic, assign) BOOL thirdArrowUp;
+
++ (instancetype)shareInstance;
+
+- (void)sortAction:(SortActionBlock)block;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 98 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonSearchView.m

@@ -0,0 +1,98 @@
+//
+//  MyLessonSearchView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/12.
+//
+
+#import "MyLessonSearchView.h"
+
+@interface MyLessonSearchView ()
+
+@property (nonatomic, copy) SortActionBlock block;
+@property (weak, nonatomic) IBOutlet UIImageView *firstArrow;
+@property (weak, nonatomic) IBOutlet UIImageView *secondArrow;
+@property (weak, nonatomic) IBOutlet UIImageView *thirdArrow;
+
+@end
+
+
+@implementation MyLessonSearchView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.firstArrowUp = NO;
+    self.secondArrowUp = NO;
+    self.thirdArrowUp = NO;
+}
+
++ (instancetype)shareInstance {
+    MyLessonSearchView *view = [[[NSBundle mainBundle] loadNibNamed:@"MyLessonSearchView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)sortAction:(SortActionBlock)block {
+    if (block) {
+        self.block = block;
+    }
+}
+
+- (IBAction)buttonClickAction:(UIButton *)sender {
+    NSInteger index = sender.tag - 1000;
+    BOOL isHidden;
+    if (index == 1) {
+        self.firstArrowUp = !self.firstArrowUp;
+        self.secondArrowUp = NO;
+        self.thirdArrowUp = NO;
+        isHidden = !self.firstArrowUp;
+    }
+    else if (index == 2) {
+        self.secondArrowUp = !self.secondArrowUp;
+        self.firstArrowUp = NO;
+        self.thirdArrowUp = NO;
+        isHidden = !self.secondArrowUp;
+    }
+    else {
+        self.thirdArrowUp = !self.thirdArrowUp;
+        self.firstArrowUp = NO;
+        self.secondArrowUp = NO;
+        isHidden = !self.thirdArrowUp;
+    }
+    
+    if (self.block) {
+        if (isHidden) {
+            index = 4;
+        }
+        self.block(index);
+    }
+}
+
+- (void)setFirstArrowUp:(BOOL)firstArrowUp {
+    _firstArrowUp = firstArrowUp;
+    NSString *imageName = firstArrowUp ? @"sort_up" : @"sort_down";
+    [_firstArrow setImage:[UIImage imageNamed:imageName]];
+}
+
+- (void)setSecondArrowUp:(BOOL)secondArrowUp {
+    _secondArrowUp = secondArrowUp;
+    NSString *imageName = secondArrowUp ? @"sort_up" : @"sort_down";
+    [_secondArrow setImage:[UIImage imageNamed:imageName]];
+
+
+}
+
+- (void)setThirdArrowUp:(BOOL)thirdArrowUp {
+    _thirdArrowUp = thirdArrowUp;
+    NSString *imageName = thirdArrowUp ? @"sort_up" : @"sort_down";
+    [_thirdArrow setImage:[UIImage imageNamed:imageName]];
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 168 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonSearchView.xib

@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="MyLessonSearchView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="88"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LpR-2y-gXZ">
+                    <rect key="frame" x="0.0" y="0.0" width="414" height="88"/>
+                    <subviews>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sav-8B-TD3">
+                            <rect key="frame" x="0.0" y="0.0" width="131.5" height="88"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down" translatesAutoresizingMaskIntoConstraints="NO" id="vSU-NS-Qou">
+                                    <rect key="frame" x="113.5" y="41" width="8" height="6"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="6" id="L0G-Nt-hlU"/>
+                                        <constraint firstAttribute="width" constant="8" id="nhm-Fv-ewC"/>
+                                    </constraints>
+                                </imageView>
+                                <button opaque="NO" tag="1001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CSP-VE-Q55">
+                                    <rect key="frame" x="0.0" y="0.0" width="131.5" height="88"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                    <state key="normal" title="2022年04月">
+                                        <color key="titleColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                                    </state>
+                                    <connections>
+                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="TaJ-ah-38O"/>
+                                    </connections>
+                                </button>
+                            </subviews>
+                            <color key="backgroundColor" red="0.96078431369999995" green="0.96078431369999995" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="trailing" secondItem="CSP-VE-Q55" secondAttribute="trailing" id="0bd-hm-rCy"/>
+                                <constraint firstAttribute="bottom" secondItem="CSP-VE-Q55" secondAttribute="bottom" id="5ye-zJ-qJd"/>
+                                <constraint firstAttribute="trailing" secondItem="vSU-NS-Qou" secondAttribute="trailing" constant="10" id="g2D-zv-qIp"/>
+                                <constraint firstItem="CSP-VE-Q55" firstAttribute="top" secondItem="sav-8B-TD3" secondAttribute="top" id="lqg-EV-zPD"/>
+                                <constraint firstItem="vSU-NS-Qou" firstAttribute="centerY" secondItem="sav-8B-TD3" secondAttribute="centerY" id="vSN-3Z-GaR"/>
+                                <constraint firstItem="CSP-VE-Q55" firstAttribute="leading" secondItem="sav-8B-TD3" secondAttribute="leading" id="zIY-Ko-K7m"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EXN-FR-v0M">
+                            <rect key="frame" x="141.5" y="0.0" width="131" height="88"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down" translatesAutoresizingMaskIntoConstraints="NO" id="OTv-DP-LWv">
+                                    <rect key="frame" x="103" y="41" width="8" height="6"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="8" id="5Xg-pv-7Nq"/>
+                                        <constraint firstAttribute="height" constant="6" id="z2o-1V-B1s"/>
+                                    </constraints>
+                                </imageView>
+                                <button opaque="NO" tag="1002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4ob-Ur-wiA">
+                                    <rect key="frame" x="0.0" y="0.0" width="131" height="88"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                    <state key="normal" title="课程状态">
+                                        <color key="titleColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="calibratedRGB"/>
+                                    </state>
+                                    <connections>
+                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="dy9-XT-PTc"/>
+                                    </connections>
+                                </button>
+                            </subviews>
+                            <color key="backgroundColor" red="0.96078431369999995" green="0.96078431369999995" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="trailing" secondItem="OTv-DP-LWv" secondAttribute="trailing" constant="20" id="Agt-B1-juL"/>
+                                <constraint firstItem="4ob-Ur-wiA" firstAttribute="leading" secondItem="EXN-FR-v0M" secondAttribute="leading" id="GtX-9e-ehq"/>
+                                <constraint firstAttribute="trailing" secondItem="4ob-Ur-wiA" secondAttribute="trailing" id="YNZ-vD-gf4"/>
+                                <constraint firstItem="OTv-DP-LWv" firstAttribute="centerY" secondItem="EXN-FR-v0M" secondAttribute="centerY" id="b3Z-oq-v2w"/>
+                                <constraint firstAttribute="bottom" secondItem="4ob-Ur-wiA" secondAttribute="bottom" id="jwa-36-Cbd"/>
+                                <constraint firstItem="4ob-Ur-wiA" firstAttribute="top" secondItem="EXN-FR-v0M" secondAttribute="top" id="ljE-Zk-4Wc"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tfS-Rc-iEN">
+                            <rect key="frame" x="282.5" y="0.0" width="131.5" height="88"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down" translatesAutoresizingMaskIntoConstraints="NO" id="2nN-nP-Pcx">
+                                    <rect key="frame" x="103.5" y="41" width="8" height="6"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="6" id="Hqu-N6-YGq"/>
+                                        <constraint firstAttribute="width" constant="8" id="RHc-EF-HM2"/>
+                                    </constraints>
+                                </imageView>
+                                <button opaque="NO" tag="1003" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cgC-dL-lRH">
+                                    <rect key="frame" x="0.0" y="0.0" width="131.5" height="88"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                    <state key="normal" title="全部声部">
+                                        <color key="titleColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                                    </state>
+                                    <connections>
+                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="nuc-JZ-JJe"/>
+                                    </connections>
+                                </button>
+                            </subviews>
+                            <color key="backgroundColor" red="0.96078431369999995" green="0.96078431369999995" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstItem="2nN-nP-Pcx" firstAttribute="centerY" secondItem="tfS-Rc-iEN" secondAttribute="centerY" id="5EQ-2B-7AS"/>
+                                <constraint firstAttribute="trailing" secondItem="cgC-dL-lRH" secondAttribute="trailing" id="736-JC-2Pv"/>
+                                <constraint firstItem="cgC-dL-lRH" firstAttribute="top" secondItem="tfS-Rc-iEN" secondAttribute="top" id="Jda-N3-CeP"/>
+                                <constraint firstAttribute="trailing" secondItem="2nN-nP-Pcx" secondAttribute="trailing" constant="20" id="fhr-tv-oYh"/>
+                                <constraint firstAttribute="bottom" secondItem="cgC-dL-lRH" secondAttribute="bottom" id="i38-qz-i66"/>
+                                <constraint firstItem="cgC-dL-lRH" firstAttribute="leading" secondItem="tfS-Rc-iEN" secondAttribute="leading" id="zXE-H5-6j1"/>
+                            </constraints>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" red="0.96078431369999995" green="0.96078431369999995" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
+                    <constraints>
+                        <constraint firstItem="tfS-Rc-iEN" firstAttribute="leading" secondItem="EXN-FR-v0M" secondAttribute="trailing" constant="10" id="4dx-rG-JsD"/>
+                        <constraint firstItem="EXN-FR-v0M" firstAttribute="bottom" secondItem="sav-8B-TD3" secondAttribute="bottom" id="9F3-pd-MYs"/>
+                        <constraint firstItem="tfS-Rc-iEN" firstAttribute="width" secondItem="sav-8B-TD3" secondAttribute="width" id="CLF-fI-pzs"/>
+                        <constraint firstItem="EXN-FR-v0M" firstAttribute="top" secondItem="sav-8B-TD3" secondAttribute="top" id="FLx-ZH-cjQ"/>
+                        <constraint firstItem="tfS-Rc-iEN" firstAttribute="top" secondItem="sav-8B-TD3" secondAttribute="top" id="Hbw-pi-fCh"/>
+                        <constraint firstItem="sav-8B-TD3" firstAttribute="top" secondItem="LpR-2y-gXZ" secondAttribute="top" id="Ihc-cJ-1Oh"/>
+                        <constraint firstItem="tfS-Rc-iEN" firstAttribute="bottom" secondItem="sav-8B-TD3" secondAttribute="bottom" id="Xfd-4u-1IF"/>
+                        <constraint firstAttribute="bottom" secondItem="sav-8B-TD3" secondAttribute="bottom" id="bu2-X6-Yg6"/>
+                        <constraint firstItem="EXN-FR-v0M" firstAttribute="width" secondItem="sav-8B-TD3" secondAttribute="width" id="fPc-ee-c1N"/>
+                        <constraint firstAttribute="trailing" secondItem="tfS-Rc-iEN" secondAttribute="trailing" id="u1e-Ax-BTi"/>
+                        <constraint firstItem="sav-8B-TD3" firstAttribute="leading" secondItem="LpR-2y-gXZ" secondAttribute="leading" id="uCG-Vn-Bi5"/>
+                        <constraint firstItem="EXN-FR-v0M" firstAttribute="leading" secondItem="sav-8B-TD3" secondAttribute="trailing" constant="10" id="vlA-mz-du1"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="size" keyPath="shadowOffset">
+                            <size key="value" width="0.0" height="2"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowOpacity">
+                            <real key="value" value="1"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowRadius">
+                            <real key="value" value="7"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="shadowUIColor">
+                            <color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.070000000000000007" colorSpace="calibratedRGB"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="LpR-2y-gXZ" secondAttribute="trailing" id="TJN-ui-GfD"/>
+                <constraint firstItem="LpR-2y-gXZ" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="cRb-QE-c94"/>
+                <constraint firstItem="LpR-2y-gXZ" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="jZD-EQ-305"/>
+                <constraint firstAttribute="bottom" secondItem="LpR-2y-gXZ" secondAttribute="bottom" id="mqe-U8-IPW"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="firstArrow" destination="vSU-NS-Qou" id="Kv5-mp-IhS"/>
+                <outlet property="firstButton" destination="CSP-VE-Q55" id="Lyn-Ga-7zx"/>
+                <outlet property="secondArrow" destination="OTv-DP-LWv" id="t4Z-hT-MB6"/>
+                <outlet property="secondButton" destination="4ob-Ur-wiA" id="DiD-8c-xf0"/>
+                <outlet property="thirdArrow" destination="2nN-nP-Pcx" id="VyH-DI-YOp"/>
+                <outlet property="thirdButton" destination="cgC-dL-lRH" id="ct4-B7-EIj"/>
+            </connections>
+            <point key="canvasLocation" x="131.8840579710145" y="-33.482142857142854"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="sort_down" width="8" height="6"/>
+    </resources>
+</document>

+ 21 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLiveCourseCell.h

@@ -0,0 +1,21 @@
+//
+//  MyLiveCourseCell.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/12.
+//
+
+#import <UIKit/UIKit.h>
+#import "LiveLessonModel.h"
+
+typedef void(^LiveLessonChatAction)(NSString * _Nonnull targetId);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MyLiveCourseCell : UITableViewCell
+
+- (void)configCellWithSource:(LiveLessonModel *)model callback:(LiveLessonChatAction)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 90 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLiveCourseCell.m

@@ -0,0 +1,90 @@
+//
+//  MyLiveCourseCell.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/12.
+//
+
+#import "MyLiveCourseCell.h"
+
+@interface MyLiveCourseCell ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *courseCoverImage;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseNameLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *subjectName;
+
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *statusLabel;
+
+@property (nonatomic, strong) NSString *targetId;
+
+@property (nonatomic, copy) LiveLessonChatAction callback;
+@end
+
+@implementation MyLiveCourseCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+- (void)configCellWithSource:(LiveLessonModel *)model callback:(LiveLessonChatAction)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    [self.courseCoverImage sd_setImageWithURL:[NSURL URLWithString:model.backgroundPic] placeholderImage:[UIImage imageNamed:@"video_placeholder"]];
+    self.courseNameLabel.text = [NSString returnNoNullStringWithString:model.courseGroupName];
+    self.subjectName.text = [NSString returnNoNullStringWithString:model.subjectName];
+    self.descLabel.text = [NSString stringWithFormat:@"%.0f人已购买",model.studentCount];
+    self.targetId = model.courseGroupId;
+    // time
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *startDate = [formatter dateFromString:model.startTime];
+    NSDate *endDate = [formatter dateFromString:model.endTime];
+    
+    [formatter setDateFormat:@"yyyy/MM/dd HH:mm"];
+    NSString *courseBegin = [formatter stringFromDate:startDate];
+    [formatter setDateFormat:@"HH:mm"];
+    NSString *endTime = [formatter stringFromDate:endDate];
+    self.timeLabel.text = [NSString stringWithFormat:@"%@~%@",[NSString returnNoNullStringWithString:courseBegin], [NSString returnNoNullStringWithString:endTime]];
+    
+    //  课程状态
+    [self evaluateStatus:model.status];
+}
+
+- (void)evaluateStatus:(NSString *)status {
+    if ([status isEqualToString:@"ING"]) { // 进行中
+        self.statusLabel.text = @"进行中";
+        self.statusLabel.textColor = THEMECOLOR;
+    }
+    else if ([status isEqualToString:@"NOT_START"]) { // 为开始
+        self.statusLabel.text = @"未开始";
+        self.statusLabel.textColor = HexRGB(0xff802c);
+    }
+    else if ([status isEqualToString:@"COMPLETE"]) { // 已结束
+        self.statusLabel.text = @"已结束";
+        self.statusLabel.textColor = HexRGB(0x999999);
+    }
+}
+
+- (IBAction)chatAction:(id)sender {
+    if (self.callback) {
+        self.callback(self.targetId);
+    }
+}
+
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 198 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLiveCourseCell.xib

@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="164" id="KGk-i7-Jjw" customClass="MyLiveCourseCell">
+            <rect key="frame" x="0.0" y="0.0" width="396" height="164"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
+                <rect key="frame" x="0.0" y="0.0" width="396" height="164"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9Mv-FD-03n">
+                        <rect key="frame" x="14" y="0.0" width="368" height="152"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="video_placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="NWN-u6-1To">
+                                <rect key="frame" x="11" y="16" width="105" height="71"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="105" id="FfC-qz-2vt"/>
+                                    <constraint firstAttribute="height" constant="71" id="I46-Vb-KPv"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="4"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </imageView>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z3n-pP-QqQ">
+                                <rect key="frame" x="10" y="102" width="348" height="1"/>
+                                <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="1" id="h6v-qm-9HE"/>
+                                </constraints>
+                            </view>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="从零开始学竖笛直播课" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9C1-zD-NKp">
+                                <rect key="frame" x="128" y="17" width="153" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="jZt-hb-zgs"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
+                                <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="进行中" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VrX-Hy-enc">
+                                <rect key="frame" x="314" y="111" width="43" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="nme-QD-dNX"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <color key="textColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nk8-cr-bIe">
+                                <rect key="frame" x="165.5" y="68" width="190.5" height="20"/>
+                                <subviews>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L8Z-vN-njT">
+                                        <rect key="frame" x="0.0" y="4.5" width="1" height="11"/>
+                                        <color key="backgroundColor" red="0.82745098039999998" green="0.82745098039999998" blue="0.82745098039999998" alpha="1" colorSpace="calibratedRGB"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="11" id="kC6-Sk-pFt"/>
+                                            <constraint firstAttribute="width" constant="1" id="sHX-nY-QUC"/>
+                                        </constraints>
+                                    </view>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="6人已购买" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Z2r-ta-wPC">
+                                        <rect key="frame" x="7" y="2" width="61.5" height="16"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                        <color key="textColor" red="1" green="0.50196078430000002" blue="0.17254901959999999" alpha="1" colorSpace="calibratedRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="6hD-Zm-lqn"/>
+                                    <constraint firstItem="Z2r-ta-wPC" firstAttribute="leading" secondItem="L8Z-vN-njT" secondAttribute="trailing" constant="6" id="DdG-Rm-I06"/>
+                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Z2r-ta-wPC" secondAttribute="trailing" constant="2" id="Jyv-hq-k4o"/>
+                                    <constraint firstItem="L8Z-vN-njT" firstAttribute="centerY" secondItem="Nk8-cr-bIe" secondAttribute="centerY" id="VPS-kd-fiV"/>
+                                    <constraint firstItem="L8Z-vN-njT" firstAttribute="leading" secondItem="Nk8-cr-bIe" secondAttribute="leading" id="l6d-g2-l32"/>
+                                    <constraint firstItem="Z2r-ta-wPC" firstAttribute="centerY" secondItem="Nk8-cr-bIe" secondAttribute="centerY" id="npN-uI-5WD"/>
+                                </constraints>
+                            </view>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="course_time" translatesAutoresizingMaskIntoConstraints="NO" id="zwg-bj-X8b">
+                                <rect key="frame" x="11" y="114" width="16" height="16"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="16" id="D2y-TK-hj5"/>
+                                    <constraint firstAttribute="width" constant="16" id="jJm-KX-qcy"/>
+                                </constraints>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2021/09/17 14:00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QUH-rb-n4x">
+                                <rect key="frame" x="34" y="114" width="105" height="16"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8e5-WE-PwG">
+                                <rect key="frame" x="130" y="70" width="30.5" height="16"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="长笛" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GLH-rY-bmS">
+                                        <rect key="frame" x="4" y="1" width="22.5" height="13"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="11"/>
+                                        <color key="textColor" red="1" green="0.5490196078431373" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="1" green="0.94509803921568625" blue="0.87058823529411766" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="16" id="2kj-oi-wkU"/>
+                                    <constraint firstAttribute="bottom" secondItem="GLH-rY-bmS" secondAttribute="bottom" constant="2" id="Qwe-R2-kYB"/>
+                                    <constraint firstItem="GLH-rY-bmS" firstAttribute="top" secondItem="8e5-WE-PwG" secondAttribute="top" constant="1" id="aJC-lf-Zrs"/>
+                                    <constraint firstAttribute="trailing" secondItem="GLH-rY-bmS" secondAttribute="trailing" constant="4" id="liw-dJ-aUw"/>
+                                    <constraint firstItem="GLH-rY-bmS" firstAttribute="leading" secondItem="8e5-WE-PwG" secondAttribute="leading" constant="4" id="vuP-BL-Lp9"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="4"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2Kh-s4-xZJ">
+                                <rect key="frame" x="286" y="7" width="40" height="40"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="40" id="G8p-eG-zeE"/>
+                                    <constraint firstAttribute="width" constant="40" id="W6r-uH-v7W"/>
+                                </constraints>
+                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                <state key="normal" image="chat_chat"/>
+                                <connections>
+                                    <action selector="chatAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="sIl-Bo-eWo"/>
+                                </connections>
+                            </button>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstItem="9C1-zD-NKp" firstAttribute="leading" secondItem="NWN-u6-1To" secondAttribute="trailing" constant="12" id="9xV-WZ-Jeb"/>
+                            <constraint firstAttribute="trailing" secondItem="Nk8-cr-bIe" secondAttribute="trailing" constant="12" id="CVV-yo-0Sx"/>
+                            <constraint firstItem="zwg-bj-X8b" firstAttribute="leading" secondItem="9Mv-FD-03n" secondAttribute="leading" constant="11" id="Eg4-fY-s6L"/>
+                            <constraint firstItem="VrX-Hy-enc" firstAttribute="top" secondItem="Z3n-pP-QqQ" secondAttribute="bottom" constant="8" id="HJr-KG-LRz"/>
+                            <constraint firstItem="Z3n-pP-QqQ" firstAttribute="top" secondItem="NWN-u6-1To" secondAttribute="bottom" constant="15" id="HWE-Lc-PGR"/>
+                            <constraint firstAttribute="trailing" secondItem="VrX-Hy-enc" secondAttribute="trailing" constant="11" id="IuH-hK-LDm"/>
+                            <constraint firstItem="QUH-rb-n4x" firstAttribute="leading" secondItem="zwg-bj-X8b" secondAttribute="trailing" constant="7" id="Kv8-pd-LT7"/>
+                            <constraint firstItem="Nk8-cr-bIe" firstAttribute="centerY" secondItem="8e5-WE-PwG" secondAttribute="centerY" id="WJO-du-YZM"/>
+                            <constraint firstItem="2Kh-s4-xZJ" firstAttribute="leading" secondItem="9C1-zD-NKp" secondAttribute="trailing" constant="5" id="Wf6-Mf-Upf"/>
+                            <constraint firstItem="zwg-bj-X8b" firstAttribute="top" secondItem="Z3n-pP-QqQ" secondAttribute="bottom" constant="11" id="YNp-yH-cDb"/>
+                            <constraint firstItem="NWN-u6-1To" firstAttribute="top" secondItem="9Mv-FD-03n" secondAttribute="top" constant="16" id="cGY-p8-lN7"/>
+                            <constraint firstItem="NWN-u6-1To" firstAttribute="leading" secondItem="9Mv-FD-03n" secondAttribute="leading" constant="11" id="cfe-2g-SQh"/>
+                            <constraint firstItem="8e5-WE-PwG" firstAttribute="leading" secondItem="NWN-u6-1To" secondAttribute="trailing" constant="14" id="gct-Bj-cAn"/>
+                            <constraint firstItem="Z3n-pP-QqQ" firstAttribute="leading" secondItem="9Mv-FD-03n" secondAttribute="leading" constant="10" id="hry-ZU-tVs"/>
+                            <constraint firstItem="9C1-zD-NKp" firstAttribute="top" secondItem="NWN-u6-1To" secondAttribute="top" constant="1" id="jfN-JM-ITb"/>
+                            <constraint firstItem="2Kh-s4-xZJ" firstAttribute="centerY" secondItem="9C1-zD-NKp" secondAttribute="centerY" id="mRw-yl-KmV"/>
+                            <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="2Kh-s4-xZJ" secondAttribute="trailing" id="nNd-mX-E6C"/>
+                            <constraint firstAttribute="trailing" secondItem="Z3n-pP-QqQ" secondAttribute="trailing" constant="10" id="oVA-kc-t3T"/>
+                            <constraint firstItem="8e5-WE-PwG" firstAttribute="bottom" secondItem="NWN-u6-1To" secondAttribute="bottom" constant="-1" id="r3t-nW-e8s"/>
+                            <constraint firstItem="QUH-rb-n4x" firstAttribute="centerY" secondItem="zwg-bj-X8b" secondAttribute="centerY" id="uBT-wz-dHP"/>
+                            <constraint firstItem="Nk8-cr-bIe" firstAttribute="leading" secondItem="8e5-WE-PwG" secondAttribute="trailing" constant="5" id="zoz-sK-NnJ"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="10"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="9Mv-FD-03n" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="AO0-g2-drH"/>
+                    <constraint firstAttribute="bottom" secondItem="9Mv-FD-03n" secondAttribute="bottom" constant="12" id="VYf-HS-AeG"/>
+                    <constraint firstItem="9Mv-FD-03n" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="14" id="ZcW-pC-Pdu"/>
+                    <constraint firstAttribute="trailing" secondItem="9Mv-FD-03n" secondAttribute="trailing" constant="14" id="zxh-ku-GLf"/>
+                </constraints>
+            </tableViewCellContentView>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <connections>
+                <outlet property="courseCoverImage" destination="NWN-u6-1To" id="5H2-Pf-5WA"/>
+                <outlet property="courseNameLabel" destination="9C1-zD-NKp" id="dMl-ob-iwk"/>
+                <outlet property="descLabel" destination="Z2r-ta-wPC" id="DTT-W9-umA"/>
+                <outlet property="statusLabel" destination="VrX-Hy-enc" id="6M9-tY-aZT"/>
+                <outlet property="subjectName" destination="GLH-rY-bmS" id="CtN-f5-rMC"/>
+                <outlet property="timeLabel" destination="QUH-rb-n4x" id="RV0-zl-r5M"/>
+            </connections>
+            <point key="canvasLocation" x="186.95652173913044" y="118.52678571428571"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="chat_chat" width="19" height="18"/>
+        <image name="course_time" width="16" height="16"/>
+        <image name="video_placeholder" width="168" height="111"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä