Jelajahi Sumber

我的课程->小组课

Steven 2 hari lalu
induk
melakukan
9b707581e4
75 mengubah file dengan 3551 tambahan dan 335 penghapusan
  1. 114 0
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. 1 1
      KulexiuForStudent/KulexiuForStudent.xcodeproj/xcshareddata/xcschemes/KulexiuForStudent.xcscheme
  3. 7 0
      KulexiuForStudent/KulexiuForStudent/AppDelegate.m
  4. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_group.imageset/Contents.json
  5. TEMPAT SAMPAH
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_group.imageset/course_group@2x.png
  6. TEMPAT SAMPAH
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_group.imageset/course_group@3x.png
  7. TEMPAT SAMPAH
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_musicRoom.imageset/course_musicRoom@2x.png
  8. TEMPAT SAMPAH
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_musicRoom.imageset/course_musicRoom@3x.png
  9. TEMPAT SAMPAH
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/lesson_Live@2x.png
  10. TEMPAT SAMPAH
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/lesson_Live.imageset/lesson_Live@3x.png
  11. 14 2
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h
  12. 21 2
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m
  13. 8 3
      KulexiuForStudent/KulexiuForStudent/Module/Course/Controller/CourseViewController.m
  14. 7 1
      KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/Controller/MusicRoomDetailViewController.h
  15. 2 1
      KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/Controller/MusicRoomDetailViewController.m
  16. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/View/MusicRoomCourseInfoCell.h
  17. 6 2
      KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/View/MusicRoomCourseInfoCell.m
  18. 2 1
      KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/View/MusicRoomCourseInfoCell.xib
  19. 24 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Controller/MyGroupCourseGroupController.h
  20. 255 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Controller/MyGroupCourseGroupController.m
  21. 47 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Model/GroupCourseGroupInfoModel.h
  22. 284 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Model/GroupCourseGroupInfoModel.m
  23. 23 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupHeadView.h
  24. 134 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupHeadView.m
  25. 317 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupHeadView.xib
  26. 24 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupNavView.h
  27. 47 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupNavView.m
  28. 70 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupNavView.xib
  29. 20 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseListCell.h
  30. 161 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseListCell.m
  31. 248 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseListCell.xib
  32. 0 4
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseGroupView/GroupCourseSortView.h
  33. 10 32
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseGroupView/GroupCourseSortView.m
  34. 74 136
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseGroupView/GroupCourseSortView.xib
  35. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/MusicRoomCourseCell.h
  36. 4 1
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/MusicRoomCourseCell.m
  37. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/MusicRoomCourseCell.xib
  38. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/Model/StudentGroupCourseListModel.h
  39. 7 3
      KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/Model/StudentGroupCourseListModel.m
  40. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/View/ProgramCourseGroupBodyView.h
  41. 25 59
      KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/View/ProgramCourseGroupBodyView.m
  42. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Controller/HomeArrangeCourseController.h
  43. 19 2
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Controller/HomeArrangeCourseController.m
  44. 2 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Model/ArrangeLiveCourseModel.h
  45. 7 4
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Model/ArrangeLiveCourseModel.m
  46. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseDescAlertView.h
  47. 0 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseDescAlertView.m
  48. 0 16
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseTeacherDescCell.m
  49. 2 35
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseTeacherDescCell.xib
  50. 19 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/GroupCourseArrangeCell.h
  51. 80 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/GroupCourseArrangeCell.m
  52. 239 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/GroupCourseArrangeCell.xib
  53. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeAccompanyCourseView.m
  54. 18 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeGroupCourseView.h
  55. 357 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeGroupCourseView.m
  56. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeLiveCourseView.m
  57. 14 14
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeRankView.m
  58. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeVIPCourseView.m
  59. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/LiveCourseArrangeCell.m
  60. 5 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/Controller/HomeViewController.m
  61. 6 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/NoticeCenter/Controller/NotiferMessageViewController.m
  62. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Mine/Homework/View/HomeworkSortView.m
  63. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Controller/MyCourseViewController.h
  64. 21 4
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Controller/MyCourseViewController.m
  65. 3 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/LiveLessonModel.h
  66. 17 1
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/LiveLessonModel.m
  67. 0 1
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/AccompanyCourseGroup/MyAccompanyCourseGroupView.m
  68. 19 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupListCell.h
  69. 101 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupListCell.m
  70. 240 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupListCell.xib
  71. 18 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupView.h
  72. 368 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupView.m
  73. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/LiveCourseGroup/MyLiveCourseGroupView.m
  74. 2 1
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyCourseSortView/MyCourseRankSortView.m
  75. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonBodyView.m

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

@@ -741,12 +741,26 @@
 		BC9DA08E2CF9647300674ED9 /* delay_check_ light.json in Resources */ = {isa = PBXBuildFile; fileRef = BC9DA08A2CF9647300674ED9 /* delay_check_ light.json */; };
 		BC9DA08F2CF9647300674ED9 /* delay_check_seaGrass_left.json in Resources */ = {isa = PBXBuildFile; fileRef = BC9DA08B2CF9647300674ED9 /* delay_check_seaGrass_left.json */; };
 		BC9DA0912CF9649D00674ED9 /* delay_check_ bubble.json in Resources */ = {isa = PBXBuildFile; fileRef = BC9DA0902CF9649D00674ED9 /* delay_check_ bubble.json */; };
+		BCA0CB302D1A5FD400488F8E /* MyGroupCourseGroupController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA0CB2F2D1A5FD400488F8E /* MyGroupCourseGroupController.m */; };
+		BCA0CB3A2D1A61B600488F8E /* GroupCourseListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA0CB382D1A61B600488F8E /* GroupCourseListCell.m */; };
+		BCA0CB3B2D1A61B600488F8E /* GroupCourseGroupHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA0CB322D1A61B600488F8E /* GroupCourseGroupHeadView.m */; };
+		BCA0CB3C2D1A61B600488F8E /* GroupCourseGroupNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA0CB352D1A61B600488F8E /* GroupCourseGroupNavView.m */; };
+		BCA0CB3D2D1A61B600488F8E /* GroupCourseGroupHeadView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA0CB332D1A61B600488F8E /* GroupCourseGroupHeadView.xib */; };
+		BCA0CB3E2D1A61B600488F8E /* GroupCourseGroupNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA0CB362D1A61B600488F8E /* GroupCourseGroupNavView.xib */; };
+		BCA0CB3F2D1A61B600488F8E /* GroupCourseListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA0CB392D1A61B600488F8E /* GroupCourseListCell.xib */; };
+		BCA0CB422D1A625200488F8E /* GroupCourseGroupInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA0CB412D1A625200488F8E /* GroupCourseGroupInfoModel.m */; };
 		BCA1136828A3A5CF007FAFB9 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCA1136728A3A5CF007FAFB9 /* Accelerate.framework */; };
 		BCA193B8282B6094004A585D /* RecentCourseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA193B7282B6094004A585D /* RecentCourseModel.m */; };
 		BCA336992C942B280074DF75 /* KSSourceDownloadAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA336962C942B270074DF75 /* KSSourceDownloadAlert.m */; };
 		BCA3369A2C942B280074DF75 /* KSSourceDownloadAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA336972C942B280074DF75 /* KSSourceDownloadAlert.xib */; };
 		BCA353F12859BB2900377661 /* MusicRoomCourseCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA353EF2859BB2700377661 /* MusicRoomCourseCell.xib */; };
 		BCA353F22859BB2900377661 /* MusicRoomCourseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA353F02859BB2900377661 /* MusicRoomCourseCell.m */; };
+		BCA9A5D02D19185800C7CC9D /* HomeArrangeGroupCourseView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA9A5CF2D19185800C7CC9D /* HomeArrangeGroupCourseView.m */; };
+		BCA9A5D42D1918C500C7CC9D /* GroupCourseArrangeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA9A5D22D1918C500C7CC9D /* GroupCourseArrangeCell.m */; };
+		BCA9A5D52D1918C500C7CC9D /* GroupCourseArrangeCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA9A5D32D1918C500C7CC9D /* GroupCourseArrangeCell.xib */; };
+		BCAAD0AE2D1938EB0069872D /* MyGroupCourseGroupView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCAAD0AD2D1938EB0069872D /* MyGroupCourseGroupView.m */; };
+		BCAAD0B22D19390A0069872D /* MyGroupCourseGroupListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCAAD0B02D19390A0069872D /* MyGroupCourseGroupListCell.m */; };
+		BCAAD0B32D19390A0069872D /* MyGroupCourseGroupListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCAAD0B12D19390A0069872D /* MyGroupCourseGroupListCell.xib */; };
 		BCB574EC2BC4D643005EE78F /* cloudCourse_Ani.json in Resources */ = {isa = PBXBuildFile; fileRef = BCB574EB2BC4D643005EE78F /* cloudCourse_Ani.json */; };
 		BCB5B2D12ABAFE8E005BF25D /* HomeMusicSheetLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB5B2D02ABAFE8E005BF25D /* HomeMusicSheetLayout.m */; };
 		BCB5B2D52ABB1E13005BF25D /* KSEmptyStatusView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB5B2D22ABB1E12005BF25D /* KSEmptyStatusView.m */; };
@@ -2274,6 +2288,19 @@
 		BC9DA08B2CF9647300674ED9 /* delay_check_seaGrass_left.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = delay_check_seaGrass_left.json; sourceTree = "<group>"; };
 		BC9DA08C2CF9647300674ED9 /* delay_check_seaGrass_right.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = delay_check_seaGrass_right.json; sourceTree = "<group>"; };
 		BC9DA0902CF9649D00674ED9 /* delay_check_ bubble.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "delay_check_ bubble.json"; sourceTree = "<group>"; };
+		BCA0CB2E2D1A5FD400488F8E /* MyGroupCourseGroupController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGroupCourseGroupController.h; sourceTree = "<group>"; };
+		BCA0CB2F2D1A5FD400488F8E /* MyGroupCourseGroupController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyGroupCourseGroupController.m; sourceTree = "<group>"; };
+		BCA0CB312D1A61B600488F8E /* GroupCourseGroupHeadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GroupCourseGroupHeadView.h; sourceTree = "<group>"; };
+		BCA0CB322D1A61B600488F8E /* GroupCourseGroupHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GroupCourseGroupHeadView.m; sourceTree = "<group>"; };
+		BCA0CB332D1A61B600488F8E /* GroupCourseGroupHeadView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GroupCourseGroupHeadView.xib; sourceTree = "<group>"; };
+		BCA0CB342D1A61B600488F8E /* GroupCourseGroupNavView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GroupCourseGroupNavView.h; sourceTree = "<group>"; };
+		BCA0CB352D1A61B600488F8E /* GroupCourseGroupNavView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GroupCourseGroupNavView.m; sourceTree = "<group>"; };
+		BCA0CB362D1A61B600488F8E /* GroupCourseGroupNavView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GroupCourseGroupNavView.xib; sourceTree = "<group>"; };
+		BCA0CB372D1A61B600488F8E /* GroupCourseListCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GroupCourseListCell.h; sourceTree = "<group>"; };
+		BCA0CB382D1A61B600488F8E /* GroupCourseListCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GroupCourseListCell.m; sourceTree = "<group>"; };
+		BCA0CB392D1A61B600488F8E /* GroupCourseListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GroupCourseListCell.xib; sourceTree = "<group>"; };
+		BCA0CB402D1A625200488F8E /* GroupCourseGroupInfoModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GroupCourseGroupInfoModel.h; sourceTree = "<group>"; };
+		BCA0CB412D1A625200488F8E /* GroupCourseGroupInfoModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GroupCourseGroupInfoModel.m; sourceTree = "<group>"; };
 		BCA1136728A3A5CF007FAFB9 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
 		BCA193B6282B6094004A585D /* RecentCourseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentCourseModel.h; sourceTree = "<group>"; };
 		BCA193B7282B6094004A585D /* RecentCourseModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCourseModel.m; sourceTree = "<group>"; };
@@ -2283,6 +2310,16 @@
 		BCA353EE2859BB2600377661 /* MusicRoomCourseCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicRoomCourseCell.h; sourceTree = "<group>"; };
 		BCA353EF2859BB2700377661 /* MusicRoomCourseCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MusicRoomCourseCell.xib; sourceTree = "<group>"; };
 		BCA353F02859BB2900377661 /* MusicRoomCourseCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MusicRoomCourseCell.m; sourceTree = "<group>"; };
+		BCA9A5CE2D19185800C7CC9D /* HomeArrangeGroupCourseView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeArrangeGroupCourseView.h; sourceTree = "<group>"; };
+		BCA9A5CF2D19185800C7CC9D /* HomeArrangeGroupCourseView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeArrangeGroupCourseView.m; sourceTree = "<group>"; };
+		BCA9A5D12D1918C500C7CC9D /* GroupCourseArrangeCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GroupCourseArrangeCell.h; sourceTree = "<group>"; };
+		BCA9A5D22D1918C500C7CC9D /* GroupCourseArrangeCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GroupCourseArrangeCell.m; sourceTree = "<group>"; };
+		BCA9A5D32D1918C500C7CC9D /* GroupCourseArrangeCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GroupCourseArrangeCell.xib; sourceTree = "<group>"; };
+		BCAAD0AC2D1938EB0069872D /* MyGroupCourseGroupView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGroupCourseGroupView.h; sourceTree = "<group>"; };
+		BCAAD0AD2D1938EB0069872D /* MyGroupCourseGroupView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyGroupCourseGroupView.m; sourceTree = "<group>"; };
+		BCAAD0AF2D19390A0069872D /* MyGroupCourseGroupListCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyGroupCourseGroupListCell.h; sourceTree = "<group>"; };
+		BCAAD0B02D19390A0069872D /* MyGroupCourseGroupListCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyGroupCourseGroupListCell.m; sourceTree = "<group>"; };
+		BCAAD0B12D19390A0069872D /* MyGroupCourseGroupListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyGroupCourseGroupListCell.xib; sourceTree = "<group>"; };
 		BCB574EB2BC4D643005EE78F /* cloudCourse_Ani.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = cloudCourse_Ani.json; sourceTree = "<group>"; };
 		BCB5B2CF2ABAFE8E005BF25D /* HomeMusicSheetLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeMusicSheetLayout.h; sourceTree = "<group>"; };
 		BCB5B2D02ABAFE8E005BF25D /* HomeMusicSheetLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeMusicSheetLayout.m; sourceTree = "<group>"; };
@@ -3183,6 +3220,7 @@
 		275FA1F727E7356A00CFEA2E /* Course */ = {
 			isa = PBXGroup;
 			children = (
+				BCAAD0B72D1940970069872D /* MyGroupCourse */,
 				BCFB9B9B2CE49F7A00B66BC0 /* VipCourse */,
 				BC494A73286952A200CCD343 /* MusicRoom */,
 				BC11923B280ED9CC00A716F7 /* AccompanyCourse */,
@@ -4087,6 +4125,7 @@
 				BC7354972CEED2EB00C2B35C /* MyCourseGroupNavView.m */,
 				BC7354982CEED2EB00C2B35C /* MyCourseGroupNavView.xib */,
 				BC7354642CEED28000C2B35C /* AccompanyCourseGroup */,
+				BCAAD0AB2D1938D50069872D /* GroupCourseGroup */,
 				BC73546A2CEED28000C2B35C /* LiveCourseGroup */,
 				BC7354702CEED28000C2B35C /* MusicRoomCourseGroup */,
 				BC7354742CEED28000C2B35C /* MyCourseSortView */,
@@ -4515,6 +4554,11 @@
 				BC2C1BB02CEB555500EDEB97 /* HomeArrangeVIPCourseView.m */,
 				BC2C1BB22CEB556100EDEB97 /* HomeArrangeAccompanyCourseView.h */,
 				BC2C1BB32CEB556100EDEB97 /* HomeArrangeAccompanyCourseView.m */,
+				BCA9A5CE2D19185800C7CC9D /* HomeArrangeGroupCourseView.h */,
+				BCA9A5CF2D19185800C7CC9D /* HomeArrangeGroupCourseView.m */,
+				BCA9A5D12D1918C500C7CC9D /* GroupCourseArrangeCell.h */,
+				BCA9A5D22D1918C500C7CC9D /* GroupCourseArrangeCell.m */,
+				BCA9A5D32D1918C500C7CC9D /* GroupCourseArrangeCell.xib */,
 				BC2C1BB52CEB556E00EDEB97 /* HomeArrangeLiveCourseView.h */,
 				BC2C1BB62CEB556E00EDEB97 /* HomeArrangeLiveCourseView.m */,
 				BC2C1BB82CEB557700EDEB97 /* HomeArrangeVideoCourseView.h */,
@@ -5798,6 +5842,62 @@
 			path = LoadingManager;
 			sourceTree = "<group>";
 		};
+		BCAAD0AB2D1938D50069872D /* GroupCourseGroup */ = {
+			isa = PBXGroup;
+			children = (
+				BCAAD0AC2D1938EB0069872D /* MyGroupCourseGroupView.h */,
+				BCAAD0AD2D1938EB0069872D /* MyGroupCourseGroupView.m */,
+				BCAAD0AF2D19390A0069872D /* MyGroupCourseGroupListCell.h */,
+				BCAAD0B02D19390A0069872D /* MyGroupCourseGroupListCell.m */,
+				BCAAD0B12D19390A0069872D /* MyGroupCourseGroupListCell.xib */,
+			);
+			path = GroupCourseGroup;
+			sourceTree = "<group>";
+		};
+		BCAAD0B42D1940970069872D /* Controller */ = {
+			isa = PBXGroup;
+			children = (
+				BCA0CB2E2D1A5FD400488F8E /* MyGroupCourseGroupController.h */,
+				BCA0CB2F2D1A5FD400488F8E /* MyGroupCourseGroupController.m */,
+			);
+			path = Controller;
+			sourceTree = "<group>";
+		};
+		BCAAD0B52D1940970069872D /* Model */ = {
+			isa = PBXGroup;
+			children = (
+				BCA0CB402D1A625200488F8E /* GroupCourseGroupInfoModel.h */,
+				BCA0CB412D1A625200488F8E /* GroupCourseGroupInfoModel.m */,
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		BCAAD0B62D1940970069872D /* View */ = {
+			isa = PBXGroup;
+			children = (
+				BCA0CB312D1A61B600488F8E /* GroupCourseGroupHeadView.h */,
+				BCA0CB322D1A61B600488F8E /* GroupCourseGroupHeadView.m */,
+				BCA0CB332D1A61B600488F8E /* GroupCourseGroupHeadView.xib */,
+				BCA0CB342D1A61B600488F8E /* GroupCourseGroupNavView.h */,
+				BCA0CB352D1A61B600488F8E /* GroupCourseGroupNavView.m */,
+				BCA0CB362D1A61B600488F8E /* GroupCourseGroupNavView.xib */,
+				BCA0CB372D1A61B600488F8E /* GroupCourseListCell.h */,
+				BCA0CB382D1A61B600488F8E /* GroupCourseListCell.m */,
+				BCA0CB392D1A61B600488F8E /* GroupCourseListCell.xib */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		BCAAD0B72D1940970069872D /* MyGroupCourse */ = {
+			isa = PBXGroup;
+			children = (
+				BCAAD0B42D1940970069872D /* Controller */,
+				BCAAD0B52D1940970069872D /* Model */,
+				BCAAD0B62D1940970069872D /* View */,
+			);
+			path = MyGroupCourse;
+			sourceTree = "<group>";
+		};
 		BCB6340A27F6D29500ACFDCF /* Live */ = {
 			isa = PBXGroup;
 			children = (
@@ -6799,6 +6899,7 @@
 				BCC0F6B02A8CDD4000C4EFA4 /* high_staff.png in Resources */,
 				BCECE2482B3D670500C0D555 /* FeedbackBodyView.xib in Resources */,
 				275FA23A27E7356B00CFEA2E /* VefiBodyView.xib in Resources */,
+				BCA9A5D52D1918C500C7CC9D /* GroupCourseArrangeCell.xib in Resources */,
 				BC82D70C2CF470B8007C947B /* VIPCourseCell.xib in Resources */,
 				BCCE95D52AB043EF00AB6385 /* mutiMusic_Ani.json in Resources */,
 				BC119258280FA85300A716F7 /* HomeworkListCell.xib in Resources */,
@@ -6807,6 +6908,9 @@
 				BC106C3B2A9338A7000759A9 /* custom_loading.json in Resources */,
 				BC89AC1A2AB08FA100B077AF /* TenantMusicCollectionViewCell.xib in Resources */,
 				2723B63227F157D500E0B90B /* GroupSettingBodyView.xib in Resources */,
+				BCA0CB3D2D1A61B600488F8E /* GroupCourseGroupHeadView.xib in Resources */,
+				BCA0CB3E2D1A61B600488F8E /* GroupCourseGroupNavView.xib in Resources */,
+				BCA0CB3F2D1A61B600488F8E /* GroupCourseListCell.xib in Resources */,
 				BC5A4B692CF40C35008C2FDD /* CourseGroupPlanAlertView.xib in Resources */,
 				BC5A4B6A2CF40C35008C2FDD /* CourseGroupPlanDescView.xib in Resources */,
 				BC5A4B6B2CF40C35008C2FDD /* CourseGroupPlanAddView.xib in Resources */,
@@ -6852,6 +6956,7 @@
 				BC119280280FB10900A716F7 /* AccompanyRemarkCell.xib in Resources */,
 				BC5A4B512CF40BF9008C2FDD /* ProgramCourseInfoView.xib in Resources */,
 				BC5A4B532CF40BF9008C2FDD /* VipCouseInfoCell.xib in Resources */,
+				BCAAD0B32D19390A0069872D /* MyGroupCourseGroupListCell.xib in Resources */,
 				BC7354992CEED2EB00C2B35C /* MyCourseGroupNavView.xib in Resources */,
 				BC71D271288804CD0010F14B /* img_26.png in Resources */,
 				BC12639F28FF8E7400509E90 /* HomeRecommendMusicView.xib in Resources */,
@@ -7299,6 +7404,7 @@
 				BCCE95E72AB057BF00AB6385 /* MorePageSearchView.m in Sources */,
 				2723B61E27F157D500E0B90B /* GroupNoticeEditController.m in Sources */,
 				BCFDA63728BCA1C60022B497 /* HomeRecentCourseView.m in Sources */,
+				BCA9A5D02D19185800C7CC9D /* HomeArrangeGroupCourseView.m in Sources */,
 				BC0212FE27FC66AA0040569F /* InstrumentMessageModel.m in Sources */,
 				BC0D1F752810165500C5D9E5 /* VideoCourseModel.m in Sources */,
 				BC802D9D28BC546B0079E350 /* HomeHotMusicCollectionCell.m in Sources */,
@@ -7371,6 +7477,7 @@
 				BCFB9BA72CE58C5400B66BC0 /* MusicRoomGroupViewController.m in Sources */,
 				BC12636D28FEA20100509E90 /* RecentMusicView.m in Sources */,
 				BC8C2C5F2823F57100FBA5D5 /* MyAddressListCell.m in Sources */,
+				BCA0CB422D1A625200488F8E /* GroupCourseGroupInfoModel.m in Sources */,
 				275FA22C27E7356B00CFEA2E /* CourseViewController.m in Sources */,
 				BC106C102A933829000759A9 /* TXLiveMessageUnBlockUser.m in Sources */,
 				BC84183F2AC2D96600D8F90E /* PasswordCheckBodyView.m in Sources */,
@@ -7393,6 +7500,7 @@
 				BC31BF2F2B21925700F7D538 /* IACircularSliderTrackLayer.m in Sources */,
 				BC85A9E62C6B570E003C1ABE /* KSRealtimeAnalyzer.m in Sources */,
 				BCB9091728530E9C00F5FF69 /* KSShopCardView.m in Sources */,
+				BCAAD0B22D19390A0069872D /* MyGroupCourseGroupListCell.m in Sources */,
 				BCCDB4332AB1C03A003C8E5F /* TenantTicketAlert.m in Sources */,
 				BC7401212CD25A920056756A /* KSBaseGuideView.m in Sources */,
 				BC7401222CD25A920056756A /* KSBaseGuideModel.m in Sources */,
@@ -7532,6 +7640,7 @@
 				BC106C372A9338A7000759A9 /* TXLiveChatListCell.m in Sources */,
 				BC106C242A933869000759A9 /* TXTestGenerateUserSig.m in Sources */,
 				2723B61F27F157D500E0B90B /* GroupNoticeModel.m in Sources */,
+				BCAAD0AE2D1938EB0069872D /* MyGroupCourseGroupView.m in Sources */,
 				BC83A8362AD27C470033D48B /* TenantNotiferCenterController.m in Sources */,
 				BC7F7B762C92DD9500265AE1 /* KSDeleteAccountTipsAlert.m in Sources */,
 				275FA1E627E7351900CFEA2E /* KSUpdateAlert.m in Sources */,
@@ -7757,6 +7866,7 @@
 				BC2C1BB42CEB556100EDEB97 /* HomeArrangeAccompanyCourseView.m in Sources */,
 				BC11922B280ED8E800A716F7 /* CourseNavView.m in Sources */,
 				BC3332862CEC35B000649FF9 /* LiveCourseArrangeCell.m in Sources */,
+				BCA0CB302D1A5FD400488F8E /* MyGroupCourseGroupController.m in Sources */,
 				BCC0F6632A8CD8F500C4EFA4 /* TXTimeView.m in Sources */,
 				BCECE2472B3D670500C0D555 /* FeedbackListModel.m in Sources */,
 				BCC0F60F2A8CD86C00C4EFA4 /* TXClassroomMsgModel.m in Sources */,
@@ -7764,6 +7874,9 @@
 				BCB6348627F6D29600ACFDCF /* LiveSeatApplyCell.m in Sources */,
 				BC31BF222B21925700F7D538 /* ToneTuningBodyView.m in Sources */,
 				275FA23127E7356B00CFEA2E /* FirstSettingViewController.m in Sources */,
+				BCA0CB3A2D1A61B600488F8E /* GroupCourseListCell.m in Sources */,
+				BCA0CB3B2D1A61B600488F8E /* GroupCourseGroupHeadView.m in Sources */,
+				BCA0CB3C2D1A61B600488F8E /* GroupCourseGroupNavView.m in Sources */,
 				BC2932FD2AAEF4AB0024D98E /* InsititutionMineViewController.m in Sources */,
 				BC2C1BBD2CEB579B00EDEB97 /* HomeArrangeSortView.m in Sources */,
 				BCC0F6D12A8CE13A00C4EFA4 /* KSTipsView.m in Sources */,
@@ -7898,6 +8011,7 @@
 				BC12636428FE930C00509E90 /* ChatUserInfo.m in Sources */,
 				27F9033227E87C2E00C08A19 /* SettingViewController.m in Sources */,
 				BC106C142A933829000759A9 /* TXLiveMessageSeatResponse.m in Sources */,
+				BCA9A5D42D1918C500C7CC9D /* GroupCourseArrangeCell.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 1 - 1
KulexiuForStudent/KulexiuForStudent.xcodeproj/xcshareddata/xcschemes/KulexiuForStudent.xcscheme

@@ -51,7 +51,7 @@
       </Testables>
    </TestAction>
    <LaunchAction
-      buildConfiguration = "TEST"
+      buildConfiguration = "DEV"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       launchStyle = "0"

+ 7 - 0
KulexiuForStudent/KulexiuForStudent/AppDelegate.m

@@ -808,6 +808,13 @@ didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
                 CustomNavViewController *navCtrl = self.tabBarController.selectedViewController;
                 [navCtrl pushViewController:ctrl animated:YES];
             }
+            else if ([pageType isEqualToString:@"groupClass"]) { // 我的课程 ->小组课
+                DISPLAY_INDEX index = DISPLAY_INDEX_GROUP;
+                MyCourseViewController *ctrl = [[MyCourseViewController alloc] init];
+                [ctrl displayWithIndex:index];
+                CustomNavViewController *navCtrl = self.tabBarController.selectedViewController;
+                [navCtrl pushViewController:ctrl animated:YES];
+            }
             else if ([pageType isEqualToString:@"liveClass"]) { // 我的课程 ->直播课
                 DISPLAY_INDEX index = DISPLAY_INDEX_LIVE;
                 MyCourseViewController *ctrl = [[MyCourseViewController alloc] init];

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

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

TEMPAT SAMPAH
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_group.imageset/course_group@2x.png


TEMPAT SAMPAH
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_group.imageset/course_group@3x.png


TEMPAT SAMPAH
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_musicRoom.imageset/course_musicRoom@2x.png


TEMPAT SAMPAH
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Course/course_musicRoom.imageset/course_musicRoom@3x.png


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


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


+ 14 - 2
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h

@@ -538,6 +538,7 @@ NS_ASSUME_NONNULL_BEGIN
 // /api-student/courseSchedule/queryStudentLiveCourse
 /// 我的课程-直播课
 /// @param post post
+/// @param courseType LIVE | GROUP
 /// @param classDate 月份 yyyy-MM
 /// @param status 课程状态(NOT_START:未开始 ING:进行中 COMPLETE:已完成 CANCEL:已取消)
 /// @param subjectId 声部id
@@ -546,7 +547,7 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param rows 条数
 /// @param success 成功
 /// @param faliure 失败
-+ (void)queryMyLiveCourse:(NSString *)post classDate:(NSString *)classDate status:(NSString *)status subjectId:(NSString *)subjectId search:(NSString *)search page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
++ (void)queryMyLiveCourse:(NSString *)post courseType:(NSString *)courseType classDate:(NSString *)classDate status:(NSString *)status subjectId:(NSString *)subjectId search:(NSString *)search page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
 // /api-student/videoLesson/selectMyGroup
 
@@ -1111,13 +1112,14 @@ NS_ASSUME_NONNULL_BEGIN
 
 /// 查询直播课
 /// @param post post
+/// @param courseType LIVE、GROUP
 /// @param search 搜索
 /// @param subjectId 声部ID
 /// @param page 分页
 /// @param rows 条数
 /// @param success 成功
 /// @param faliure 失败
-+ (void)queryLiveCourseGroupRequest:(NSString *)post search:(NSString *)search subjectId:(NSString *)subjectId page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
++ (void)queryLiveCourseGroupRequest:(NSString *)post courseType:(NSString *)courseType search:(NSString *)search subjectId:(NSString *)subjectId page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
 #pragma mark ---- 我的课程组
 
@@ -1142,6 +1144,16 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param faliure 失败
 + (void)getCourseGroupDetailRequest:(NSString *)post courseGroupId:(NSString *)courseGroupId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
+
+// courseGroup/queryCourseInfo
+
+/// 查询课程详情头部信息
+/// @param get get
+/// @param courseGroupId 课程组详情
+/// @param success 成功
+/// @param faliure 失败
++ (void)getCourseGroupInfoRequest:(NSString *)get courseGroupId:(NSString *)courseGroupId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 // /courseSchedule/list
 
 /// 查询课程组关联课程

+ 21 - 2
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m

@@ -1134,6 +1134,7 @@
 // /api-student/courseSchedule/queryStudentLiveCourse
 /// 我的课程-直播课
 /// @param post post
+/// @param courseType LIVE | GROUP
 /// @param classDate 月份 yyyy-MM
 /// @param status 课程状态(NOT_START:未开始 ING:进行中 COMPLETE:已完成 CANCEL:已取消)
 /// @param subjectId 声部id
@@ -1142,10 +1143,11 @@
 /// @param rows 条数
 /// @param success 成功
 /// @param faliure 失败
-+ (void)queryMyLiveCourse:(NSString *)post classDate:(NSString *)classDate status:(NSString *)status subjectId:(NSString *)subjectId search:(NSString *)search page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
++ (void)queryMyLiveCourse:(NSString *)post courseType:(NSString *)courseType classDate:(NSString *)classDate status:(NSString *)status subjectId:(NSString *)subjectId search:(NSString *)search page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
     NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-student/courseSchedule/queryStudentLiveCourse"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:courseType forKey:@"courseType"];
     [parm setValue:classDate forKey:@"classDate"];
     [parm setValue:status forKey:@"courseState"];
     [parm setValue:subjectId forKey:@"subjectId"];
@@ -2116,17 +2118,19 @@
 
 /// 查询直播课
 /// @param post post
+/// @param courseType LIVE、GROUP
 /// @param search 搜索
 /// @param subjectId 声部ID
 /// @param page 分页
 /// @param rows 条数
 /// @param success 成功
 /// @param faliure 失败
-+ (void)queryLiveCourseGroupRequest:(NSString *)post search:(NSString *)search subjectId:(NSString *)subjectId page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
++ (void)queryLiveCourseGroupRequest:(NSString *)post courseType:(NSString *)courseType search:(NSString *)search subjectId:(NSString *)subjectId page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
     NSString *url = [NSString stringWithFormat:@"%@%@",hostURL, @"/api-student/courseGroup/queryPageCourseGroup"];
     
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:courseType forKey:@"courseType"];
     [parm setValue:search forKey:@"search"];
     [parm setValue:@(page) forKey:@"page"];
     [parm setValue:@(rows) forKey:@"rows"];
@@ -2179,6 +2183,21 @@
     [self request:post andWithUrl:url and:parm success:success faliure:faliure];
 }
 
+// courseGroup/queryCourseInfo
+
+/// 查询课程详情头部信息
+/// @param get get
+/// @param courseGroupId 课程组详情
+/// @param success 成功
+/// @param faliure 失败
++ (void)getCourseGroupInfoRequest:(NSString *)get courseGroupId:(NSString *)courseGroupId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestHeader];
+    NSString *url = [NSString stringWithFormat:@"%@%@",hostURL, @"/api-student/courseGroup/queryCourseInfo"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:courseGroupId forKey:@"groupId"];
+    [self request:get andWithUrl:url and:parm success:success faliure:faliure];
+}
+
 // /courseSchedule/list
 
 /// 查询课程组关联课程

+ 8 - 3
KulexiuForStudent/KulexiuForStudent/Module/Course/Controller/CourseViewController.m

@@ -442,8 +442,9 @@
     }
     else {
         MusicRoomCourseCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MusicRoomCourseCell"];
+        BOOL isGroup = [model.courseType isEqualToString:@"GROUP"] ? YES : NO;
         MJWeakSelf;
-        [cell configWithSource:model beforeTime:self.pianoStartTime callback:^(NSString * _Nonnull targetId) {
+        [cell configWithSource:model isGroup:isGroup beforeTime:self.pianoStartTime callback:^(NSString * _Nonnull targetId) {
             [weakSelf chatAction:targetId groupName:@"" isGroup:YES];
         }];
         return cell;
@@ -462,7 +463,10 @@
         [self liveCourseDetail:model.courseId courseGroupId:model.courseGoupId];
     }
     else if ([model.courseType isEqualToString:@"PIANO_ROOM_CLASS"]) { // 琴房课详情
-        [self showMusicRoomDetail:model];
+        [self showMusicRoomDetail:model isGroup:NO];
+    }
+    else if ([model.courseType isEqualToString:@"GROUP"]) { // 小组课
+        [self showMusicRoomDetail:model isGroup:YES];
     }
     else {
         [self showAccompanyDetailAction:model];
@@ -517,8 +521,9 @@
     [self.navigationController pushViewController:detailVC animated:YES];
 }
 
-- (void)showMusicRoomDetail:(TableCourseModel *)source {
+- (void)showMusicRoomDetail:(TableCourseModel *)source isGroup:(BOOL)isGroup {
     MusicRoomDetailViewController *detailVC = [[MusicRoomDetailViewController alloc] init];
+    detailVC.courseType = isGroup ? MUTIL_COURSE_TYPE_GROUP : MUTIL_COURSE_TYPE_MUSIC;
     detailVC.courseId = source.courseId;
     detailVC.courseGroupId = source.courseGoupId;
     [self.navigationController pushViewController:detailVC animated:YES];

+ 7 - 1
KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/Controller/MusicRoomDetailViewController.h

@@ -7,12 +7,18 @@
 
 #import "KSBaseViewController.h"
 
+typedef NS_ENUM(NSInteger, MUTIL_COURSE_TYPE) {
+    MUTIL_COURSE_TYPE_MUSIC,
+    MUTIL_COURSE_TYPE_GROUP
+};
 
 NS_ASSUME_NONNULL_BEGIN
 
-/// 琴房课详情
+/// 琴房课详情 | 小组课详情
 @interface MusicRoomDetailViewController : KSBaseViewController
 
+@property (nonatomic, assign) MUTIL_COURSE_TYPE courseType;
+
 @property (nonatomic, strong) NSString *courseId;
 
 @property (nonatomic, strong) NSString *courseGroupId;

+ 2 - 1
KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/Controller/MusicRoomDetailViewController.m

@@ -182,8 +182,9 @@
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     if (indexPath.row == 0) {
         MusicRoomCourseInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MusicRoomCourseInfoCell"];
+        BOOL isGroup = self.courseType == MUTIL_COURSE_TYPE_GROUP ? YES : NO;
         MJWeakSelf;
-        [cell configWithSource:self.homeworkModel chatAction:^(NSString * _Nonnull targetId) {
+        [cell configWithSource:self.homeworkModel isGroup:isGroup chatAction:^(NSString * _Nonnull targetId) {
             [weakSelf chatAction:targetId];
         }];
         return cell;

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/View/MusicRoomCourseInfoCell.h

@@ -15,7 +15,7 @@ typedef void(^MusicRoomGroupChatAction)(NSString *targetId);
 
 @interface MusicRoomCourseInfoCell : UITableViewCell
 
-- (void)configWithSource:(HomeworkDetailModel *)model chatAction:(MusicRoomGroupChatAction)callback;
+- (void)configWithSource:(HomeworkDetailModel *)model isGroup:(BOOL)isGroup chatAction:(MusicRoomGroupChatAction)callback;
 
 @end
 

+ 6 - 2
KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/View/MusicRoomCourseInfoCell.m

@@ -9,6 +9,8 @@
 
 @interface MusicRoomCourseInfoCell ()
 
+@property (weak, nonatomic) IBOutlet UIImageView *courseImage;
+
 @property (weak, nonatomic) IBOutlet UILabel *statusLabel;
 
 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *attendenceImgLeft;
@@ -39,7 +41,9 @@
 }
 
 
-- (void)configWithSource:(HomeworkDetailModel *)model chatAction:(MusicRoomGroupChatAction)callback {    // time
+- (void)configWithSource:(HomeworkDetailModel *)model isGroup:(BOOL)isGroup chatAction:(MusicRoomGroupChatAction)callback {    // time
+    NSString *courseImgName = isGroup ? @"course_group" : @"course_musicRoom";
+    [self.courseImage setImage:[UIImage imageNamed:courseImgName]];
     NSDateFormatter *formatter = [NSObject getDateformatter];
     [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
     NSDate *startDate = [formatter dateFromString:model.startTime];
@@ -81,7 +85,7 @@
         NSString *imageName = model.attendanceStatus ? @"course_attendence" : @"course_noArrive";
         [self.attendentStatusImage setImage:[UIImage imageNamed:imageName]];
     }
-    self.studentName.text = [NSString returnNoNullStringWithString:model.studentName];
+    self.studentName.text = [NSString returnNoNullStringWithString:model.teacherName];
 }
 
 

+ 2 - 1
KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/View/MusicRoomCourseInfoCell.xib

@@ -158,6 +158,7 @@
                 <outlet property="attendenceImgLeft" destination="7og-r8-Be3" id="Iad-Tg-YaG"/>
                 <outlet property="attendenceImgWidth" destination="0ly-ym-r0i" id="9dB-Gr-Fjw"/>
                 <outlet property="attendentStatusImage" destination="cPi-Jc-34J" id="eBk-ji-6Ar"/>
+                <outlet property="courseImage" destination="qgw-qJ-GKe" id="h12-uj-CQT"/>
                 <outlet property="courseName" destination="09N-Zc-juN" id="X1d-qP-Lz2"/>
                 <outlet property="courseSubject" destination="kbx-pS-TGd" id="bmc-zg-wR2"/>
                 <outlet property="courseTime" destination="DZc-wF-kiD" id="T4x-I1-8LT"/>
@@ -169,7 +170,7 @@
         </tableViewCell>
     </objects>
     <resources>
-        <image name="course_musicRoom" width="40" height="40"/>
+        <image name="course_musicRoom" width="56" height="56"/>
         <image name="course_time" width="16" height="16"/>
         <systemColor name="systemBackgroundColor">
             <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>

+ 24 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Controller/MyGroupCourseGroupController.h

@@ -0,0 +1,24 @@
+//
+//  MyGroupCourseGroupController.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/24.
+//
+
+#import "KSBaseViewController.h"
+#import "JXCategoryView.h"
+#import "JXPagerView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MyGroupCourseGroupController : KSBaseViewController
+
+@property (nonatomic, strong) NSString *courseGroupId; // 课程组ID
+
+@property (nonatomic, strong) JXPagerView *pagerView;
+@property (nonatomic, strong, readonly) JXCategoryTitleView *categoryView;
+@property (nonatomic, strong) NSArray <NSString *> *titles;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 255 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Controller/MyGroupCourseGroupController.m

@@ -0,0 +1,255 @@
+//
+//  MyGroupCourseGroupController.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/24.
+//
+
+#import "MyGroupCourseGroupController.h"
+#import "GroupCourseGroupNavView.h"
+#import "GroupCourseGroupHeadView.h"
+#import "GroupCourseGroupInfoModel.h"
+#import "JXCategoryView.h"
+#import "JXPagerListRefreshView.h"
+#import "ProgramCourseGroupBodyView.h"
+
+@interface MyGroupCourseGroupController ()<JXPagerViewDelegate,JXCategoryViewDelegate>
+
+@property (nonatomic, strong) GroupCourseGroupNavView *navView;
+
+@property (nonatomic, strong) GroupCourseGroupHeadView *headView;
+
+@property (nonatomic, strong) NSMutableArray *listViewArray;
+
+@property (nonatomic, assign) NSInteger headHeight;
+
+@property (nonatomic, assign) NSInteger topViewHeight;
+
+
+@property (nonatomic, assign) BOOL isFirstLoad;
+
+@property (nonatomic, assign) NSInteger enterStartTime;  // 开课前可进入时间配置(分钟)
+
+@property (nonatomic, assign) NSInteger quitEndTime;    // 结束后退出时间配置(分钟)
+
+@property (nonatomic, strong) GroupCourseGroupInfoModel *infoModel;
+
+@end
+
+@implementation MyGroupCourseGroupController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    self.ks_prefersNavigationBarHidden = YES;
+    [self requestRoomConfig];
+    [self configUI];
+    self.isFirstLoad = YES;
+}
+
+- (void)configUI {
+    [self.scrollView removeFromSuperview];
+    
+    [self.view addSubview:self.navView];
+    CGFloat navHeight = [GroupCourseGroupNavView getViewHeight];
+    [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.mas_equalTo(self.view);
+        make.height.mas_equalTo(navHeight);
+    }];
+    self.headHeight = CGFLOAT_MIN;
+    
+    self.titles = @[@""];
+    [self configCategoryView:navHeight];
+}
+
+- (void)requestRoomConfig {
+    [KSNetworkingManager selectRoomConfigRequest:KS_GET success:^(NSDictionary * _Nonnull dic) {
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            NSDictionary *result = [dic ks_dictionaryValueForKey:@"data"];
+            self.enterStartTime = [result ks_integerValueForKey:@"groupStartTime"];
+            self.quitEndTime = [result ks_integerValueForKey:@"groupEndTime"];
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        
+    }];
+}
+
+- (void)configCategoryView:(NSInteger)topHeight {
+    
+    _categoryView = [[JXCategoryTitleView alloc] initWithFrame:CGRectMake(0, topHeight, KPortraitWidth, self.headHeight)];
+    self.categoryView.titles = self.titles;
+    self.categoryView.delegate = self;
+    self.categoryView.titleFont = [UIFont systemFontOfSize:16.0f];
+    self.categoryView.titleSelectedFont = [UIFont systemFontOfSize:16.0f weight:UIFontWeightSemibold];
+    self.categoryView.titleSelectedColor = HexRGB(0x333333);
+    self.categoryView.titleColor = HexRGB(0x666666);
+    self.categoryView.titleColorGradientEnabled = YES;
+    
+    _pagerView = [self preferredPagingView];
+    self.pagerView.frame = CGRectMake(0, topHeight, KPortraitWidth, KPortraitHeight - topHeight);
+    self.pagerView.backgroundColor = [UIColor clearColor];
+    self.pagerView.mainTableView.backgroundColor = [UIColor clearColor];
+    self.pagerView.listContainerView.backgroundColor = [UIColor clearColor];
+//    self.pagerView.mainTableView.gestureDelegate = self;
+    self.categoryView.listContainer = (id<JXCategoryViewListContainer>)self.pagerView.listContainerView;
+    self.pagerView.listContainerView.listCellBackgroundColor = [UIColor clearColor];
+    [self.view addSubview:self.pagerView];
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+    [super viewDidAppear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = (self.categoryView.selectedIndex == 0);
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
+    // 刷新课程详情
+    [self requestCourseInfo];
+    if (self.isFirstLoad == NO) {
+        [self refreshListPage];
+    }
+    self.isFirstLoad = NO;
+}
+
+- (void)requestCourseInfo {
+    
+    [KSNetworkingManager getCourseGroupInfoRequest:KS_GET courseGroupId:self.courseGroupId success:^(NSDictionary * _Nonnull dic) {
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            NSDictionary *parm = [dic ks_dictionaryValueForKey:@"data"];
+            self.infoModel = [[GroupCourseGroupInfoModel alloc] initWithDictionary:parm];
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+        [self refreshHeadView];
+    } faliure:^(NSError * _Nonnull error) {
+        [self refreshHeadView];
+    }];
+}
+
+- (void)refreshHeadView {
+    [self refreshListPage];
+    self.topViewHeight = [GroupCourseGroupHeadView getViewHeight:self.infoModel];
+    [self.headView configWithSource:self.infoModel];
+    [self.pagerView resizeTableHeaderViewHeightWithAnimatable:NO duration:0.3f curve:UIViewAnimationCurveEaseInOut];
+}
+
+
+- (void)refreshListPage {
+    id value = self.listViewArray[0];
+    if ([value isKindOfClass:[ProgramCourseGroupBodyView class]]) {
+        ProgramCourseGroupBodyView *listView = (ProgramCourseGroupBodyView *)value;
+        listView.enterStartTime = self.enterStartTime;
+        listView.quitEndTime = self.quitEndTime;
+        [listView beginFirstRefresh];
+    }
+}
+
+- (JXPagerView *)preferredPagingView {
+    return [[JXPagerListRefreshView alloc] initWithDelegate:self];
+}
+
+#pragma mark - JXPagerViewDelegate
+
+- (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView {
+    return self.headView;
+}
+
+- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView {
+    return self.topViewHeight;
+}
+
+- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return 1;
+}
+
+- (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return self.categoryView;
+}
+
+- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView {
+    //和categoryView的item数量一致
+    return self.titles.count;
+}
+
+- (id<JXPagerViewListViewDelegate>)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index {
+    
+    ProgramCourseGroupBodyView *listView = [[ProgramCourseGroupBodyView alloc] init];
+    listView.naviController = self.navigationController;
+    listView.selectIndex = index;
+    listView.courseGroupId = self.courseGroupId;
+    listView.courseType = COURSE_GROUP_TYPE_GROUP;
+    [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+    self.listViewArray[index] = listView;
+    [listView beginFirstRefresh];
+    return listView;
+}
+
+- (void)pagerView:(JXPagerView *)pagerView mainTableViewDidScroll:(UIScrollView *)scrollView {
+    
+    NSLog(@"sscroll content offset y %f", scrollView.contentOffset.y);
+//    CGFloat height = self.topViewHeight;
+//    CGFloat space = scrollView.contentOffset.y;
+//    if (space > 100) {
+//        CGFloat rate = (space - 100) / (height - 100);
+//        NSLog(@"rate ---------%f",rate);
+//        self.navView.backgroundColor = HexRGBAlpha(0xffffff, rate);
+//        if (rate == 1) {
+//            self.bgImageView.hidden = YES;
+//        }
+//        else {
+//            self.bgImageView.hidden = NO;
+//        }
+//    }
+//    else {
+//        self.navView.backgroundColor = [UIColor clearColor];
+//        self.bgImageView.hidden = NO;
+//    }
+}
+
+- (void)dealloc {
+   [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark ----- lazying
+
+- (GroupCourseGroupNavView *)navView {
+    if (!_navView) {
+        _navView = [GroupCourseGroupNavView sharedInstance];
+        MJWeakSelf;
+        [_navView navActionCallback:^{
+            [weakSelf backAction];
+        }];
+    }
+    return _navView;
+}
+
+- (NSMutableArray *)listViewArray {
+    if (!_listViewArray) {
+        _listViewArray = [NSMutableArray arrayWithArray:@[@""]];
+    }
+    return _listViewArray;
+}
+
+- (GroupCourseGroupHeadView *)headView {
+    if (!_headView) {
+        _headView = [GroupCourseGroupHeadView sharedInstance];
+    }
+    return _headView;
+}
+
+/*
+#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

+ 47 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Model/GroupCourseGroupInfoModel.h

@@ -0,0 +1,47 @@
+//
+//  GroupCourseGroupInfoModel.h
+//
+//  Created by Steven  on 2024/12/23
+//  Copyright (c) 2024 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface GroupCourseGroupInfoModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, strong) NSString *backgroundPic;
+@property (nonatomic, strong) NSString *courseIntroduce;
+@property (nonatomic, strong) NSString *salesEndDate;
+@property (nonatomic, strong) NSString *status;
+@property (nonatomic, assign) double mixStudentNum;
+@property (nonatomic, strong) NSString *courseGroupName;
+@property (nonatomic, assign) double auditVersion;
+@property (nonatomic, strong) NSString *salesStartDate;
+@property (nonatomic, strong) NSString *teacherName;
+@property (nonatomic, strong) NSString *subjectName;
+@property (nonatomic, assign) BOOL myself;
+@property (nonatomic, strong) NSString *courseStartTime;
+@property (nonatomic, strong) NSString *imGroupId;
+@property (nonatomic, assign) double singleCourseMinutes;
+@property (nonatomic, assign) double teacherId;
+@property (nonatomic, strong) NSString *coursePlan;
+@property (nonatomic, assign) double degreeFlag;
+@property (nonatomic, assign) double studentCount;
+@property (nonatomic, assign) double courseGroupId;
+@property (nonatomic, strong) NSString *avatar;
+@property (nonatomic, assign) double courseNum;
+@property (nonatomic, assign) double existBuy;
+@property (nonatomic, assign) double maxStudentNum;
+@property (nonatomic, strong) NSString *reason;
+@property (nonatomic, assign) double teacherFlag;
+@property (nonatomic, strong) NSString *userName;
+@property (nonatomic, assign) double coursePrice;
+@property (nonatomic, assign) double completeCourseNum;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 284 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/Model/GroupCourseGroupInfoModel.m

@@ -0,0 +1,284 @@
+//
+//  GroupCourseGroupInfoModel.m
+//
+//  Created by Steven  on 2024/12/23
+//  Copyright (c) 2024 __MyCompanyName__. All rights reserved.
+//
+
+#import "GroupCourseGroupInfoModel.h"
+
+
+NSString *const kGroupCourseGroupInfoModelBackgroundPic = @"backgroundPic";
+NSString *const kGroupCourseGroupInfoModelCourseIntroduce = @"courseIntroduce";
+NSString *const kGroupCourseGroupInfoModelSalesEndDate = @"salesEndDate";
+NSString *const kGroupCourseGroupInfoModelStatus = @"status";
+NSString *const kGroupCourseGroupInfoModelMixStudentNum = @"mixStudentNum";
+NSString *const kGroupCourseGroupInfoModelCourseGroupName = @"courseGroupName";
+NSString *const kGroupCourseGroupInfoModelAuditVersion = @"auditVersion";
+NSString *const kGroupCourseGroupInfoModelSalesStartDate = @"salesStartDate";
+NSString *const kGroupCourseGroupInfoModelTeacherName = @"teacherName";
+NSString *const kGroupCourseGroupInfoModelSubjectName = @"subjectName";
+NSString *const kGroupCourseGroupInfoModelMyself = @"myself";
+NSString *const kGroupCourseGroupInfoModelCourseStartTime = @"courseStartTime";
+NSString *const kGroupCourseGroupInfoModelImGroupId = @"imGroupId";
+NSString *const kGroupCourseGroupInfoModelSingleCourseMinutes = @"singleCourseMinutes";
+NSString *const kGroupCourseGroupInfoModelTeacherId = @"teacherId";
+NSString *const kGroupCourseGroupInfoModelCoursePlan = @"coursePlan";
+NSString *const kGroupCourseGroupInfoModelDegreeFlag = @"degreeFlag";
+NSString *const kGroupCourseGroupInfoModelStudentCount = @"studentCount";
+NSString *const kGroupCourseGroupInfoModelCourseGroupId = @"courseGroupId";
+NSString *const kGroupCourseGroupInfoModelAvatar = @"avatar";
+NSString *const kGroupCourseGroupInfoModelCourseNum = @"courseNum";
+NSString *const kGroupCourseGroupInfoModelExistBuy = @"existBuy";
+NSString *const kGroupCourseGroupInfoModelMaxStudentNum = @"maxStudentNum";
+NSString *const kGroupCourseGroupInfoModelReason = @"reason";
+NSString *const kGroupCourseGroupInfoModelTeacherFlag = @"teacherFlag";
+NSString *const kGroupCourseGroupInfoModelUserName = @"userName";
+NSString *const kGroupCourseGroupInfoModelCoursePrice = @"coursePrice";
+NSString *const kGroupCourseGroupInfoModelCompleteCourseNum = @"completeCourseNum";
+
+@interface GroupCourseGroupInfoModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation GroupCourseGroupInfoModel
+
+@synthesize backgroundPic = _backgroundPic;
+@synthesize courseIntroduce = _courseIntroduce;
+@synthesize salesEndDate = _salesEndDate;
+@synthesize status = _status;
+@synthesize mixStudentNum = _mixStudentNum;
+@synthesize courseGroupName = _courseGroupName;
+@synthesize auditVersion = _auditVersion;
+@synthesize salesStartDate = _salesStartDate;
+@synthesize teacherName = _teacherName;
+@synthesize subjectName = _subjectName;
+@synthesize myself = _myself;
+@synthesize courseStartTime = _courseStartTime;
+@synthesize imGroupId = _imGroupId;
+@synthesize singleCourseMinutes = _singleCourseMinutes;
+@synthesize teacherId = _teacherId;
+@synthesize coursePlan = _coursePlan;
+@synthesize degreeFlag = _degreeFlag;
+@synthesize studentCount = _studentCount;
+@synthesize courseGroupId = _courseGroupId;
+@synthesize avatar = _avatar;
+@synthesize courseNum = _courseNum;
+@synthesize existBuy = _existBuy;
+@synthesize maxStudentNum = _maxStudentNum;
+@synthesize reason = _reason;
+@synthesize teacherFlag = _teacherFlag;
+@synthesize userName = _userName;
+@synthesize coursePrice = _coursePrice;
+@synthesize completeCourseNum = _completeCourseNum;
+
++ (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.backgroundPic = [self objectOrNilForKey:kGroupCourseGroupInfoModelBackgroundPic fromDictionary:dict];
+            self.courseIntroduce = [self objectOrNilForKey:kGroupCourseGroupInfoModelCourseIntroduce fromDictionary:dict];
+            self.salesEndDate = [self objectOrNilForKey:kGroupCourseGroupInfoModelSalesEndDate fromDictionary:dict];
+            self.status = [self objectOrNilForKey:kGroupCourseGroupInfoModelStatus fromDictionary:dict];
+            self.mixStudentNum = [[self objectOrNilForKey:kGroupCourseGroupInfoModelMixStudentNum fromDictionary:dict] doubleValue];
+            self.courseGroupName = [self objectOrNilForKey:kGroupCourseGroupInfoModelCourseGroupName fromDictionary:dict];
+            self.auditVersion = [[self objectOrNilForKey:kGroupCourseGroupInfoModelAuditVersion fromDictionary:dict] doubleValue];
+            self.salesStartDate = [self objectOrNilForKey:kGroupCourseGroupInfoModelSalesStartDate fromDictionary:dict];
+            self.teacherName = [self objectOrNilForKey:kGroupCourseGroupInfoModelTeacherName fromDictionary:dict];
+            self.subjectName = [self objectOrNilForKey:kGroupCourseGroupInfoModelSubjectName fromDictionary:dict];
+            self.myself = [[self objectOrNilForKey:kGroupCourseGroupInfoModelMyself fromDictionary:dict] boolValue];
+            self.courseStartTime = [self objectOrNilForKey:kGroupCourseGroupInfoModelCourseStartTime fromDictionary:dict];
+            self.imGroupId = [self objectOrNilForKey:kGroupCourseGroupInfoModelImGroupId fromDictionary:dict];
+            self.singleCourseMinutes = [[self objectOrNilForKey:kGroupCourseGroupInfoModelSingleCourseMinutes fromDictionary:dict] doubleValue];
+            self.teacherId = [[self objectOrNilForKey:kGroupCourseGroupInfoModelTeacherId fromDictionary:dict] doubleValue];
+            self.coursePlan = [self objectOrNilForKey:kGroupCourseGroupInfoModelCoursePlan fromDictionary:dict];
+            self.degreeFlag = [[self objectOrNilForKey:kGroupCourseGroupInfoModelDegreeFlag fromDictionary:dict] doubleValue];
+            self.studentCount = [[self objectOrNilForKey:kGroupCourseGroupInfoModelStudentCount fromDictionary:dict] doubleValue];
+            self.courseGroupId = [[self objectOrNilForKey:kGroupCourseGroupInfoModelCourseGroupId fromDictionary:dict] doubleValue];
+            self.avatar = [self objectOrNilForKey:kGroupCourseGroupInfoModelAvatar fromDictionary:dict];
+            self.courseNum = [[self objectOrNilForKey:kGroupCourseGroupInfoModelCourseNum fromDictionary:dict] doubleValue];
+            self.existBuy = [[self objectOrNilForKey:kGroupCourseGroupInfoModelExistBuy fromDictionary:dict] doubleValue];
+            self.maxStudentNum = [[self objectOrNilForKey:kGroupCourseGroupInfoModelMaxStudentNum fromDictionary:dict] doubleValue];
+            self.reason = [self objectOrNilForKey:kGroupCourseGroupInfoModelReason fromDictionary:dict];
+            self.teacherFlag = [[self objectOrNilForKey:kGroupCourseGroupInfoModelTeacherFlag fromDictionary:dict] doubleValue];
+            self.userName = [self objectOrNilForKey:kGroupCourseGroupInfoModelUserName fromDictionary:dict];
+            self.coursePrice = [[self objectOrNilForKey:kGroupCourseGroupInfoModelCoursePrice fromDictionary:dict] doubleValue];
+            self.completeCourseNum = [[self objectOrNilForKey:kGroupCourseGroupInfoModelCompleteCourseNum fromDictionary:dict] doubleValue];
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:self.backgroundPic forKey:kGroupCourseGroupInfoModelBackgroundPic];
+    [mutableDict setValue:self.courseIntroduce forKey:kGroupCourseGroupInfoModelCourseIntroduce];
+    [mutableDict setValue:self.salesEndDate forKey:kGroupCourseGroupInfoModelSalesEndDate];
+    [mutableDict setValue:self.status forKey:kGroupCourseGroupInfoModelStatus];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.mixStudentNum] forKey:kGroupCourseGroupInfoModelMixStudentNum];
+    [mutableDict setValue:self.courseGroupName forKey:kGroupCourseGroupInfoModelCourseGroupName];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.auditVersion] forKey:kGroupCourseGroupInfoModelAuditVersion];
+    [mutableDict setValue:self.salesStartDate forKey:kGroupCourseGroupInfoModelSalesStartDate];
+    [mutableDict setValue:self.teacherName forKey:kGroupCourseGroupInfoModelTeacherName];
+    [mutableDict setValue:self.subjectName forKey:kGroupCourseGroupInfoModelSubjectName];
+    [mutableDict setValue:[NSNumber numberWithBool:self.myself] forKey:kGroupCourseGroupInfoModelMyself];
+    [mutableDict setValue:self.courseStartTime forKey:kGroupCourseGroupInfoModelCourseStartTime];
+    [mutableDict setValue:self.imGroupId forKey:kGroupCourseGroupInfoModelImGroupId];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.singleCourseMinutes] forKey:kGroupCourseGroupInfoModelSingleCourseMinutes];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.teacherId] forKey:kGroupCourseGroupInfoModelTeacherId];
+    [mutableDict setValue:self.coursePlan forKey:kGroupCourseGroupInfoModelCoursePlan];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.degreeFlag] forKey:kGroupCourseGroupInfoModelDegreeFlag];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.studentCount] forKey:kGroupCourseGroupInfoModelStudentCount];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.courseGroupId] forKey:kGroupCourseGroupInfoModelCourseGroupId];
+    [mutableDict setValue:self.avatar forKey:kGroupCourseGroupInfoModelAvatar];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.courseNum] forKey:kGroupCourseGroupInfoModelCourseNum];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.existBuy] forKey:kGroupCourseGroupInfoModelExistBuy];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.maxStudentNum] forKey:kGroupCourseGroupInfoModelMaxStudentNum];
+    [mutableDict setValue:self.reason forKey:kGroupCourseGroupInfoModelReason];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.teacherFlag] forKey:kGroupCourseGroupInfoModelTeacherFlag];
+    [mutableDict setValue:self.userName forKey:kGroupCourseGroupInfoModelUserName];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.coursePrice] forKey:kGroupCourseGroupInfoModelCoursePrice];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.completeCourseNum] forKey:kGroupCourseGroupInfoModelCompleteCourseNum];
+    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.backgroundPic = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelBackgroundPic];
+    self.courseIntroduce = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelCourseIntroduce];
+    self.salesEndDate = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelSalesEndDate];
+    self.status = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelStatus];
+    self.mixStudentNum = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelMixStudentNum];
+    self.courseGroupName = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelCourseGroupName];
+    self.auditVersion = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelAuditVersion];
+    self.salesStartDate = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelSalesStartDate];
+    self.teacherName = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelTeacherName];
+    self.subjectName = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelSubjectName];
+    self.myself = [aDecoder decodeBoolForKey:kGroupCourseGroupInfoModelMyself];
+    self.courseStartTime = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelCourseStartTime];
+    self.imGroupId = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelImGroupId];
+    self.singleCourseMinutes = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelSingleCourseMinutes];
+    self.teacherId = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelTeacherId];
+    self.coursePlan = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelCoursePlan];
+    self.degreeFlag = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelDegreeFlag];
+    self.studentCount = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelStudentCount];
+    self.courseGroupId = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelCourseGroupId];
+    self.avatar = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelAvatar];
+    self.courseNum = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelCourseNum];
+    self.existBuy = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelExistBuy];
+    self.maxStudentNum = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelMaxStudentNum];
+    self.reason = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelReason];
+    self.teacherFlag = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelTeacherFlag];
+    self.userName = [aDecoder decodeObjectForKey:kGroupCourseGroupInfoModelUserName];
+    self.coursePrice = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelCoursePrice];
+    self.completeCourseNum = [aDecoder decodeDoubleForKey:kGroupCourseGroupInfoModelCompleteCourseNum];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeObject:_backgroundPic forKey:kGroupCourseGroupInfoModelBackgroundPic];
+    [aCoder encodeObject:_courseIntroduce forKey:kGroupCourseGroupInfoModelCourseIntroduce];
+    [aCoder encodeObject:_salesEndDate forKey:kGroupCourseGroupInfoModelSalesEndDate];
+    [aCoder encodeObject:_status forKey:kGroupCourseGroupInfoModelStatus];
+    [aCoder encodeDouble:_mixStudentNum forKey:kGroupCourseGroupInfoModelMixStudentNum];
+    [aCoder encodeObject:_courseGroupName forKey:kGroupCourseGroupInfoModelCourseGroupName];
+    [aCoder encodeDouble:_auditVersion forKey:kGroupCourseGroupInfoModelAuditVersion];
+    [aCoder encodeObject:_salesStartDate forKey:kGroupCourseGroupInfoModelSalesStartDate];
+    [aCoder encodeObject:_teacherName forKey:kGroupCourseGroupInfoModelTeacherName];
+    [aCoder encodeObject:_subjectName forKey:kGroupCourseGroupInfoModelSubjectName];
+    [aCoder encodeBool:_myself forKey:kGroupCourseGroupInfoModelMyself];
+    [aCoder encodeObject:_courseStartTime forKey:kGroupCourseGroupInfoModelCourseStartTime];
+    [aCoder encodeObject:_imGroupId forKey:kGroupCourseGroupInfoModelImGroupId];
+    [aCoder encodeDouble:_singleCourseMinutes forKey:kGroupCourseGroupInfoModelSingleCourseMinutes];
+    [aCoder encodeDouble:_teacherId forKey:kGroupCourseGroupInfoModelTeacherId];
+    [aCoder encodeObject:_coursePlan forKey:kGroupCourseGroupInfoModelCoursePlan];
+    [aCoder encodeDouble:_degreeFlag forKey:kGroupCourseGroupInfoModelDegreeFlag];
+    [aCoder encodeDouble:_studentCount forKey:kGroupCourseGroupInfoModelStudentCount];
+    [aCoder encodeDouble:_courseGroupId forKey:kGroupCourseGroupInfoModelCourseGroupId];
+    [aCoder encodeObject:_avatar forKey:kGroupCourseGroupInfoModelAvatar];
+    [aCoder encodeDouble:_courseNum forKey:kGroupCourseGroupInfoModelCourseNum];
+    [aCoder encodeDouble:_existBuy forKey:kGroupCourseGroupInfoModelExistBuy];
+    [aCoder encodeDouble:_maxStudentNum forKey:kGroupCourseGroupInfoModelMaxStudentNum];
+    [aCoder encodeObject:_reason forKey:kGroupCourseGroupInfoModelReason];
+    [aCoder encodeDouble:_teacherFlag forKey:kGroupCourseGroupInfoModelTeacherFlag];
+    [aCoder encodeObject:_userName forKey:kGroupCourseGroupInfoModelUserName];
+    [aCoder encodeDouble:_coursePrice forKey:kGroupCourseGroupInfoModelCoursePrice];
+    [aCoder encodeDouble:_completeCourseNum forKey:kGroupCourseGroupInfoModelCompleteCourseNum];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    GroupCourseGroupInfoModel *copy = [[GroupCourseGroupInfoModel alloc] init];
+    
+    if (copy) {
+
+        copy.backgroundPic = [self.backgroundPic copyWithZone:zone];
+        copy.courseIntroduce = [self.courseIntroduce copyWithZone:zone];
+        copy.salesEndDate = [self.salesEndDate copyWithZone:zone];
+        copy.status = [self.status copyWithZone:zone];
+        copy.mixStudentNum = self.mixStudentNum;
+        copy.courseGroupName = [self.courseGroupName copyWithZone:zone];
+        copy.auditVersion = self.auditVersion;
+        copy.salesStartDate = [self.salesStartDate copyWithZone:zone];
+        copy.teacherName = [self.teacherName copyWithZone:zone];
+        copy.subjectName = [self.subjectName copyWithZone:zone];
+        copy.myself = self.myself;
+        copy.courseStartTime = [self.courseStartTime copyWithZone:zone];
+        copy.imGroupId = [self.imGroupId copyWithZone:zone];
+        copy.singleCourseMinutes = self.singleCourseMinutes;
+        copy.teacherId = self.teacherId;
+        copy.coursePlan = [self.coursePlan copyWithZone:zone];
+        copy.degreeFlag = self.degreeFlag;
+        copy.studentCount = self.studentCount;
+        copy.courseGroupId = self.courseGroupId;
+        copy.avatar = [self.avatar copyWithZone:zone];
+        copy.courseNum = self.courseNum;
+        copy.existBuy = self.existBuy;
+        copy.maxStudentNum = self.maxStudentNum;
+        copy.reason = [self.reason copyWithZone:zone];
+        copy.teacherFlag = self.teacherFlag;
+        copy.userName = [self.userName copyWithZone:zone];
+        copy.coursePrice = self.coursePrice;
+        copy.completeCourseNum = self.completeCourseNum;
+    }
+    
+    return copy;
+}
+
+
+@end

+ 23 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupHeadView.h

@@ -0,0 +1,23 @@
+//
+//  GroupCourseGroupHeadView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import <UIKit/UIKit.h>
+#import "GroupCourseGroupInfoModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupCourseGroupHeadView : UIView
+
++ (instancetype)sharedInstance;
+
+- (void)configWithSource:(GroupCourseGroupInfoModel *)model;
+
++ (CGFloat)getViewHeight:(GroupCourseGroupInfoModel *)source;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 134 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupHeadView.m

@@ -0,0 +1,134 @@
+//
+//  GroupCourseGroupHeadView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "GroupCourseGroupHeadView.h"
+
+@interface GroupCourseGroupHeadView ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *coverImage;
+@property (weak, nonatomic) IBOutlet UILabel *courseName;
+
+@property (weak, nonatomic) IBOutlet UIView *orderUserBg;
+@property (weak, nonatomic) IBOutlet UILabel *orderUser;
+@property (weak, nonatomic) IBOutlet UILabel *courseTime;
+@property (weak, nonatomic) IBOutlet UILabel *tagLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *priceLabel;
+@property (weak, nonatomic) IBOutlet UILabel *courseCount;
+@property (weak, nonatomic) IBOutlet UILabel *subjectLabel;
+@property (weak, nonatomic) IBOutlet UILabel *courseDesc;
+
+@property (weak, nonatomic) IBOutlet UIImageView *teacherAvatar;
+@property (weak, nonatomic) IBOutlet UILabel *teacherName;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseIntroduce;
+
+@end
+
+@implementation GroupCourseGroupHeadView
+
+
++ (instancetype)sharedInstance {
+    GroupCourseGroupHeadView *view = [[[NSBundle mainBundle] loadNibNamed:@"GroupCourseGroupHeadView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)configWithSource:(GroupCourseGroupInfoModel *)model {
+    [self.coverImage sd_setImageWithURL:[NSURL URLWithString:[model.backgroundPic getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:@"video_placeholder"]];
+    self.courseName.text = [NSString returnNoNullStringWithString:model.courseGroupName];
+    self.orderUser.text = [NSString stringWithFormat:@"剩余%.0f个名额", model.maxStudentNum - model.studentCount];
+    // time
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *startDate = [formatter dateFromString:model.courseStartTime];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
+    NSString *courseBegin = [formatter stringFromDate:startDate];
+    self.courseTime.text = [NSString returnNoNullStringWithString:courseBegin];
+    self.subjectLabel.text = [NSString returnNoNullStringWithString:model.subjectName];
+    
+    if (model.coursePrice > 0) {
+        NSString *mountMsg = [NSString formatAllDoubleNum:model.coursePrice];
+        self.priceLabel.text = mountMsg;
+        self.tagLabel.hidden = NO;
+    }
+    else {
+        self.priceLabel.text = [NSString  stringWithFormat:@"免费"];
+        self.tagLabel.hidden = YES;
+    }
+    self.courseCount.text = [NSString stringWithFormat:@"/%.0f课时",model.courseNum];
+
+    [self.teacherAvatar sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:TEACHER_AVATAR]];
+    self.teacherName.text = [NSString returnNoNullStringWithString:model.userName];
+    
+    // 课程
+    NSMutableAttributedString *attrs = [[NSMutableAttributedString alloc] initWithString:@"已上课时 " attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular],NSForegroundColorAttributeName:HexRGB(0x999999)}];
+    NSAttributedString *finishNumAttr = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%.0f", model.completeCourseNum] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightSemibold],NSForegroundColorAttributeName:THEMECOLOR}];
+    [attrs appendAttributedString:finishNumAttr];
+    
+    NSAttributedString *totalDescAttr = [[NSAttributedString alloc] initWithString:@" /总课时 " attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular],NSForegroundColorAttributeName:HexRGB(0x999999)}];
+    [attrs appendAttributedString:totalDescAttr];
+    NSAttributedString *totalNumAttr = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%.0f", model.courseNum] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightSemibold],NSForegroundColorAttributeName:HexRGB(0x333333)}];
+    [attrs appendAttributedString:totalNumAttr];
+    self.courseDesc.attributedText = attrs;
+    
+    
+    NSString *introduce = model.courseIntroduce;
+    if (![NSString isEmptyString:introduce]) {
+        introduce = [introduce replaceAll:@"\n" WithString:@" "];
+    }
+    else {
+        introduce = @"暂无介绍";
+    }
+    
+    NSMutableParagraphStyle *paragraphStyle = [GroupCourseGroupHeadView getParagraphStyleWithFont:[UIFont systemFontOfSize:13.0f] lineHeight:22.0f];
+    CGFloat baselineOffset = [GroupCourseGroupHeadView getBaseOffline:[UIFont systemFontOfSize:13.0f] lineHeight:22.0f];
+    NSMutableAttributedString *introduceAttrs = [[NSMutableAttributedString alloc] initWithString:introduce attributes:@{NSParagraphStyleAttributeName:paragraphStyle, NSBaselineOffsetAttributeName:@(baselineOffset),NSFontAttributeName:[UIFont systemFontOfSize:13.0f], NSForegroundColorAttributeName:HexRGB(0x777777)}];
+    self.courseIntroduce.attributedText = introduceAttrs;
+}
+
+
++ (CGFloat)getViewHeight:(GroupCourseGroupInfoModel *)source {
+    NSString *introduce = source.courseIntroduce;
+    if (![NSString isEmptyString:introduce]) {
+        introduce = [introduce replaceAll:@"\n" WithString:@" "];
+    }
+    else {
+        introduce = @"暂无介绍";
+    }
+    CGFloat imageHeight = KPortraitWidth / 16 * 9;
+    CGFloat planHeight = 79 + [GroupCourseGroupHeadView getViewRealHeight:introduce];
+    return 135 + imageHeight + planHeight;
+}
+
++ (CGFloat)getBaseOffline:(UIFont *)font lineHeight:(CGFloat)lineHeight {
+    CGFloat baselineOffset = (lineHeight - font.lineHeight) / 4;
+    return baselineOffset;
+}
+
++ (NSMutableParagraphStyle *)getParagraphStyleWithFont:(UIFont *)font lineHeight:(CGFloat)lineHeigh {
+    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
+    paragraphStyle.maximumLineHeight = lineHeigh;
+    paragraphStyle.minimumLineHeight = lineHeigh;
+    return paragraphStyle;
+}
+
++ (CGFloat)getViewRealHeight:(NSString *)planString {
+    NSMutableParagraphStyle *paragraphStyle = [self getParagraphStyleWithFont:[UIFont systemFontOfSize:13.0f] lineHeight:22.0f];
+    CGFloat baselineOffset = [self getBaseOffline:[UIFont systemFontOfSize:13.0f] lineHeight:22.0f];
+    CGFloat height = [planString boundingRectWithSize:CGSizeMake(KPortraitWidth - 26, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSParagraphStyleAttributeName:paragraphStyle, NSBaselineOffsetAttributeName:@(baselineOffset),NSFontAttributeName:[UIFont systemFontOfSize:13.0f]} context:nil].size.height + 1;
+    return height;
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 317 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupHeadView.xib

@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <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="GroupCourseGroupHeadView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="505"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AnK-wf-4BP">
+                    <rect key="frame" x="0.0" y="0.0" width="393" height="356"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="video_placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="aHt-s4-D8T">
+                            <rect key="frame" x="0.0" y="0.0" width="393" height="221"/>
+                            <constraints>
+                                <constraint firstAttribute="width" secondItem="aHt-s4-D8T" secondAttribute="height" multiplier="16:9" id="CuK-sb-2aR"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="6"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </imageView>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0p4-wR-LI6">
+                            <rect key="frame" x="8" y="8" width="12" height="19"/>
+                            <subviews>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WXY-Wu-N8t">
+                                    <rect key="frame" x="6" y="9.6666666666666679" width="0.0" height="0.0"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                    <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                            </subviews>
+                            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.40000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstItem="WXY-Wu-N8t" firstAttribute="leading" secondItem="0p4-wR-LI6" secondAttribute="leading" constant="6" id="B4W-m4-6WC"/>
+                                <constraint firstItem="WXY-Wu-N8t" firstAttribute="centerY" secondItem="0p4-wR-LI6" secondAttribute="centerY" id="LgV-z8-BK9"/>
+                                <constraint firstAttribute="height" constant="19" id="MaT-L9-H9g"/>
+                                <constraint firstAttribute="trailing" secondItem="WXY-Wu-N8t" secondAttribute="trailing" constant="6" id="sfc-ey-UM7"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="3"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </view>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="著名大号大师严琦带你去走近音乐的异想世界" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xNR-qb-bSK">
+                            <rect key="frame" x="14" y="229" width="365" height="22"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="22" id="Mq4-2p-Jrc"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                            <color key="textColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <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="cWt-tT-seb">
+                            <rect key="frame" x="347" y="312" width="0.0" height="24"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="24" id="KVO-pT-iPI"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="20"/>
+                            <color key="textColor" red="0.95686274510000002" green="0.27058823529999998" blue="0.25490196079999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="/1课时" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="C6q-FO-iK4">
+                            <rect key="frame" x="349" y="317" width="32" height="17"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="17" id="rlG-mJ-N7P"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="11"/>
+                            <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" 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="9s2-dK-o6k">
+                            <rect key="frame" x="338" y="318" width="7" height="16"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="16" id="hEL-qQ-c3g"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="14"/>
+                            <color key="textColor" red="0.95686274510000002" green="0.27058823529999998" blue="0.25490196079999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mine_page_live_tag" translatesAutoresizingMaskIntoConstraints="NO" id="b7F-Ah-faY">
+                            <rect key="frame" x="14" y="263" width="20" height="16"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="16" id="3E7-iL-X34"/>
+                                <constraint firstAttribute="width" constant="20" id="lgh-HS-RTg"/>
+                            </constraints>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="开课时间:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Rjf-aS-wHE">
+                            <rect key="frame" x="41" y="261" width="62.666666666666657" height="20"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="20" id="mBc-pd-hfb"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="2024-11-16 09:30" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tI3-dq-1Qx">
+                            <rect key="frame" x="103.66666666666669" y="261" width="117.33333333333331" height="20"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="20" id="lT0-gl-akp"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="x71-SB-35W">
+                            <rect key="frame" x="14" y="291" width="365" height="1"/>
+                            <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="evi-h1-UEz"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" horizontalCompressionResistancePriority="752" translatesAutoresizingMaskIntoConstraints="NO" id="HX4-58-7dZ">
+                            <rect key="frame" x="301" y="261.66666666666669" width="78" height="19"/>
+                            <subviews>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="剩余2个名额" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cfo-DH-vsM">
+                                    <rect key="frame" x="4" y="2.3333333333333153" width="70" height="14.333333333333336"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                    <color key="textColor" red="1" green="0.40784313729999999" blue="0.1529411765" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                            </subviews>
+                            <color key="backgroundColor" red="1" green="0.50196078430000002" blue="0.17254901959999999" alpha="0.070000000000000007" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstItem="cfo-DH-vsM" firstAttribute="leading" secondItem="HX4-58-7dZ" secondAttribute="leading" constant="4" id="2Ye-FI-s79"/>
+                                <constraint firstAttribute="trailing" secondItem="cfo-DH-vsM" secondAttribute="trailing" constant="4" id="NVN-YV-cAP"/>
+                                <constraint firstAttribute="height" constant="19" id="k5A-YY-pam"/>
+                                <constraint firstItem="cfo-DH-vsM" firstAttribute="centerY" secondItem="HX4-58-7dZ" secondAttribute="centerY" id="qgL-Jz-iko"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="2"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </view>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="严琦" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YTe-Wh-9ux">
+                            <rect key="frame" x="62" y="304" width="30" height="22"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="22" id="VS0-J4-wTr"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BbF-PF-VI1">
+                            <rect key="frame" x="78" y="326" width="0.0" height="16"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="16" id="KXa-mr-Bv8"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                            <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrange_course_icon" translatesAutoresizingMaskIntoConstraints="NO" id="0G1-Qu-QuA">
+                            <rect key="frame" x="62" y="327" width="12" height="14"/>
+                        </imageView>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="teacher_avatar" translatesAutoresizingMaskIntoConstraints="NO" id="mbV-Hx-bnE">
+                            <rect key="frame" x="12" y="304" width="40" height="40"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="40" id="7xk-1J-YTy"/>
+                                <constraint firstAttribute="width" constant="40" id="QXv-vp-d3y"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="20"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </imageView>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="b7F-Ah-faY" firstAttribute="leading" secondItem="AnK-wf-4BP" secondAttribute="leading" constant="14" id="0ge-CG-MTF"/>
+                        <constraint firstItem="HX4-58-7dZ" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="tI3-dq-1Qx" secondAttribute="trailing" constant="10" id="2BH-uG-0TP"/>
+                        <constraint firstItem="9s2-dK-o6k" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="BbF-PF-VI1" secondAttribute="trailing" constant="10" id="2S5-xa-ndw"/>
+                        <constraint firstItem="C6q-FO-iK4" firstAttribute="leading" secondItem="cWt-tT-seb" secondAttribute="trailing" constant="2" id="2hu-7N-a8r"/>
+                        <constraint firstItem="0G1-Qu-QuA" firstAttribute="bottom" secondItem="mbV-Hx-bnE" secondAttribute="bottom" constant="-3" id="6Cy-AD-NID"/>
+                        <constraint firstItem="aHt-s4-D8T" firstAttribute="leading" secondItem="AnK-wf-4BP" secondAttribute="leading" id="6Ud-a4-JIc"/>
+                        <constraint firstItem="cWt-tT-seb" firstAttribute="leading" secondItem="9s2-dK-o6k" secondAttribute="trailing" constant="2" id="86T-Cf-WSC"/>
+                        <constraint firstItem="HX4-58-7dZ" firstAttribute="centerY" secondItem="tI3-dq-1Qx" secondAttribute="centerY" id="D3j-ny-W7N"/>
+                        <constraint firstAttribute="trailing" secondItem="aHt-s4-D8T" secondAttribute="trailing" id="D4L-VW-Jvc"/>
+                        <constraint firstAttribute="bottom" secondItem="C6q-FO-iK4" secondAttribute="bottom" constant="22" id="FPN-Xl-q20"/>
+                        <constraint firstAttribute="trailing" secondItem="C6q-FO-iK4" secondAttribute="trailing" constant="12" id="GKQ-xF-rvr"/>
+                        <constraint firstItem="tI3-dq-1Qx" firstAttribute="leading" secondItem="Rjf-aS-wHE" secondAttribute="trailing" id="HpP-Lw-3EG"/>
+                        <constraint firstItem="Rjf-aS-wHE" firstAttribute="leading" secondItem="b7F-Ah-faY" secondAttribute="trailing" constant="7" id="LLp-NY-23y"/>
+                        <constraint firstAttribute="bottom" secondItem="mbV-Hx-bnE" secondAttribute="bottom" constant="12" id="MI6-Qv-hdA"/>
+                        <constraint firstItem="0p4-wR-LI6" firstAttribute="top" secondItem="aHt-s4-D8T" secondAttribute="top" constant="8" id="NNB-h4-UKg"/>
+                        <constraint firstItem="YTe-Wh-9ux" firstAttribute="leading" secondItem="mbV-Hx-bnE" secondAttribute="trailing" constant="10" id="ODD-Sh-y4P"/>
+                        <constraint firstItem="aHt-s4-D8T" firstAttribute="top" secondItem="AnK-wf-4BP" secondAttribute="top" id="RD4-SY-hRF"/>
+                        <constraint firstItem="0G1-Qu-QuA" firstAttribute="leading" secondItem="YTe-Wh-9ux" secondAttribute="leading" id="RIV-x8-aDI"/>
+                        <constraint firstItem="xNR-qb-bSK" firstAttribute="leading" secondItem="AnK-wf-4BP" secondAttribute="leading" constant="14" id="UPX-5W-f7L"/>
+                        <constraint firstItem="mbV-Hx-bnE" firstAttribute="top" secondItem="YTe-Wh-9ux" secondAttribute="top" id="XgH-DR-7Iz"/>
+                        <constraint firstItem="x71-SB-35W" firstAttribute="top" secondItem="b7F-Ah-faY" secondAttribute="bottom" constant="12" id="XtM-Wm-8Wr"/>
+                        <constraint firstItem="tI3-dq-1Qx" firstAttribute="centerY" secondItem="Rjf-aS-wHE" secondAttribute="centerY" id="Yj8-Wb-KNH"/>
+                        <constraint firstItem="BbF-PF-VI1" firstAttribute="centerY" secondItem="0G1-Qu-QuA" secondAttribute="centerY" id="ZZB-SD-GrJ"/>
+                        <constraint firstItem="C6q-FO-iK4" firstAttribute="bottom" secondItem="cWt-tT-seb" secondAttribute="bottom" constant="-2" id="fOE-3z-phS"/>
+                        <constraint firstItem="BbF-PF-VI1" firstAttribute="leading" secondItem="0G1-Qu-QuA" secondAttribute="trailing" constant="4" id="iK5-a0-Q0L"/>
+                        <constraint firstItem="0p4-wR-LI6" firstAttribute="leading" secondItem="aHt-s4-D8T" secondAttribute="leading" constant="8" id="jH6-0a-VXN"/>
+                        <constraint firstItem="b7F-Ah-faY" firstAttribute="top" secondItem="xNR-qb-bSK" secondAttribute="bottom" constant="12" id="mF7-Yc-eV1"/>
+                        <constraint firstItem="Rjf-aS-wHE" firstAttribute="centerY" secondItem="b7F-Ah-faY" secondAttribute="centerY" id="p8i-WX-5fp"/>
+                        <constraint firstAttribute="trailing" secondItem="xNR-qb-bSK" secondAttribute="trailing" constant="14" id="sO9-to-jgg"/>
+                        <constraint firstItem="cWt-tT-seb" firstAttribute="leading" secondItem="9s2-dK-o6k" secondAttribute="trailing" constant="2" id="t2b-1n-LSD"/>
+                        <constraint firstItem="x71-SB-35W" firstAttribute="leading" secondItem="AnK-wf-4BP" secondAttribute="leading" constant="14" id="tJX-re-JM9"/>
+                        <constraint firstItem="cWt-tT-seb" firstAttribute="bottom" secondItem="9s2-dK-o6k" secondAttribute="bottom" constant="2" id="u52-2A-BdI"/>
+                        <constraint firstItem="mbV-Hx-bnE" firstAttribute="top" secondItem="x71-SB-35W" secondAttribute="bottom" constant="12" id="uE3-UD-ftI"/>
+                        <constraint firstItem="mbV-Hx-bnE" firstAttribute="leading" secondItem="AnK-wf-4BP" secondAttribute="leading" constant="12" id="uGB-Yx-QCx"/>
+                        <constraint firstAttribute="trailing" secondItem="HX4-58-7dZ" secondAttribute="trailing" constant="14" id="uJK-V0-w7v"/>
+                        <constraint firstItem="xNR-qb-bSK" firstAttribute="top" secondItem="aHt-s4-D8T" secondAttribute="bottom" constant="8" id="vZf-3A-AIM"/>
+                        <constraint firstAttribute="trailing" secondItem="x71-SB-35W" secondAttribute="trailing" constant="14" id="voP-FF-TiI"/>
+                        <constraint firstItem="tI3-dq-1Qx" firstAttribute="centerY" secondItem="Rjf-aS-wHE" secondAttribute="centerY" id="w2M-LD-W4V"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Hda-fO-ads">
+                    <rect key="frame" x="14" y="368" width="365" height="137"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="minePage_course_introduce" translatesAutoresizingMaskIntoConstraints="NO" id="5o1-8f-tcE">
+                            <rect key="frame" x="12" y="12" width="18" height="18"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="18" id="O1p-VD-rue"/>
+                                <constraint firstAttribute="width" constant="18" id="hpR-qd-ntj"/>
+                            </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="qE8-hC-MnO">
+                            <rect key="frame" x="36" y="12" width="59.666666666666657" height="18"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="18" id="7xp-tf-zZB"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
+                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="VIP定制课是客制化的1v1线上课程。老师根据您的学习需求和希望达到的成果定制教学内容。为了提高您的上课体验,约课前请与老师充分沟通,达成一致后课根据老师的空闲时间约定上课时间。" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hIr-WK-MPf">
+                            <rect key="frame" x="12" y="55" width="341" height="70"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                            <color key="textColor" red="0.46666666670000001" green="0.46666666670000001" blue="0.46666666670000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9E4-IH-PKP">
+                            <rect key="frame" x="12" y="42" width="341" height="1"/>
+                            <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="FlM-Fo-Un1"/>
+                            </constraints>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstAttribute="trailing" secondItem="9E4-IH-PKP" secondAttribute="trailing" constant="12" id="0BC-2V-ZhJ"/>
+                        <constraint firstItem="5o1-8f-tcE" firstAttribute="leading" secondItem="Hda-fO-ads" secondAttribute="leading" constant="12" id="4H4-Ts-FO6"/>
+                        <constraint firstItem="5o1-8f-tcE" firstAttribute="top" secondItem="Hda-fO-ads" secondAttribute="top" constant="12" id="F2q-x5-ZPb"/>
+                        <constraint firstItem="hIr-WK-MPf" firstAttribute="leading" secondItem="Hda-fO-ads" secondAttribute="leading" constant="12" id="SyT-bL-Uxe"/>
+                        <constraint firstItem="qE8-hC-MnO" firstAttribute="leading" secondItem="5o1-8f-tcE" secondAttribute="trailing" constant="6" id="U7V-EZ-zeW"/>
+                        <constraint firstItem="hIr-WK-MPf" firstAttribute="top" secondItem="9E4-IH-PKP" secondAttribute="bottom" constant="12" id="XbW-GZ-1pg"/>
+                        <constraint firstAttribute="trailing" secondItem="hIr-WK-MPf" secondAttribute="trailing" constant="12" id="Z0g-Wy-LS9"/>
+                        <constraint firstItem="9E4-IH-PKP" firstAttribute="top" secondItem="5o1-8f-tcE" secondAttribute="bottom" constant="12" id="jJ0-qn-N3m"/>
+                        <constraint firstItem="qE8-hC-MnO" firstAttribute="centerY" secondItem="5o1-8f-tcE" secondAttribute="centerY" id="je9-nO-mMF"/>
+                        <constraint firstItem="9E4-IH-PKP" firstAttribute="leading" secondItem="Hda-fO-ads" secondAttribute="leading" constant="12" id="ndi-BE-hjJ"/>
+                        <constraint firstAttribute="bottom" secondItem="hIr-WK-MPf" secondAttribute="bottom" constant="12" id="vJX-zG-Ahr"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="8"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="Hda-fO-ads" secondAttribute="bottom" id="I60-Go-wnP"/>
+                <constraint firstItem="AnK-wf-4BP" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="I9z-3B-cLa"/>
+                <constraint firstAttribute="trailing" secondItem="Hda-fO-ads" secondAttribute="trailing" constant="14" id="OcW-zp-x3h"/>
+                <constraint firstItem="Hda-fO-ads" firstAttribute="top" secondItem="AnK-wf-4BP" secondAttribute="bottom" constant="12" id="RL5-aS-5Cr"/>
+                <constraint firstItem="AnK-wf-4BP" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="b33-8w-dfy"/>
+                <constraint firstAttribute="trailing" secondItem="AnK-wf-4BP" secondAttribute="trailing" id="xnY-5s-jUP"/>
+                <constraint firstItem="Hda-fO-ads" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="yBe-pp-k3f"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="courseCount" destination="C6q-FO-iK4" id="8cI-8x-gjO"/>
+                <outlet property="courseDesc" destination="BbF-PF-VI1" id="H73-9A-dq2"/>
+                <outlet property="courseIntroduce" destination="hIr-WK-MPf" id="NAw-dY-9Zq"/>
+                <outlet property="courseName" destination="xNR-qb-bSK" id="rF1-vK-9cr"/>
+                <outlet property="courseTime" destination="tI3-dq-1Qx" id="e8U-Ch-0KC"/>
+                <outlet property="coverImage" destination="aHt-s4-D8T" id="qLr-1d-crD"/>
+                <outlet property="orderUser" destination="cfo-DH-vsM" id="iAF-ZJ-mTd"/>
+                <outlet property="orderUserBg" destination="HX4-58-7dZ" id="zz9-M5-usj"/>
+                <outlet property="priceLabel" destination="cWt-tT-seb" id="5bF-eZ-Gib"/>
+                <outlet property="subjectLabel" destination="WXY-Wu-N8t" id="0V3-27-9gZ"/>
+                <outlet property="tagLabel" destination="9s2-dK-o6k" id="BNj-8H-303"/>
+                <outlet property="teacherAvatar" destination="mbV-Hx-bnE" id="TMC-Hb-iRX"/>
+                <outlet property="teacherName" destination="YTe-Wh-9ux" id="YK2-8u-Qhn"/>
+            </connections>
+            <point key="canvasLocation" x="43.511450381679388" y="-102.46478873239437"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="arrange_course_icon" width="12" height="14"/>
+        <image name="minePage_course_introduce" width="18" height="18"/>
+        <image name="mine_page_live_tag" width="20" height="16"/>
+        <image name="teacher_avatar" width="150" height="150"/>
+        <image name="video_placeholder" width="103" height="72"/>
+    </resources>
+</document>

+ 24 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupNavView.h

@@ -0,0 +1,24 @@
+//
+//  GroupCourseGroupNavView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^GroupCourseNavCallback)(void);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupCourseGroupNavView : UIView
+
++ (instancetype)sharedInstance;
+
+- (void)navActionCallback:(GroupCourseNavCallback)callback;
+
++ (CGFloat)getViewHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 47 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupNavView.m

@@ -0,0 +1,47 @@
+//
+//  GroupCourseGroupNavView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "GroupCourseGroupNavView.h"
+
+@interface GroupCourseGroupNavView ()
+
+@property (nonatomic, copy) GroupCourseNavCallback callback;
+
+@end
+
+@implementation GroupCourseGroupNavView
+
++ (instancetype)sharedInstance {
+    GroupCourseGroupNavView *view = [[[NSBundle mainBundle] loadNibNamed:@"GroupCourseGroupNavView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)navActionCallback:(GroupCourseNavCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (IBAction)backAction:(id)sender {
+    if (self.callback) {
+        self.callback();
+    }
+}
+
+
++ (CGFloat)getViewHeight {
+    return kNaviBarHeight;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 70 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseGroupNavView.xib

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <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="GroupCourseGroupNavView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="80"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Twy-FB-6kP">
+                    <rect key="frame" x="0.0" y="36" width="393" height="44"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="back_black" translatesAutoresizingMaskIntoConstraints="NO" id="hhu-eK-oE8">
+                            <rect key="frame" x="15" y="12" width="12" height="20"/>
+                        </imageView>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oAo-cF-u9t">
+                            <rect key="frame" x="0.0" y="2" width="40" height="40"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="40" id="fF4-db-O85"/>
+                                <constraint firstAttribute="height" constant="40" id="ibI-7c-nrz"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="backAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="cJm-fm-hWg"/>
+                            </connections>
+                        </button>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="课程组详情" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cob-Lg-OoP">
+                            <rect key="frame" x="152" y="9.6666666666666643" width="89.333333333333314" height="25"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="25" id="Gjp-Qd-ItY"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
+                            <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                    </subviews>
+                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="44" id="02L-uT-zoh"/>
+                        <constraint firstItem="hhu-eK-oE8" firstAttribute="centerY" secondItem="Twy-FB-6kP" secondAttribute="centerY" id="7Qy-nK-Vdm"/>
+                        <constraint firstItem="hhu-eK-oE8" firstAttribute="leading" secondItem="Twy-FB-6kP" secondAttribute="leading" constant="15" id="FOl-iX-cKS"/>
+                        <constraint firstItem="cob-Lg-OoP" firstAttribute="centerX" secondItem="Twy-FB-6kP" secondAttribute="centerX" id="Pkh-Fs-b5h"/>
+                        <constraint firstItem="oAo-cF-u9t" firstAttribute="leading" secondItem="Twy-FB-6kP" secondAttribute="leading" id="Qpn-s1-qEP"/>
+                        <constraint firstItem="oAo-cF-u9t" firstAttribute="centerY" secondItem="hhu-eK-oE8" secondAttribute="centerY" id="Rvz-s3-waO"/>
+                        <constraint firstItem="cob-Lg-OoP" firstAttribute="centerY" secondItem="oAo-cF-u9t" secondAttribute="centerY" id="r29-py-C6z"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="Twy-FB-6kP" secondAttribute="trailing" id="M2m-0F-MjX"/>
+                <constraint firstAttribute="bottom" secondItem="Twy-FB-6kP" secondAttribute="bottom" id="hke-Ti-OVP"/>
+                <constraint firstItem="Twy-FB-6kP" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="ux3-v8-rVl"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="43.511450381679388" y="-54.225352112676056"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="back_black" width="12" height="20"/>
+    </resources>
+</document>

+ 20 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseListCell.h

@@ -0,0 +1,20 @@
+//
+//  GroupCourseListCell.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import <UIKit/UIKit.h>
+#import "StudentGroupCourseListModel.h"
+#import "ProgramCourseListCell.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupCourseListCell : UITableViewCell
+
+- (void)configWithSource:(StudentGroupCourseListModel *)model beforeTime:(NSInteger)beforeTime callback:(GroupListModelCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 161 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseListCell.m

@@ -0,0 +1,161 @@
+//
+//  GroupCourseListCell.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "GroupCourseListCell.h"
+
+@interface GroupCourseListCell ()
+
+@property (weak, nonatomic) IBOutlet UIButton *enterButton;
+
+@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *statusLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseGroupName;
+
+@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
+
+@property (weak, nonatomic) IBOutlet UIImageView *arriveStatus;
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *arriveStatusWidth;
+
+@property (weak, nonatomic) IBOutlet UIView *subjectView;
+@property (weak, nonatomic) IBOutlet UILabel *subjectLabel;
+
+@property (nonatomic, strong) StudentGroupCourseListModel *sourceModel;
+
+@property (nonatomic, copy) GroupListModelCallback callback;
+
+@property (nonatomic, assign) NSInteger beforeTime;
+
+@property (weak, nonatomic) IBOutlet UILabel *coursPlanLabel;
+
+@end
+
+@implementation GroupCourseListCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+- (void)configWithSource:(StudentGroupCourseListModel *)model beforeTime:(NSInteger)beforeTime callback:(GroupListModelCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    self.sourceModel = model;
+    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 *lessonBegin = [formatter stringFromDate:startDate];
+    [formatter setDateFormat:@"HH:mm"];
+    NSString *lessonEnd = [formatter stringFromDate:endDate];
+    self.timeLabel.text = [NSString stringWithFormat:@"%@~%@",[NSString returnNoNullStringWithString:lessonBegin],[NSString returnNoNullStringWithString:lessonEnd]];
+    self.courseGroupName.text = [NSString returnNoNullStringWithString:model.courseGroupName];
+    self.nameLabel.text = [NSString returnNoNullStringWithString:model.userName];
+    self.subjectLabel.text = [NSString returnNoNullStringWithString:model.subjectName];
+    if ([NSString isEmptyString:model.subjectName]) {
+        self.subjectView.hidden = YES;
+    }
+    else {
+        self.subjectView.hidden = NO;
+    }
+    [self evaluateWithSource:model];
+    
+    // 描述
+    NSString *planDesc = model.coursePlan;
+    
+    if ([NSString isEmptyString:planDesc]) {
+        planDesc = @"暂无课程规划";
+    }
+    NSMutableParagraphStyle *paragraphStyle = [GroupCourseListCell getParagraphStyleWithFont:[UIFont systemFontOfSize:13.0f] lineHeight:22.0f];
+    CGFloat baselineOffset = [GroupCourseListCell getBaseOffline:[UIFont systemFontOfSize:13.0f] lineHeight:22.0f];
+    NSMutableAttributedString *attrs = [[NSMutableAttributedString alloc] initWithString:planDesc attributes:@{NSParagraphStyleAttributeName:paragraphStyle, NSBaselineOffsetAttributeName:@(baselineOffset),NSFontAttributeName:[UIFont systemFontOfSize:13.0f], NSForegroundColorAttributeName:HexRGB(0x777777)}];
+    self.coursPlanLabel.attributedText = attrs;
+}
+
+
+- (void)evaluateWithSource:(StudentGroupCourseListModel *)model {
+    NSString *imageName = model.attendanceStatus ? @"course_attendence" : @"course_noArrive";
+    if ([model.status isEqualToString:@"ING"]) {
+        self.statusLabel.text = @"进行中";
+        self.statusLabel.textColor = THEMECOLOR;
+        self.arriveStatus.hidden = YES;
+        self.arriveStatusWidth.constant = 0.0f;
+        self.enterButton.hidden = NO;
+        self.enterButton.userInteractionEnabled = YES;
+    }
+    else if ([model.status isEqualToString:@"NOT_START"]) {
+        self.statusLabel.text = @"未开始";
+        self.statusLabel.textColor = HexRGB(0xFF802C);
+        self.arriveStatus.hidden = YES;
+        self.arriveStatusWidth.constant = 0.0f;
+        
+        // 判断按钮显示调课还是进入教室
+        NSDate *currentDate = [NSDate date];
+        NSDate *beginDate = [self getCourseBeginDate:model.startTime];
+        NSTimeInterval beginTimeInterval = [beginDate timeIntervalSinceDate:currentDate];
+        BOOL canChange = NO;
+        if (beginTimeInterval > self.beforeTime * 60) {
+            canChange = YES;
+        }
+        if (canChange) {
+            self.enterButton.hidden = YES;
+            self.enterButton.userInteractionEnabled = NO;
+        }
+        else {
+            self.enterButton.hidden = NO;
+            self.enterButton.userInteractionEnabled = YES;
+        }
+    }
+    else if ([model.status isEqualToString:@"COMPLETE"]) {
+        self.statusLabel.text = @"已结束";
+        self.statusLabel.textColor = HexRGB(0x999999);
+        self.arriveStatus.hidden = NO;
+        self.arriveStatusWidth.constant = 36.0f;
+        self.enterButton.hidden = YES;
+        self.enterButton.userInteractionEnabled = NO;
+    }
+    [self.arriveStatus setImage:[UIImage imageNamed:imageName]];
+}
+
+
+- (IBAction)enterClassRoom:(id)sender {
+    if (self.callback) {
+        self.callback(self.sourceModel);
+    }
+}
+
+- (NSDate *)getCourseBeginDate:(NSString *)beginTime {
+    NSDateFormatter *dateFormatter = [NSObject getDateformatter];
+    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *beginDate = [dateFormatter dateFromString:beginTime];
+    return beginDate;
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
++ (CGFloat)getBaseOffline:(UIFont *)font lineHeight:(CGFloat)lineHeight {
+    CGFloat baselineOffset = (lineHeight - font.lineHeight) / 4;
+    return baselineOffset;
+}
+
++ (NSMutableParagraphStyle *)getParagraphStyleWithFont:(UIFont *)font lineHeight:(CGFloat)lineHeigh {
+    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
+    paragraphStyle.maximumLineHeight = lineHeigh;
+    paragraphStyle.minimumLineHeight = lineHeigh;
+    return paragraphStyle;
+}
+
+
+@end

+ 248 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/MyGroupCourse/View/GroupCourseListCell.xib

@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <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="189" id="KGk-i7-Jjw" customClass="GroupCourseListCell">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="189"/>
+            <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="320" height="189"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LWM-GL-2PH">
+                        <rect key="frame" x="14" y="0.0" width="292" height="177"/>
+                        <subviews>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iLa-EZ-zRx">
+                                <rect key="frame" x="0.0" y="0.0" width="292" height="111"/>
+                                <subviews>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gqH-Nk-A1o">
+                                        <rect key="frame" x="10" y="46" width="272" 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="EuM-DR-pbM"/>
+                                        </constraints>
+                                    </view>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="course_time" translatesAutoresizingMaskIntoConstraints="NO" id="sqA-d1-zSQ">
+                                        <rect key="frame" x="12" y="15" width="16" height="16"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="16" id="bQx-Mq-diy"/>
+                                            <constraint firstAttribute="width" constant="16" id="p2n-Kf-OZ5"/>
+                                        </constraints>
+                                    </imageView>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZYo-j3-z1x">
+                                        <rect key="frame" x="35" y="14" width="0.0" height="18"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="18" id="dJl-Sb-ip9"/>
+                                        </constraints>
+                                        <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                        <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="进行中" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ppo-xJ-iwM">
+                                        <rect key="frame" x="238" y="12" width="42" height="22"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="22" id="TFc-SF-woq"/>
+                                        </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="custom" customColorSpace="sRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="course_group" translatesAutoresizingMaskIntoConstraints="NO" id="HoS-AU-9Xu">
+                                        <rect key="frame" x="12" y="59" width="40" height="40"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="40" id="ahR-zj-ifd"/>
+                                            <constraint firstAttribute="width" constant="40" id="qep-w8-8cv"/>
+                                        </constraints>
+                                        <userDefinedRuntimeAttributes>
+                                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                                <real key="value" value="20"/>
+                                            </userDefinedRuntimeAttribute>
+                                        </userDefinedRuntimeAttributes>
+                                    </imageView>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gRy-bX-ROl">
+                                        <rect key="frame" x="62" y="58" width="0.0" height="21"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="21" id="bqC-gq-peK"/>
+                                        </constraints>
+                                        <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                        <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="merge_next" translatesAutoresizingMaskIntoConstraints="NO" id="Sa1-UP-VsZ">
+                                        <rect key="frame" x="268" y="73" width="12" height="12"/>
+                                        <constraints>
+                                            <constraint firstAttribute="width" constant="12" id="BpF-1U-NnJ"/>
+                                            <constraint firstAttribute="height" constant="12" id="cX3-gL-Fr8"/>
+                                        </constraints>
+                                    </imageView>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RGo-uj-cZC">
+                                        <rect key="frame" x="62" y="83" width="0.0" height="17"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="17" id="rqY-aO-o1b"/>
+                                        </constraints>
+                                        <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                        <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                    <view contentMode="scaleToFill" horizontalCompressionResistancePriority="752" translatesAutoresizingMaskIntoConstraints="NO" id="drt-My-D0t">
+                                        <rect key="frame" x="67" y="83" width="8" height="17"/>
+                                        <subviews>
+                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mey-Xj-mmX">
+                                                <rect key="frame" x="4" y="8.6666666666666714" width="0.0" height="0.0"/>
+                                                <fontDescription key="fontDescription" type="system" pointSize="10"/>
+                                                <color key="textColor" red="1" green="0.54901960780000003" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                <nil key="highlightedColor"/>
+                                            </label>
+                                        </subviews>
+                                        <color key="backgroundColor" red="1" green="0.94509803920000002" blue="0.87058823529999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="17" id="XF5-8r-fEl"/>
+                                            <constraint firstItem="Mey-Xj-mmX" firstAttribute="centerY" secondItem="drt-My-D0t" secondAttribute="centerY" id="aC3-vI-T6x"/>
+                                            <constraint firstItem="Mey-Xj-mmX" firstAttribute="leading" secondItem="drt-My-D0t" secondAttribute="leading" constant="4" id="lhh-pn-QD0"/>
+                                            <constraint firstAttribute="trailing" secondItem="Mey-Xj-mmX" secondAttribute="trailing" constant="4" id="v46-hj-Rkg"/>
+                                        </constraints>
+                                        <userDefinedRuntimeAttributes>
+                                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                                <real key="value" value="4"/>
+                                            </userDefinedRuntimeAttribute>
+                                        </userDefinedRuntimeAttributes>
+                                    </view>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Sta-67-USN">
+                                        <rect key="frame" x="67" y="59.666666666666657" width="36" height="18"/>
+                                        <constraints>
+                                            <constraint firstAttribute="width" constant="36" id="G8H-lt-3Tu"/>
+                                            <constraint firstAttribute="height" constant="18" id="cpK-rP-URc"/>
+                                        </constraints>
+                                    </imageView>
+                                    <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LoT-BK-0di">
+                                        <rect key="frame" x="218" y="12" width="62" height="22"/>
+                                        <color key="backgroundColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="22" id="ae9-jw-tHc"/>
+                                            <constraint firstAttribute="width" constant="62" id="qy7-Kr-ynt"/>
+                                        </constraints>
+                                        <fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
+                                        <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="11"/>
+                                            </userDefinedRuntimeAttribute>
+                                        </userDefinedRuntimeAttributes>
+                                    </button>
+                                </subviews>
+                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                                <constraints>
+                                    <constraint firstAttribute="trailing" secondItem="LoT-BK-0di" secondAttribute="trailing" constant="12" id="3Jw-qQ-51b"/>
+                                    <constraint firstItem="drt-My-D0t" firstAttribute="leading" secondItem="RGo-uj-cZC" secondAttribute="trailing" constant="5" id="3fY-QR-qYD"/>
+                                    <constraint firstItem="Sta-67-USN" firstAttribute="centerY" secondItem="gRy-bX-ROl" secondAttribute="centerY" id="7Ni-vZ-Xzm"/>
+                                    <constraint firstItem="Sa1-UP-VsZ" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="drt-My-D0t" secondAttribute="trailing" constant="5" id="Aoi-ZV-feJ"/>
+                                    <constraint firstItem="ZYo-j3-z1x" firstAttribute="leading" secondItem="sqA-d1-zSQ" secondAttribute="trailing" constant="7" id="E5t-0T-7e8"/>
+                                    <constraint firstAttribute="trailing" secondItem="Sa1-UP-VsZ" secondAttribute="trailing" constant="12" id="E6J-hS-iYJ"/>
+                                    <constraint firstItem="RGo-uj-cZC" firstAttribute="top" secondItem="gRy-bX-ROl" secondAttribute="bottom" constant="4" id="Jo2-75-YiS"/>
+                                    <constraint firstItem="sqA-d1-zSQ" firstAttribute="leading" secondItem="iLa-EZ-zRx" secondAttribute="leading" constant="12" id="LAe-M7-WH4"/>
+                                    <constraint firstAttribute="trailing" secondItem="gqH-Nk-A1o" secondAttribute="trailing" constant="10" id="NZX-6q-dw0"/>
+                                    <constraint firstItem="gqH-Nk-A1o" firstAttribute="top" secondItem="sqA-d1-zSQ" secondAttribute="bottom" constant="15" id="RJ7-H0-2yF"/>
+                                    <constraint firstItem="HoS-AU-9Xu" firstAttribute="leading" secondItem="iLa-EZ-zRx" secondAttribute="leading" constant="12" id="SOH-Yn-Lga"/>
+                                    <constraint firstItem="ppo-xJ-iwM" firstAttribute="centerY" secondItem="ZYo-j3-z1x" secondAttribute="centerY" id="Zsf-Pt-Ca2"/>
+                                    <constraint firstAttribute="bottom" secondItem="Sa1-UP-VsZ" secondAttribute="bottom" constant="26" id="aS1-rw-Wih"/>
+                                    <constraint firstItem="LoT-BK-0di" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="ZYo-j3-z1x" secondAttribute="trailing" constant="5" id="ach-gw-EIT"/>
+                                    <constraint firstItem="Sa1-UP-VsZ" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Sta-67-USN" secondAttribute="trailing" constant="5" id="bCe-97-Chy"/>
+                                    <constraint firstItem="LoT-BK-0di" firstAttribute="top" secondItem="iLa-EZ-zRx" secondAttribute="top" constant="12" id="eBk-gi-6zc"/>
+                                    <constraint firstItem="gqH-Nk-A1o" firstAttribute="leading" secondItem="iLa-EZ-zRx" secondAttribute="leading" constant="10" id="eUd-64-Goa"/>
+                                    <constraint firstItem="gRy-bX-ROl" firstAttribute="top" secondItem="HoS-AU-9Xu" secondAttribute="top" constant="-1" id="efS-dz-5Nl"/>
+                                    <constraint firstItem="drt-My-D0t" firstAttribute="centerY" secondItem="RGo-uj-cZC" secondAttribute="centerY" id="f1N-WP-1bZ"/>
+                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="drt-My-D0t" secondAttribute="trailing" constant="12" id="hyC-mw-Zs0"/>
+                                    <constraint firstAttribute="trailing" secondItem="ppo-xJ-iwM" secondAttribute="trailing" constant="12" id="k1b-fC-hlN"/>
+                                    <constraint firstItem="gRy-bX-ROl" firstAttribute="leading" secondItem="HoS-AU-9Xu" secondAttribute="trailing" constant="10" id="kDm-en-hLE"/>
+                                    <constraint firstItem="sqA-d1-zSQ" firstAttribute="top" secondItem="iLa-EZ-zRx" secondAttribute="top" constant="15" id="p83-xS-z25"/>
+                                    <constraint firstItem="ZYo-j3-z1x" firstAttribute="centerY" secondItem="sqA-d1-zSQ" secondAttribute="centerY" id="qe2-nZ-cdT"/>
+                                    <constraint firstItem="RGo-uj-cZC" firstAttribute="leading" secondItem="gRy-bX-ROl" secondAttribute="leading" id="rKF-mN-Y0Y"/>
+                                    <constraint firstAttribute="bottom" secondItem="HoS-AU-9Xu" secondAttribute="bottom" constant="12" id="tEa-Zs-UqB"/>
+                                    <constraint firstItem="Sta-67-USN" firstAttribute="leading" secondItem="gRy-bX-ROl" secondAttribute="trailing" constant="5" id="xs5-jm-4XI"/>
+                                    <constraint firstItem="HoS-AU-9Xu" firstAttribute="top" secondItem="gqH-Nk-A1o" secondAttribute="bottom" constant="12" id="xuv-B6-fks"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qeE-Ft-83e">
+                                <rect key="frame" x="12" y="111" width="268" height="54"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="严琦老师带您零基础学习大号,通过4节课的学习掌握大号演奏的基本方式,培养良好的吐息习惯。" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vGB-9D-omH">
+                                        <rect key="frame" x="7" y="6" width="254" height="42"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                        <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="trailing" secondItem="vGB-9D-omH" secondAttribute="trailing" constant="7" id="DLq-xj-fag"/>
+                                    <constraint firstItem="vGB-9D-omH" firstAttribute="top" secondItem="qeE-Ft-83e" secondAttribute="top" constant="6" id="Z09-cf-MNg"/>
+                                    <constraint firstAttribute="bottom" secondItem="vGB-9D-omH" secondAttribute="bottom" constant="6" id="fJp-91-trb"/>
+                                    <constraint firstItem="vGB-9D-omH" firstAttribute="leading" secondItem="qeE-Ft-83e" secondAttribute="leading" constant="7" id="jKA-Ho-vFW"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="6"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstItem="iLa-EZ-zRx" firstAttribute="leading" secondItem="LWM-GL-2PH" secondAttribute="leading" id="0Cf-dH-Khh"/>
+                            <constraint firstItem="qeE-Ft-83e" firstAttribute="leading" secondItem="LWM-GL-2PH" secondAttribute="leading" constant="12" id="DbI-ss-oAn"/>
+                            <constraint firstItem="iLa-EZ-zRx" firstAttribute="top" secondItem="LWM-GL-2PH" secondAttribute="top" id="L5s-Id-E27"/>
+                            <constraint firstAttribute="trailing" secondItem="qeE-Ft-83e" secondAttribute="trailing" constant="12" id="ZcC-r7-XNd"/>
+                            <constraint firstAttribute="trailing" secondItem="iLa-EZ-zRx" secondAttribute="trailing" id="mfx-s6-tdv"/>
+                            <constraint firstItem="qeE-Ft-83e" firstAttribute="top" secondItem="iLa-EZ-zRx" secondAttribute="bottom" id="rM8-gQ-B7T"/>
+                            <constraint firstAttribute="bottom" secondItem="qeE-Ft-83e" secondAttribute="bottom" constant="12" id="uTX-mt-T4L"/>
+                        </constraints>
+                    </view>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="LWM-GL-2PH" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="3ne-Oq-aif"/>
+                    <constraint firstAttribute="trailing" secondItem="LWM-GL-2PH" secondAttribute="trailing" constant="14" id="Js8-9I-hdI"/>
+                    <constraint firstAttribute="bottom" secondItem="LWM-GL-2PH" secondAttribute="bottom" constant="12" id="P4t-7v-kiq"/>
+                    <constraint firstItem="LWM-GL-2PH" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="14" id="gfz-hv-2lh"/>
+                </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="arriveStatus" destination="Sta-67-USN" id="AzA-fm-0EI"/>
+                <outlet property="arriveStatusWidth" destination="G8H-lt-3Tu" id="IXD-CG-QGz"/>
+                <outlet property="coursPlanLabel" destination="vGB-9D-omH" id="2bk-vl-lGD"/>
+                <outlet property="courseGroupName" destination="gRy-bX-ROl" id="Qmi-4e-GSd"/>
+                <outlet property="enterButton" destination="LoT-BK-0di" id="mAz-tk-FWv"/>
+                <outlet property="nameLabel" destination="RGo-uj-cZC" id="fsp-J1-2MS"/>
+                <outlet property="statusLabel" destination="ppo-xJ-iwM" id="Pvp-Q0-2WW"/>
+                <outlet property="subjectLabel" destination="Mey-Xj-mmX" id="hj8-RB-ATf"/>
+                <outlet property="subjectView" destination="drt-My-D0t" id="uLE-77-rMO"/>
+                <outlet property="timeLabel" destination="ZYo-j3-z1x" id="4sI-nh-mmz"/>
+            </connections>
+            <point key="canvasLocation" x="42.748091603053432" y="98.943661971830991"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="course_group" width="56" height="56"/>
+        <image name="course_time" width="16" height="16"/>
+        <image name="merge_next" width="14" height="14"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 0 - 4
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseGroupView/GroupCourseSortView.h

@@ -8,7 +8,6 @@
 #import <UIKit/UIKit.h>
 
 typedef NS_ENUM(NSInteger, SORT_TYPE) {
-    SORT_TYPE_TIME = 1,   // 课程时间
     SORT_TYPE_STATUS = 2, // 课程状态
     SORT_TYPE_ATTENDENCE = 3,  // 考勤筛选
     SORT_TYPE_HIDDEN = 4, // 隐藏
@@ -22,12 +21,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, assign) BOOL showWhiteBg;
 
-@property (weak, nonatomic) IBOutlet UILabel *firstLabel;
 @property (weak, nonatomic) IBOutlet UILabel *secondLabel;
 @property (weak, nonatomic) IBOutlet UILabel *thirdLabel;
 
-@property (nonatomic, assign) BOOL firstArrowUp;
-
 @property (nonatomic, assign) BOOL secondArrowUp;
 
 @property (nonatomic, assign) BOOL thirdArrowUp;

+ 10 - 32
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseGroupView/GroupCourseSortView.m

@@ -10,11 +10,9 @@
 @interface GroupCourseSortView ()
 
 @property (nonatomic, copy) SortActionBlock block;
-@property (weak, nonatomic) IBOutlet UIView *firstWihteView;
 @property (weak, nonatomic) IBOutlet UIView *secondWhiteView;
 @property (weak, nonatomic) IBOutlet UIView *thirdWihteView;
 
-@property (weak, nonatomic) IBOutlet UIImageView *firstArrow;
 @property (weak, nonatomic) IBOutlet UIImageView *secondArrow;
 @property (weak, nonatomic) IBOutlet UIImageView *thirdArrow;
 
@@ -24,7 +22,6 @@
 @implementation GroupCourseSortView
 - (void)awakeFromNib {
     [super awakeFromNib];
-    self.firstArrowUp = NO;
     self.secondArrowUp = NO;
     self.thirdArrowUp = NO;
 }
@@ -43,21 +40,13 @@
 - (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) {
+    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;
     }
@@ -70,25 +59,12 @@
     }
 }
 
-- (void)setFirstArrowUp:(BOOL)firstArrowUp {
-    _firstArrowUp = firstArrowUp;
-    NSString *imageName = firstArrowUp ? @"sort_up_blue" : @"sort_down_grey";
-    [_firstArrow setImage:[UIImage imageNamed:imageName]];
-    UIColor *titleColor = nil;
-    if (firstArrowUp) {
-        titleColor = THEMECOLOR;
-    }
-    else {
-        titleColor = HexRGB(0x131415);
-    }
-    _firstLabel.textColor = titleColor;
-}
 
 - (void)setSecondArrowUp:(BOOL)secondArrowUp {
     _secondArrowUp = secondArrowUp;
     NSString *imageName = secondArrowUp ? @"sort_up_blue" : @"sort_down_grey";
     [_secondArrow setImage:[UIImage imageNamed:imageName]];
-    
+
     UIColor *titleColor = nil;
     if (secondArrowUp) {
         titleColor = THEMECOLOR;
@@ -97,7 +73,6 @@
         titleColor = HexRGB(0x131415);
     }
     _secondLabel.textColor = titleColor;
-
 }
 
 - (void)setThirdArrowUp:(BOOL)thirdArrowUp {
@@ -116,11 +91,14 @@
 
 - (void)setShowWhiteBg:(BOOL)showWhiteBg {
     _showWhiteBg = showWhiteBg;
-    if (showWhiteBg) {
-        self.firstWihteView.hidden = NO;
-        self.secondWhiteView.hidden = NO;
-        self.thirdWihteView.hidden = NO;
-    }
+//    if (showWhiteBg) {
+//        self.secondWhiteView.backgroundColor = [UIColor whiteColor];
+//        self.thirdWihteView.backgroundColor = [UIColor whiteColor];
+//    }
+//    else {
+//        self.secondWhiteView.backgroundColor = [UIColor clearColor];
+//        self.thirdWihteView.backgroundColor = [UIColor clearColor];
+//    }
 }
 + (CGFloat)getViewHeight {
     return 50.0f;

+ 74 - 136
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseGroupView/GroupCourseSortView.xib

@@ -10,96 +10,44 @@
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
         <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="GroupCourseSortView">
-            <rect key="frame" x="0.0" y="0.0" width="375" height="55"/>
+            <rect key="frame" x="0.0" y="0.0" width="375" height="38"/>
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nUQ-28-ciH">
-                    <rect key="frame" x="14" y="0.0" width="347" height="55"/>
+                    <rect key="frame" x="14" y="0.0" width="347" height="38"/>
                     <subviews>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3ud-K6-gBw">
-                            <rect key="frame" x="0.0" y="0.0" width="109" height="55"/>
-                            <subviews>
-                                <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aMc-qL-Urw">
-                                    <rect key="frame" x="4.9999999999999929" y="16.666666666666668" width="127.33333333333331" height="22.000000000000004"/>
-                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="22" id="0KX-Sp-gSa"/>
-                                    </constraints>
-                                    <userDefinedRuntimeAttributes>
-                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="11"/>
-                                        </userDefinedRuntimeAttribute>
-                                    </userDefinedRuntimeAttributes>
-                                </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="XXXX年XX月" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cfT-LB-SNv">
-                                    <rect key="frame" x="17" y="19" width="89.333333333333329" height="17"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                    <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="aFu-Ok-mVy">
-                                    <rect key="frame" x="111.33333333333333" y="25" width="9" height="5"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="5" id="f2v-0M-H3l"/>
-                                        <constraint firstAttribute="width" constant="9" id="zTE-EP-L2e"/>
-                                    </constraints>
-                                </imageView>
-                                <button opaque="NO" tag="1001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ac9-lB-T0k">
-                                    <rect key="frame" x="0.0" y="0.0" width="109" height="55"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                    <state key="normal">
-                                        <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="IiH-Q8-iJf"/>
-                                    </connections>
-                                </button>
-                            </subviews>
-                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                            <constraints>
-                                <constraint firstItem="aMc-qL-Urw" firstAttribute="leading" secondItem="cfT-LB-SNv" secondAttribute="leading" constant="-12" id="0wS-wv-cqh"/>
-                                <constraint firstItem="cfT-LB-SNv" firstAttribute="centerX" secondItem="3ud-K6-gBw" secondAttribute="centerX" constant="7" id="6fu-Rx-39P"/>
-                                <constraint firstItem="aFu-Ok-mVy" firstAttribute="trailing" secondItem="aMc-qL-Urw" secondAttribute="trailing" constant="-12" id="F1D-4S-yAe"/>
-                                <constraint firstAttribute="bottom" secondItem="Ac9-lB-T0k" secondAttribute="bottom" id="FjI-Y5-7yE"/>
-                                <constraint firstItem="cfT-LB-SNv" firstAttribute="centerY" secondItem="3ud-K6-gBw" secondAttribute="centerY" id="J0t-LD-eL1"/>
-                                <constraint firstItem="Ac9-lB-T0k" firstAttribute="leading" secondItem="3ud-K6-gBw" secondAttribute="leading" id="g1O-Id-15a"/>
-                                <constraint firstItem="aFu-Ok-mVy" firstAttribute="centerY" secondItem="3ud-K6-gBw" secondAttribute="centerY" id="gDl-5L-mjU"/>
-                                <constraint firstItem="aFu-Ok-mVy" firstAttribute="leading" secondItem="cfT-LB-SNv" secondAttribute="trailing" constant="5" id="llT-OJ-w6i"/>
-                                <constraint firstItem="Ac9-lB-T0k" firstAttribute="top" secondItem="3ud-K6-gBw" secondAttribute="top" id="ofj-Sg-mn8"/>
-                                <constraint firstItem="aMc-qL-Urw" firstAttribute="centerY" secondItem="cfT-LB-SNv" secondAttribute="centerY" id="s31-wv-m1e"/>
-                                <constraint firstAttribute="trailing" secondItem="Ac9-lB-T0k" secondAttribute="trailing" id="tlR-cR-LCw"/>
-                            </constraints>
-                        </view>
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z8Q-fT-2Vr">
-                            <rect key="frame" x="119" y="0.0" width="109" height="55"/>
+                            <rect key="frame" x="0.0" y="0.0" width="168" height="38"/>
                             <subviews>
-                                <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FvZ-Cn-UvC">
-                                    <rect key="frame" x="21.666666666666657" y="16.666666666666668" width="94" height="22.000000000000004"/>
+                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FvZ-Cn-UvC">
+                                    <rect key="frame" x="0.0" y="6" width="168" height="26"/>
+                                    <subviews>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全部状态" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vxK-r7-9sg">
+                                            <rect key="frame" x="49.666666666666657" y="4.6666666666666661" width="56" height="17"/>
+                                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                            <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="idf-14-rMz">
+                                            <rect key="frame" x="109.66666666666667" y="10.666666666666668" width="9" height="5"/>
+                                        </imageView>
+                                    </subviews>
                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                     <constraints>
-                                        <constraint firstAttribute="height" constant="22" id="uMS-WH-w0m"/>
+                                        <constraint firstItem="idf-14-rMz" firstAttribute="centerY" secondItem="vxK-r7-9sg" secondAttribute="centerY" id="7ri-Ir-YWv"/>
+                                        <constraint firstItem="idf-14-rMz" firstAttribute="leading" secondItem="vxK-r7-9sg" secondAttribute="trailing" constant="4" id="MQe-TX-qmZ"/>
+                                        <constraint firstAttribute="height" constant="26" id="fcA-qG-XNs"/>
+                                        <constraint firstItem="vxK-r7-9sg" firstAttribute="centerY" secondItem="FvZ-Cn-UvC" secondAttribute="centerY" id="iKB-ub-tAI"/>
+                                        <constraint firstItem="vxK-r7-9sg" firstAttribute="centerX" secondItem="FvZ-Cn-UvC" secondAttribute="centerX" constant="-6.5" id="ziM-I9-SVE"/>
                                     </constraints>
                                     <userDefinedRuntimeAttributes>
                                         <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="11"/>
+                                            <real key="value" value="4"/>
                                         </userDefinedRuntimeAttribute>
                                     </userDefinedRuntimeAttributes>
                                 </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全部状态" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vxK-r7-9sg">
-                                    <rect key="frame" x="33.666666666666657" y="19" width="56" height="17"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                    <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="idf-14-rMz">
-                                    <rect key="frame" x="94.666666666666657" y="25" width="9" height="5"/>
-                                    <constraints>
-                                        <constraint firstAttribute="width" constant="9" id="2rB-eK-C35"/>
-                                        <constraint firstAttribute="height" constant="5" id="PIL-WN-xkd"/>
-                                    </constraints>
-                                </imageView>
                                 <button opaque="NO" tag="1002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="j1t-mT-XyA">
-                                    <rect key="frame" x="0.0" y="0.0" width="109" height="55"/>
+                                    <rect key="frame" x="0.0" y="6" width="168" height="26"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <state key="normal">
                                         <color key="titleColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="calibratedRGB"/>
@@ -111,49 +59,48 @@
                             </subviews>
                             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                             <constraints>
-                                <constraint firstItem="j1t-mT-XyA" firstAttribute="leading" secondItem="Z8Q-fT-2Vr" secondAttribute="leading" id="0ib-n1-ca3"/>
-                                <constraint firstItem="idf-14-rMz" firstAttribute="trailing" secondItem="FvZ-Cn-UvC" secondAttribute="trailing" constant="-12" id="52B-YO-Bif"/>
-                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="leading" secondItem="vxK-r7-9sg" secondAttribute="leading" constant="-12" id="8gm-W4-scE"/>
-                                <constraint firstAttribute="bottom" secondItem="j1t-mT-XyA" secondAttribute="bottom" id="FZL-fn-2Dt"/>
-                                <constraint firstItem="vxK-r7-9sg" firstAttribute="centerX" secondItem="Z8Q-fT-2Vr" secondAttribute="centerX" constant="7" id="MaH-dZ-7ix"/>
-                                <constraint firstItem="vxK-r7-9sg" firstAttribute="centerY" secondItem="Z8Q-fT-2Vr" secondAttribute="centerY" id="VqG-LO-GJj"/>
-                                <constraint firstAttribute="trailing" secondItem="j1t-mT-XyA" secondAttribute="trailing" id="VxY-bB-unG"/>
-                                <constraint firstItem="j1t-mT-XyA" firstAttribute="top" secondItem="Z8Q-fT-2Vr" secondAttribute="top" id="cMc-ie-YnM"/>
-                                <constraint firstItem="idf-14-rMz" firstAttribute="leading" secondItem="vxK-r7-9sg" secondAttribute="trailing" constant="5" id="dLB-Vt-NCZ"/>
-                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="centerY" secondItem="vxK-r7-9sg" secondAttribute="centerY" id="hWh-Qq-GIs"/>
-                                <constraint firstItem="idf-14-rMz" firstAttribute="centerY" secondItem="Z8Q-fT-2Vr" secondAttribute="centerY" id="yDm-pc-vUp"/>
+                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="trailing" secondItem="j1t-mT-XyA" secondAttribute="trailing" id="BJQ-kF-pKn"/>
+                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="centerY" secondItem="Z8Q-fT-2Vr" secondAttribute="centerY" id="Lnn-d6-Snd"/>
+                                <constraint firstAttribute="trailing" secondItem="FvZ-Cn-UvC" secondAttribute="trailing" id="W76-jq-bzh"/>
+                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="leading" secondItem="Z8Q-fT-2Vr" secondAttribute="leading" id="YU8-rx-anV"/>
+                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="bottom" secondItem="j1t-mT-XyA" secondAttribute="bottom" id="ZOr-cc-3da"/>
+                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="leading" secondItem="j1t-mT-XyA" secondAttribute="leading" id="cxj-3g-uAd"/>
+                                <constraint firstItem="FvZ-Cn-UvC" firstAttribute="top" secondItem="j1t-mT-XyA" secondAttribute="top" id="dKu-EM-1rX"/>
                             </constraints>
                         </view>
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yMy-1B-zxV">
-                            <rect key="frame" x="238" y="0.0" width="109" height="55"/>
+                            <rect key="frame" x="179" y="0.0" width="168" height="38"/>
                             <subviews>
-                                <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s7M-qE-XDr">
-                                    <rect key="frame" x="7.6666666666666856" y="16.666666666666668" width="94" height="22.000000000000004"/>
+                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s7M-qE-XDr">
+                                    <rect key="frame" x="0.0" y="6" width="168" height="26"/>
+                                    <subviews>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全部考勤" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Xc-2m-8mt">
+                                            <rect key="frame" x="49.666666666666657" y="4.6666666666666661" width="55.666666666666657" height="17"/>
+                                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                            <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="grW-VA-qlz">
+                                            <rect key="frame" x="109.33333333333331" y="10.666666666666668" width="9" height="5"/>
+                                        </imageView>
+                                    </subviews>
                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                     <constraints>
-                                        <constraint firstAttribute="height" constant="22" id="mvo-Js-pra"/>
+                                        <constraint firstAttribute="height" constant="26" id="AXP-7R-f9G"/>
+                                        <constraint firstItem="9Xc-2m-8mt" firstAttribute="centerX" secondItem="s7M-qE-XDr" secondAttribute="centerX" constant="-6.5" id="GeR-yo-YKF"/>
+                                        <constraint firstItem="grW-VA-qlz" firstAttribute="leading" secondItem="9Xc-2m-8mt" secondAttribute="trailing" constant="4" id="LXD-UI-o4a"/>
+                                        <constraint firstItem="grW-VA-qlz" firstAttribute="centerY" secondItem="s7M-qE-XDr" secondAttribute="centerY" id="Vkh-1O-BF8"/>
+                                        <constraint firstItem="9Xc-2m-8mt" firstAttribute="centerY" secondItem="s7M-qE-XDr" secondAttribute="centerY" id="aMU-h5-T5n"/>
+                                        <constraint firstItem="9Xc-2m-8mt" firstAttribute="centerY" secondItem="s7M-qE-XDr" secondAttribute="centerY" id="mrr-SQ-TiM"/>
                                     </constraints>
                                     <userDefinedRuntimeAttributes>
                                         <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="11"/>
+                                            <real key="value" value="4"/>
                                         </userDefinedRuntimeAttribute>
                                     </userDefinedRuntimeAttributes>
                                 </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全部考勤" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Xc-2m-8mt">
-                                    <rect key="frame" x="19.666666666666686" y="19" width="56" height="17"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                    <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="grW-VA-qlz">
-                                    <rect key="frame" x="80.666666666666686" y="25" width="9" height="5"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="5" id="hAG-sG-mv7"/>
-                                        <constraint firstAttribute="width" constant="9" id="sqn-jl-TbO"/>
-                                    </constraints>
-                                </imageView>
                                 <button opaque="NO" tag="1003" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5J6-Qp-5o7">
-                                    <rect key="frame" x="0.0" y="0.0" width="109" height="55"/>
+                                    <rect key="frame" x="0.0" y="6" width="168" height="26"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <state key="normal">
                                         <color key="titleColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
@@ -165,34 +112,28 @@
                             </subviews>
                             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                             <constraints>
-                                <constraint firstItem="5J6-Qp-5o7" firstAttribute="leading" secondItem="yMy-1B-zxV" secondAttribute="leading" id="0pe-f0-slu"/>
-                                <constraint firstItem="grW-VA-qlz" firstAttribute="centerY" secondItem="yMy-1B-zxV" secondAttribute="centerY" id="47f-2b-PEp"/>
-                                <constraint firstItem="9Xc-2m-8mt" firstAttribute="centerX" secondItem="yMy-1B-zxV" secondAttribute="centerX" constant="-7" id="4bT-SA-PhH"/>
-                                <constraint firstItem="s7M-qE-XDr" firstAttribute="centerY" secondItem="9Xc-2m-8mt" secondAttribute="centerY" id="7PO-WH-aaV"/>
-                                <constraint firstAttribute="trailing" secondItem="5J6-Qp-5o7" secondAttribute="trailing" id="8jw-zM-6iK"/>
-                                <constraint firstItem="5J6-Qp-5o7" firstAttribute="top" secondItem="yMy-1B-zxV" secondAttribute="top" id="HUX-nk-toA"/>
-                                <constraint firstAttribute="bottom" secondItem="5J6-Qp-5o7" secondAttribute="bottom" id="SLT-UZ-dPb"/>
-                                <constraint firstItem="9Xc-2m-8mt" firstAttribute="centerY" secondItem="yMy-1B-zxV" secondAttribute="centerY" id="jhO-f9-KY6"/>
-                                <constraint firstItem="grW-VA-qlz" firstAttribute="leading" secondItem="9Xc-2m-8mt" secondAttribute="trailing" constant="5" id="m1B-rA-bFZ"/>
-                                <constraint firstItem="grW-VA-qlz" firstAttribute="trailing" secondItem="s7M-qE-XDr" secondAttribute="trailing" constant="-12" id="mGV-zF-ekd"/>
-                                <constraint firstItem="s7M-qE-XDr" firstAttribute="leading" secondItem="9Xc-2m-8mt" secondAttribute="leading" constant="-12" id="vbs-hs-Ih7"/>
+                                <constraint firstAttribute="trailing" secondItem="s7M-qE-XDr" secondAttribute="trailing" id="1Dl-2B-iWo"/>
+                                <constraint firstItem="s7M-qE-XDr" firstAttribute="leading" secondItem="yMy-1B-zxV" secondAttribute="leading" id="HmD-ul-KMV"/>
+                                <constraint firstItem="5J6-Qp-5o7" firstAttribute="trailing" secondItem="s7M-qE-XDr" secondAttribute="trailing" id="PMQ-Jm-RMR"/>
+                                <constraint firstItem="5J6-Qp-5o7" firstAttribute="bottom" secondItem="s7M-qE-XDr" secondAttribute="bottom" id="bIh-7O-uq3"/>
+                                <constraint firstItem="s7M-qE-XDr" firstAttribute="centerY" secondItem="yMy-1B-zxV" secondAttribute="centerY" id="q9K-TX-wmm"/>
+                                <constraint firstItem="5J6-Qp-5o7" firstAttribute="top" secondItem="s7M-qE-XDr" secondAttribute="top" id="wL7-3u-bf5"/>
+                                <constraint firstItem="5J6-Qp-5o7" firstAttribute="leading" secondItem="s7M-qE-XDr" secondAttribute="leading" id="yvj-A6-a5K"/>
                             </constraints>
                         </view>
                     </subviews>
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
-                        <constraint firstItem="Z8Q-fT-2Vr" firstAttribute="top" secondItem="3ud-K6-gBw" secondAttribute="top" id="7Vc-Lw-Cz5"/>
-                        <constraint firstItem="yMy-1B-zxV" firstAttribute="top" secondItem="3ud-K6-gBw" secondAttribute="top" id="7vF-v2-rbp"/>
-                        <constraint firstItem="3ud-K6-gBw" firstAttribute="top" secondItem="nUQ-28-ciH" secondAttribute="top" id="Kwb-PF-i4E"/>
-                        <constraint firstAttribute="trailing" secondItem="yMy-1B-zxV" secondAttribute="trailing" id="a8j-cM-Bk3"/>
-                        <constraint firstItem="Z8Q-fT-2Vr" firstAttribute="width" secondItem="3ud-K6-gBw" secondAttribute="width" id="dvD-UR-61H"/>
-                        <constraint firstItem="Z8Q-fT-2Vr" firstAttribute="leading" secondItem="3ud-K6-gBw" secondAttribute="trailing" constant="10" id="g49-fx-rbj"/>
-                        <constraint firstAttribute="bottom" secondItem="3ud-K6-gBw" secondAttribute="bottom" id="jS1-OF-iaY"/>
-                        <constraint firstItem="yMy-1B-zxV" firstAttribute="leading" secondItem="Z8Q-fT-2Vr" secondAttribute="trailing" constant="10" id="obg-cI-Ey6"/>
-                        <constraint firstItem="3ud-K6-gBw" firstAttribute="leading" secondItem="nUQ-28-ciH" secondAttribute="leading" id="pPn-cT-EMU"/>
-                        <constraint firstItem="Z8Q-fT-2Vr" firstAttribute="bottom" secondItem="3ud-K6-gBw" secondAttribute="bottom" id="s1y-gn-zl5"/>
-                        <constraint firstItem="yMy-1B-zxV" firstAttribute="width" secondItem="3ud-K6-gBw" secondAttribute="width" id="uUy-6G-XIb"/>
-                        <constraint firstItem="yMy-1B-zxV" firstAttribute="bottom" secondItem="3ud-K6-gBw" secondAttribute="bottom" id="yBY-DV-CGv"/>
+                        <constraint firstItem="yMy-1B-zxV" firstAttribute="leading" secondItem="Z8Q-fT-2Vr" secondAttribute="trailing" constant="11" id="56q-qr-G9Z"/>
+                        <constraint firstItem="yMy-1B-zxV" firstAttribute="top" secondItem="nUQ-28-ciH" secondAttribute="top" id="8Ji-Nz-NFE"/>
+                        <constraint firstItem="yMy-1B-zxV" firstAttribute="width" secondItem="Z8Q-fT-2Vr" secondAttribute="width" id="FXX-NF-S5e"/>
+                        <constraint firstAttribute="bottom" secondItem="Z8Q-fT-2Vr" secondAttribute="bottom" id="TLq-uB-RdI"/>
+                        <constraint firstItem="Z8Q-fT-2Vr" firstAttribute="leading" secondItem="nUQ-28-ciH" secondAttribute="leading" id="VqG-xa-vtm"/>
+                        <constraint firstItem="yMy-1B-zxV" firstAttribute="top" secondItem="nUQ-28-ciH" secondAttribute="top" id="Xa5-Ur-OCg"/>
+                        <constraint firstAttribute="bottom" secondItem="yMy-1B-zxV" secondAttribute="bottom" id="gjN-r5-iwd"/>
+                        <constraint firstItem="Z8Q-fT-2Vr" firstAttribute="top" secondItem="nUQ-28-ciH" secondAttribute="top" id="m3V-mQ-mFc"/>
+                        <constraint firstAttribute="trailing" secondItem="yMy-1B-zxV" secondAttribute="trailing" id="vTw-nM-zEb"/>
+                        <constraint firstAttribute="trailing" secondItem="yMy-1B-zxV" secondAttribute="trailing" id="wmh-zI-69h"/>
                     </constraints>
                     <userDefinedRuntimeAttributes>
                         <userDefinedRuntimeAttribute type="size" keyPath="shadowOffset">
@@ -203,18 +144,15 @@
             </subviews>
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <constraints>
-                <constraint firstAttribute="bottom" secondItem="nUQ-28-ciH" secondAttribute="bottom" id="8Ge-mS-YzV"/>
-                <constraint firstAttribute="trailing" secondItem="nUQ-28-ciH" secondAttribute="trailing" constant="14" id="9yc-y0-4fF"/>
-                <constraint firstItem="nUQ-28-ciH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="igM-Q3-fAI"/>
-                <constraint firstItem="nUQ-28-ciH" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="yVO-Aa-YHu"/>
+                <constraint firstAttribute="bottom" secondItem="nUQ-28-ciH" secondAttribute="bottom" id="B0N-at-Kzv"/>
+                <constraint firstAttribute="trailing" secondItem="nUQ-28-ciH" secondAttribute="trailing" constant="14" id="I85-K9-Dtr"/>
+                <constraint firstItem="nUQ-28-ciH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="idR-e7-slI"/>
+                <constraint firstItem="nUQ-28-ciH" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="qEH-dZ-aR2"/>
             </constraints>
             <nil key="simulatedTopBarMetrics"/>
             <nil key="simulatedBottomBarMetrics"/>
             <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
             <connections>
-                <outlet property="firstArrow" destination="aFu-Ok-mVy" id="HfH-fU-Kon"/>
-                <outlet property="firstLabel" destination="cfT-LB-SNv" id="fxC-FN-FHH"/>
-                <outlet property="firstWihteView" destination="aMc-qL-Urw" id="TQr-no-EXT"/>
                 <outlet property="secondArrow" destination="idf-14-rMz" id="vtq-9G-6Dc"/>
                 <outlet property="secondLabel" destination="vxK-r7-9sg" id="fKB-7V-W3z"/>
                 <outlet property="secondWhiteView" destination="FvZ-Cn-UvC" id="PCo-eX-gaH"/>
@@ -222,7 +160,7 @@
                 <outlet property="thirdLabel" destination="9Xc-2m-8mt" id="1q0-e6-Dmr"/>
                 <outlet property="thirdWihteView" destination="s7M-qE-XDr" id="Nky-Dj-ksz"/>
             </connections>
-            <point key="canvasLocation" x="41.984732824427482" y="-148.94366197183101"/>
+            <point key="canvasLocation" x="41.984732824427482" y="-142.95774647887325"/>
         </view>
     </objects>
     <resources>

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Course/View/MusicRoomCourseCell.h

@@ -14,7 +14,7 @@ typedef void(^MusicRoomChatAction)(NSString *targetId);
 
 @interface MusicRoomCourseCell : UITableViewCell
 
-- (void)configWithSource:(id)source beforeTime:(NSInteger)beforeTime callback:(MusicRoomChatAction)callback;
+- (void)configWithSource:(id)source isGroup:(BOOL)isGroup beforeTime:(NSInteger)beforeTime callback:(MusicRoomChatAction)callback;
 
 @end
 

+ 4 - 1
KulexiuForStudent/KulexiuForStudent/Module/Course/View/MusicRoomCourseCell.m

@@ -11,6 +11,7 @@
 
 @interface MusicRoomCourseCell ()
 
+@property (weak, nonatomic) IBOutlet UIImageView *courseImage;
 
 @property (weak, nonatomic) IBOutlet UILabel *courseTimeLabel;
 @property (weak, nonatomic) IBOutlet UILabel *courseName;
@@ -36,10 +37,12 @@
     self.selectionStyle = UITableViewCellSelectionStyleNone;
 }
 
-- (void)configWithSource:(id)source beforeTime:(NSInteger)beforeTime callback:(MusicRoomChatAction)callback {
+- (void)configWithSource:(id)source isGroup:(BOOL)isGroup beforeTime:(NSInteger)beforeTime callback:(MusicRoomChatAction)callback {
     if (callback) {
         self.callback = callback;
     }
+    NSString *courseImgName = isGroup ? @"course_group" : @"course_musicRoom";
+    [self.courseImage setImage:[UIImage imageNamed:courseImgName]];
     if ([source isKindOfClass:[TableCourseModel class]]) {
         TableCourseModel *model = (TableCourseModel *)source;
         self.targetId = model.imGroupId;

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/View/MusicRoomCourseCell.xib

@@ -188,6 +188,7 @@
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <connections>
                 <outlet property="buttonWidth" destination="e5h-nv-3mR" id="lkB-Jc-g20"/>
+                <outlet property="courseImage" destination="KUE-40-5Jn" id="Su6-2N-lDP"/>
                 <outlet property="courseName" destination="l2B-EY-GWY" id="D00-Cj-zrr"/>
                 <outlet property="courseTimeLabel" destination="UxS-Xs-zTk" id="dkq-PI-dck"/>
                 <outlet property="memberCount" destination="W7K-ER-kaU" id="IsT-RS-XCe"/>

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/Model/StudentGroupCourseListModel.h

@@ -25,6 +25,7 @@
 @property (nonatomic, strong) NSString *startTime;
 @property (nonatomic, strong) NSString *courseGroupName;
 @property (nonatomic, strong) NSString *status;
+@property (nonatomic, strong) NSString *coursePlan;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
 - (instancetype)initWithDictionary:(NSDictionary *)dict;

+ 7 - 3
KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/Model/StudentGroupCourseListModel.m

@@ -22,6 +22,7 @@ NSString *const kStudentGroupCourseListModelAttendanceStatus = @"attendanceStatu
 NSString *const kStudentGroupCourseListModelStartTime = @"startTime";
 NSString *const kStudentGroupCourseListModelCourseGroupName = @"courseGroupName";
 NSString *const kStudentGroupCourseListModelStatus = @"status";
+NSString *const kStudentGroupCourseListModelCoursePlan = @"coursePlan";
 
 
 @interface StudentGroupCourseListModel ()
@@ -46,7 +47,7 @@ NSString *const kStudentGroupCourseListModelStatus = @"status";
 @synthesize startTime = _startTime;
 @synthesize courseGroupName = _courseGroupName;
 @synthesize status = _status;
-
+@synthesize coursePlan = _coursePlan;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
 {
@@ -74,7 +75,7 @@ NSString *const kStudentGroupCourseListModelStatus = @"status";
             self.startTime = [self objectOrNilForKey:kStudentGroupCourseListModelStartTime fromDictionary:dict];
             self.courseGroupName = [self objectOrNilForKey:kStudentGroupCourseListModelCourseGroupName fromDictionary:dict];
             self.status = [self objectOrNilForKey:kStudentGroupCourseListModelStatus fromDictionary:dict];
-
+            self.coursePlan = [self objectOrNilForKey:kStudentGroupCourseListModelCoursePlan fromDictionary:dict];
     }
     
     return self;
@@ -98,7 +99,7 @@ NSString *const kStudentGroupCourseListModelStatus = @"status";
     [mutableDict setValue:self.startTime forKey:kStudentGroupCourseListModelStartTime];
     [mutableDict setValue:self.courseGroupName forKey:kStudentGroupCourseListModelCourseGroupName];
     [mutableDict setValue:self.status forKey:kStudentGroupCourseListModelStatus];
-
+    [mutableDict setValue:self.coursePlan forKey:kStudentGroupCourseListModelCoursePlan];
     return [NSDictionary dictionaryWithDictionary:mutableDict];
 }
 
@@ -139,6 +140,7 @@ NSString *const kStudentGroupCourseListModelStatus = @"status";
     self.startTime = [aDecoder decodeObjectForKey:kStudentGroupCourseListModelStartTime];
     self.courseGroupName = [aDecoder decodeObjectForKey:kStudentGroupCourseListModelCourseGroupName];
     self.status = [aDecoder decodeObjectForKey:kStudentGroupCourseListModelStatus];
+    self.coursePlan = [aDecoder decodeObjectForKey:kStudentGroupCourseListModelCoursePlan];
     return self;
 }
 
@@ -159,6 +161,7 @@ NSString *const kStudentGroupCourseListModelStatus = @"status";
     [aCoder encodeObject:_startTime forKey:kStudentGroupCourseListModelStartTime];
     [aCoder encodeObject:_courseGroupName forKey:kStudentGroupCourseListModelCourseGroupName];
     [aCoder encodeObject:_status forKey:kStudentGroupCourseListModelStatus];
+    [aCoder encodeObject:_coursePlan forKey:kStudentGroupCourseListModelCoursePlan];
 }
 
 - (id)copyWithZone:(NSZone *)zone
@@ -181,6 +184,7 @@ NSString *const kStudentGroupCourseListModelStatus = @"status";
         copy.startTime = [self.startTime copyWithZone:zone];
         copy.courseGroupName = [self.courseGroupName copyWithZone:zone];
         copy.status = [self.status copyWithZone:zone];
+        copy.coursePlan = [self.coursePlan copyWithZone:zone];
     }
     
     return copy;

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/View/ProgramCourseGroupBodyView.h

@@ -11,6 +11,7 @@ typedef NS_ENUM(NSInteger, COURSE_GROUP_TYPE) {
     COURSE_GROUP_TYPE_VIP,
     COURSE_GROUP_TYPE_ACCOMPANY,
     COURSE_GROUP_TYPE_MUSICROOM,
+    COURSE_GROUP_TYPE_GROUP,
 };
 
 NS_ASSUME_NONNULL_BEGIN

+ 25 - 59
KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/View/ProgramCourseGroupBodyView.m

@@ -20,11 +20,10 @@
 #import "RecordCheckManager.h"
 #import <KSFullDatePicker.h>
 #import "KSSmallChoosePicker.h"
+#import "GroupCourseListCell.h"
 
 @interface ProgramCourseGroupBodyView ()<UITableViewDelegate,UITableViewDataSource>
 
-@property (nonatomic, strong) NSDateFormatter *dateFormatter;
-
 @property (nonatomic, strong) NSMutableArray *dataArray;
 
 @property (nonatomic, strong) StateView *promptView;
@@ -34,7 +33,6 @@
 
 @property (nonatomic, strong) GroupCourseSortView *sortView;
 
-@property (nonatomic, strong) NSString *classDate;
 
 @property (nonatomic, strong) NSString *attendanceStatus;
 
@@ -73,6 +71,10 @@
         self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
         [self.tableView registerNib:[UINib nibWithNibName:@"ProgramCourseListCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"ProgramCourseListCell"];
         [self.tableView registerNib:[UINib nibWithNibName:@"MusicRoomCourseListCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MusicRoomCourseListCell"];
+        [self.tableView registerNib:[UINib nibWithNibName:@"GroupCourseListCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"GroupCourseListCell"];
+
+        self.tableView.estimatedRowHeight = 123.0f;
+        self.tableView.rowHeight = UITableViewAutomaticDimension;
         
         UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, iPhoneXSafeBottomMargin)];
         bottomView.backgroundColor = [UIColor clearColor];
@@ -93,9 +95,6 @@
 - (void)configDefault {
     self.secondChooseIndex = 1;
     self.thirdChooseIndex = 1;
-    [self.dateFormatter setDateFormat:@"yyyy-MM"];
-    NSDate *currentDate = [NSDate date];
-    self.classDate = [self.dateFormatter stringFromDate:currentDate];
 }
 
 - (void)forceScroll {
@@ -143,7 +142,8 @@
 }
 
 - (void)requestData {
-    [KSNetworkingManager courseScheduleListRequest:KS_POST courseGroupId:self.courseGroupId classMonth:self.classDate attendanceStatus:self.attendanceStatus courseStatus:self.courseStatus success:^(NSDictionary * _Nonnull dic) {
+    NSString *classDate = nil;
+    [KSNetworkingManager courseScheduleListRequest:KS_POST courseGroupId:self.courseGroupId classMonth:classDate attendanceStatus:self.attendanceStatus courseStatus:self.courseStatus success:^(NSDictionary * _Nonnull dic) {
         [self endRefresh];
         if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
             NSArray *sourceArray = [dic ks_arrayValueForKey:@"data"];
@@ -202,9 +202,6 @@
             make.left.right.top.mas_equalTo(self);
             make.height.mas_equalTo(sortViewHeight);
         }];
-        [self.dateFormatter setDateFormat:@"yyyy年MM月"];
-        NSDate *currentDate = [NSDate date];
-        [self.sortView.firstLabel setText:[self.dateFormatter stringFromDate:currentDate]];
     }
 
     [self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
@@ -218,10 +215,6 @@
     return self.dataArray.count;
 }
 
-- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
-    return 123.0f;
-}
-
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     StudentGroupCourseListModel *model = self.dataArray[indexPath.row];
     if (self.courseType == COURSE_GROUP_TYPE_VIP || self.courseType == COURSE_GROUP_TYPE_ACCOMPANY) {
@@ -232,6 +225,14 @@
         }];
         return cell;
     }
+    else if (self.courseType == COURSE_GROUP_TYPE_GROUP) {
+        GroupCourseListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GroupCourseListCell"];
+        MJWeakSelf;
+        [cell configWithSource:model beforeTime:self.enterStartTime callback:^(StudentGroupCourseListModel * _Nonnull model) {
+            [weakSelf enterClassRoom:model];
+        }];
+        return cell;
+    }
     else {
         MusicRoomCourseListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MusicRoomCourseListCell"];
         MJWeakSelf;
@@ -278,8 +279,16 @@
         detailVC.courseGroupId = [NSString stringWithFormat:@"%.0f",courseModel.courseGoupId];
         [self.naviController pushViewController:detailVC animated:YES];
     }
+    else if (self.courseType == COURSE_GROUP_TYPE_GROUP) {
+        MusicRoomDetailViewController *ctrl = [[MusicRoomDetailViewController alloc] init];
+        ctrl.courseType = MUTIL_COURSE_TYPE_GROUP;
+        ctrl.courseId = courseModel.courseId;
+        ctrl.courseGroupId = [NSString stringWithFormat:@"%.0f",courseModel.courseGoupId];
+        [self.naviController pushViewController:ctrl animated:YES];
+    }
     else if (self.courseType == COURSE_GROUP_TYPE_MUSICROOM) {
         MusicRoomDetailViewController *ctrl = [[MusicRoomDetailViewController alloc] init];
+        ctrl.courseType = MUTIL_COURSE_TYPE_MUSIC;
         ctrl.courseId = courseModel.courseId;
         ctrl.courseGroupId = [NSString stringWithFormat:@"%.0f",courseModel.courseGoupId];
         [self.naviController pushViewController:ctrl animated:YES];
@@ -426,19 +435,9 @@
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
-
-- (NSDateFormatter *)dateFormatter {
-    if (!_dateFormatter) {
-        _dateFormatter = [NSObject getDateformatter];
-    }
-    return _dateFormatter;
-}
 - (void)sortWithType:(SORT_TYPE)type {
     
-    if (type == SORT_TYPE_TIME) { // time
-        [self showPickerView];
-    }
-    else if (type == SORT_TYPE_STATUS) { // 状态
+     if (type == SORT_TYPE_STATUS) { // 状态
         MJWeakSelf;
         KSSmallChoosePicker *picker = [[KSSmallChoosePicker alloc] initWithTitle:@"" sourceData:@[@"全部",@"未开始",@"进行中",@"已结束"] lastChoose:self.secondChooseIndex chooseColor:THEMECOLOR chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
             weakSelf.secondChooseIndex = chooseIndex;
@@ -535,46 +534,13 @@
     }
 }
 
-- (void)showPickerView {
-    [self.dateFormatter setDateFormat:@"yyyy-MM"];
-    NSDate *preDate = [NSDate date];
-    if (![NSString isEmptyString:self.classDate]) {
-        preDate = [self.dateFormatter dateFromString:self.classDate];
-    }
-    
-    KSFullDatePicker *picker = [[KSFullDatePicker alloc] initWithTitle:@"" date:preDate pickMode:KSDATEPICKER_MODE_YEAR_MONTH sureButtonColor:THEMECOLOR selectDateBlock:^(NSString *date) {
-
-        self.classDate = date;
-        NSString *displayTime = [self getTimeDisplay:date];
-        [self.sortView.firstLabel setText:displayTime];
-        [self resetPickerStatus];
-        // 请求数据
-        [self refreshAndRequestData];
-    } cancleBlock:^{
-        [self resetPickerStatus];
-    }];
-    [picker show];
-}
+
 
 - (void)hiddenPopView {
-    self.sortView.firstArrowUp = NO;
     self.sortView.secondArrowUp = NO;
     self.sortView.thirdArrowUp = NO;
 }
 
-
-- (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;
-}
-
 - (void)setSortBgColor:(UIColor *)sortBgColor {
     _sortBgColor = sortBgColor;
     self.sortView.backgroundColor = sortBgColor;

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Controller/HomeArrangeCourseController.h

@@ -12,6 +12,7 @@
 typedef NS_ENUM(NSInteger, DISPLAY_INDEX) {
     DISPLAY_INDEX_VIP = 0,    // VIP定制
     DISPLAY_INDEX_FIRST,      // 趣纠课
+    DISPLAY_INDEX_GROUP,      // 小组课
     DISPLAY_INDEX_LIVE,       // 直播课
     DISPLAY_INDEX_VIDEO,       // 视频课
 };

+ 19 - 2
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Controller/HomeArrangeCourseController.m

@@ -16,6 +16,7 @@
 #import "HomeArrangeLiveCourseView.h"
 #import "HomeArrangeVideoCourseView.h"
 #import "CourseDescAlertView.h"
+#import "HomeArrangeGroupCourseView.h"
 
 #define HIDE_COURSETIPS (@"HIDE_COURSETIPS")
 
@@ -53,7 +54,7 @@
     imageView.frame = CGRectMake(0, 0, KPortraitWidth, height);
     [self.view addSubview:imageView];
     
-    self.titles = @[@"VIP定制课",@"趣纠课",@"直播课",@"视频课"];
+    self.titles = @[@"VIP定制课", @"趣纠课", @"小组课", @"直播课", @"视频课"];
     [self.view addSubview:self.navView];
     CGFloat navHeight = [HomeArrangeNavView getViewHeight];
     [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -152,6 +153,10 @@
             HomeArrangeAccompanyCourseView *courseView = (HomeArrangeAccompanyCourseView *)view;
             courseView.subjectList = [self.subjectList mutableCopy];
         }
+        else if ([view isKindOfClass:[HomeArrangeGroupCourseView class]]) {
+            HomeArrangeGroupCourseView *courseView = (HomeArrangeGroupCourseView *)view;
+            courseView.subjectList = [self.subjectList mutableCopy];
+        }
         else if ([view isKindOfClass:[HomeArrangeLiveCourseView class]]) {
             HomeArrangeLiveCourseView *courseView = (HomeArrangeLiveCourseView *)view;
             courseView.subjectList = [self.subjectList mutableCopy];
@@ -221,6 +226,18 @@
         return listView;
     }
     else if (index == 2) {
+        HomeArrangeGroupCourseView *listView = [[HomeArrangeGroupCourseView alloc] init];
+        listView.naviController = self.navigationController;
+        [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+        self.listViewArray[index] = listView;
+        listView.selectIndex = index;
+        if (self.subjectList) {
+            listView.subjectList = [self.subjectList mutableCopy];
+        }
+        [listView beginFirstRefresh];
+        return listView;
+    }
+    else if (index == 3) {
         HomeArrangeLiveCourseView *listView = [[HomeArrangeLiveCourseView alloc] init];
         listView.naviController = self.navigationController;
         [self.listViewArray replaceObjectAtIndex:index withObject:listView];
@@ -276,7 +293,7 @@
 
 - (NSMutableArray *)listViewArray {
     if (!_listViewArray) {
-        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@"",@"",@""]];
+        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@"",@"",@"",@""]];
     }
     return _listViewArray;
 }

+ 2 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Model/ArrangeLiveCourseModel.h

@@ -32,6 +32,8 @@
 @property (nonatomic, strong) NSString *reason;
 @property (nonatomic, strong) NSString *userName;
 @property (nonatomic, assign) double coursePrice;
+@property (nonatomic, assign) NSInteger maxStudentNum;
+
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
 - (instancetype)initWithDictionary:(NSDictionary *)dict;

+ 7 - 4
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/Model/ArrangeLiveCourseModel.m

@@ -29,7 +29,7 @@ NSString *const kArrangeLiveCourseModelExistBuy = @"existBuy";
 NSString *const kArrangeLiveCourseModelReason = @"reason";
 NSString *const kArrangeLiveCourseModelUserName = @"userName";
 NSString *const kArrangeLiveCourseModelCoursePrice = @"coursePrice";
-
+NSString *const kArrangeLiveCourseModelMaxStudentNum = @"maxStudentNum";
 
 @interface ArrangeLiveCourseModel ()
 
@@ -60,7 +60,7 @@ NSString *const kArrangeLiveCourseModelCoursePrice = @"coursePrice";
 @synthesize reason = _reason;
 @synthesize userName = _userName;
 @synthesize coursePrice = _coursePrice;
-
+@synthesize maxStudentNum = _maxStudentNum;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
 {
@@ -95,7 +95,7 @@ NSString *const kArrangeLiveCourseModelCoursePrice = @"coursePrice";
             self.reason = [self objectOrNilForKey:kArrangeLiveCourseModelReason fromDictionary:dict];
             self.userName = [self objectOrNilForKey:kArrangeLiveCourseModelUserName fromDictionary:dict];
             self.coursePrice = [[self objectOrNilForKey:kArrangeLiveCourseModelCoursePrice fromDictionary:dict] doubleValue];
-
+            self.maxStudentNum = [[self objectOrNilForKey:kArrangeLiveCourseModelMaxStudentNum fromDictionary:dict] integerValue];
     }
     
     return self;
@@ -126,7 +126,7 @@ NSString *const kArrangeLiveCourseModelCoursePrice = @"coursePrice";
     [mutableDict setValue:self.reason forKey:kArrangeLiveCourseModelReason];
     [mutableDict setValue:self.userName forKey:kArrangeLiveCourseModelUserName];
     [mutableDict setValue:[NSNumber numberWithDouble:self.coursePrice] forKey:kArrangeLiveCourseModelCoursePrice];
-
+    [mutableDict setValue:[NSNumber numberWithInteger:self.maxStudentNum] forKey:kArrangeLiveCourseModelMaxStudentNum];
     return [NSDictionary dictionaryWithDictionary:mutableDict];
 }
 
@@ -174,6 +174,7 @@ NSString *const kArrangeLiveCourseModelCoursePrice = @"coursePrice";
     self.reason = [aDecoder decodeObjectForKey:kArrangeLiveCourseModelReason];
     self.userName = [aDecoder decodeObjectForKey:kArrangeLiveCourseModelUserName];
     self.coursePrice = [aDecoder decodeDoubleForKey:kArrangeLiveCourseModelCoursePrice];
+    self.maxStudentNum = [aDecoder decodeIntegerForKey:kArrangeLiveCourseModelMaxStudentNum];
     return self;
 }
 
@@ -201,6 +202,7 @@ NSString *const kArrangeLiveCourseModelCoursePrice = @"coursePrice";
     [aCoder encodeObject:_reason forKey:kArrangeLiveCourseModelReason];
     [aCoder encodeObject:_userName forKey:kArrangeLiveCourseModelUserName];
     [aCoder encodeDouble:_coursePrice forKey:kArrangeLiveCourseModelCoursePrice];
+    [aCoder encodeInteger:_maxStudentNum forKey:kArrangeLiveCourseModelMaxStudentNum];
 }
 
 - (id)copyWithZone:(NSZone *)zone
@@ -230,6 +232,7 @@ NSString *const kArrangeLiveCourseModelCoursePrice = @"coursePrice";
         copy.reason = [self.reason copyWithZone:zone];
         copy.userName = [self.userName copyWithZone:zone];
         copy.coursePrice = self.coursePrice;
+        copy.maxStudentNum = self.maxStudentNum;
     }
     
     return copy;

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseDescAlertView.h

@@ -18,6 +18,7 @@ typedef NS_ENUM(NSInteger, SHOWTYPE) {
 typedef NS_ENUM(NSInteger, COURSE_DISPLAY_INDEX) {
     COURSE_DISPLAY_INDEX_VIP = 0,
     COURSE_DISPLAY_INDEX_ACCOMPANY,
+    COURSE_DISPLAY_INDEX_GROUP,
     COURSE_DISPLAY_INDEX_LIVE,
     COURSE_DISPLAY_INDEX_VIDEO,
     COURSE_DISPLAY_INDEX_MUSICROOM,

File diff ditekan karena terlalu besar
+ 0 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseDescAlertView.m


+ 0 - 16
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseTeacherDescCell.m

@@ -6,15 +6,10 @@
 //
 
 #import "CourseTeacherDescCell.h"
-#import "KSStarView.h"
 
 @interface CourseTeacherDescCell ()
 @property (weak, nonatomic) IBOutlet UILabel *tagLabel;
 
-@property (weak, nonatomic) IBOutlet KSStarView *starView;
-
-@property (weak, nonatomic) IBOutlet UILabel *noStarLabel;
-
 @property (weak, nonatomic) IBOutlet UILabel *teacherName;
 
 @property (weak, nonatomic) IBOutlet UIImageView *teacherAvatar;
@@ -35,7 +30,6 @@
     [super awakeFromNib];
     // Initialization code
     self.selectionStyle = UITableViewCellSelectionStyleNone;
-    self.starView.allowMark = NO;
 }
 
 
@@ -43,16 +37,6 @@
     self.teacherName.text = [NSString returnNoNullStringWithString:model.userName];
     [self.teacherAvatar sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:TEACHER_AVATAR]];
     self.teacherDesc.text = [NSString stringWithFormat:@"%@·%@",[NSString returnNoNullStringWithString:model.school], [NSString returnNoNullStringWithString:model.schoolSubject]];
-    double starNum = [model.starGrade doubleValue];
-    if (starNum <= 0) {
-        self.starView.hidden = YES;
-        self.noStarLabel.hidden = NO;
-    }
-    else {
-        self.noStarLabel.hidden = YES;
-        self.starView.hidden = NO;
-        self.starView.rate = model.starGrade.doubleValue / 5.0f;
-    }
     self.finishCount.text = [NSString stringWithFormat:@"已上课时%zd节", [model.expTime integerValue]];
     
     self.courseDuration.text = [NSString stringWithFormat:@"/%@分钟", model.courseMinutes];

+ 2 - 35
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/CourseTeacherDescCell.xib

@@ -33,7 +33,7 @@
                                 </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="kSc-Bn-tRF">
-                                <rect key="frame" x="94" y="14" width="0.0" height="22"/>
+                                <rect key="frame" x="94" y="14" width="241" height="22"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="22" id="NrO-ml-kfW"/>
                                 </constraints>
@@ -50,24 +50,6 @@
                                 <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
-                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5fv-Zu-mpb">
-                                <rect key="frame" x="245" y="15.666666666666664" width="90" height="19"/>
-                                <subviews>
-                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RQI-Hg-dao" customClass="KSStarView">
-                                        <rect key="frame" x="0.0" y="0.0" width="90" height="19"/>
-                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                    </view>
-                                </subviews>
-                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                <constraints>
-                                    <constraint firstAttribute="trailing" secondItem="RQI-Hg-dao" secondAttribute="trailing" id="7mA-aA-hOr"/>
-                                    <constraint firstItem="RQI-Hg-dao" firstAttribute="leading" secondItem="5fv-Zu-mpb" secondAttribute="leading" id="Eyi-X3-93v"/>
-                                    <constraint firstAttribute="height" constant="19" id="KUc-ms-RwL"/>
-                                    <constraint firstAttribute="width" constant="90" id="cNI-F7-5DC"/>
-                                    <constraint firstAttribute="bottom" secondItem="RQI-Hg-dao" secondAttribute="bottom" id="iFi-o0-4gM"/>
-                                    <constraint firstItem="RQI-Hg-dao" firstAttribute="top" secondItem="5fv-Zu-mpb" secondAttribute="top" id="uI9-NV-dTm"/>
-                                </constraints>
-                            </view>
                             <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrange_course_icon" translatesAutoresizingMaskIntoConstraints="NO" id="VcT-no-hdl">
                                 <rect key="frame" x="94" y="65" width="12" height="14"/>
                             </imageView>
@@ -98,15 +80,6 @@
                                 <color key="textColor" red="0.95686274509803915" green="0.27058823529411763" blue="0.25490196078431371" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <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="foG-ZX-f0E">
-                                <rect key="frame" x="287" y="17" width="48" height="16"/>
-                                <constraints>
-                                    <constraint firstAttribute="height" constant="16" id="rXa-R8-xbj"/>
-                                </constraints>
-                                <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                                <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                <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="vnz-ny-LSC">
                                 <rect key="frame" x="280.33333333333331" y="64" width="7" height="16"/>
                                 <constraints>
@@ -119,23 +92,19 @@
                         </subviews>
                         <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         <constraints>
-                            <constraint firstItem="foG-ZX-f0E" firstAttribute="centerY" secondItem="kSc-Bn-tRF" secondAttribute="centerY" id="02X-9H-UQT"/>
-                            <constraint firstAttribute="trailing" secondItem="5fv-Zu-mpb" secondAttribute="trailing" constant="12" id="1tU-B1-3Fz"/>
+                            <constraint firstAttribute="trailing" secondItem="kSc-Bn-tRF" secondAttribute="trailing" constant="12" id="1q9-Qw-Xjy"/>
                             <constraint firstItem="TOg-Vl-8yz" firstAttribute="leading" secondItem="14o-Dv-2M4" secondAttribute="trailing" constant="2" id="751-Wg-80V"/>
                             <constraint firstItem="TOg-Vl-8yz" firstAttribute="bottom" secondItem="kQq-1l-JW1" secondAttribute="bottom" id="D5d-rh-U7d"/>
                             <constraint firstItem="EAh-FG-nIZ" firstAttribute="leading" secondItem="L4X-4j-TAS" secondAttribute="leading" constant="12" id="DsS-f7-EtI"/>
-                            <constraint firstItem="5fv-Zu-mpb" firstAttribute="centerY" secondItem="kSc-Bn-tRF" secondAttribute="centerY" id="F7P-fW-fRe"/>
                             <constraint firstItem="kQq-1l-JW1" firstAttribute="leading" secondItem="VcT-no-hdl" secondAttribute="trailing" constant="4" id="FtU-yM-3mE"/>
                             <constraint firstItem="14o-Dv-2M4" firstAttribute="leading" secondItem="vnz-ny-LSC" secondAttribute="trailing" constant="2" id="HOx-l6-YON"/>
                             <constraint firstAttribute="trailing" secondItem="TOg-Vl-8yz" secondAttribute="trailing" constant="12" id="Hbg-0s-54b"/>
                             <constraint firstAttribute="trailing" secondItem="wAx-0C-FLk" secondAttribute="trailing" constant="12" id="HhT-HG-0n3"/>
-                            <constraint firstItem="5fv-Zu-mpb" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="kSc-Bn-tRF" secondAttribute="trailing" constant="10" id="Ilb-h5-EyA"/>
                             <constraint firstItem="EAh-FG-nIZ" firstAttribute="centerY" secondItem="L4X-4j-TAS" secondAttribute="centerY" id="OnS-3f-0Ut"/>
                             <constraint firstAttribute="bottom" secondItem="14o-Dv-2M4" secondAttribute="bottom" constant="13" id="XbV-al-MfW"/>
                             <constraint firstItem="wAx-0C-FLk" firstAttribute="top" secondItem="kSc-Bn-tRF" secondAttribute="bottom" constant="4" id="XgW-i3-DQ9"/>
                             <constraint firstItem="wAx-0C-FLk" firstAttribute="leading" secondItem="EAh-FG-nIZ" secondAttribute="trailing" constant="12" id="cok-gl-jCk"/>
                             <constraint firstItem="14o-Dv-2M4" firstAttribute="bottom" secondItem="vnz-ny-LSC" secondAttribute="bottom" constant="1" id="egl-nX-nvq"/>
-                            <constraint firstAttribute="trailing" secondItem="foG-ZX-f0E" secondAttribute="trailing" constant="12" id="eyD-ZO-KsZ"/>
                             <constraint firstItem="VcT-no-hdl" firstAttribute="leading" secondItem="EAh-FG-nIZ" secondAttribute="trailing" constant="12" id="fS9-Yc-O4U"/>
                             <constraint firstItem="vnz-ny-LSC" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="kQq-1l-JW1" secondAttribute="trailing" constant="4" id="t1L-rq-YgT"/>
                             <constraint firstItem="kSc-Bn-tRF" firstAttribute="leading" secondItem="EAh-FG-nIZ" secondAttribute="trailing" constant="12" id="w8s-1K-2cE"/>
@@ -161,9 +130,7 @@
             <connections>
                 <outlet property="courseDuration" destination="TOg-Vl-8yz" id="3ex-KD-7nL"/>
                 <outlet property="finishCount" destination="kQq-1l-JW1" id="wCh-fT-dve"/>
-                <outlet property="noStarLabel" destination="foG-ZX-f0E" id="tLq-rh-wlh"/>
                 <outlet property="priceLabel" destination="14o-Dv-2M4" id="OyV-af-Idv"/>
-                <outlet property="starView" destination="RQI-Hg-dao" id="Tn4-Ul-ZLq"/>
                 <outlet property="tagLabel" destination="vnz-ny-LSC" id="Git-uY-KS1"/>
                 <outlet property="teacherAvatar" destination="EAh-FG-nIZ" id="BP7-Ey-KML"/>
                 <outlet property="teacherDesc" destination="wAx-0C-FLk" id="Pb4-WY-jcR"/>

+ 19 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/GroupCourseArrangeCell.h

@@ -0,0 +1,19 @@
+//
+//  GroupCourseArrangeCell.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import <UIKit/UIKit.h>
+#import "ArrangeLiveCourseModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupCourseArrangeCell : UICollectionViewCell
+
+- (void)configWithSource:(ArrangeLiveCourseModel *)model;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 80 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/GroupCourseArrangeCell.m

@@ -0,0 +1,80 @@
+//
+//  GroupCourseArrangeCell.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "GroupCourseArrangeCell.h"
+
+@interface GroupCourseArrangeCell ()
+
+@property (weak, nonatomic) IBOutlet UILabel *tagLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseStartTime;
+
+@property (weak, nonatomic) IBOutlet UILabel *subjectLabel;
+
+@property (weak, nonatomic) IBOutlet UIImageView *courseImage;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseName;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseDesc;
+
+@property (weak, nonatomic) IBOutlet UILabel *priceLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseCount;
+
+@property (weak, nonatomic) IBOutlet UIImageView *teacherAvatar;
+
+@property (weak, nonatomic) IBOutlet UILabel *teacherName;
+
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+
+@end
+
+@implementation GroupCourseArrangeCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+}
+
+- (void)configWithSource:(ArrangeLiveCourseModel *)model {
+    // time
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *startDate = [formatter dateFromString:model.courseStartTime];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
+    NSString *courseBegin = [formatter stringFromDate:startDate];
+    self.courseStartTime.text = [NSString returnNoNullStringWithString:courseBegin];
+    self.subjectLabel.text = [NSString returnNoNullStringWithString:model.subjectName];
+    
+    [self.courseImage sd_setImageWithURL:[NSURL URLWithString:[model.backgroundPic getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:@"video_placeholder"]];
+    self.courseName.text = [NSString returnNoNullStringWithString:model.courseGroupName];
+    
+    NSString *introduce = model.courseIntroduce;
+    if (![NSString isEmptyString:introduce]) {
+        introduce = [introduce replaceAll:@"\n" WithString:@" "];
+        self.courseDesc.text = [NSString returnNoNullStringWithString:introduce];
+    }
+    else {
+        self.courseDesc.text = @"暂无介绍";
+    }
+    if (model.coursePrice > 0) {
+        NSString *mountMsg = [NSString formatAllDoubleNum:model.coursePrice];
+        self.priceLabel.text = mountMsg;
+        self.tagLabel.hidden = NO;
+    }
+    else {
+        self.tagLabel.hidden = YES;
+        self.priceLabel.text = [NSString  stringWithFormat:@"免费"];
+    }
+    
+    self.courseCount.text = [NSString stringWithFormat:@"/%.0f课时",model.courseNum];
+    self.teacherName.text = [NSString returnNoNullStringWithString:model.teacherName];
+    [self.teacherAvatar sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:TEACHER_AVATAR]];
+    self.descLabel.text = [NSString stringWithFormat:@"剩余%.0f个名额", model.maxStudentNum - model.studentCount];
+}
+
+@end

+ 239 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/GroupCourseArrangeCell.xib

@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.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"/>
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="GroupCourseArrangeCell">
+            <rect key="frame" x="0.0" y="0.0" width="343" height="333"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="343" height="333"/>
+                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rNL-1B-gdI">
+                        <rect key="frame" x="0.0" y="0.0" width="343" height="333"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrange_live_tag" translatesAutoresizingMaskIntoConstraints="NO" id="lrL-Hj-K0e">
+                                <rect key="frame" x="12" y="15" width="20" height="16"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="16" id="BRN-7R-0WI"/>
+                                    <constraint firstAttribute="width" constant="20" id="tyF-of-2Hu"/>
+                                </constraints>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="开课时间:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yKB-Mh-kEV">
+                                <rect key="frame" x="39" y="13" width="62.666666666666657" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="bwZ-2M-uA6"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="s3T-ZE-UQh">
+                                <rect key="frame" x="101.66666666666667" y="13" width="0.0" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="8of-4G-AHR"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="video_placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="Os8-Nn-7BW">
+                                <rect key="frame" x="12" y="46.000000000000014" width="319" height="179.33333333333337"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" secondItem="Os8-Nn-7BW" secondAttribute="height" multiplier="16:9" id="3fl-VL-cJx"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="6"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </imageView>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kit-uC-3TG">
+                                <rect key="frame" x="20" y="54" width="12" height="19"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oiI-0u-hUk">
+                                        <rect key="frame" x="6" y="9.6666666666666643" width="0.0" height="0.0"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                        <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.40000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="trailing" secondItem="oiI-0u-hUk" secondAttribute="trailing" constant="6" id="31r-Hr-GBJ"/>
+                                    <constraint firstItem="oiI-0u-hUk" firstAttribute="centerY" secondItem="kit-uC-3TG" secondAttribute="centerY" id="MNT-J0-br6"/>
+                                    <constraint firstAttribute="height" constant="19" id="ZJb-gT-YTw"/>
+                                    <constraint firstItem="oiI-0u-hUk" firstAttribute="leading" secondItem="kit-uC-3TG" secondAttribute="leading" constant="6" id="n1H-k6-hqt"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="3"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cDo-QS-aQU">
+                                <rect key="frame" x="12" y="233.33333333333334" width="319" height="22"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="22" id="HCu-mn-xv1"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                                <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <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="70G-0T-Hf2">
+                                <rect key="frame" x="12" y="259.33333333333331" width="319" height="27.666666666666686"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                <color key="textColor" red="0.46666666670000001" green="0.46666666670000001" blue="0.46666666670000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0dg-x6-tnL">
+                                <rect key="frame" x="300" y="296" width="0.0" height="24"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="24" id="j9n-HU-BQE"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="20"/>
+                                <color key="textColor" red="0.95686274510000002" green="0.27058823529999998" blue="0.25490196079999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="/课时" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cb7-UB-AbR">
+                                <rect key="frame" x="302" y="301" width="29" height="17"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="17" id="lF1-Po-UTd"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="林老师" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EQp-Yo-Ip9">
+                                <rect key="frame" x="44" y="298" width="42" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="0Xa-uF-2VS"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="teacher_avatar" translatesAutoresizingMaskIntoConstraints="NO" id="ICh-6B-8NG">
+                                <rect key="frame" x="12" y="295" width="26" height="26"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="26" id="031-WW-v0l"/>
+                                    <constraint firstAttribute="height" constant="26" id="J8z-pc-T1Q"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="13"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="¥" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JyZ-5i-yaw">
+                                <rect key="frame" x="291" y="301" width="7" height="17"/>
+                                <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="14"/>
+                                <color key="textColor" red="0.95686274510000002" green="0.27058823529999998" blue="0.25490196079999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <view contentMode="scaleToFill" horizontalCompressionResistancePriority="752" translatesAutoresizingMaskIntoConstraints="NO" id="Q3D-yo-S6d">
+                                <rect key="frame" x="92" y="298.66666666666669" width="79" height="19"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="剩余3个名额" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QP0-xm-KMP">
+                                        <rect key="frame" x="4" y="2" width="71" height="15"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                        <color key="textColor" red="1" green="0.40784313725490196" blue="0.15294117647058825" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="1" green="0.50196078431372548" blue="0.17254901960784313" alpha="0.070000000000000007" colorSpace="custom" customColorSpace="sRGB"/>
+                                <constraints>
+                                    <constraint firstItem="QP0-xm-KMP" firstAttribute="leading" secondItem="Q3D-yo-S6d" secondAttribute="leading" constant="4" id="1Ub-td-NSW"/>
+                                    <constraint firstAttribute="height" constant="19" id="Rm7-e4-qg6"/>
+                                    <constraint firstItem="QP0-xm-KMP" firstAttribute="centerY" secondItem="Q3D-yo-S6d" secondAttribute="centerY" id="V7x-Xr-GE6"/>
+                                    <constraint firstAttribute="trailing" secondItem="QP0-xm-KMP" secondAttribute="trailing" constant="4" id="l2O-xb-unn"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="2"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="s3T-ZE-UQh" secondAttribute="trailing" constant="12" id="5Iw-mQ-9LE"/>
+                            <constraint firstItem="0dg-x6-tnL" firstAttribute="leading" secondItem="JyZ-5i-yaw" secondAttribute="trailing" constant="2" id="5lI-08-Y1p"/>
+                            <constraint firstItem="Os8-Nn-7BW" firstAttribute="top" secondItem="lrL-Hj-K0e" secondAttribute="bottom" constant="15" id="BC7-lq-p97"/>
+                            <constraint firstItem="kit-uC-3TG" firstAttribute="leading" secondItem="Os8-Nn-7BW" secondAttribute="leading" constant="8" id="Fbg-R2-HhG"/>
+                            <constraint firstItem="kit-uC-3TG" firstAttribute="top" secondItem="Os8-Nn-7BW" secondAttribute="top" constant="8" id="JUn-di-xcs"/>
+                            <constraint firstItem="lrL-Hj-K0e" firstAttribute="top" secondItem="rNL-1B-gdI" secondAttribute="top" constant="15" id="JmF-iA-yjP"/>
+                            <constraint firstAttribute="trailing" secondItem="70G-0T-Hf2" secondAttribute="trailing" constant="12" id="K5d-Hk-nMM"/>
+                            <constraint firstItem="0dg-x6-tnL" firstAttribute="bottom" secondItem="JyZ-5i-yaw" secondAttribute="bottom" constant="2" id="KdP-Jt-z0I"/>
+                            <constraint firstItem="s3T-ZE-UQh" firstAttribute="centerY" secondItem="yKB-Mh-kEV" secondAttribute="centerY" id="MHd-WO-9Ax"/>
+                            <constraint firstItem="ICh-6B-8NG" firstAttribute="top" secondItem="70G-0T-Hf2" secondAttribute="bottom" constant="8" id="NxE-VG-3JY"/>
+                            <constraint firstItem="cDo-QS-aQU" firstAttribute="top" secondItem="Os8-Nn-7BW" secondAttribute="bottom" constant="8" id="OFz-u2-rgz"/>
+                            <constraint firstItem="EQp-Yo-Ip9" firstAttribute="centerY" secondItem="ICh-6B-8NG" secondAttribute="centerY" id="Ogb-ED-aqr"/>
+                            <constraint firstItem="JyZ-5i-yaw" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Q3D-yo-S6d" secondAttribute="trailing" constant="10" id="Or3-pi-zSe"/>
+                            <constraint firstItem="s3T-ZE-UQh" firstAttribute="leading" secondItem="yKB-Mh-kEV" secondAttribute="trailing" id="SD8-yO-BPb"/>
+                            <constraint firstItem="Os8-Nn-7BW" firstAttribute="leading" secondItem="rNL-1B-gdI" secondAttribute="leading" constant="12" id="UFv-26-w24"/>
+                            <constraint firstAttribute="trailing" secondItem="Os8-Nn-7BW" secondAttribute="trailing" constant="12" id="WmM-HV-6b1"/>
+                            <constraint firstItem="yKB-Mh-kEV" firstAttribute="centerY" secondItem="lrL-Hj-K0e" secondAttribute="centerY" id="X0D-qU-con"/>
+                            <constraint firstItem="ICh-6B-8NG" firstAttribute="leading" secondItem="rNL-1B-gdI" secondAttribute="leading" constant="12" id="b54-bU-F0R"/>
+                            <constraint firstItem="s3T-ZE-UQh" firstAttribute="centerY" secondItem="yKB-Mh-kEV" secondAttribute="centerY" id="cZV-N9-4fc"/>
+                            <constraint firstItem="yKB-Mh-kEV" firstAttribute="leading" secondItem="lrL-Hj-K0e" secondAttribute="trailing" constant="7" id="ch6-IB-ZFT"/>
+                            <constraint firstAttribute="trailing" secondItem="cDo-QS-aQU" secondAttribute="trailing" constant="12" id="drj-6s-wr2"/>
+                            <constraint firstAttribute="bottom" secondItem="cb7-UB-AbR" secondAttribute="bottom" constant="15" id="exN-KI-pjy"/>
+                            <constraint firstItem="70G-0T-Hf2" firstAttribute="top" secondItem="cDo-QS-aQU" secondAttribute="bottom" constant="4" id="gSH-LR-SBI"/>
+                            <constraint firstItem="cb7-UB-AbR" firstAttribute="leading" secondItem="0dg-x6-tnL" secondAttribute="trailing" constant="2" id="ie9-HG-FNm"/>
+                            <constraint firstItem="EQp-Yo-Ip9" firstAttribute="leading" secondItem="ICh-6B-8NG" secondAttribute="trailing" constant="6" id="mhV-YM-K9H"/>
+                            <constraint firstItem="70G-0T-Hf2" firstAttribute="leading" secondItem="rNL-1B-gdI" secondAttribute="leading" constant="12" id="oSN-c8-ZbR"/>
+                            <constraint firstAttribute="bottom" secondItem="ICh-6B-8NG" secondAttribute="bottom" constant="12" id="qvY-NM-2vW"/>
+                            <constraint firstAttribute="trailing" secondItem="cb7-UB-AbR" secondAttribute="trailing" constant="12" id="rlp-8k-abT"/>
+                            <constraint firstItem="Q3D-yo-S6d" firstAttribute="centerY" secondItem="EQp-Yo-Ip9" secondAttribute="centerY" id="uoz-Pm-usj"/>
+                            <constraint firstItem="cb7-UB-AbR" firstAttribute="bottom" secondItem="0dg-x6-tnL" secondAttribute="bottom" constant="-2" id="vOW-XS-Tgs"/>
+                            <constraint firstItem="Q3D-yo-S6d" firstAttribute="leading" secondItem="EQp-Yo-Ip9" secondAttribute="trailing" constant="6" id="wZt-in-Yyl"/>
+                            <constraint firstItem="lrL-Hj-K0e" firstAttribute="leading" secondItem="rNL-1B-gdI" secondAttribute="leading" constant="12" id="xc1-WI-K6w"/>
+                            <constraint firstItem="cDo-QS-aQU" firstAttribute="leading" secondItem="rNL-1B-gdI" secondAttribute="leading" constant="12" id="ydC-cf-KaG"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="10"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+            </view>
+            <viewLayoutGuide key="safeArea" id="SEy-5g-ep8"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="rNL-1B-gdI" secondAttribute="trailing" id="4ck-Qd-DRx"/>
+                <constraint firstItem="rNL-1B-gdI" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="Xx9-7N-cBq"/>
+                <constraint firstItem="rNL-1B-gdI" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="gwA-XK-bhf"/>
+                <constraint firstAttribute="bottom" secondItem="rNL-1B-gdI" secondAttribute="bottom" id="soG-i7-qLG"/>
+            </constraints>
+            <size key="customSize" width="343" height="333"/>
+            <connections>
+                <outlet property="courseCount" destination="cb7-UB-AbR" id="KbJ-mY-WXF"/>
+                <outlet property="courseDesc" destination="70G-0T-Hf2" id="gGu-9q-DA9"/>
+                <outlet property="courseImage" destination="Os8-Nn-7BW" id="FaK-HZ-G3Y"/>
+                <outlet property="courseName" destination="cDo-QS-aQU" id="1EF-7L-nJp"/>
+                <outlet property="courseStartTime" destination="s3T-ZE-UQh" id="31R-wJ-hJD"/>
+                <outlet property="descLabel" destination="QP0-xm-KMP" id="5mg-EJ-ot6"/>
+                <outlet property="priceLabel" destination="0dg-x6-tnL" id="lfY-aC-FQZ"/>
+                <outlet property="subjectLabel" destination="oiI-0u-hUk" id="Qwt-Yc-aUB"/>
+                <outlet property="tagLabel" destination="JyZ-5i-yaw" id="SDW-fY-Dyd"/>
+                <outlet property="teacherAvatar" destination="ICh-6B-8NG" id="3t5-j8-Fgv"/>
+                <outlet property="teacherName" destination="EQp-Yo-Ip9" id="jPj-mz-mjZ"/>
+            </connections>
+            <point key="canvasLocation" x="263.35877862595419" y="78.521126760563391"/>
+        </collectionViewCell>
+    </objects>
+    <resources>
+        <image name="arrange_live_tag" width="20" height="16"/>
+        <image name="teacher_avatar" width="150" height="150"/>
+        <image name="video_placeholder" width="103" height="72"/>
+    </resources>
+</document>

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeAccompanyCourseView.m

@@ -64,7 +64,7 @@
         self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
         [self.tableView registerNib:[UINib nibWithNibName:@"CourseTeacherDescCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CourseTeacherDescCell"];
 
-        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, 10)];
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, 20)];
         bottomView.backgroundColor = [UIColor clearColor];
         self.tableView.tableFooterView = bottomView;
         

+ 18 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeGroupCourseView.h

@@ -0,0 +1,18 @@
+//
+//  HomeArrangeGroupCourseView.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "kSJXCollectionView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HomeArrangeGroupCourseView : kSJXCollectionView
+
+@property (nonatomic, strong) NSMutableArray *subjectList;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 357 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeGroupCourseView.m

@@ -0,0 +1,357 @@
+//
+//  HomeArrangeGroupCourseView.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "HomeArrangeGroupCourseView.h"
+#import "StateView.h"
+#import "Reachability.h"
+#import "HomeArrangeSortView.h"
+#import "GroupCourseArrangeCell.h"
+#import "HomeArrangeSortView.h"
+#import "ArrangeLiveCourseModel.h"
+#import <KSChoosePicker.h>
+#import "UserInfoManager.h"
+#import "KSBaseWKWebViewController.h"
+
+
+@interface HomeArrangeGroupCourseView ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
+
+@property (nonatomic, strong) HomeArrangeSortView *searchView;
+
+@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, strong) NSString *searchKey;
+
+@property (nonatomic, strong) NSString *subjectId;
+
+@property (nonatomic, assign) NSInteger subjectIndex;
+
+@end
+
+
+@implementation HomeArrangeGroupCourseView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor = [UIColor clearColor];
+        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
+        layout.sectionInset = UIEdgeInsetsMake(0, 14, 12, 14);
+        
+        self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) collectionViewLayout:layout];
+        self.collectionView.backgroundColor = [UIColor clearColor];
+        self.collectionView.delegate = self;
+        self.collectionView.dataSource = self;
+        self.collectionView.showsVerticalScrollIndicator = NO;
+        self.collectionView.showsHorizontalScrollIndicator = NO;
+        [self.collectionView registerNib:[UINib nibWithNibName:@"GroupCourseArrangeCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"GroupCourseArrangeCell"];
+        [self addSubview:self.collectionView];
+        self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+        
+        MJWeakSelf;
+        self.collectionView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+            [weakSelf resetParamenter];
+            [weakSelf requestData];
+        }];
+        self.collectionView.mj_footer = [KSGifRefreshFooter footerWithRefreshingBlock:^{
+            if (weakSelf.isLoadMore) {
+                weakSelf.pages += 1;
+                [weakSelf requestData];
+            }
+            else {
+                [weakSelf.collectionView.mj_footer endRefreshingWithNoMoreData];
+            }
+        }];
+    }
+    return self;
+}
+
+- (void)endRefresh {
+    @weakObj(self);
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        @strongObj(self);
+        [self.collectionView.mj_header endRefreshing];
+        [self.collectionView.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.collectionView.mj_footer resetNoMoreData];
+    [self setPromptString:@"暂无内容" imageName:@"empty_course" inView:self.collectionView];
+    [self.collectionView reloadData];
+}
+
+- (void)requestData {
+    [KSNetworkingManager queryLiveCourseGroupRequest:KS_POST courseType:@"GROUP" search:self.searchKey subjectId:self.subjectId page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+        [self endRefresh];
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            NSArray *sourceArray = [[dic ks_dictionaryValueForKey:@"data"] ks_arrayValueForKey:@"rows"];
+            for (NSDictionary *parm in sourceArray) {
+                ArrangeLiveCourseModel *model = [[ArrangeLiveCourseModel alloc] initWithDictionary:parm];
+                [self.dataArray addObject:model];
+            }
+            
+            if (sourceArray.count < self.rows) {
+                self.isLoadMore = NO;
+            }
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+        [self.collectionView reloadData];
+        [self changePromptLabelStateWithArray:self.dataArray];
+    } faliure:^(NSError * _Nonnull error) {
+        [self endRefresh];
+        if (self.networkAvaiable == NO) {
+            [self setPromptString:@"暂无网络" imageName:@"no_networking" inView:self.collectionView];
+        }
+        [self.dataArray removeAllObjects];
+        [self.collectionView reloadData];
+        [self changePromptLabelStateWithArray:self.dataArray];
+    }];
+}
+
+- (void)beginRefreshImmediately {
+    [self.collectionView.mj_header beginRefreshing];
+}
+
+- (void)selectCellAtIndexPath:(NSIndexPath *)indexPath {
+    
+    if (self.lastSelectedIndexPath == indexPath) {
+        return;
+    }
+    if (self.lastSelectedIndexPath != nil) {
+        UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:self.lastSelectedIndexPath];
+        [cell setSelected:NO];
+    }
+    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
+    [cell setSelected:YES];
+    self.lastSelectedIndexPath = indexPath;
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    CGFloat searchViewHeight = [HomeArrangeSortView getViewHeight];
+    if (![self.subviews containsObject:self.searchView]) {
+        [self addSubview:self.searchView];
+        [self.searchView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.right.top.mas_equalTo(self);
+            make.height.mas_equalTo(searchViewHeight);
+        }];
+    }
+
+    [self.collectionView mas_remakeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.bottom.mas_equalTo(self);
+        make.top.mas_equalTo(self.searchView.mas_bottom);
+    }];
+}
+
+- (void)beginFirstRefresh {
+    if (!self.isHeaderRefreshed) {
+        [self beginRefreshImmediately];
+    }
+}
+
+#pragma mark ----- collection view
+- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
+    return 1;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+    return self.dataArray.count;
+}
+
+- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+    GroupCourseArrangeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"GroupCourseArrangeCell" forIndexPath:indexPath];
+    
+    ArrangeLiveCourseModel *model = [self.dataArray objectAtIndex:indexPath.row];
+    [cell configWithSource:model];
+    return cell;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+    ArrangeLiveCourseModel *model = self.dataArray[indexPath.row];
+    KSBaseWKWebViewController *ctrl = [[KSBaseWKWebViewController alloc] init];
+    NSString *url = [NSString stringWithFormat:@"%@%@%@", WEBHOST, @"/#/groupDetail?groupId=",model.courseGroupId];
+    ctrl.url = url;
+    [self.naviController pushViewController:ctrl animated:YES];
+}
+
+- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
+    CGFloat width = KPortraitWidth - 28;
+    if (IS_IPAD) {
+        width = (KPortraitWidth - 28 - 12) / 2.0f;
+    }
+    CGFloat height = (width - 12 * 2) / 16 * 9 + 143;
+    return CGSizeMake(width, height);
+}
+
+/**
+ 设置没有数据时的显示
+ 
+ @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, KPortraitWidth, KPortraitHeight - 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
+
+- (HomeArrangeSortView *)searchView {
+    if (!_searchView) {
+        _searchView = [HomeArrangeSortView sharedInstance];
+        MJWeakSelf;
+        [_searchView searchActionCallback:^(HOME_ARRANGE_SORT type, NSString * _Nullable searchKey) {
+            [weakSelf courseSortAction:type searchKey:searchKey];
+        }];
+    }
+    return _searchView;
+}
+
+- (void)courseSortAction:(HOME_ARRANGE_SORT)type searchKey:(NSString *)searchKey {
+    switch (type) {
+        case HOME_ARRANGE_SORT_SUBJECT:
+        {
+            [self searchSubject];
+        }
+            break;
+        case HOME_ARRANGE_SORT_SEARCH:
+        {
+            [self evaluateSource:searchKey];
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+
+- (void)evaluateSource:(NSString *)searchKey {
+    self.searchKey = searchKey;
+    [self refreshAndRequestData];
+}
+
+- (void)searchSubject {
+    if (self.subjectList.count) {
+        NSMutableArray *nameArray = [NSMutableArray array];
+        for (NSDictionary *parm in self.subjectList) {
+            [nameArray addObject:[parm ks_stringValueForKey:@"subjectName"]];
+        }
+        MJWeakSelf;
+        KSChoosePicker *picker = [[KSChoosePicker alloc] initWithTitle:@"" sourceData:nameArray lastChooseIndex:self.subjectIndex sureButtonColor:THEMECOLOR chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
+            weakSelf.searchView.arrowUp = NO;
+            weakSelf.subjectIndex = chooseIndex;
+            weakSelf.searchView.subjectLabel.text = returnValue;
+            NSDictionary *parm = self.subjectList[chooseIndex];
+            weakSelf.subjectId = [parm ks_stringValueForKey:@"subjectId"];
+            [weakSelf refreshAndRequestData];
+        } cancel:^{
+            weakSelf.searchView.arrowUp = NO;
+        }];
+        [picker showPicker];
+    }
+    else {
+        [LOADING_MANAGER MBShowAUTOHidingInWindow:@"无声部信息"];
+    }
+}
+
+- (void)setSubjectList:(NSMutableArray *)subjectList {
+    _subjectList = subjectList;
+    [self defaultSubject:subjectList];
+}
+
+- (void)defaultSubject:(NSMutableArray *)subjectList {
+    
+    self.subjectId = USER_MANAGER.userInfo.subjectId;
+    self.searchView.subjectLabel.text = [NSString returnNoNullStringWithString:USER_MANAGER.userInfo.subjectName];
+    for (NSInteger index = 0; index < subjectList.count; index++) {
+        NSDictionary *parm = subjectList[index];
+        if ([[parm ks_stringValueForKey:@"subjectId"] isEqualToString:self.subjectId]) {
+            self.subjectIndex = index;
+            break;
+        }
+    }
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeLiveCourseView.m

@@ -100,7 +100,7 @@
 }
 
 - (void)requestData {
-    [KSNetworkingManager queryLiveCourseGroupRequest:KS_POST search:self.searchKey subjectId:self.subjectId page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+    [KSNetworkingManager queryLiveCourseGroupRequest:KS_POST courseType:@"LIVE" search:self.searchKey subjectId:self.subjectId page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
         [self endRefresh];
         if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
             NSArray *sourceArray = [[dic ks_dictionaryValueForKey:@"data"] ks_arrayValueForKey:@"rows"];

+ 14 - 14
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeRankView.m

@@ -71,21 +71,21 @@ typedef NS_ENUM(NSInteger, RANK_BUTTON_TYPE) {
             make.top.bottom.mas_equalTo(self.buttonContainer);
             make.width.mas_equalTo(74.0f);
         }];
-        [self.buttonContainer addSubview:self.scoreButton];
-        [self.scoreButton mas_makeConstraints:^(MASConstraintMaker *make) {
-            make.left.mas_equalTo(self.priceButton.mas_right).offset(space);
-            make.top.bottom.mas_equalTo(self.buttonContainer);
-            make.width.mas_equalTo(58.0f);
-        }];
-    }
-    else {
-        [self.buttonContainer addSubview:self.scoreButton];
-        [self.scoreButton mas_makeConstraints:^(MASConstraintMaker *make) {
-            make.left.mas_equalTo(self.finishButton.mas_right).offset(space);
-            make.top.bottom.mas_equalTo(self.buttonContainer);
-            make.width.mas_equalTo(58.0f);
-        }];
+//        [self.buttonContainer addSubview:self.scoreButton];
+//        [self.scoreButton mas_makeConstraints:^(MASConstraintMaker *make) {
+//            make.left.mas_equalTo(self.priceButton.mas_right).offset(space);
+//            make.top.bottom.mas_equalTo(self.buttonContainer);
+//            make.width.mas_equalTo(58.0f);
+//        }];
     }
+//    else {
+//        [self.buttonContainer addSubview:self.scoreButton];
+//        [self.scoreButton mas_makeConstraints:^(MASConstraintMaker *make) {
+//            make.left.mas_equalTo(self.finishButton.mas_right).offset(space);
+//            make.top.bottom.mas_equalTo(self.buttonContainer);
+//            make.width.mas_equalTo(58.0f);
+//        }];
+//    }
 }
 
 - (void)sortAction:(ArrangeRankCallback)callback {

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/HomeArrangeVIPCourseView.m

@@ -64,7 +64,7 @@
         self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
         [self.tableView registerNib:[UINib nibWithNibName:@"CourseTeacherDescCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CourseTeacherDescCell"];
 
-        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, 10)];
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, 20)];
         bottomView.backgroundColor = [UIColor clearColor];
         self.tableView.tableFooterView = bottomView;
         

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/ArrangeCourse/View/LiveCourseArrangeCell.m

@@ -8,6 +8,7 @@
 #import "LiveCourseArrangeCell.h"
 
 @interface LiveCourseArrangeCell ()
+
 @property (weak, nonatomic) IBOutlet UILabel *tagLabel;
 
 @property (weak, nonatomic) IBOutlet UILabel *courseStartTime;

+ 5 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/Controller/HomeViewController.m

@@ -898,6 +898,11 @@
                 [ctrl displayWithIndex:DISPLAY_INDEX_FIRST];
                 [self.navigationController pushViewController:ctrl animated:YES];
             }
+            else if ([model.linkUrl isEqualToString:@"native-bookGroup"]) {
+                HomeArrangeCourseController *ctrl = [[HomeArrangeCourseController alloc] init];
+                [ctrl displayWithIndex:DISPLAY_INDEX_GROUP];
+                [self.navigationController pushViewController:ctrl animated:YES];
+            }
             else if ([model.linkUrl isEqualToString:@"native-bookLive"]) {
                 HomeArrangeCourseController *ctrl = [[HomeArrangeCourseController alloc] init];
                 [ctrl displayWithIndex:DISPLAY_INDEX_LIVE];

+ 6 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/NoticeCenter/Controller/NotiferMessageViewController.m

@@ -279,6 +279,12 @@
                     [ctrl displayWithIndex:index];
                     [self.navigationController pushViewController:ctrl animated:YES];
                 }
+                else if ([pageType isEqualToString:@"groupClass"]) { // 我的课程 ->小组课
+                    DISPLAY_INDEX index = DISPLAY_INDEX_GROUP;
+                    MyCourseViewController *ctrl = [[MyCourseViewController alloc] init];
+                    [ctrl displayWithIndex:index];
+                    [self.navigationController pushViewController:ctrl animated:YES];
+                }
                 else if ([pageType isEqualToString:@"liveClass"]) { // 我的课程 ->直播课
                     DISPLAY_INDEX index = DISPLAY_INDEX_LIVE;
                     MyCourseViewController *ctrl = [[MyCourseViewController alloc] init];

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Mine/Homework/View/HomeworkSortView.m

@@ -22,7 +22,7 @@
 - (void)awakeFromNib {
     [super awakeFromNib];
     self.searchField.delegate = self;
-    self.searchField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"请输入课程组名称" attributes:@{NSForegroundColorAttributeName:HexRGBAlpha(0x000000, 0.4),NSFontAttributeName:[UIFont systemFontOfSize:14.0f]}];
+    self.searchField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"请输入老师名称" attributes:@{NSForegroundColorAttributeName:HexRGBAlpha(0x000000, 0.4),NSFontAttributeName:[UIFont systemFontOfSize:14.0f]}];
 }
 
 + (instancetype)shareInstance {

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

@@ -13,6 +13,7 @@
 typedef NS_ENUM(NSInteger, DISPLAY_INDEX) {
     DISPLAY_INDEX_VIP = 0,    // VIP定制
     DISPLAY_INDEX_FIRST,  // 趣纠课
+    DISPLAY_INDEX_GROUP,  // 小组课
     DISPLAY_INDEX_LIVE,       // 直播课
     DISPLAY_INDEX_VIDEO,       // 视频课
     DISPLAY_INDEX_MUSIC,      // 琴房课

+ 21 - 4
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Controller/MyCourseViewController.m

@@ -20,6 +20,7 @@
 #import "MyMusicRoomCourseGroupView.h"
 
 #import "CourseDescAlertView.h"
+#import "MyGroupCourseGroupView.h"
 
 #define HEADER_HEIGHT (44)
 
@@ -70,7 +71,7 @@
         make.height.mas_equalTo(navHeight);
     }];
     
-    self.titles = @[@"VIP定制课", @"趣纠课", @"直播课",@"视频课",@"琴房课"];
+    self.titles = @[@"VIP定制课", @"趣纠课", @"小组课", @"直播课",@"视频课",@"琴房课"];
     [self configCategoryView:navHeight];
 }
 
@@ -84,7 +85,7 @@
     self.categoryView.titleSelectedColor = HexRGB(0x333333);
     self.categoryView.titleColor = HexRGB(0x666666);
     self.categoryView.titleColorGradientEnabled = YES;
-    self.categoryView.cellSpacing = 10.0f;
+//    self.categoryView.cellSpacing = 10.0f;
     
     JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init];
     lineView.indicatorHeight = 4.0f;
@@ -158,6 +159,10 @@
             MyAccompanyCourseGroupView *pageView = (MyAccompanyCourseGroupView *)view;
             pageView.subjectList = [self.subjectList mutableCopy];
         }
+        else if ([view isKindOfClass:[MyGroupCourseGroupView class]]) {
+            MyGroupCourseGroupView *pageView = (MyGroupCourseGroupView *)view;
+            pageView.subjectList = [self.subjectList mutableCopy];
+        }
         else if ([view isKindOfClass:[MyLiveCourseGroupView class]]) {
             MyLiveCourseGroupView *pageView = (MyLiveCourseGroupView *)view;
             pageView.subjectList = [self.subjectList mutableCopy];
@@ -231,7 +236,7 @@
         return listView;
     }
     else if (index == 2) {
-        MyLiveCourseGroupView *listView = [[MyLiveCourseGroupView alloc] init];
+        MyGroupCourseGroupView *listView = [[MyGroupCourseGroupView alloc] init];
         listView.naviController = self.navigationController;
         [self.listViewArray replaceObjectAtIndex:index withObject:listView];
         self.listViewArray[index] = listView;
@@ -243,6 +248,18 @@
         return listView;
     }
     else if (index == 3) {
+        MyLiveCourseGroupView *listView = [[MyLiveCourseGroupView alloc] init];
+        listView.naviController = self.navigationController;
+        [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+        self.listViewArray[index] = listView;
+        listView.selectIndex = index;
+        if (self.subjectList) {
+            listView.subjectList = [self.subjectList mutableCopy];
+        }
+        [listView beginFirstRefresh];
+        return listView;
+    }
+    else if (index == 4) {
         MyVideoCourseGroupView *listView = [[MyVideoCourseGroupView alloc] init];
         listView.naviController = self.navigationController;
         [self.listViewArray replaceObjectAtIndex:index withObject:listView];
@@ -334,7 +351,7 @@
 
 - (NSMutableArray *)listViewArray {
     if (!_listViewArray) {
-        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@"",@"",@"",@""]];
+        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@"",@"",@"",@"",@""]];
     }
     return _listViewArray;
 }

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

@@ -35,6 +35,9 @@
 @property (nonatomic, assign) NSInteger courseNum;
 @property (nonatomic, assign) NSInteger completeCourseNum;
 
+@property (nonatomic, assign) NSInteger maxStudentNum;
+@property (nonatomic, assign) NSInteger studentCount;
+
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
 - (instancetype)initWithDictionary:(NSDictionary *)dict;
 - (NSDictionary *)dictionaryRepresentation;

+ 17 - 1
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/Model/LiveLessonModel.m

@@ -31,6 +31,9 @@ NSString *const kLiveLessonModelStartTime = @"startTime";
 NSString *const kLiveLessonModelUserId = @"userId";
 NSString *const kLiveLessonModelCourseNum = @"courseNum";
 NSString *const kLiveLessonModelCompleteCourseNum = @"completeCourseNum";
+NSString *const kLiveLessonModelMaxStudentNum = @"maxStudentNum";
+NSString *const kLiveLessonModelStudentCount = @"studentCount";
+
 
 @interface LiveLessonModel ()
 
@@ -63,6 +66,8 @@ NSString *const kLiveLessonModelCompleteCourseNum = @"completeCourseNum";
 @synthesize userId = _userId;
 @synthesize courseNum = _courseNum;
 @synthesize completeCourseNum = _completeCourseNum;
+@synthesize maxStudentNum = _maxStudentNum;
+@synthesize studentCount = _studentCount;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
 {
@@ -99,7 +104,8 @@ NSString *const kLiveLessonModelCompleteCourseNum = @"completeCourseNum";
             self.userId = [self objectOrNilForKey:kLiveLessonModelUserId fromDictionary:dict];
         self.courseNum = [[self objectOrNilForKey:kLiveLessonModelCourseNum fromDictionary:dict] integerValue];
         self.completeCourseNum = [[self objectOrNilForKey:kLiveLessonModelCompleteCourseNum fromDictionary:dict] integerValue];
-
+        self.maxStudentNum = [[self objectOrNilForKey:kLiveLessonModelMaxStudentNum fromDictionary:dict] integerValue];
+        self.studentCount = [[self objectOrNilForKey:kLiveLessonModelStudentCount fromDictionary:dict] integerValue];
     }
     
     return self;
@@ -132,6 +138,8 @@ NSString *const kLiveLessonModelCompleteCourseNum = @"completeCourseNum";
     [mutableDict setValue:self.userId forKey:kLiveLessonModelUserId];
     [mutableDict setValue:[NSNumber numberWithInteger:self.courseNum] forKey:kLiveLessonModelCourseNum];
     [mutableDict setValue:[NSNumber numberWithInteger:self.completeCourseNum] forKey:kLiveLessonModelCompleteCourseNum];
+    [mutableDict setValue:[NSNumber numberWithInteger:self.maxStudentNum] forKey:kLiveLessonModelMaxStudentNum];
+    [mutableDict setValue:[NSNumber numberWithInteger:self.studentCount] forKey:kLiveLessonModelStudentCount];
     return [NSDictionary dictionaryWithDictionary:mutableDict];
 }
 
@@ -181,6 +189,9 @@ NSString *const kLiveLessonModelCompleteCourseNum = @"completeCourseNum";
     self.userId = [aDecoder decodeObjectForKey:kLiveLessonModelUserId];
     self.courseNum = [aDecoder decodeIntegerForKey:kLiveLessonModelCourseNum];
     self.completeCourseNum = [aDecoder decodeIntegerForKey:kLiveLessonModelCompleteCourseNum];
+    self.maxStudentNum = [aDecoder decodeIntegerForKey:kLiveLessonModelMaxStudentNum];
+    self.studentCount = [aDecoder decodeIntegerForKey:kLiveLessonModelStudentCount];
+
     return self;
 }
 
@@ -210,6 +221,9 @@ NSString *const kLiveLessonModelCompleteCourseNum = @"completeCourseNum";
     [aCoder encodeObject:_userId forKey:kLiveLessonModelUserId];
     [aCoder encodeInteger:_courseNum forKey:kLiveLessonModelCourseNum];
     [aCoder encodeInteger:_completeCourseNum forKey:kLiveLessonModelCompleteCourseNum];
+    [aCoder encodeInteger:_maxStudentNum forKey:kLiveLessonModelMaxStudentNum];
+    [aCoder encodeInteger:_studentCount forKey:kLiveLessonModelStudentCount];
+
 }
 
 - (id)copyWithZone:(NSZone *)zone
@@ -241,6 +255,8 @@ NSString *const kLiveLessonModelCompleteCourseNum = @"completeCourseNum";
         copy.userId = [self.userId copyWithZone:zone];
         copy.courseNum = self.courseNum;
         copy.completeCourseNum = self.completeCourseNum;
+        copy.maxStudentNum = self.maxStudentNum;
+        copy.studentCount = self.studentCount;
     }
     
     return copy;

+ 0 - 1
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/AccompanyCourseGroup/MyAccompanyCourseGroupView.m

@@ -199,7 +199,6 @@
 
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     // 课程详情
-    // 课程详情
     ProgramCourseGroupModel *model = self.dataArray[indexPath.row];
     AccompanyCourseGroupViewController *ctrl = [[AccompanyCourseGroupViewController alloc] init];
     ctrl.courseGroupId = model.courseGroupId;

+ 19 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupListCell.h

@@ -0,0 +1,19 @@
+//
+//  MyGroupCourseGroupListCell.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import <UIKit/UIKit.h>
+#import "LiveLessonModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MyGroupCourseGroupListCell : UICollectionViewCell
+
+- (void)configWithSource:(LiveLessonModel *)model;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 101 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupListCell.m

@@ -0,0 +1,101 @@
+//
+//  MyGroupCourseGroupListCell.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "MyGroupCourseGroupListCell.h"
+
+@interface MyGroupCourseGroupListCell ()
+
+@property (weak, nonatomic) IBOutlet UILabel *courseStatus;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseTime;
+
+@property (weak, nonatomic) IBOutlet UIImageView *courseCover;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseSubject;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseTitle;
+
+@property (weak, nonatomic) IBOutlet UILabel *courseDesc;
+
+@property (weak, nonatomic) IBOutlet UILabel *finishDesc;
+
+@property (weak, nonatomic) IBOutlet UIImageView *avatar;
+
+@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *bookDesc;
+
+@end
+
+@implementation MyGroupCourseGroupListCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+}
+
+- (void)configWithSource:(LiveLessonModel *)model {
+    [self evaluateGroupStatus:model.status sourceModel:model];
+    // time
+    NSDateFormatter *formatter = [NSObject getDateformatter];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *startDate = [formatter dateFromString:model.startTime];
+    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
+    NSString *courseBegin = [formatter stringFromDate:startDate];
+    self.courseTime.text = [NSString returnNoNullStringWithString:courseBegin];
+    
+    [self.courseCover sd_setImageWithURL:[NSURL URLWithString:[model.cover getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:@"video_placeholder"]];
+    self.courseSubject.text = [NSString returnNoNullStringWithString:model.subjectName];
+    self.courseTitle.text = [NSString returnNoNullStringWithString:model.name];
+    
+    NSString *introduce = model.courseIntroduce;
+    if (![NSString isEmptyString:introduce]) {
+        introduce = [introduce replaceAll:@"\n" WithString:@" "];
+        self.courseDesc.text = [NSString returnNoNullStringWithString:introduce];
+    }
+    else {
+        self.courseDesc.text = @"暂无介绍";
+    }
+    
+    NSMutableAttributedString *attrs = [[NSMutableAttributedString alloc] initWithString:@"已上课时 " attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular],NSForegroundColorAttributeName:HexRGB(0x999999)}];
+    NSAttributedString *finishNumAttr = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%zd", model.completeCourseNum] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightSemibold],NSForegroundColorAttributeName:THEMECOLOR}];
+    [attrs appendAttributedString:finishNumAttr];
+    
+    NSAttributedString *totalDescAttr = [[NSAttributedString alloc] initWithString:@" /总课时 " attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular],NSForegroundColorAttributeName:HexRGB(0x999999)}];
+    [attrs appendAttributedString:totalDescAttr];
+    NSAttributedString *totalNumAttr = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%zd", model.courseNum] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightSemibold],NSForegroundColorAttributeName:HexRGB(0x333333)}];
+    [attrs appendAttributedString:totalNumAttr];
+    self.finishDesc.attributedText = attrs;
+    [self.avatar sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:TEACHER_AVATAR]];
+    self.nameLabel.text = [NSString returnNoNullStringWithString:model.name];
+}
+
+
+- (void)evaluateGroupStatus:(NSString *)status sourceModel:(LiveLessonModel *)model {
+    NSString *desc = [NSString stringWithFormat:@"%zd人学习", model.studentCount];
+    if ([status isEqualToString:@"ING"]) {
+        self.courseStatus.text = @"已开课";
+        self.courseStatus.textColor = THEMECOLOR;
+    }
+    else if ([status isEqualToString:@"NOT_START"]) {
+        self.courseStatus.text = @"未开课";
+        self.courseStatus.textColor = HexRGB(0xFF802C);
+//        desc = [NSString stringWithFormat:@"剩余%zd个名额", model.maxStudentNum - model.studentCount];
+    }
+    else if ([status isEqualToString:@"COMPLETE"]) {
+        self.courseStatus.text = @"已结课";
+        self.courseStatus.textColor = HexRGB(0x999999);
+    }
+    else if ([status isEqualToString:@"CANCEL"]) {
+        self.courseStatus.text = @"已取消";
+        self.courseStatus.textColor = HexRGB(0x999999);
+//        desc = [NSString stringWithFormat:@"剩余%zd个名额", model.maxStudentNum - model.studentCount];
+    }
+    self.bookDesc.text = desc;
+}
+
+@end

+ 240 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupListCell.xib

@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.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"/>
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="MyGroupCourseGroupListCell">
+            <rect key="frame" x="0.0" y="0.0" width="328" height="323"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="328" height="323"/>
+                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eqc-ti-GJ3">
+                        <rect key="frame" x="0.0" y="0.0" width="328" height="323"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="mine_page_live_tag" translatesAutoresizingMaskIntoConstraints="NO" id="0y5-zm-9jL">
+                                <rect key="frame" x="12" y="15" width="20" height="16"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="16" id="eXI-pn-Vo0"/>
+                                    <constraint firstAttribute="width" constant="20" id="jYh-6P-qi3"/>
+                                </constraints>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="keF-8e-s1s">
+                                <rect key="frame" x="316" y="13" width="0.0" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="D6V-QD-dh0"/>
+                                </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="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="video_placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="uRX-TL-BeC">
+                                <rect key="frame" x="12" y="46" width="304" height="171"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" secondItem="uRX-TL-BeC" secondAttribute="height" multiplier="16:9" id="0JJ-We-HR3"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="6"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </imageView>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wcU-a5-Q32">
+                                <rect key="frame" x="20" y="54" width="12" height="19"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZC8-u0-0mZ">
+                                        <rect key="frame" x="6" y="9.6666666666666643" width="0.0" height="0.0"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                        <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.40000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
+                                <constraints>
+                                    <constraint firstItem="ZC8-u0-0mZ" firstAttribute="centerY" secondItem="wcU-a5-Q32" secondAttribute="centerY" id="0d2-MX-IIB"/>
+                                    <constraint firstAttribute="height" constant="19" id="9Iy-nK-rFR"/>
+                                    <constraint firstAttribute="trailing" secondItem="ZC8-u0-0mZ" secondAttribute="trailing" constant="6" id="Zo6-kv-WXf"/>
+                                    <constraint firstItem="ZC8-u0-0mZ" firstAttribute="leading" secondItem="wcU-a5-Q32" secondAttribute="leading" constant="6" id="heb-rb-G8U"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="3"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="32w-na-a4G">
+                                <rect key="frame" x="12" y="225" width="304" height="22"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="22" id="5AT-IM-ChD"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                                <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <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="tf8-r5-3J4">
+                                <rect key="frame" x="12" y="251" width="304" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="gHs-PD-uF5"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                <color key="textColor" red="0.46666666670000001" green="0.46666666670000001" blue="0.46666666670000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cxg-7G-6x4">
+                                <rect key="frame" x="316" y="290" width="0.0" height="16"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="16" id="KCW-P1-64f"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="arrange_course_icon" translatesAutoresizingMaskIntoConstraints="NO" id="8b2-TR-usR">
+                                <rect key="frame" x="302" y="291" width="12" height="14"/>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="开课时间:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HiN-qT-QfT">
+                                <rect key="frame" x="39" y="13" width="62.666666666666657" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="JNO-8g-lxE"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tUk-OX-oQD">
+                                <rect key="frame" x="101.66666666666667" y="13" width="0.0" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="OEh-OR-doK"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="teacher_avatar" translatesAutoresizingMaskIntoConstraints="NO" id="AFv-Bg-m8r">
+                                <rect key="frame" x="12" y="285" width="26" height="26"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="26" id="N83-ce-Lne"/>
+                                    <constraint firstAttribute="width" constant="26" id="ylg-Nl-qiS"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="13"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LtK-ig-Xvf">
+                                <rect key="frame" x="44" y="288" width="0.0" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="0gX-OH-xwK"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <view contentMode="scaleToFill" horizontalCompressionResistancePriority="752" translatesAutoresizingMaskIntoConstraints="NO" id="pU5-Uo-TdG">
+                                <rect key="frame" x="50" y="288.66666666666669" width="79" height="19"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="剩余3个名额" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="z8Y-wD-cTT">
+                                        <rect key="frame" x="4" y="2" width="71" height="15"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                        <color key="textColor" red="1" green="0.40784313729999999" blue="0.1529411765" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" red="1" green="0.50196078430000002" blue="0.17254901959999999" alpha="0.070000000000000007" colorSpace="custom" customColorSpace="sRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="19" id="1t2-Rc-iUN"/>
+                                    <constraint firstItem="z8Y-wD-cTT" firstAttribute="leading" secondItem="pU5-Uo-TdG" secondAttribute="leading" constant="4" id="8WF-Vg-ZEq"/>
+                                    <constraint firstAttribute="trailing" secondItem="z8Y-wD-cTT" secondAttribute="trailing" constant="4" id="NJJ-nE-cnY"/>
+                                    <constraint firstItem="z8Y-wD-cTT" firstAttribute="centerY" secondItem="pU5-Uo-TdG" secondAttribute="centerY" id="p2m-9e-1CE"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="2"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="uRX-TL-BeC" firstAttribute="leading" secondItem="eqc-ti-GJ3" secondAttribute="leading" constant="12" id="2SO-Ff-IQz"/>
+                            <constraint firstItem="tUk-OX-oQD" firstAttribute="centerY" secondItem="0y5-zm-9jL" secondAttribute="centerY" id="4VZ-l2-5jr"/>
+                            <constraint firstItem="HiN-qT-QfT" firstAttribute="leading" secondItem="0y5-zm-9jL" secondAttribute="trailing" constant="7" id="4w4-xO-9Lb"/>
+                            <constraint firstItem="keF-8e-s1s" firstAttribute="centerY" secondItem="tUk-OX-oQD" secondAttribute="centerY" id="8LW-tq-jMk"/>
+                            <constraint firstItem="HiN-qT-QfT" firstAttribute="centerY" secondItem="0y5-zm-9jL" secondAttribute="centerY" id="9JG-PP-OjX"/>
+                            <constraint firstItem="cxg-7G-6x4" firstAttribute="leading" secondItem="8b2-TR-usR" secondAttribute="trailing" constant="2" id="EPx-KF-E2V"/>
+                            <constraint firstAttribute="bottom" secondItem="AFv-Bg-m8r" secondAttribute="bottom" constant="12" id="ERu-4M-OTr"/>
+                            <constraint firstItem="32w-na-a4G" firstAttribute="leading" secondItem="eqc-ti-GJ3" secondAttribute="leading" constant="12" id="FrV-Wu-iWh"/>
+                            <constraint firstItem="AFv-Bg-m8r" firstAttribute="leading" secondItem="eqc-ti-GJ3" secondAttribute="leading" constant="12" id="Gdr-Lg-mLl"/>
+                            <constraint firstItem="uRX-TL-BeC" firstAttribute="top" secondItem="0y5-zm-9jL" secondAttribute="bottom" constant="15" id="JrX-A6-tVe"/>
+                            <constraint firstItem="tUk-OX-oQD" firstAttribute="centerY" secondItem="HiN-qT-QfT" secondAttribute="centerY" id="L7t-66-nhk"/>
+                            <constraint firstItem="pU5-Uo-TdG" firstAttribute="leading" secondItem="LtK-ig-Xvf" secondAttribute="trailing" constant="6" id="OBs-Si-Rxc"/>
+                            <constraint firstAttribute="trailing" secondItem="32w-na-a4G" secondAttribute="trailing" constant="12" id="OHI-Wa-8Bc"/>
+                            <constraint firstAttribute="trailing" secondItem="keF-8e-s1s" secondAttribute="trailing" constant="12" id="Pbe-Rx-M8T"/>
+                            <constraint firstItem="LtK-ig-Xvf" firstAttribute="centerY" secondItem="pU5-Uo-TdG" secondAttribute="centerY" id="QSj-ic-LlI"/>
+                            <constraint firstItem="tf8-r5-3J4" firstAttribute="leading" secondItem="eqc-ti-GJ3" secondAttribute="leading" constant="12" id="SOR-3y-qhn"/>
+                            <constraint firstItem="8b2-TR-usR" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="pU5-Uo-TdG" secondAttribute="trailing" constant="10" id="W1c-Df-5gL"/>
+                            <constraint firstItem="32w-na-a4G" firstAttribute="top" secondItem="uRX-TL-BeC" secondAttribute="bottom" constant="8" id="XvE-gb-b4g"/>
+                            <constraint firstItem="cxg-7G-6x4" firstAttribute="centerY" secondItem="8b2-TR-usR" secondAttribute="centerY" id="Y2t-8d-3HA"/>
+                            <constraint firstItem="0y5-zm-9jL" firstAttribute="leading" secondItem="eqc-ti-GJ3" secondAttribute="leading" constant="12" id="a6D-hR-yEi"/>
+                            <constraint firstAttribute="trailing" secondItem="uRX-TL-BeC" secondAttribute="trailing" constant="12" id="aLt-Yg-nM7"/>
+                            <constraint firstItem="wcU-a5-Q32" firstAttribute="leading" secondItem="uRX-TL-BeC" secondAttribute="leading" constant="8" id="axR-nA-iYO"/>
+                            <constraint firstAttribute="trailing" secondItem="tf8-r5-3J4" secondAttribute="trailing" constant="12" id="cQ5-Pz-iIJ"/>
+                            <constraint firstItem="tf8-r5-3J4" firstAttribute="top" secondItem="32w-na-a4G" secondAttribute="bottom" constant="4" id="clN-ta-mbl"/>
+                            <constraint firstItem="AFv-Bg-m8r" firstAttribute="top" relation="greaterThanOrEqual" secondItem="tf8-r5-3J4" secondAttribute="bottom" constant="8" id="gLC-oh-J8p"/>
+                            <constraint firstAttribute="trailing" secondItem="cxg-7G-6x4" secondAttribute="trailing" constant="12" id="iKy-T6-7Ky"/>
+                            <constraint firstItem="0y5-zm-9jL" firstAttribute="top" secondItem="eqc-ti-GJ3" secondAttribute="top" constant="15" id="kcp-Hc-Hib"/>
+                            <constraint firstItem="wcU-a5-Q32" firstAttribute="top" secondItem="uRX-TL-BeC" secondAttribute="top" constant="8" id="nrv-aF-ifF"/>
+                            <constraint firstItem="8b2-TR-usR" firstAttribute="centerY" secondItem="LtK-ig-Xvf" secondAttribute="centerY" id="nwm-6d-8Su"/>
+                            <constraint firstItem="LtK-ig-Xvf" firstAttribute="leading" secondItem="AFv-Bg-m8r" secondAttribute="trailing" constant="6" id="q0m-JH-x1N"/>
+                            <constraint firstItem="keF-8e-s1s" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="tUk-OX-oQD" secondAttribute="trailing" constant="10" id="umD-Np-gaZ"/>
+                            <constraint firstItem="tUk-OX-oQD" firstAttribute="leading" secondItem="HiN-qT-QfT" secondAttribute="trailing" id="vwf-J9-c0S"/>
+                            <constraint firstItem="tUk-OX-oQD" firstAttribute="centerY" secondItem="HiN-qT-QfT" secondAttribute="centerY" id="w0V-fy-klj"/>
+                            <constraint firstItem="AFv-Bg-m8r" firstAttribute="centerY" secondItem="LtK-ig-Xvf" secondAttribute="centerY" id="zgE-3C-RZg"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="10"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+            </view>
+            <viewLayoutGuide key="safeArea" id="SEy-5g-ep8"/>
+            <constraints>
+                <constraint firstItem="eqc-ti-GJ3" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="ACv-fU-JBM"/>
+                <constraint firstAttribute="trailing" secondItem="eqc-ti-GJ3" secondAttribute="trailing" id="Shp-N3-ZL3"/>
+                <constraint firstAttribute="bottom" secondItem="eqc-ti-GJ3" secondAttribute="bottom" id="XlZ-YT-cur"/>
+                <constraint firstItem="eqc-ti-GJ3" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="l44-23-05X"/>
+            </constraints>
+            <size key="customSize" width="328" height="323"/>
+            <connections>
+                <outlet property="avatar" destination="AFv-Bg-m8r" id="v6s-a1-3GR"/>
+                <outlet property="bookDesc" destination="z8Y-wD-cTT" id="fuf-Yi-oGr"/>
+                <outlet property="courseCover" destination="uRX-TL-BeC" id="IVP-sb-b1S"/>
+                <outlet property="courseDesc" destination="tf8-r5-3J4" id="Gjl-XS-CKI"/>
+                <outlet property="courseStatus" destination="keF-8e-s1s" id="q79-JO-dDF"/>
+                <outlet property="courseSubject" destination="ZC8-u0-0mZ" id="OAv-F0-FaS"/>
+                <outlet property="courseTime" destination="tUk-OX-oQD" id="bRV-tS-qLo"/>
+                <outlet property="courseTitle" destination="32w-na-a4G" id="fmV-A5-jZr"/>
+                <outlet property="finishDesc" destination="cxg-7G-6x4" id="Eyw-uo-xAo"/>
+                <outlet property="nameLabel" destination="LtK-ig-Xvf" id="Ni1-hH-NL1"/>
+            </connections>
+            <point key="canvasLocation" x="245.80152671755724" y="116.54929577464789"/>
+        </collectionViewCell>
+    </objects>
+    <resources>
+        <image name="arrange_course_icon" width="12" height="14"/>
+        <image name="mine_page_live_tag" width="20" height="16"/>
+        <image name="teacher_avatar" width="150" height="150"/>
+        <image name="video_placeholder" width="103" height="72"/>
+    </resources>
+</document>

+ 18 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupView.h

@@ -0,0 +1,18 @@
+//
+//  MyGroupCourseGroupView.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "kSJXCollectionView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MyGroupCourseGroupView : kSJXCollectionView
+
+@property (nonatomic, strong) NSMutableArray *subjectList;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 368 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/GroupCourseGroup/MyGroupCourseGroupView.m

@@ -0,0 +1,368 @@
+//
+//  MyGroupCourseGroupView.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2024/12/23.
+//
+
+#import "MyGroupCourseGroupView.h"
+#import "MyGroupCourseGroupListCell.h"
+#import "MyCourseSearchView.h"
+#import "StateView.h"
+#import "Reachability.h"
+#import "LiveLessonModel.h"
+#import "MyCourseRankSortView.h"
+#import "MyGroupCourseGroupController.h"
+
+@interface MyGroupCourseGroupView ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
+
+@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, strong) MyCourseSearchView *searchView;
+
+@property (nonatomic, strong) NSString *searchKey;
+
+@property (nonatomic, strong) NSString *subjectId;
+
+@property (nonatomic, strong) NSString *status;
+
+@property (nonatomic, strong) NSString *classDate;
+
+@property (nonatomic, assign) NSInteger subjectChooseIndex;
+
+@property (nonatomic, assign) NSInteger statusChooseIndex;
+
+@property (nonatomic, strong) MyCourseRankSortView *sortView;
+
+@property (nonatomic, strong) NSMutableArray *statusArray;
+
+@end
+
+@implementation MyGroupCourseGroupView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor = [UIColor clearColor];
+        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
+        layout.sectionInset = UIEdgeInsetsMake(0, 14, 12, 14);
+        
+        self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) collectionViewLayout:layout];
+        self.collectionView.backgroundColor = [UIColor clearColor];
+        self.collectionView.delegate = self;
+        self.collectionView.dataSource = self;
+        self.collectionView.showsVerticalScrollIndicator = NO;
+        self.collectionView.showsHorizontalScrollIndicator = NO;
+        [self.collectionView registerNib:[UINib nibWithNibName:@"MyGroupCourseGroupListCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"MyGroupCourseGroupListCell"];
+        [self addSubview:self.collectionView];
+        self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+        MJWeakSelf;
+        self.collectionView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+            [weakSelf resetParamenter];
+            [weakSelf requestData];
+        }];
+        self.collectionView.mj_footer = [KSGifRefreshFooter footerWithRefreshingBlock:^{
+            if (weakSelf.isLoadMore) {
+                weakSelf.pages += 1;
+                [weakSelf requestData];
+            }
+            else {
+                [weakSelf.collectionView.mj_footer endRefreshingWithNoMoreData];
+            }
+        }];
+    }
+    return self;
+}
+
+- (void)endRefresh {
+    @weakObj(self);
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        @strongObj(self);
+        [self.collectionView.mj_header endRefreshing];
+        [self.collectionView.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.collectionView.mj_footer resetNoMoreData];
+    [self setPromptString:@"暂无内容" imageName:@"empty_course" inView:self.collectionView];
+    [self.collectionView reloadData];
+}
+
+- (void)requestData {
+    [KSNetworkingManager queryMyLiveCourse:KS_POST courseType:@"GROUP" classDate:self.classDate status:self.status subjectId:self.subjectId search:self.searchKey page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+        [self endRefresh];
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            NSArray *sourceArray = [[dic ks_dictionaryValueForKey:@"data"] ks_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 {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+        [self.collectionView reloadData];
+        [self changePromptLabelStateWithArray:self.dataArray];
+    } faliure:^(NSError * _Nonnull error) {
+        [self endRefresh];
+        if (self.networkAvaiable == NO) {
+            [self setPromptString:@"暂无网络" imageName:@"no_networking" inView:self.collectionView];
+        }
+        [self.dataArray removeAllObjects];
+        [self.collectionView reloadData];
+        [self changePromptLabelStateWithArray:self.dataArray];
+    }];
+}
+
+- (void)beginRefreshImmediately {
+    [self.collectionView.mj_header beginRefreshing];
+}
+
+- (void)selectCellAtIndexPath:(NSIndexPath *)indexPath {
+    
+    if (self.lastSelectedIndexPath == indexPath) {
+        return;
+    }
+    if (self.lastSelectedIndexPath != nil) {
+        UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:self.lastSelectedIndexPath];
+        [cell setSelected:NO];
+    }
+    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
+    [cell setSelected:YES];
+    self.lastSelectedIndexPath = indexPath;
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    CGFloat searchViewHeight = [MyCourseSearchView getViewHeight];
+
+    if (![self.subviews containsObject:self.searchView]) {
+        [self addSubview:self.searchView];
+        [self.searchView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.right.top.mas_equalTo(self);
+            make.height.mas_equalTo(searchViewHeight);
+        }];
+    }
+
+    [self.collectionView mas_remakeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.bottom.mas_equalTo(self);
+        make.top.mas_equalTo(self.searchView.mas_bottom);
+    }];
+}
+
+
+- (void)beginFirstRefresh {
+    if (!self.isHeaderRefreshed) {
+        [self beginRefreshImmediately];
+    }
+}
+
+#pragma mark ----- collection view
+- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
+    return 1;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+    return self.dataArray.count;
+}
+
+- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+    MyGroupCourseGroupListCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyGroupCourseGroupListCell" forIndexPath:indexPath];
+    
+    LiveLessonModel *model = [self.dataArray objectAtIndex:indexPath.row];
+    [cell configWithSource:model];
+    return cell;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+    LiveLessonModel *model = self.dataArray[indexPath.row];
+    MyGroupCourseGroupController *ctrl = [[MyGroupCourseGroupController alloc] init];
+    ctrl.courseGroupId = model.courseGoupId;
+    [self.naviController pushViewController:ctrl animated:YES];
+}
+
+- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
+    CGFloat width = KPortraitWidth - 28;
+    if (IS_IPAD) {
+        width = (KPortraitWidth - 28 - 12) / 2.0f;
+    }
+    CGFloat height = (width - 12 * 2) / 16 * 9 + 143;
+    return CGSizeMake(width, height);
+}
+
+#pragma mark ------ lazying
+- (MyCourseSearchView *)searchView {
+    if (!_searchView) {
+        _searchView = [MyCourseSearchView sharedInstance];
+        [_searchView configPlaceholder:@"请输入课程组或老师名称"];
+        MJWeakSelf;
+        [_searchView searchActionCallback:^(MY_COURSE_SORT type, NSString * _Nullable searchKey) {
+            [weakSelf searchAction:type searchKey:searchKey];
+        }];
+    }
+    return _searchView;
+}
+
+- (void)searchAction:(MY_COURSE_SORT)type searchKey:(NSString *)searchKey {
+    switch (type) {
+        case MY_COURSE_SORT_RANK:
+        {
+            [self showSortView];
+        }
+            break;
+        case MY_COURSE_SORT_SEARCH:
+        {
+            [self evaluateSource:searchKey];
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)showSortView {
+    self.searchView.arrowUp = YES;
+    [self.sortView refreshUI:self.statusChooseIndex subjectId:self.subjectChooseIndex];
+    [self.sortView showInView:[NSObject getKeyWindow]];
+}
+
+- (void)evaluateSource:(NSString *)searchKey {
+    self.searchKey = searchKey;
+    [self refreshAndRequestData];
+}
+
+/**
+ 设置没有数据时的显示
+ 
+ @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, KPortraitWidth, KPortraitHeight - 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;
+}
+
+- (MyCourseRankSortView *)sortView {
+    if (!_sortView) {
+        _sortView = [MyCourseRankSortView sharedInstance];
+        [_sortView configWithStatusArray:self.statusArray subjectArray:self.subjectList];
+        MJWeakSelf;
+        [_sortView sortActionCallback:^(MY_COURSE_SORTTYPE type, NSString * _Nullable status, NSString * _Nullable subjectId, NSInteger statusIndex, NSInteger subjectIndex) {
+            [weakSelf sortActionWithType:type status:status subjectId:subjectId statusChooseIndex:statusIndex subjectChooseIndex:subjectIndex];
+        }];
+    }
+    return _sortView;
+}
+
+- (void)sortActionWithType:(MY_COURSE_SORTTYPE)type status:(NSString *)status subjectId:(NSString *)subjectId statusChooseIndex:(NSInteger)statusChooseIndex subjectChooseIndex:(NSInteger)subjectChooseIndex  {
+    self.searchView.arrowUp = NO;
+    if (type == MY_COURSE_SORTTYPE_SORT) {
+        self.statusChooseIndex = statusChooseIndex;
+        self.subjectChooseIndex = subjectChooseIndex;
+        self.status = status;
+        self.subjectId = subjectId;
+        if ([NSString isEmptyString:status]) {
+            self.status = nil;
+        }
+        if ([NSString isEmptyString:subjectId]) {
+            self.subjectId = nil;
+        }
+        [self refreshAndRequestData];
+    }
+}
+
+- (NSMutableArray *)statusArray {
+    if (!_statusArray) {
+        _statusArray = [NSMutableArray arrayWithArray:@[@{@"name":@"全部",@"id":@""},@{@"name":@"未开课",@"id":@"NOT_START"},@{@"name":@"已开课",@"id":@"ING"},@{@"name":@"已结课",@"id":@"COMPLETE"}]];
+    }
+    return _statusArray;
+}
+
+- (void)setSubjectList:(NSMutableArray *)subjectList {
+    NSMutableArray *array = [NSMutableArray arrayWithArray:subjectList];
+    [array insertObject:@{@"name":@"全部",@"id":@""} atIndex:0];
+    _subjectList = array;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/LiveCourseGroup/MyLiveCourseGroupView.m

@@ -108,7 +108,7 @@
 }
 
 - (void)requestData {
-    [KSNetworkingManager queryMyLiveCourse:KS_POST classDate:self.classDate status:self.status subjectId:self.subjectId search:self.searchKey page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+    [KSNetworkingManager queryMyLiveCourse:KS_POST courseType:@"LIVE" classDate:self.classDate status:self.status subjectId:self.subjectId search:self.searchKey page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
         [self endRefresh];
         if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
             NSArray *sourceArray = [[dic ks_dictionaryValueForKey:@"data"] ks_arrayValueForKey:@"rows"];

+ 2 - 1
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyCourseSortView/MyCourseRankSortView.m

@@ -192,8 +192,9 @@
                 topHeight += (buttonHeight + topSpace);
             }
         }
-        topHeight += 18; // 底部区域
     }
+    topHeight += 18; // 底部区域
+
     if (topHeight > 303) {
         topHeight = 303.0f;
     }

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonBodyView.m

@@ -159,7 +159,7 @@
     }
     else if (self.selectIndex == 1) { // 直播课
         NSString *searchKey = nil;
-        [KSNetworkingManager queryMyLiveCourse:KS_POST classDate:self.classDate status:self.status subjectId:self.subjectId search:searchKey page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+        [KSNetworkingManager queryMyLiveCourse:KS_POST courseType:@"LIVE" classDate:self.classDate status:self.status subjectId:self.subjectId search:searchKey page:self.pages rows:self.rows success:^(NSDictionary * _Nonnull dic) {
             [self endRefresh];
             if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
                 NSArray *sourceArray = [[dic ks_dictionaryValueForKey:@"data"] ks_arrayValueForKey:@"rows"];
@@ -442,7 +442,7 @@
         MusicRoomListModel *model = self.dataArray[indexPath.row];
         MusicRoomCourseCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MusicRoomCourseCell"];
         MJWeakSelf;
-        [cell configWithSource:model beforeTime:0 callback:^(NSString * _Nonnull targetId) {
+        [cell configWithSource:model isGroup:NO beforeTime:0 callback:^(NSString * _Nonnull targetId) {
             [weakSelf chatAction:targetId];
         }];
         return cell;

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini