Browse Source

学生端直播

Steven 2 years ago
parent
commit
77094193b7
78 changed files with 2409 additions and 380 deletions
  1. 76 0
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. 18 0
      KulexiuForStudent/KulexiuForStudent.xcodeproj/xcuserdata/wangzhi.xcuserdatad/xcschemes/xcschememanagement.plist
  3. BIN
      KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/UserInterfaceState.xcuserstate
  4. 34 0
      KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  5. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_icon.imageset/Contents.json
  6. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_icon.imageset/notice_icon@2x.png
  7. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_icon.imageset/notice_icon@3x.png
  8. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_more.imageset/Contents.json
  9. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_more.imageset/notice_more@2x.png
  10. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_more.imageset/notice_more@3x.png
  11. 5 5
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSBaseViewController.m
  12. 2 11
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSBaseWKWebViewController.m
  13. 10 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h
  14. 24 6
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m
  15. 2 1
      KulexiuForStudent/KulexiuForStudent/Common/Define/PrefixHeader.pch
  16. 8 0
      KulexiuForStudent/KulexiuForStudent/Common/Tools/Extension/NSDictionary+Extension.h
  17. 10 0
      KulexiuForStudent/KulexiuForStudent/Common/Tools/Extension/NSDictionary+Extension.m
  18. 1 1
      KulexiuForStudent/KulexiuForStudent/Common/Tools/KSVideoHelper.h
  19. 31 5
      KulexiuForStudent/KulexiuForStudent/Common/Tools/KSVideoHelper.m
  20. 5 3
      KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/KSChatConversationViewController.m
  21. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/KSChatListViewController.m
  22. 25 2
      KulexiuForStudent/KulexiuForStudent/Module/Classroom/Controller/NewClassRoomViewController.m
  23. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Classroom/View/TitleView/ClassTitleView.m
  24. 38 2
      KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.m
  25. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/View/AccompanyRemarkCell.xib
  26. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.xib
  27. 249 96
      KulexiuForStudent/KulexiuForStudent/Module/Home/Controller/HomeViewController.m
  28. 33 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/Model/NoticeSourceModel.h
  29. 190 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/Model/NoticeSourceModel.m
  30. 29 23
      KulexiuForStudent/KulexiuForStudent/Module/Home/NoticeCenter/Controller/NotiferMessageViewController.m
  31. 5 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeHotAlbumCell.xib
  32. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeInformationCell.h
  33. 7 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeInformationCell.m
  34. 0 1
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeIntroduceView.m
  35. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeNavView.h
  36. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeNavView.m
  37. 19 6
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeNavView.xib
  38. 28 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/PublicNoticeView.h
  39. 47 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/PublicNoticeView.m
  40. 94 0
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/PublicNoticeView.xib
  41. 3 32
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/TeacherShowCell.m
  42. 5 9
      KulexiuForStudent/KulexiuForStudent/Module/Home/View/TeacherShowCell.xib
  43. 10 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.h
  44. 479 129
      KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.m
  45. 4 1
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSChatroomMessageCenter.h
  46. 5 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSChatroomMessageCenter.m
  47. 17 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCPauseLiveMessage.h
  48. 38 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCPauseLiveMessage.m
  49. 27 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCShopRushMessage.h
  50. 49 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCShopRushMessage.m
  51. 22 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomLikeCount.h
  52. 39 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomLikeCount.m
  53. 33 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomSeatsControl.h
  54. 50 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomSeatsControl.m
  55. 6 2
      KulexiuForStudent/KulexiuForStudent/Module/Live/Model/KSLiveStreamVideo.h
  56. 11 3
      KulexiuForStudent/KulexiuForStudent/Module/Live/Model/KSLiveStreamVideo.m
  57. 30 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/AnimationView/LiveAnimationView.h
  58. 147 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/AnimationView/LiveAnimationView.m
  59. 29 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveBadNetView.h
  60. 144 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveBadNetView.m
  61. 2 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEmptyView.h
  62. 24 1
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEmptyView.m
  63. 21 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEndView.h
  64. 98 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEndView.m
  65. 3 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomBottomView.h
  66. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Mine/Controller/MineViewController.m
  67. 10 0
      KulexiuForStudent/KulexiuForStudent/Module/Mine/Homework/Controller/HomeworkDetailViewController.m
  68. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Mine/MineCourse/View/MyLessonBodyView.m
  69. 6 0
      KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/Classroom/ClassroomService.m
  70. 17 5
      KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/Classroom/Message/MemberChangeMessage.m
  71. 3 0
      KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/Classroom/Model/Classroom.m
  72. 29 23
      KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/RTC/RTCService.m
  73. BIN
      KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_group_portrait@2x.png
  74. BIN
      KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_group_portrait@3x.png
  75. BIN
      KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait@2x.png
  76. BIN
      KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait@3x.png
  77. BIN
      KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait_msg@2x.png
  78. BIN
      KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait_msg@3x.png

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

@@ -358,6 +358,13 @@
 		BC0212FB27FC61D30040569F /* KSSegmentControl.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0212FA27FC61D30040569F /* KSSegmentControl.m */; };
 		BC0212FE27FC66AA0040569F /* InstrumentMessageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0212FD27FC66AA0040569F /* InstrumentMessageModel.m */; };
 		BC02130127FC6ADD0040569F /* UIView+SubViewExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02130027FC6ADD0040569F /* UIView+SubViewExtension.m */; };
+		BC02381428685064005560CA /* KSLiveEndView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02381028685063005560CA /* KSLiveEndView.m */; };
+		BC02381528685064005560CA /* KSLiveBadNetView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02381228685064005560CA /* KSLiveBadNetView.m */; };
+		BC02381928685087005560CA /* LiveAnimationView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02381728685087005560CA /* LiveAnimationView.m */; };
+		BC02381F28685D6D005560CA /* RCChatroomLikeCount.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02381E28685D6D005560CA /* RCChatroomLikeCount.m */; };
+		BC02382228685F4B005560CA /* KSRCPauseLiveMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02382028685F4B005560CA /* KSRCPauseLiveMessage.m */; };
+		BC02382528685F87005560CA /* KSRCShopRushMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02382428685F87005560CA /* KSRCShopRushMessage.m */; };
+		BC02382828685FC0005560CA /* RCChatroomSeatsControl.m in Sources */ = {isa = PBXBuildFile; fileRef = BC02382628685FC0005560CA /* RCChatroomSeatsControl.m */; };
 		BC0A2265284471300065C1AB /* KSLiveBlockUser.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0A2264284471300065C1AB /* KSLiveBlockUser.m */; };
 		BC0A2268284471460065C1AB /* KSLiveUnBlockUser.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0A2267284471460065C1AB /* KSLiveUnBlockUser.m */; };
 		BC0D1F6D281013DF00C5D9E5 /* MyVideoCourseBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0D1F6C281013DF00C5D9E5 /* MyVideoCourseBodyView.m */; };
@@ -690,6 +697,11 @@
 		BCBFDF4D28115C7A0052AFE5 /* HomeHotCourseView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCBFDF4C28115C7A0052AFE5 /* HomeHotCourseView.xib */; };
 		BCBFDF5028115D9A0052AFE5 /* HomeIntroduceView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCBFDF4F28115D9A0052AFE5 /* HomeIntroduceView.m */; };
 		BCBFDF5228115DA40052AFE5 /* HomeIntroduceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCBFDF5128115DA40052AFE5 /* HomeIntroduceView.xib */; };
+		BCD457A1286313D70010B493 /* NotiferNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD4579E286313D70010B493 /* NotiferNavView.m */; };
+		BCD457A2286313D70010B493 /* NotiferNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCD457A0286313D70010B493 /* NotiferNavView.xib */; };
+		BCD457AB286469600010B493 /* PublicNoticeView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD457A92864695F0010B493 /* PublicNoticeView.m */; };
+		BCD457AC286469600010B493 /* PublicNoticeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCD457AA286469600010B493 /* PublicNoticeView.xib */; };
+		BCD457AF28646B580010B493 /* NoticeSourceModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD457AE28646B580010B493 /* NoticeSourceModel.m */; };
 		BCEBB8E82840B87100A76BE8 /* KSLiveChatroomMemberUp.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEBB8E72840B87100A76BE8 /* KSLiveChatroomMemberUp.m */; };
 		BCED5CA7284F55A0009A42DE /* FriendListModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BCED5CA6284F55A0009A42DE /* FriendListModel.m */; };
 		BCFE53E72812765600AD6786 /* HomeHotAlbumCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFE53E52812765600AD6786 /* HomeHotAlbumCell.m */; };
@@ -1392,6 +1404,20 @@
 		BC0212FD27FC66AA0040569F /* InstrumentMessageModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstrumentMessageModel.m; sourceTree = "<group>"; };
 		BC0212FF27FC6ADD0040569F /* UIView+SubViewExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+SubViewExtension.h"; sourceTree = "<group>"; };
 		BC02130027FC6ADD0040569F /* UIView+SubViewExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+SubViewExtension.m"; sourceTree = "<group>"; };
+		BC02381028685063005560CA /* KSLiveEndView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSLiveEndView.m; sourceTree = "<group>"; };
+		BC02381128685063005560CA /* KSLiveEndView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSLiveEndView.h; sourceTree = "<group>"; };
+		BC02381228685064005560CA /* KSLiveBadNetView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSLiveBadNetView.m; sourceTree = "<group>"; };
+		BC02381328685064005560CA /* KSLiveBadNetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSLiveBadNetView.h; sourceTree = "<group>"; };
+		BC02381728685087005560CA /* LiveAnimationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveAnimationView.m; sourceTree = "<group>"; };
+		BC02381828685087005560CA /* LiveAnimationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveAnimationView.h; sourceTree = "<group>"; };
+		BC02381D28685D6D005560CA /* RCChatroomLikeCount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCChatroomLikeCount.h; sourceTree = "<group>"; };
+		BC02381E28685D6D005560CA /* RCChatroomLikeCount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCChatroomLikeCount.m; sourceTree = "<group>"; };
+		BC02382028685F4B005560CA /* KSRCPauseLiveMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSRCPauseLiveMessage.m; sourceTree = "<group>"; };
+		BC02382128685F4B005560CA /* KSRCPauseLiveMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSRCPauseLiveMessage.h; sourceTree = "<group>"; };
+		BC02382328685F87005560CA /* KSRCShopRushMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSRCShopRushMessage.h; sourceTree = "<group>"; };
+		BC02382428685F87005560CA /* KSRCShopRushMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSRCShopRushMessage.m; sourceTree = "<group>"; };
+		BC02382628685FC0005560CA /* RCChatroomSeatsControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCChatroomSeatsControl.m; sourceTree = "<group>"; };
+		BC02382728685FC0005560CA /* RCChatroomSeatsControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCChatroomSeatsControl.h; sourceTree = "<group>"; };
 		BC0A2263284471300065C1AB /* KSLiveBlockUser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KSLiveBlockUser.h; sourceTree = "<group>"; };
 		BC0A2264284471300065C1AB /* KSLiveBlockUser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KSLiveBlockUser.m; sourceTree = "<group>"; };
 		BC0A2266284471460065C1AB /* KSLiveUnBlockUser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KSLiveUnBlockUser.h; sourceTree = "<group>"; };
@@ -1969,6 +1995,14 @@
 		BCBFDF4E28115D9A0052AFE5 /* HomeIntroduceView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeIntroduceView.h; sourceTree = "<group>"; };
 		BCBFDF4F28115D9A0052AFE5 /* HomeIntroduceView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeIntroduceView.m; sourceTree = "<group>"; };
 		BCBFDF5128115DA40052AFE5 /* HomeIntroduceView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeIntroduceView.xib; sourceTree = "<group>"; };
+		BCD4579E286313D70010B493 /* NotiferNavView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotiferNavView.m; sourceTree = "<group>"; };
+		BCD4579F286313D70010B493 /* NotiferNavView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotiferNavView.h; sourceTree = "<group>"; };
+		BCD457A0286313D70010B493 /* NotiferNavView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NotiferNavView.xib; sourceTree = "<group>"; };
+		BCD457A82864695F0010B493 /* PublicNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublicNoticeView.h; sourceTree = "<group>"; };
+		BCD457A92864695F0010B493 /* PublicNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PublicNoticeView.m; sourceTree = "<group>"; };
+		BCD457AA286469600010B493 /* PublicNoticeView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PublicNoticeView.xib; sourceTree = "<group>"; };
+		BCD457AD28646B580010B493 /* NoticeSourceModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoticeSourceModel.h; sourceTree = "<group>"; };
+		BCD457AE28646B580010B493 /* NoticeSourceModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoticeSourceModel.m; sourceTree = "<group>"; };
 		BCEBB8E62840B87100A76BE8 /* KSLiveChatroomMemberUp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KSLiveChatroomMemberUp.h; sourceTree = "<group>"; };
 		BCEBB8E72840B87100A76BE8 /* KSLiveChatroomMemberUp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KSLiveChatroomMemberUp.m; sourceTree = "<group>"; };
 		BCED5CA5284F55A0009A42DE /* FriendListModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FriendListModel.h; sourceTree = "<group>"; };
@@ -2337,6 +2371,8 @@
 		275FA1F527E7356A00CFEA2E /* Model */ = {
 			isa = PBXGroup;
 			children = (
+				BCD457AD28646B580010B493 /* NoticeSourceModel.h */,
+				BCD457AE28646B580010B493 /* NoticeSourceModel.m */,
 				BCA193B6282B6094004A585D /* RecentCourseModel.h */,
 				BCA193B7282B6094004A585D /* RecentCourseModel.m */,
 				BC40BA19281251EC00DEC0D1 /* HomeMessageModel.h */,
@@ -2410,6 +2446,9 @@
 				BCFE53F328128A9600AD6786 /* TeacherShowCell.h */,
 				BCFE53F428128A9600AD6786 /* TeacherShowCell.m */,
 				BCFE53F528128A9600AD6786 /* TeacherShowCell.xib */,
+				BCD457A82864695F0010B493 /* PublicNoticeView.h */,
+				BCD457A92864695F0010B493 /* PublicNoticeView.m */,
+				BCD457AA286469600010B493 /* PublicNoticeView.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -3602,6 +3641,15 @@
 			name = Frameworks;
 			sourceTree = "<group>";
 		};
+		BC02381628685087005560CA /* AnimationView */ = {
+			isa = PBXGroup;
+			children = (
+				BC02381728685087005560CA /* LiveAnimationView.m */,
+				BC02381828685087005560CA /* LiveAnimationView.h */,
+			);
+			path = AnimationView;
+			sourceTree = "<group>";
+		};
 		BC1191F9280ED63C00A716F7 /* MineCourse */ = {
 			isa = PBXGroup;
 			children = (
@@ -3818,6 +3866,9 @@
 				BC7663112827E49800C91A1D /* NotiferMessageCell.h */,
 				BC7663122827E49800C91A1D /* NotiferMessageCell.m */,
 				BC7663132827E49900C91A1D /* NotiferMessageCell.xib */,
+				BCD4579F286313D70010B493 /* NotiferNavView.h */,
+				BCD4579E286313D70010B493 /* NotiferNavView.m */,
+				BCD457A0286313D70010B493 /* NotiferNavView.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -4247,6 +4298,14 @@
 		BCB6340B27F6D29500ACFDCF /* LiveRoomMessage */ = {
 			isa = PBXGroup;
 			children = (
+				BC02382728685FC0005560CA /* RCChatroomSeatsControl.h */,
+				BC02382628685FC0005560CA /* RCChatroomSeatsControl.m */,
+				BC02382128685F4B005560CA /* KSRCPauseLiveMessage.h */,
+				BC02382028685F4B005560CA /* KSRCPauseLiveMessage.m */,
+				BC02382328685F87005560CA /* KSRCShopRushMessage.h */,
+				BC02382428685F87005560CA /* KSRCShopRushMessage.m */,
+				BC02381D28685D6D005560CA /* RCChatroomLikeCount.h */,
+				BC02381E28685D6D005560CA /* RCChatroomLikeCount.m */,
 				BCB6342527F6D29500ACFDCF /* KSChatroomMessageCenter.h */,
 				BCB6341527F6D29500ACFDCF /* KSChatroomMessageCenter.m */,
 				BCB6341827F6D29500ACFDCF /* KSLiveChatroomClose.h */,
@@ -4313,11 +4372,16 @@
 		BCB6343627F6D29500ACFDCF /* View */ = {
 			isa = PBXGroup;
 			children = (
+				BC02381628685087005560CA /* AnimationView */,
 				BCB9090E2852EF0000F5FF69 /* DragWindow */,
 				BCB635A827F6D93300ACFDCF /* KSChatVideoView.h */,
 				BCB635A727F6D93300ACFDCF /* KSChatVideoView.m */,
 				BCB635A527F6D90600ACFDCF /* KSLiveEmptyView.h */,
 				BCB635A427F6D90600ACFDCF /* KSLiveEmptyView.m */,
+				BC02381328685064005560CA /* KSLiveBadNetView.h */,
+				BC02381228685064005560CA /* KSLiveBadNetView.m */,
+				BC02381128685063005560CA /* KSLiveEndView.h */,
+				BC02381028685063005560CA /* KSLiveEndView.m */,
 				BCB6343727F6D29500ACFDCF /* InputBar */,
 				BCB6344D27F6D29500ACFDCF /* KSChatroomTextCell.h */,
 				BCB6345927F6D29600ACFDCF /* KSChatroomTextCell.m */,
@@ -4987,6 +5051,7 @@
 				BC5367C9283F6D72008428E8 /* HomeVideoCourseView.xib in Resources */,
 				2723B66127F15CFB00E0B90B /* SettingBodyView.xib in Resources */,
 				BC11928C280FB44300A716F7 /* HomeworkVideoView.xib in Resources */,
+				BCD457A2286313D70010B493 /* NotiferNavView.xib in Resources */,
 				275E8AB527E18F8B00DD3F6E /* Assets.xcassets in Resources */,
 				BC119275280FB01100A716F7 /* AccompanyHomeworkCell.xib in Resources */,
 				BC119280280FB10900A716F7 /* AccompanyRemarkCell.xib in Resources */,
@@ -5057,6 +5122,7 @@
 				275FA23827E7356B00CFEA2E /* FirstSettingBodyView.xib in Resources */,
 				BC542E622840A60E00633781 /* UseBodyView.xib in Resources */,
 				BC8B6E042856E06700866917 /* UMSocialSDKResources.bundle in Resources */,
+				BCD457AC286469600010B493 /* PublicNoticeView.xib in Resources */,
 				BC27A070280FF56C00F91E27 /* AccompanyStudentEvaCell.xib in Resources */,
 				2723B63927F157D500E0B90B /* GroupMemberListCell.xib in Resources */,
 				BC8A45A0283DC33400094BBB /* JudgePageView.xib in Resources */,
@@ -5297,6 +5363,7 @@
 				2779357227E324A70010E277 /* SearchView.m in Sources */,
 				BC8A459C283DC33400094BBB /* KSXMLInfoParse.m in Sources */,
 				2723B64927F15BDC00E0B90B /* KSJXBodyView.m in Sources */,
+				BC02382228685F4B005560CA /* KSRCPauseLiveMessage.m in Sources */,
 				BCB6354E27F6D2A300ACFDCF /* KSWhiteboardView.m in Sources */,
 				2779356527E324A70010E277 /* KSMediaManager.m in Sources */,
 				2779355C27E324A70010E277 /* KSChoosePicker.m in Sources */,
@@ -5325,6 +5392,7 @@
 				2779358A27E324A80010E277 /* ArchiveTools.m in Sources */,
 				BC0A2268284471460065C1AB /* KSLiveUnBlockUser.m in Sources */,
 				BCB908F12850B08D00F5FF69 /* KSChatMusicShareCell.m in Sources */,
+				BC02381928685087005560CA /* LiveAnimationView.m in Sources */,
 				BC8A45AA283DC33400094BBB /* TrackChooseView.m in Sources */,
 				BC8A45B2283DC33400094BBB /* CloudFeedbackView.m in Sources */,
 				BCB6355A27F6D2A300ACFDCF /* KSRemoteUserManager.m in Sources */,
@@ -5347,6 +5415,7 @@
 				275FA22C27E7356B00CFEA2E /* CourseViewController.m in Sources */,
 				2779358D27E324A80010E277 /* DZNSegmentedControl.m in Sources */,
 				2779352027E324A60010E277 /* CALayer+Color.m in Sources */,
+				BCD457A1286313D70010B493 /* NotiferNavView.m in Sources */,
 				2723B62C27F157D500E0B90B /* ApplyBottomView.m in Sources */,
 				BC8A4595283DC33400094BBB /* GCDTimer.m in Sources */,
 				BCB6356127F6D2A300ACFDCF /* SongDownloadCallbackMessage.m in Sources */,
@@ -5365,6 +5434,7 @@
 				2779359427E324A80010E277 /* TZAssetCell.m in Sources */,
 				BCB635B227F6E1A600ACFDCF /* LiveRoomBottomView.m in Sources */,
 				2723B5CE27F157BE00E0B90B /* KSRCloudMediaManager.m in Sources */,
+				BC02381428685064005560CA /* KSLiveEndView.m in Sources */,
 				2779357027E324A70010E277 /* UITextView_Toolbar.m in Sources */,
 				BCB6356427F6D2A300ACFDCF /* InviteUpgradeMessage.m in Sources */,
 				2779355327E324A70010E277 /* VoNetworking+RequestManager.m in Sources */,
@@ -5442,6 +5512,7 @@
 				2779353A27E324A60010E277 /* UILabel+QWTopLeftLabel.m in Sources */,
 				BC542E5D2840A60100633781 /* UserSettingViewController.m in Sources */,
 				BC119213280ED6A900A716F7 /* MyLessonBodyView.m in Sources */,
+				BC02381F28685D6D005560CA /* RCChatroomLikeCount.m in Sources */,
 				BC8A45A3283DC33400094BBB /* JudgePageView.m in Sources */,
 				BCB6354227F6D2A300ACFDCF /* VideoListView.m in Sources */,
 				2779359A27E324A80010E277 /* TZPhotoPreviewController.m in Sources */,
@@ -5513,6 +5584,7 @@
 				BCED5CA7284F55A0009A42DE /* FriendListModel.m in Sources */,
 				2779356027E324A70010E277 /* KSRecordStatusView.m in Sources */,
 				2723B62B27F157D500E0B90B /* ApplyMemberModel.m in Sources */,
+				BCD457AB286469600010B493 /* PublicNoticeView.m in Sources */,
 				BC40B9FE281177BD00DEC0D1 /* HomeInformationCell.m in Sources */,
 				2779354D27E324A70010E277 /* KSGifRefreshFooter.m in Sources */,
 				BC119288280FB3B100A716F7 /* KSStarView.m in Sources */,
@@ -5609,6 +5681,7 @@
 				2723B63827F157D500E0B90B /* GroupApplyChooseCell.m in Sources */,
 				BC8B6DC62856CAF600866917 /* KSDocumentViewController.m in Sources */,
 				2723B66827F15CFC00E0B90B /* FeedbackBodyView.m in Sources */,
+				BC02382828685FC0005560CA /* RCChatroomSeatsControl.m in Sources */,
 				2779354927E324A60010E277 /* MBProgressHUD+KSShow.m in Sources */,
 				BCB6346327F6D29600ACFDCF /* KSRCMessageModel.m in Sources */,
 				BCB6359B27F6D2AB00ACFDCF /* KSBeatView.m in Sources */,
@@ -5631,6 +5704,7 @@
 				2779352A27E324A60010E277 /* UIView+Dealloc.m in Sources */,
 				2779352D27E324A60010E277 /* NSString+CZHSizeExtension.m in Sources */,
 				BC8C2C7E28265D8E00FBA5D5 /* KSNewsAlert.m in Sources */,
+				BC02382528685F87005560CA /* KSRCShopRushMessage.m in Sources */,
 				BC119259280FA85300A716F7 /* HomeworkListCell.m in Sources */,
 				2779353827E324A60010E277 /* UIView+KSExtension.m in Sources */,
 				2723B5CD27F157BE00E0B90B /* GroupListModel.m in Sources */,
@@ -5646,6 +5720,7 @@
 				2779359D27E324A80010E277 /* TZImageManager.m in Sources */,
 				BCA353F22859BB2900377661 /* MusicRoomCourseCell.m in Sources */,
 				2723B5BE27F157B100E0B90B /* ChatNavView.m in Sources */,
+				BC02381528685064005560CA /* KSLiveBadNetView.m in Sources */,
 				BC119218280ED6A900A716F7 /* MyLessonSearchView.m in Sources */,
 				BCB6354C27F6D2A300ACFDCF /* VideoMaskView.m in Sources */,
 				2723B66D27F15CFC00E0B90B /* ModifyNameBodyView.m in Sources */,
@@ -5721,6 +5796,7 @@
 				2779358327E324A80010E277 /* LLPhotoBrowser.m in Sources */,
 				BCB6353B27F6D2A300ACFDCF /* MessageDataSource.m in Sources */,
 				275FA23027E7356B00CFEA2E /* PasswordLoginController.m in Sources */,
+				BCD457AF28646B580010B493 /* NoticeSourceModel.m in Sources */,
 				2779351327E324A50010E277 /* NSDictionary+KSSafe.m in Sources */,
 				BCB6355427F6D2A300ACFDCF /* UIView+MBProgressHUD.m in Sources */,
 				2779352B27E324A60010E277 /* NSObject+Parse.m in Sources */,

+ 18 - 0
KulexiuForStudent/KulexiuForStudent.xcodeproj/xcuserdata/wangzhi.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -10,5 +10,23 @@
 			<integer>31</integer>
 		</dict>
 	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>275E8AA427E18F8800DD3F6E</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>275E8ABF27E18F8C00DD3F6E</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>275E8AC927E18F8C00DD3F6E</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
 </dict>
 </plist>

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


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

@@ -3,4 +3,38 @@
    uuid = "C42D83E3-CB7A-44AF-B9C2-6DDDEC116980"
    type = "0"
    version = "2.0">
+   <Breakpoints>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "822F0FEC-1359-41D0-B1A2-66E94C0891D0"
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "KulexiuForStudent/Common/Base/KSNetworkingManager.m"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "784"
+            endingLineNumber = "784"
+            landmarkName = "+queryGroupDetail:groupId:success:faliure:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "1810CE7E-B98C-4855-A767-4FD2705B3141"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "KulexiuForStudent/Common/Tools/Extension/NSDictionary+Extension.m"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "99"
+            endingLineNumber = "99"
+            landmarkName = "-notNullValueForKey:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+   </Breakpoints>
 </Bucket>

+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_icon.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_icon.imageset/notice_icon@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_icon.imageset/notice_icon@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_more.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_more.imageset/notice_more@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/notice_more.imageset/notice_more@3x.png


+ 5 - 5
KulexiuForStudent/KulexiuForStudent/Common/Base/KSBaseViewController.m

@@ -411,12 +411,12 @@
 
 // 关闭菊花
 -(void)removehub{
-    dispatch_main_async_safe(^{
+//    dispatch_main_async_safe(^{
+//        [self removeLoadingView];
+//    })
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
         [self removeLoadingView];
-    })
-//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-//        
-//    });
+    });
 }
 
 -(void)removeLoadingView {

+ 2 - 11
KulexiuForStudent/KulexiuForStudent/Common/Base/KSBaseWKWebViewController.m

@@ -291,15 +291,6 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
         // 回到登录页面
         [self backLoginView];
     }
-    // chat
-    else if ([[parm stringValueForKey:@"api"] isEqualToString:@"openConversationActivity"]) {
-        NSDictionary *valueDic = [parm dictionaryValueForKey:@"content"];
-        NSString *name = [valueDic stringValueForKey:@"name"];
-        NSString *userId = [NSString stringWithFormat:@"%.0f",[valueDic floatValueForKey:@"userId"]];
-        KSChatConversationViewController *conversationVC = [[KSChatConversationViewController alloc] initWithConversationType:ConversationType_PRIVATE targetId:[NSString returnNoNullStringWithString:userId]];
-        conversationVC.title = [NSString returnNoNullStringWithString:name];
-        [self.navigationController pushViewController:conversationVC animated:YES];
-    }
     else if ([[parm stringValueForKey:@"api"] isEqualToString:@"openWebView"]) { // 打开新页面
         NSDictionary *valueDic = [parm dictionaryValueForKey:@"content"];
         
@@ -450,7 +441,7 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
     else if ([[parm stringValueForKey:@"api"] isEqualToString:@"joinChatGroup"]) {
         NSDictionary *valueDic = [parm dictionaryValueForKey:@"content"];
         NSString *targetId = [valueDic stringValueForKey:@"id"];
-        if ([valueDic stringValueForKey:@"single"]) { // 单聊
+        if ([[valueDic stringValueForKey:@"type"] isEqualToString:@"single"]) { // 单聊
             
             KSChatConversationViewController *ctrl = [[KSChatConversationViewController alloc] init];
             ctrl.targetId = targetId;
@@ -458,7 +449,7 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
             [self.navigationController pushViewController:ctrl animated:YES];
             
         }
-        else if ([valueDic stringValueForKey:@"multi"]) { // 群聊
+        else if ([[valueDic stringValueForKey:@"type"] isEqualToString:@"multi"]) { // 群聊
             KSChatConversationViewController *ctrl = [[KSChatConversationViewController alloc] init];
             ctrl.targetId = targetId;
             ctrl.conversationType = ConversationType_GROUP;

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

@@ -213,6 +213,16 @@ NS_ASSUME_NONNULL_BEGIN
  @param faliure 失败
  */
 + (void)verifyLoginImageRequest:(NSString *)post phone:(NSString *)phone code:(NSString *)code success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+// 首页公告查询
+//  /api-cms/helpCenterContent/list
+
+/// 公告查询
+/// @param post post
+/// @param success 成功
+/// @param faliure 失败
++ (void)helpCenterContentListRequest:(NSString *)post success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 #pragma mark ----- 查询用户信息
 // /api-auth/queryUserInfo
 

+ 24 - 6
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m

@@ -68,15 +68,15 @@
  */
 + (void)request:(NSString *)post andWithUrl:(NSString *)myUrl and:(id)parm success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     __block NSDictionary *dic;
-    NSLog(@"----url ------%@",myUrl);
+//    NSLog(@"----url ------%@",myUrl);
 #pragma mark  ----- 签名
 //    parm = [NSString signToMD5:parm];
-    NSLog(@"%@",[parm mj_JSONString]);
+//    NSLog(@"%@",[parm mj_JSONString]);
     // post
     if ([post isEqualToString:KS_POST]) {
         [[VoNetworking sharedManager] postWithUrl:myUrl refreshRequest:YES cache:NO params:parm progressBlock:^(int64_t bytesRead, int64_t totalBytes) {
             
-            NSLog(@"%lld--%lld",bytesRead,totalBytes);
+//            NSLog(@"%lld--%lld",bytesRead,totalBytes);
             
         } successBlock:^(id response) {
             
@@ -109,7 +109,7 @@
     else {
         [[VoNetworking sharedManager] getWithUrl:myUrl refreshRequest:YES cache:NO params:parm progressBlock:^(int64_t bytesRead, int64_t totalBytes) {
             
-            NSLog(@"%lld--%lld",bytesRead,totalBytes);
+//            NSLog(@"%lld--%lld",bytesRead,totalBytes);
             
         } successBlock:^(id response) {
             
@@ -127,7 +127,7 @@
             return ;
             
         } failBlock:^(NSError *error) {
-            NSLog(@"%@",error.description);
+//            NSLog(@"%@",error.description);
             faliure(error);
             if (error.code == -1001) {
                 [self showMessage:@"网络请求超时"];
@@ -654,6 +654,24 @@
     [self request:post andWithUrl:url and:parm success:success faliure:faliure];
 }
 
+// 首页公告查询
+//  /api-cms/helpCenterContent/list
+
+/// 公告查询
+/// @param post post
+/// @param success 成功
+/// @param faliure 失败
++ (void)helpCenterContentListRequest:(NSString *)post success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-cms/helpCenterContent/list"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:@"2" forKey:@"catalogIds"];
+    [parm setValue:@"STUDENT" forKey:@"catalogType"];
+    [parm setValue:@(1) forKey:@"page"];
+    [parm setValue:@(5) forKey:@"rows"];
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
+
 #pragma mark ----- 查询用户信息
 // /api-auth/queryUserInfo
 
@@ -892,7 +910,7 @@
 /// @param faliure 失败
 + (void)LiveroomQuit:(NSString *)post success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
-    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/liveRoom/syncUserStatus"];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-student/liveRoom/syncUserStatus"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:@"iOS" forKey:@"os"];
     [parm setValue:@"3" forKey:@"status"];

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

@@ -119,7 +119,8 @@ shouldPrevent = NO; \
 #define SEALCLASSHOST (@"https://dev.colexiu.com/api-classroom")
 #define WEBHOST (@"https://dev.colexiu.com/student")
 //#define WEBHOST (@"http://192.168.3.120:5000")
-#define SOCKET_URL (@"wss://dev.colexiu.com/audioAnalysis")
+//#define SOCKET_URL (@"wss://dev.colexiu.com/audioAnalysis")
+#define SOCKET_URL (@"ws://192.168.3.26:8090/audioAnalysis")
 #define JSPUSH_ENVIRONMENT (NO)
 #define RCIM_KEY (@"0vnjpoad0jbdz")
 #define SUBMIT_UUID (NO)

+ 8 - 0
KulexiuForStudent/KulexiuForStudent/Common/Tools/Extension/NSDictionary+Extension.h

@@ -27,6 +27,14 @@
 - (int)intValueForKey:(id)key;
 
 /**
+ 从字典里取int(内带判空)
+ 
+ @param key 字典Key值
+ @return long
+ */
+- (long)longValueForKey:(id)key;
+
+/**
  从字典里取long long(内带判空)
  
  @param key 字典Key值

+ 10 - 0
KulexiuForStudent/KulexiuForStudent/Common/Tools/Extension/NSDictionary+Extension.m

@@ -20,6 +20,16 @@
     return value == nil ? 0 : [value intValue];
 }
 
+/**
+ 从字典里取int(内带判空)
+ 
+ @param key 字典Key值
+ @return long
+ */
+- (long)longValueForKey:(id)key {
+    id value = [self notNullValueForKey:key];
+    return value == nil ? 0 : [value longLongValue];
+}
 
 - (long long)longlongValueForKey:(id)key {
     id value = [self notNullValueForKey:key];

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Common/Tools/KSVideoHelper.h

@@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (void)getVideoPreviewImageUrl:(NSString *)videoUrl forImageView:(UIImageView *)imageView placeholder:(UIImage *)placeHolder;
 
-+ (NSInteger)getVideoDuration:(NSString *)videoUrl;
++ (void)getVideoDuration:(NSString *)videoUrl displayInLabel:(UILabel *)displayLabel;
 
 @end
 

+ 31 - 5
KulexiuForStudent/KulexiuForStudent/Common/Tools/KSVideoHelper.m

@@ -62,11 +62,37 @@
     });
 }
 
-+ (NSInteger)getVideoDuration:(NSString *)videoUrl {
-    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL URLWithString:videoUrl] options:nil];
-    float second = asset.duration.value / asset.duration.timescale;
-    NSString *duration = [NSString stringWithFormat:@"%.0f",second];
-    return [duration integerValue];
++ (void)getVideoDuration:(NSString *)videoUrl displayInLabel:(UILabel *)displayLabel {
+    dispatch_async(dispatch_get_global_queue(0, 0), ^{
+        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL URLWithString:videoUrl] options:nil];
+        float second = asset.duration.value / asset.duration.timescale;
+        NSString *durationString = [NSString stringWithFormat:@"%.0f",second];
+        NSInteger duration = [durationString integerValue];
+        NSString *timeDesc = @"00:00";
+        if (duration / 60 > 0) {
+            NSInteger secondTime = duration % 60;
+            NSString *secondStr = @"";
+            if (secondTime < 10) {
+                secondStr = [NSString stringWithFormat:@"0%zd",secondTime];
+            } else {
+                secondStr = [NSString stringWithFormat:@"%zd",secondTime];
+            }
+            timeDesc = [NSString stringWithFormat:@"%2ld:%@", duration / 60, secondStr];
+        }
+        else {
+            NSInteger secondTime = duration % 60;
+            NSString *secondStr = @"";
+            if (secondTime < 10) {
+                secondStr = [NSString stringWithFormat:@"0%zd",secondTime];
+            } else {
+                secondStr = [NSString stringWithFormat:@"%zd",secondTime];
+            }
+            timeDesc = [NSString stringWithFormat:@"00:%@", secondStr];
+        }
+        dispatch_async(dispatch_get_main_queue(), ^{
+            displayLabel.text = timeDesc;
+        });
+    });
 }
 
 @end

+ 5 - 3
KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/KSChatConversationViewController.m

@@ -406,9 +406,11 @@
 }
 
 - (void)willDisplayMessageCell:(RCMessageBaseCell *)cell atIndexPath:(NSIndexPath *)indexPath {
-    UIImageView *imageView = (UIImageView *)((RCMessageCell *)cell).portraitImageView;
-    imageView.contentMode = UIViewContentModeScaleAspectFill;
-    imageView.layer.masksToBounds = YES;
+    if ([cell isKindOfClass:[RCMessageCell class]]) {
+        UIImageView *imageView = (UIImageView *)((RCMessageCell *)cell).portraitImageView;
+        imageView.contentMode = UIViewContentModeScaleAspectFill;
+        imageView.layer.masksToBounds = YES;
+    }
 }
 
 

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/KSChatListViewController.m

@@ -185,14 +185,14 @@
     if (model.conversationType == ConversationType_GROUP) {
         if ([model.targetId containsString:@"FAN"]) { // 粉丝群
             [imageView setImage:[UIImage imageNamed:@"chat_fansGroup_logo"]];
-            UIImageView *tagImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"groupType_fans"]];
+            UIImageView *tagImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"group_fans"]];
             [tagView removeAllSubViews];
             [tagView addSubview:tagImage];
             tagImage.frame = CGRectMake(0, 2, 45, 17);
         }
         else if ([model.targetId containsString:@"COURSE"]) { // 课程群
             [imageView setImage:[UIImage imageNamed:@"chat_group_Logo"]];
-            UIImageView *tagImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"groupType_course"]];
+            UIImageView *tagImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"group_course"]];
             [tagView removeAllSubViews];
             [tagView addSubview:tagImage];
             tagImage.frame = CGRectMake(0, 2, 45, 17);

+ 25 - 2
KulexiuForStudent/KulexiuForStudent/Module/Classroom/Controller/NewClassRoomViewController.m

@@ -274,6 +274,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
         case ClassTitleViewActionTagMicrophone:
         {
             if (button.selected == NO) {
+                if (self.alertView && self.alertView.isShow) {
+                    [self.alertView dismissAlertView];
+                }
                 self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"确认关闭麦克风吗?" leftTitle:@"取消" rightTitle:@"确认" cancel:^{
                 } confirm:^{
                     button.selected = YES;
@@ -290,6 +293,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
         case ClassTitleViewActionTagCamera:
         {
             if (button.selected == NO) {
+                if (self.alertView && self.alertView.isShow) {
+                    [self.alertView dismissAlertView];
+                }
                 self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"确认关闭摄像头吗?" leftTitle:@"取消" rightTitle:@"确认" cancel:^{
                 } confirm:^{
                     button.selected = YES;
@@ -305,6 +311,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
         case ClassTitleViewActionTagSwitchLine:  // 切换线路
         {
             MJWeakSelf;
+            if (self.alertView && self.alertView.isShow) {
+                [self.alertView dismissAlertView];
+            }
             self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"确认切换线路吗?" leftTitle:@"取消" rightTitle:@"确认" cancel:^{
             } confirm:^{
                 [weakSelf restartRoom];
@@ -326,6 +335,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
         case ClassTitleViewActionTagHangup:
         {
             MJWeakSelf;
+            if (self.alertView && self.alertView.isShow) {
+                [self.alertView dismissAlertView];
+            }
             self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"确认退出课堂吗?" leftTitle:@"取消" rightTitle:@"确认" cancel:^{
             } confirm:^{
                 weakSelf.isQuitRoom = YES;
@@ -704,6 +716,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
 - (void)deviceDidInviteEnable:(DeviceType)type ticket:(NSString *)ticket {
     NSLog(@"deviceDidInviteEnable devicetype:%@",@(type));
     if (type == DeviceTypeCamera) {
+        if (self.alertView && self.alertView.isShow) {
+            [self.alertView dismissAlertView];
+        }
         self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"老师邀请你打开摄像头" leftTitle:@"拒绝" rightTitle:@"同意" cancel:^{
             [[ClassroomService sharedService] rejectEnableDevice:type];
         } confirm:^{
@@ -960,6 +975,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
             if ([displayMember.userId isEqualToString:[ClassroomService sharedService].currentRoom.currentDisplayURI]) {
                 if ([displayMember.userId isEqualToString:[ClassroomService sharedService].currentRoom.currentMember.userId]) {
                     self.titleView.onShowLabel.hidden = NO;
+                    // 重置举手状态
+                    [ClassroomService sharedService].currentRoom.currentMember.handUpOn = NO;
+                    [self.containerView refreshToolView];
                 }
                 [self.wBoardCtrl hideBoard];
                 [self.containerView containerViewRenderView:displayMember];
@@ -1016,7 +1034,7 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
 - (void)studentDidDisplay:(NSString *)studentId {
     NSLog(@"studentDidDisplay %@", studentId);
     [self renderMainContainerView];
-    
+
 }
 - (void)teacherDidDisplay {
     NSLog(@"teacherDidDisplay %@ ",[ClassroomService sharedService].currentRoom.teacher);
@@ -1501,7 +1519,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
 - (void)mainContainerOpertionMember:(RoomMember *)member tapButton:(UIButton *)button {
     // 🙋操作
     if (button.selected) { // 取消举手
-        
+        if (self.alertView && self.alertView.isShow) {
+            [self.alertView dismissAlertView];
+        }
         self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"确认取消举手吗?" leftTitle:@"取消" rightTitle:@"确认" cancel:^{
             
         } confirm:^{
@@ -1509,6 +1529,9 @@ typedef NS_ENUM(NSInteger, ACCOMPANYACTION) {
         }];
     }
     else {
+        if (self.alertView && self.alertView.isShow) {
+            [self.alertView dismissAlertView];
+        }
         self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"确认举手吗?" leftTitle:@"取消" rightTitle:@"确认" cancel:^{
             
         } confirm:^{

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Classroom/View/TitleView/ClassTitleView.m

@@ -51,7 +51,7 @@
     NSDictionary *dic = notification.object;
     RCMessage *message = dic[@"message"];
     Classroom *currentRoom = [ClassroomService sharedService].currentRoom;
-    if ([message.targetId isEqualToString:currentRoom.roomId]) {
+    if ([message.targetId isEqualToString:currentRoom.roomId] && [message.content isKindOfClass:[RCTextMessage class]]) {
         dispatch_main_async_safe(^{
             [self updateClassNewsButton];
         });

+ 38 - 2
KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.m

@@ -50,6 +50,10 @@
 
 @property (nonatomic, strong) OnlineClassManager *classManager;
 
+@property (nonatomic, assign) BOOL canModify;
+
+@property (nonatomic, assign) BOOL isModify; // 是否修改作业
+
 @end
 
 @implementation AccompanyDetailViewController
@@ -60,6 +64,7 @@
     [self allocTitle:@"课程详情"];
     [self configUI];
     [self requestCourseInfoMessage];
+    self.isModify = NO;
 }
 
 - (void)requestCourseInfoMessage {
@@ -103,11 +108,30 @@
         else {
             [self MBPShow:MESSAGEKEY];
         }
+        [self evaluateViewDisplay];
         [self.tableView reloadData];
     } faliure:^(NSError * _Nonnull error) {
         
     }];
 }
+
+- (void)evaluateViewDisplay {
+    // 老师布置过作业且没有点评 可以点击
+    if (self.homeworkModel.reviewHomework == 1 || self.homeworkModel.decorateHomework == 0) {
+        self.canModify = NO;
+        self.bottomView.actionButton.userInteractionEnabled = NO;
+        self.bottomView.actionButton.backgroundColor = HexRGB(0xe5e5e5);
+        [self.bottomView.actionButton setTitleColor:HexRGB(0x666666) forState:UIControlStateNormal];
+    }
+    else {
+        self.canModify = YES;
+        self.bottomView.actionButton.userInteractionEnabled = YES;
+        self.bottomView.actionButton.backgroundColor = THEMECOLOR;
+        [self.bottomView.actionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
+    }
+}
+
+
 - (void)requestEvaluateMessage {
     [KSNetworkingManager selectRepliedRequest:KS_POST courseGroupId:self.courseGroupId courseScheduleId:self.courseId success:^(NSDictionary * _Nonnull dic) {
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
@@ -136,13 +160,15 @@
     if ([self.homeworkModel.courseStatus isEqualToString:@"COMPLETE"]) {
         statusLabel.text = @"已结束";
         statusLabel.textColor = HexRGB(0x999999);
-        // 学生未提交 或者 老师已点评作业 或者老师未布置作业
-        if (self.fileArray.count == 0 || self.homeworkModel.reviewHomework == 1 || self.homeworkModel.decorateHomework == 0) {
+        // 老师已点评作业 或者老师未布置作业
+        if (self.homeworkModel.reviewHomework == 1 || self.homeworkModel.decorateHomework == 0) {
+            self.bottomView.actionButton.userInteractionEnabled = NO;
             [self.bottomView.actionButton setTitle:@"确认提交" forState:UIControlStateNormal];
             [self.bottomView.actionButton setBackgroundColor:HexRGB(0xe5e5e5)];
             [self.bottomView.actionButton setTitleColor:HexRGB(0x666666) forState:UIControlStateNormal];
         }
         else {
+            self.bottomView.actionButton.userInteractionEnabled = YES;
             [self.bottomView.actionButton setTitle:@"确认提交" forState:UIControlStateNormal];
             [self.bottomView.actionButton setBackgroundColor:THEMECOLOR];
             [self.bottomView.actionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
@@ -151,6 +177,7 @@
     else if ([self.homeworkModel.courseStatus isEqualToString:@"ING"]) {
         statusLabel.text = @"进行中";
         statusLabel.textColor = THEMECOLOR;
+        self.bottomView.actionButton.userInteractionEnabled = YES;
         [self.bottomView.actionButton setTitle:@"进入教室" forState:UIControlStateNormal];
         [self.bottomView.actionButton setBackgroundColor:THEMECOLOR];
         [self.bottomView.actionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
@@ -158,6 +185,7 @@
     else {
         statusLabel.text = @"未开始";
         statusLabel.textColor = HexRGB(0xff802c);
+        self.bottomView.actionButton.userInteractionEnabled = YES;
         [self.bottomView.actionButton setTitle:@"进入教室" forState:UIControlStateNormal];
         [self.bottomView.actionButton setBackgroundColor:THEMECOLOR];
         [self.bottomView.actionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
@@ -205,6 +233,7 @@
         // studentAttachments
         BOOL canDisplay = self.homeworkModel.decorateHomework == 1 ? YES : NO;
         AccompanyHomeworkCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AccompanyHomeworkCell"];
+        cell.canSubmit = self.canModify;
         MJWeakSelf;
         [cell configWithAttachmentArray:self.fileArray canDisplaySubmitView:canDisplay callback:^(HOMEWORKACTION action, NSInteger viewIndex) {
             [weakSelf operationActionWithType:action index:viewIndex];
@@ -308,6 +337,7 @@
     } successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
         [self hudTipWillShow:NO];
         NSString *fileUrl = [fileUrlArray lastObject];
+        self.isModify = YES;
         // 删除文件
         [self removeVideoWithPath:videoUrl];
         [self.fileArray addObject:fileUrl];
@@ -340,6 +370,7 @@
         [self.fileArray removeObjectAtIndex:index];
         [self.tableView reloadData];
     }
+    self.isModify = YES;
 }
 
 #pragma mark ------ WMPlayer
@@ -411,6 +442,10 @@
 }
 
 - (void)submitHomeworkAction {
+    if (self.isModify == NO) {
+        [self MBPShow:@"请先选择视频文件"];
+        return;
+    }
     if (self.fileArray.count == 0) {
         [self MBPShow:@"请选择作业视频"];
         return;
@@ -422,6 +457,7 @@
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             [self MBPShow:@"作业提交成功"];
             [self requestCourseInfoMessage];
+            self.isModify = NO;
         }
         else {
             [self MBPShow:MESSAGEKEY];

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/View/AccompanyRemarkCell.xib

@@ -55,11 +55,11 @@
                                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" usesAttributedText="YES" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="M7Y-he-HQe">
                                                 <rect key="frame" x="120" y="62.5" width="157" height="34.5"/>
                                                 <attributedString key="attributedText">
-                                                    <fragment content="课程结束后上传作业视频会得老师点评喔~">
+                                                    <fragment content="课程结束后上传作业视频会得老师点评喔~">
                                                         <attributes>
                                                             <color key="NSColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
                                                             <font key="NSFont" size="13" name="STSongti-SC-Regular"/>
-                                                            <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" lineSpacing="4" tighteningFactorForTruncation="0.0"/>
+                                                            <paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="wordWrapping" baseWritingDirection="natural" lineSpacing="4" tighteningFactorForTruncation="0.0"/>
                                                         </attributes>
                                                     </fragment>
                                                 </attributedString>

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Course/View/CourseForLiveCell.xib

@@ -124,7 +124,7 @@
                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MTB-cE-tDv">
                                 <rect key="frame" x="117" y="83" width="157" height="20"/>
                                 <subviews>
-                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nzy-gR-bLh">
+                                    <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nzy-gR-bLh">
                                         <rect key="frame" x="0.0" y="4.5" width="1" height="11"/>
                                         <color key="backgroundColor" red="0.82745098039999998" green="0.82745098039999998" blue="0.82745098039999998" alpha="1" colorSpace="calibratedRGB"/>
                                         <constraints>
@@ -132,7 +132,7 @@
                                             <constraint firstAttribute="height" constant="11" id="rQe-eX-5YW"/>
                                         </constraints>
                                     </view>
-                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="6人已购买" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="do8-lR-Cg5">
+                                    <label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="6人已购买" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="do8-lR-Cg5">
                                         <rect key="frame" x="7" y="3.5" width="52.5" height="13.5"/>
                                         <fontDescription key="fontDescription" type="system" pointSize="11"/>
                                         <color key="textColor" red="0.41568627450000001" green="0.41568627450000001" blue="0.41568627450000001" alpha="1" colorSpace="calibratedRGB"/>

+ 249 - 96
KulexiuForStudent/KulexiuForStudent/Module/Home/Controller/HomeViewController.m

@@ -51,11 +51,16 @@
 #import "RecentCourseModel.h"
 #import "AccompanyDetailViewController.h"
 #import "InstrumentChooseViewController.h"
+#import "UserSettingViewController.h"
+
+#import "PublicNoticeView.h"
+#import "SDCycleScrollView.h"
+#import "NoticeSourceModel.h"
 
 #define BUTTONWIDTH (65)
 #define BUTTONHEIGHT (80)
 
-@interface HomeViewController ()<TYCyclePagerViewDataSource,TYCyclePagerViewDelegate,UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate,UICollectionViewDelegate, UICollectionViewDelegateFlowLayout,UICollectionViewDataSource,WMPlayerDelegate>
+@interface HomeViewController ()<TYCyclePagerViewDataSource,TYCyclePagerViewDelegate,UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate,UICollectionViewDelegate, UICollectionViewDelegateFlowLayout,UICollectionViewDataSource,WMPlayerDelegate,SDCycleScrollViewDelegate>
 {
     WMPlayer *_wmPlayer;
     CGRect _playerFrame;
@@ -82,6 +87,11 @@
 @property (nonatomic, assign) NSInteger buttonDotWidth;
 @property (nonatomic, assign) CGFloat buttonViewHeight; // button view 高度
 
+@property (nonatomic, strong) PublicNoticeView *noticeView;
+@property (nonatomic, strong) SDCycleScrollView *noticeScrollView;
+@property (nonatomic, strong) NSMutableArray *noticeArray; // notice数据
+@property (nonatomic, strong) NSMutableArray *noticeTitleArray; // 标题数组
+
 @property (nonatomic, strong) HomeHotAlbumView *albumView; // albumView container
 @property (nonatomic, strong) NSMutableArray *albumArray;  // 热门专辑
 @property (nonatomic, strong) UICollectionView *albumCollectionView; // 专辑容器
@@ -117,6 +127,11 @@
 
 @property (nonatomic, assign) BOOL isFirstLoad;
 
+@property (nonatomic, strong) dispatch_group_t requestGroup;
+
+@property (nonatomic, strong) HomeMessageModel *flashModel;
+
+@property (nonatomic, strong) RecentCourseModel *recentCourseModel;
 @end
 
 @implementation HomeViewController
@@ -181,137 +196,207 @@
 }
 
 - (void)configNavView {
-    [self.scrollView removeFromSuperview];
+
     [self.view addSubview:self.navView];
     [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.right.top.mas_equalTo(self.view);
         make.height.mas_equalTo(kNaviBarHeight);
     }];
-}
-
-
-- (void)configUI {
-    [self.scrollView removeFromSuperview];
-    [self.view addSubview:self.tableView];
-    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.bottom.mas_equalTo(self.view);
-        make.top.mas_equalTo(self.navView.mas_bottom);
+    [self.view bringSubviewToFront:self.scrollView];
+    [self.view bringSubviewToFront:self.navView];
+    [self.scrollView mas_remakeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.view.mas_top).offset(kNaviBarHeight);
+        make.bottom.mas_equalTo(self.view.mas_bottom);
     }];
-    if (@available(iOS 11.0, *)) {
-        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
-    } else {
-        // Fallback on earlier versions
-        self.automaticallyAdjustsScrollViewInsets = NO;
-    }
-    self.tableView.tableHeaderView = self.tableHeaderView;
+    self.scrollView.backgroundColor = [UIColor clearColor];
     MJWeakSelf;
-    self.tableView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+    self.scrollView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
         [weakSelf requestData];
     }];
-    
-    // 配置 首页显示
-    [self addDisplayView];
 }
 
-- (void)addDisplayView {
-    CGFloat tableHeaderHeight = 0.0f;
-    [self.tableHeaderView addSubview:self.bannerView];
+
+- (void)configUI {
+    [self.scrollView addSubview:self.bannerView];
     // banner
     self.bannerViewHeight = [HomeBannerView getViewHeight];
-    tableHeaderHeight += self.bannerViewHeight;
+    
     [self.bannerView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
-        make.top.mas_equalTo(self.tableHeaderView.mas_top);
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.scrollView.mas_top);
         make.height.mas_equalTo(self.bannerViewHeight);
     }];
-    // button
-    [self.tableHeaderView addSubview:self.buttonContainer];
+    
+    [self.scrollView addSubview:self.noticeView];
+    [self.noticeView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.bannerView.mas_bottom);
+        make.height.mas_equalTo(CGFLOAT_MIN);
+    }];
+    [self.noticeView.adView addSubview:self.noticeScrollView];
+    [self.noticeScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.left.right.bottom.mas_equalTo(self.noticeView.adView);
+    }];
+    self.noticeView.hidden = YES;
+    
+    [self.scrollView addSubview:self.buttonContainer];
+
     self.buttonViewHeight = [HomeButtonView getViewHeight];
     [self.buttonContainer mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
-        make.top.mas_equalTo(self.bannerView.mas_bottom);
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.noticeView.mas_bottom);
         make.height.mas_equalTo(self.buttonViewHeight);
     }];
-    tableHeaderHeight += self.buttonViewHeight;
-    
+
     // 课程提醒
-    [self.tableHeaderView addSubview:self.tipsCourseView];
+    [self.scrollView addSubview:self.tipsCourseView];
     self.tipsViewHeight = CGFLOAT_MIN;
     self.tipsCourseView.hidden = YES;
     [self.tipsCourseView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
+        make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.buttonContainer.mas_bottom);
         make.height.mas_equalTo(self.tipsViewHeight);
     }];
-    tableHeaderHeight += self.tipsViewHeight;
     // 专辑
-    [self.tableHeaderView addSubview:self.albumView];
+    [self.scrollView addSubview:self.albumView];
     self.albumViewHeight = [HomeHotAlbumView getViewHeight];
     [self.albumView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
+        make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.tipsCourseView.mas_bottom);
         make.height.mas_equalTo(self.albumViewHeight);
     }];
-    tableHeaderHeight += self.albumViewHeight;
-    
+
     // 直播课
-    [self.tableHeaderView addSubview:self.liveView];
+    [self.scrollView addSubview:self.liveView];
     self.liveViewHeight = [self.liveView getViewHeightWithCount:10];
     [self.liveView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
+        make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.albumView.mas_bottom);
         make.height.mas_equalTo(self.liveViewHeight);
     }];
-    tableHeaderHeight += self.liveViewHeight;
-    
+
     // 视频课
-    [self.tableHeaderView addSubview:self.videoView];
+    [self.scrollView addSubview:self.videoView];
     self.videoViewHeight = [self.videoView getViewHeightWithCount:10];
     [self.videoView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
+        make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.liveView.mas_bottom);
         make.height.mas_equalTo(self.videoViewHeight);
     }];
-    tableHeaderHeight += self.videoViewHeight;
-    
+
     // 老师风采
-    [self.tableHeaderView addSubview:self.teacherView];
-    self.teachViewHeight = [self.teacherView getViewHeightWithSourceCount:4];
-    
+    [self.scrollView addSubview:self.teacherView];
+    self.teachViewHeight = [self.teacherView getViewHeightWithSourceCount:10];
+
     [self.teacherView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
+        make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.videoView.mas_bottom);
         make.height.mas_equalTo(self.teachViewHeight);
     }];
-    tableHeaderHeight += self.teachViewHeight;
-    
-    [self.tableHeaderView addSubview:self.informationHeadView];
+    // 资讯头部
+    [self.scrollView addSubview:self.informationHeadView];
     self.informationHeight = [HotInformationHeadView getViewHeight];
     [self.informationHeadView mas_remakeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.mas_equalTo(self.tableHeaderView);
+        make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.teacherView.mas_bottom);
         make.height.mas_equalTo(self.informationHeight);
     }];
-    tableHeaderHeight += self.informationHeight;
-    self.tableHeaderView.frame = CGRectMake(0, 0, KPortraitWidth, tableHeaderHeight);
-    [self.tableView reloadData];
+
+    // 资讯列表
+    [self.scrollView addSubview:self.tableView];
+    CGFloat tableHeight = [self getTableHeightWithCount:4];
+    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.informationHeadView.mas_bottom);
+        make.bottom.mas_equalTo(self.scrollView.mas_bottom);
+        make.height.mas_equalTo(tableHeight);
+    }];
 }
 
-- (void)refreshTableHeadHeight {
-    CGFloat tableHeaderHeight = self.bannerViewHeight + self.buttonViewHeight + self.tipsViewHeight + self.albumViewHeight + self.liveViewHeight + self.videoViewHeight + self.teachViewHeight + self.informationHeight;
-    self.tableHeaderView.frame = CGRectMake(0, 0, KPortraitWidth, tableHeaderHeight);
-    [self.tableView reloadData];
+- (CGFloat)getTableHeightWithCount:(NSInteger)count {
+    return 108 * count + 10;
 }
 
+
 - (void)requestData {
-    [self requestNewsList]; //
+    [self showhud];
+    [self requestNewsList];
+    [self requestNotice];
     [self requestCourseInfo];
     [self requestTeacherStyle];
     [self requestHotAlbum];
+    
+    dispatch_group_notify(self.requestGroup, dispatch_get_main_queue(), ^{
+        [self removehub];
+        [self.scrollView.mj_header endRefreshing];
+        [self refreshView];
+    });
 }
 
+- (void)refreshView {
+    [self.bannerScroll reloadData];
+    [self showButtonMessage];
+    [self refreshNoticeView];
+    [self refreshAlbumView];
+    [self refreshCourseView:self.recentCourseModel];
+    [self refreshCourseView];
+    [self refreshTeachView];
+    [self refreshTableView];
+
+    if (self.flashModel) {
+        [self showNewsWithSource:self.flashModel];
+    }
+}
+
+- (void)requestNotice {
+    dispatch_group_enter(self.requestGroup);
+    [KSNetworkingManager helpCenterContentListRequest:KS_POST success:^(NSDictionary * _Nonnull dic) {
+        dispatch_group_leave(self.requestGroup);
+        if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+            NSArray *sourceArray = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"rows"];
+            if (sourceArray.count) {
+                NSDictionary *parm = [sourceArray firstObject];
+                NoticeSourceModel *bannerModel = [[NoticeSourceModel alloc] initWithDictionary:parm];
+                [self.noticeArray addObject:bannerModel];
+                [self.noticeTitleArray addObject:bannerModel.title];
+            }
+            else {
+                self.bannerArray = [NSMutableArray array];
+                self.noticeTitleArray = [NSMutableArray array];
+            }
+            
+        }
+        else {
+            [self MBPShow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        dispatch_group_leave(self.requestGroup);
+    }];
+}
+
+
+- (void)refreshNoticeView {
+    if (self.noticeTitleArray.count) {
+        self.noticeView.hidden = NO;
+        [self.noticeView mas_updateConstraints:^(MASConstraintMaker *make) {
+            make.height.mas_equalTo(50.0f);
+        }];
+    }
+    else {
+        self.noticeView.hidden = YES;
+        [self.noticeView mas_updateConstraints:^(MASConstraintMaker *make) {
+            make.height.mas_equalTo(CGFLOAT_MIN);
+        }];
+    }
+    self.noticeScrollView.titlesGroup = self.noticeTitleArray;
+}
+
+
 - (void)requestNewsList {
+    dispatch_group_enter(self.requestGroup);
     [KSNetworkingManager homeNewsList:KS_POST success:^(NSDictionary * _Nonnull dic) {
+        dispatch_group_leave(self.requestGroup);
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             NSDictionary *result = [dic dictionaryValueForKey:@"data"];
             // banner
@@ -322,7 +407,6 @@
                 [bannerInfoArray addObject:model];
             }
             self.bannerArray = [NSMutableArray arrayWithArray:bannerInfoArray];
-            [self.bannerScroll reloadData];
             
             // button
             NSArray *buttonArray = [result arrayValueForKey:@"appMenu"];
@@ -332,13 +416,11 @@
                 [buttonInfoArray addObject:model];
             }
             self.buttonArray = [NSMutableArray arrayWithArray:buttonInfoArray];
-            [self showButtonMessage];
             
             // news
             NSArray *flashArray = [result arrayValueForKey:@"flashPage"];
             if (flashArray.count) {
-                HomeMessageModel *newsModel = [[HomeMessageModel alloc] initWithDictionary:[flashArray firstObject]];
-                [self showNewsWithSource:newsModel];
+                self.flashModel = [[HomeMessageModel alloc] initWithDictionary:[flashArray firstObject]];
             }
             
             // information
@@ -349,18 +431,27 @@
                 [informationInfoArray addObject:model];
             }
             self.dataArray = [NSMutableArray arrayWithArray:informationInfoArray];
-            [self.tableView reloadData];
         }
         else {
             [self MBPShow:MESSAGEKEY];
         }
     } faliure:^(NSError * _Nonnull error) {
-        
+        dispatch_group_leave(self.requestGroup);
     }];
 }
 
+- (void)refreshTableView {
+    CGFloat tableHeight = [self getTableHeightWithCount:self.dataArray.count];
+    [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
+        make.height.mas_equalTo(tableHeight);
+    }];
+    [self.tableView reloadData];
+}
+
 - (void)requestHotAlbum {
+    dispatch_group_enter(self.requestGroup);
     [KSNetworkingManager HomeHotAlbumRequest:KS_POST page:1 rows:10 success:^(NSDictionary * _Nonnull dic) {
+        dispatch_group_leave(self.requestGroup);
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             NSArray *sourceArray = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"rows"];
             NSMutableArray *albumArray = [NSMutableArray array];
@@ -373,10 +464,9 @@
         else {
             [self MBPShow:MESSAGEKEY];
         }
-        [self refreshAlbumView];
         
     } faliure:^(NSError * _Nonnull error) {
-        
+        dispatch_group_leave(self.requestGroup);
     }];
 }
 
@@ -393,15 +483,13 @@
         make.height.mas_equalTo(self.albumViewHeight);
     }];
     [self.albumCollectionView reloadData];
-    [self refreshTableHeadHeight];
 }
 
 - (void)requestCourseInfo {
-    
-//    [self showhud];
+
+    dispatch_group_enter(self.requestGroup);
     [KSNetworkingManager homeQueryLiveAndVideo:KS_GET success:^(NSDictionary * _Nonnull dic) {
-//        [self removehub];
-        [self.tableView.mj_header endRefreshing];
+        dispatch_group_leave(self.requestGroup);
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             NSDictionary *sourceDic = [dic dictionaryValueForKey:@"data"];
             NSArray *liveList = [sourceDic arrayValueForKey:@"liveList"];
@@ -423,20 +511,18 @@
             // 最近课程
             NSDictionary *parm = [sourceDic dictionaryValueForKey:@"recentCourses"];
             if (parm == nil) {
-                [self refreshCourseView:nil];
+                self.recentCourseModel = nil;
             }
             else {
-                RecentCourseModel *model = [[RecentCourseModel alloc] initWithDictionary:parm];
-                [self refreshCourseView:model];
+                self.recentCourseModel = [[RecentCourseModel alloc] initWithDictionary:parm];
             }
         }
         else {
             [self MBPShow:MESSAGEKEY];
         }
-        [self refreshCourseView];
+
     } faliure:^(NSError * _Nonnull error) {
-        [self removehub];
-        [self.tableView.mj_header endRefreshing];
+        dispatch_group_leave(self.requestGroup);
     }];
 }
 
@@ -456,7 +542,6 @@
             make.height.mas_equalTo(CGFLOAT_MIN);
         }];
     }
-    [self refreshTableHeadHeight];
 }
 
 - (void)refreshCourseView {
@@ -486,7 +571,6 @@
     
     [self.liveCourseTable reloadData];
     [self.videoCourseTable reloadData];
-    [self refreshTableHeadHeight];
 }
 
 - (void)requestUserInfo:(BOOL)checkSubject {
@@ -509,9 +593,9 @@
 }
 
 - (void)requestTeacherStyle {
-    
+    dispatch_group_enter(self.requestGroup);
     [KSNetworkingManager homeQueryTeacherStyle:KS_POST page:1 rows:10 success:^(NSDictionary * _Nonnull dic) {
-        
+        dispatch_group_leave(self.requestGroup);
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             NSArray *sourceArray = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"rows"];
             NSMutableArray *styleArray = [NSMutableArray array];
@@ -525,9 +609,8 @@
             [self MBPShow:MESSAGEKEY];
         }
         // 回调
-        [self refreshTeachView];
     } faliure:^(NSError * _Nonnull error) {
-        
+        dispatch_group_leave(self.requestGroup);
     }];
 }
 
@@ -543,8 +626,8 @@
     [self.teacherView mas_updateConstraints:^(MASConstraintMaker *make) {
         make.height.mas_equalTo(self.teachViewHeight);
     }];
+    
     [self.infoCollectionView reloadData];
-    [self refreshTableHeadHeight];
 }
 
 - (void)refreshNavView:(BOOL)checkSubject {
@@ -680,7 +763,10 @@
         HomeMessageModel *model = self.dataArray[indexPath.row];
         HomeInformationCell *cell = [tableView dequeueReusableCellWithIdentifier:@"HomeInformationCell"];
         ROWINDEX rowIndex = ROWINDEX_MIDDLE;
-        if (indexPath.row == 0) {
+        if (indexPath.row == 0 && self.dataArray.count == 1) {
+            rowIndex = ROWINDEX_TOP_BOTTOM;
+        }
+        else if (indexPath.row == 0) {
             rowIndex = ROWINDEX_TOP;
         }
         else if (indexPath.row == self.dataArray.count - 1) {
@@ -817,9 +903,23 @@
 }
     
 
-
+#pragma mark ----- SDCycleScrollViewDelegate
+- (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index {
+    NoticeSourceModel *noticeModel = self.noticeArray[index];
+    KSBaseWKWebViewController *webCtrl = [[KSBaseWKWebViewController alloc] init];
+    webCtrl.url = [NSString stringWithFormat:@"%@/#/helpCenterDetail?id=%@",WEBHOST, noticeModel.internalBaseClassIdentifier];
+    [self.navigationController pushViewController:webCtrl animated:YES];
+    
+}
 
 #pragma mark ---- lazying
+- (dispatch_group_t)requestGroup {
+    if (!_requestGroup) {
+        _requestGroup = dispatch_group_create();
+    }
+    return _requestGroup;
+}
+
 - (NSMutableArray *)buttonArray {
     if (!_buttonArray) {
         _buttonArray = [NSMutableArray array];
@@ -861,6 +961,53 @@
     }
     return _teacherArray;
 }
+
+#pragma mark ----- 公告
+- (PublicNoticeView *)noticeView {
+    if (!_noticeView) {
+        _noticeView = [PublicNoticeView shareInstance];
+        MJWeakSelf;
+        [_noticeView moreCallback:^{
+            [weakSelf moreNotice];
+        }];
+    }
+    return _noticeView;
+}
+#pragma mark -- lazying
+- (SDCycleScrollView *)noticeScrollView {
+    if (!_noticeScrollView) {
+        _noticeScrollView = [SDCycleScrollView cycleScrollViewWithFrame:CGRectZero delegate:self placeholderImage:[UIImage new]];
+        _noticeScrollView.onlyDisplayText = YES;
+        _noticeScrollView.autoScroll = NO;
+        _noticeScrollView.scrollEnabled = NO;
+        _noticeScrollView.scrollDirection = UICollectionViewScrollDirectionVertical;
+        _noticeScrollView.titleLabelTextColor = HexRGB(0x1a1a1a);
+        _noticeScrollView.titleLabelBackgroundColor = [UIColor whiteColor];
+        _noticeScrollView.titleLabelTextFont = [UIFont systemFontOfSize:14];
+        _noticeScrollView.titlesGroup = self.noticeTitleArray;
+    }
+    return _noticeScrollView;
+}
+
+- (NSMutableArray *)noticeArray {
+    if (!_noticeArray) {
+        _noticeArray = [NSMutableArray array];
+    }
+    return _noticeArray;
+}
+
+- (NSMutableArray *)noticeTitleArray {
+    if (!_noticeTitleArray) {
+        _noticeTitleArray = [NSMutableArray array];
+    }
+    return _noticeTitleArray;
+}
+- (void)moreNotice {
+    KSBaseWKWebViewController *webCtrl = [[KSBaseWKWebViewController alloc] init];
+    webCtrl.url = [NSString stringWithFormat:@"%@%@", WEBHOST, @"/#/helpCenter?catalogType=2"];
+    [self.navigationController pushViewController:webCtrl animated:YES];
+}
+
 #pragma mark ----- 最近上课
 
 - (HomeCourseTipsView *)tipsCourseView {
@@ -909,7 +1056,7 @@
 - (UICollectionView *)albumCollectionView {
     if (!_albumCollectionView) {
         UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
-//        layout.sectionInset = UIEdgeInsetsMake(12, 14, 12, 14);
+        layout.sectionInset = UIEdgeInsetsMake(12, 14, 12, 14);
         layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
         _albumCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
         _albumCollectionView.backgroundColor = [UIColor clearColor];
@@ -1040,6 +1187,7 @@
     if (!_infoCollectionView) {
         UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
         layout.scrollDirection = UICollectionViewScrollDirectionVertical;
+        layout.itemSize = CGSizeMake((KPortraitWidth - 28 - 11) / 2.0f, 164);
         _infoCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
         _infoCollectionView.backgroundColor = [UIColor clearColor];
         _infoCollectionView.delegate = self;
@@ -1171,9 +1319,14 @@
     return _navView;
 }
 
+- (void)displayUserCenter {
+    UserSettingViewController *ctrl = [[UserSettingViewController alloc] init];
+    [self.navigationController pushViewController:ctrl animated:YES];
+}
+
 - (void)navAction:(NAVACTION)action {
-    if (action == NAVACTION_SUBJECT) {
-        [self showInstrumentView:NO];
+    if (action == NAVACTION_USERCENTER) {
+        [self displayUserCenter];
     }
     else { // 消息中心
         

+ 33 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/Model/NoticeSourceModel.h

@@ -0,0 +1,33 @@
+//
+//  NoticeSourceModel.h
+//
+//  Created by Steven  on 2022/5/10
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface NoticeSourceModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, strong) NSString *internalBaseClassIdentifier;
+@property (nonatomic, strong) NSString *modifyOn;
+@property (nonatomic, strong) NSString *createOn;
+@property (nonatomic, strong) NSString *releaseTime;
+@property (nonatomic, strong) NSString *updateBy;
+@property (nonatomic, assign) double releaseStatus;
+@property (nonatomic, strong) NSString *content;
+@property (nonatomic, strong) NSString *catalogType;
+@property (nonatomic, strong) NSString *title;
+@property (nonatomic, assign) double order;
+@property (nonatomic, strong) NSString *updateName;
+@property (nonatomic, assign) double catalogId;
+@property (nonatomic, assign) double status;
+@property (nonatomic, assign) double createBy;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 190 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/Model/NoticeSourceModel.m

@@ -0,0 +1,190 @@
+//
+//  NoticeSourceModel.m
+//
+//  Created by Steven  on 2022/5/10
+//  Copyright (c) 2022 __MyCompanyName__. All rights reserved.
+//
+
+#import "NoticeSourceModel.h"
+
+
+NSString *const kNoticeSourceModelId = @"id";
+NSString *const kNoticeSourceModelModifyOn = @"modifyOn";
+NSString *const kNoticeSourceModelCreateOn = @"createOn";
+NSString *const kNoticeSourceModelReleaseTime = @"releaseTime";
+NSString *const kNoticeSourceModelUpdateBy = @"updateBy";
+NSString *const kNoticeSourceModelReleaseStatus = @"releaseStatus";
+NSString *const kNoticeSourceModelContent = @"content";
+NSString *const kNoticeSourceModelCatalogType = @"catalogType";
+NSString *const kNoticeSourceModelTitle = @"title";
+NSString *const kNoticeSourceModelOrder = @"order";
+NSString *const kNoticeSourceModelUpdateName = @"updateName";
+NSString *const kNoticeSourceModelCatalogId = @"catalogId";
+NSString *const kNoticeSourceModelStatus = @"status";
+NSString *const kNoticeSourceModelCreateBy = @"createBy";
+
+
+@interface NoticeSourceModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation NoticeSourceModel
+
+@synthesize internalBaseClassIdentifier = _internalBaseClassIdentifier;
+@synthesize modifyOn = _modifyOn;
+@synthesize createOn = _createOn;
+@synthesize releaseTime = _releaseTime;
+@synthesize updateBy = _updateBy;
+@synthesize releaseStatus = _releaseStatus;
+@synthesize content = _content;
+@synthesize catalogType = _catalogType;
+@synthesize title = _title;
+@synthesize order = _order;
+@synthesize updateName = _updateName;
+@synthesize catalogId = _catalogId;
+@synthesize status = _status;
+@synthesize createBy = _createBy;
+
+
++ (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.internalBaseClassIdentifier = [self objectOrNilForKey:kNoticeSourceModelId fromDictionary:dict];
+            self.modifyOn = [self objectOrNilForKey:kNoticeSourceModelModifyOn fromDictionary:dict];
+            self.createOn = [self objectOrNilForKey:kNoticeSourceModelCreateOn fromDictionary:dict];
+            self.releaseTime = [self objectOrNilForKey:kNoticeSourceModelReleaseTime fromDictionary:dict];
+            self.updateBy = [self objectOrNilForKey:kNoticeSourceModelUpdateBy fromDictionary:dict];
+            self.releaseStatus = [[self objectOrNilForKey:kNoticeSourceModelReleaseStatus fromDictionary:dict] doubleValue];
+            self.content = [self objectOrNilForKey:kNoticeSourceModelContent fromDictionary:dict];
+            self.catalogType = [self objectOrNilForKey:kNoticeSourceModelCatalogType fromDictionary:dict];
+            self.title = [self objectOrNilForKey:kNoticeSourceModelTitle fromDictionary:dict];
+            self.order = [[self objectOrNilForKey:kNoticeSourceModelOrder fromDictionary:dict] doubleValue];
+            self.updateName = [self objectOrNilForKey:kNoticeSourceModelUpdateName fromDictionary:dict];
+            self.catalogId = [[self objectOrNilForKey:kNoticeSourceModelCatalogId fromDictionary:dict] doubleValue];
+            self.status = [[self objectOrNilForKey:kNoticeSourceModelStatus fromDictionary:dict] doubleValue];
+            self.createBy = [[self objectOrNilForKey:kNoticeSourceModelCreateBy fromDictionary:dict] doubleValue];
+
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:self.internalBaseClassIdentifier forKey:kNoticeSourceModelId];
+    [mutableDict setValue:self.modifyOn forKey:kNoticeSourceModelModifyOn];
+    [mutableDict setValue:self.createOn forKey:kNoticeSourceModelCreateOn];
+    [mutableDict setValue:self.releaseTime forKey:kNoticeSourceModelReleaseTime];
+    [mutableDict setValue:self.updateBy forKey:kNoticeSourceModelUpdateBy];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.releaseStatus] forKey:kNoticeSourceModelReleaseStatus];
+    [mutableDict setValue:self.content forKey:kNoticeSourceModelContent];
+    [mutableDict setValue:self.catalogType forKey:kNoticeSourceModelCatalogType];
+    [mutableDict setValue:self.title forKey:kNoticeSourceModelTitle];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.order] forKey:kNoticeSourceModelOrder];
+    [mutableDict setValue:self.updateName forKey:kNoticeSourceModelUpdateName];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.catalogId] forKey:kNoticeSourceModelCatalogId];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.status] forKey:kNoticeSourceModelStatus];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.createBy] forKey:kNoticeSourceModelCreateBy];
+
+    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.internalBaseClassIdentifier = [aDecoder decodeObjectForKey:kNoticeSourceModelId];
+    self.modifyOn = [aDecoder decodeObjectForKey:kNoticeSourceModelModifyOn];
+    self.createOn = [aDecoder decodeObjectForKey:kNoticeSourceModelCreateOn];
+    self.releaseTime = [aDecoder decodeObjectForKey:kNoticeSourceModelReleaseTime];
+    self.updateBy = [aDecoder decodeObjectForKey:kNoticeSourceModelUpdateBy];
+    self.releaseStatus = [aDecoder decodeDoubleForKey:kNoticeSourceModelReleaseStatus];
+    self.content = [aDecoder decodeObjectForKey:kNoticeSourceModelContent];
+    self.catalogType = [aDecoder decodeObjectForKey:kNoticeSourceModelCatalogType];
+    self.title = [aDecoder decodeObjectForKey:kNoticeSourceModelTitle];
+    self.order = [aDecoder decodeDoubleForKey:kNoticeSourceModelOrder];
+    self.updateName = [aDecoder decodeObjectForKey:kNoticeSourceModelUpdateName];
+    self.catalogId = [aDecoder decodeDoubleForKey:kNoticeSourceModelCatalogId];
+    self.status = [aDecoder decodeDoubleForKey:kNoticeSourceModelStatus];
+    self.createBy = [aDecoder decodeDoubleForKey:kNoticeSourceModelCreateBy];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeObject:_internalBaseClassIdentifier forKey:kNoticeSourceModelId];
+    [aCoder encodeObject:_modifyOn forKey:kNoticeSourceModelModifyOn];
+    [aCoder encodeObject:_createOn forKey:kNoticeSourceModelCreateOn];
+    [aCoder encodeObject:_releaseTime forKey:kNoticeSourceModelReleaseTime];
+    [aCoder encodeObject:_updateBy forKey:kNoticeSourceModelUpdateBy];
+    [aCoder encodeDouble:_releaseStatus forKey:kNoticeSourceModelReleaseStatus];
+    [aCoder encodeObject:_content forKey:kNoticeSourceModelContent];
+    [aCoder encodeObject:_catalogType forKey:kNoticeSourceModelCatalogType];
+    [aCoder encodeObject:_title forKey:kNoticeSourceModelTitle];
+    [aCoder encodeDouble:_order forKey:kNoticeSourceModelOrder];
+    [aCoder encodeObject:_updateName forKey:kNoticeSourceModelUpdateName];
+    [aCoder encodeDouble:_catalogId forKey:kNoticeSourceModelCatalogId];
+    [aCoder encodeDouble:_status forKey:kNoticeSourceModelStatus];
+    [aCoder encodeDouble:_createBy forKey:kNoticeSourceModelCreateBy];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    NoticeSourceModel *copy = [[NoticeSourceModel alloc] init];
+    
+    if (copy) {
+
+        copy.internalBaseClassIdentifier = [self.internalBaseClassIdentifier copyWithZone:zone];
+        copy.modifyOn = [self.modifyOn copyWithZone:zone];
+        copy.createOn = [self.createOn copyWithZone:zone];
+        copy.releaseTime = [self.releaseTime copyWithZone:zone];
+        copy.updateBy = [self.updateBy copyWithZone:zone];
+        copy.releaseStatus = self.releaseStatus;
+        copy.content = [self.content copyWithZone:zone];
+        copy.catalogType = [self.catalogType copyWithZone:zone];
+        copy.title = [self.title copyWithZone:zone];
+        copy.order = self.order;
+        copy.updateName = [self.updateName copyWithZone:zone];
+        copy.catalogId = self.catalogId;
+        copy.status = self.status;
+        copy.createBy = self.createBy;
+    }
+    
+    return copy;
+}
+
+
+@end

+ 29 - 23
KulexiuForStudent/KulexiuForStudent/Module/Home/NoticeCenter/Controller/NotiferMessageViewController.m

@@ -13,9 +13,12 @@
 #import "CustomNavViewController.h"
 #import "HomeworkDetailViewController.h"
 #import "UIButton+EnlargeEdge.h"
+#import "NotiferNavView.h"
 
 @interface NotiferMessageViewController ()<UITableViewDelegate, UITableViewDataSource>
 
+@property (nonatomic, strong) NotiferNavView *navView;
+
 @property (nonatomic, strong) NotiferHeadView *headView;
 
 @property (nonatomic, strong) UITableView *tableView;
@@ -31,8 +34,7 @@
 - (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
-    [self allocTitle:@"消息盒子"];
-    [self configRightButton];
+    self.ks_prefersNavigationBarHidden = YES;
     [self configUI];
     self.hasUnreadCount = NO;
 }
@@ -43,24 +45,8 @@
     [self resetSourceAndRequest];
 }
 
-- (void)configRightButton {
-    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    [rightButton setTitle:@"全部已读" forState:UIControlStateNormal];
-    [rightButton setTitleColor:HexRGB(0x999999) forState:UIControlStateNormal];
-    [rightButton setImage:[UIImage imageNamed:@"clear_notifer"] forState:UIControlStateNormal];
-    rightButton.frame =CGRectMake(0, 0, 80, 40);
-    //使图片在右边,文字在左边(正常情况下是文字在右边,图片在左边)
-    [rightButton setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
-    //设置图片和文字之间的间隙
-    rightButton.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
-    [rightButton.titleLabel setFont:[UIFont systemFontOfSize:11.0f]];
-    [rightButton setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10];
-    [rightButton addTarget:self action:@selector(rightBtnClick) forControlEvents:UIControlEventTouchUpInside];
-    UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]initWithCustomView:rightButton];
-    self.navigationItem.rightBarButtonItem = rightItem;
-}
 
-- (void)rightBtnClick {
+- (void)clearNotiferAction {
     if (self.hasUnreadCount == NO) {
         return;
     }
@@ -78,13 +64,17 @@
 }
 
 - (void)configUI {
-    [self.scrollView removeFromSuperview];
+    [self.view addSubview:self.navView];
+    [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.mas_equalTo(self.view);
+        make.height.mas_equalTo(kNaviBarHeight);
+    }];
     [self.view addSubview:self.headView];
     [self.headView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.top.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.navView.mas_bottom);
+        make.left.right.mas_equalTo(self.view);
         make.height.mas_equalTo(100);
-    }];
-    [self.view addSubview:self.tableView];
+    }];    [self.view addSubview:self.tableView];
     [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.headView.mas_bottom);
@@ -268,6 +258,22 @@
 }
 
 #pragma mark ---- lazying
+- (NotiferNavView *)navView {
+    if (!_navView) {
+        _navView = [NotiferNavView shareInstance];
+        MJWeakSelf;
+        [_navView notiferNavAction:^(BOOL isBack) {
+            if (isBack) {
+                [weakSelf backAction];
+            }
+            else {
+                [weakSelf clearNotiferAction];
+            }
+        }];
+    }
+    return _navView;
+}
+
 - (NotiferHeadView *)headView {
     if (!_headView) {
         _headView = [NotiferHeadView shareIntance];

+ 5 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeHotAlbumCell.xib

@@ -72,6 +72,11 @@
                             <constraint firstItem="HyK-tc-JYn" firstAttribute="leading" secondItem="xPp-Kr-NCd" secondAttribute="leading" constant="7" id="oZX-c6-fga"/>
                             <constraint firstAttribute="bottom" secondItem="HyK-tc-JYn" secondAttribute="bottom" constant="2" id="vLb-NQ-3ma"/>
                         </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="8"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
                     </view>
                 </subviews>
             </view>

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeInformationCell.h

@@ -14,6 +14,7 @@ typedef NS_ENUM(NSInteger, ROWINDEX) {
     ROWINDEX_TOP,
     ROWINDEX_MIDDLE,
     ROWINDEX_BOTTOM,
+    ROWINDEX_TOP_BOTTOM,
 };
 
 @interface HomeInformationCell : UITableViewCell

+ 7 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeInformationCell.m

@@ -45,6 +45,13 @@
         maskLayer.path = maskPath.CGPath;
         self.backView.layer.mask = maskLayer;
     }
+    else if (rowIndex == ROWINDEX_TOP_BOTTOM) {
+        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, kScreenWidth - 28, 108) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight|UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(8, 8)];
+        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
+        maskLayer.frame = self.backView.bounds;
+        maskLayer.path = maskPath.CGPath;
+        self.backView.layer.mask = maskLayer;
+    }
     else {
         UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, kScreenWidth - 28, 108) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(0, 0)];
         CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];

+ 0 - 1
KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeIntroduceView.m

@@ -29,7 +29,6 @@
 - (CGFloat)getViewHeightWithSourceCount:(NSInteger)count {
     
     NSInteger row = count / 2 + count % 2;
-    
     return 56 + row * 164 + (row - 1) * 12;
     
 }

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeNavView.h

@@ -8,8 +8,8 @@
 #import <UIKit/UIKit.h>
 
 typedef NS_ENUM(NSInteger, NAVACTION) {
-    NAVACTION_SUBJECT,  // 声部
-    NAVACTION_MESSAGE,  // 消息
+    NAVACTION_USERCENTER,  // 用户
+    NAVACTION_MESSAGE,     // 消息
 };
 
 typedef void(^HomeNavCallback)(NAVACTION action);

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeNavView.m

@@ -24,9 +24,9 @@
     }
 }
 
-- (IBAction)chooseSubject:(id)sender {
+- (IBAction)toUseCenter:(id)sender {
     if (self.calback) {
-        self.calback(NAVACTION_SUBJECT);
+        self.calback(NAVACTION_USERCENTER);
     }
 }
 

+ 19 - 6
KulexiuForStudent/KulexiuForStudent/Module/Home/View/HomeNavView.xib

@@ -39,19 +39,19 @@
                     </userDefinedRuntimeAttributes>
                 </view>
                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="user_default_avatal" translatesAutoresizingMaskIntoConstraints="NO" id="q8T-4X-XH1">
-                    <rect key="frame" x="14" y="46" width="40" height="40"/>
+                    <rect key="frame" x="14" y="50" width="32" height="32"/>
                     <constraints>
-                        <constraint firstAttribute="width" constant="40" id="mbm-wS-w83"/>
-                        <constraint firstAttribute="height" constant="40" id="xbf-qL-OAg"/>
+                        <constraint firstAttribute="width" constant="32" id="mbm-wS-w83"/>
+                        <constraint firstAttribute="height" constant="32" id="xbf-qL-OAg"/>
                     </constraints>
                     <userDefinedRuntimeAttributes>
                         <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                            <real key="value" value="20"/>
+                            <real key="value" value="16"/>
                         </userDefinedRuntimeAttribute>
                     </userDefinedRuntimeAttributes>
                 </imageView>
                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="V09-v5-ugm">
-                    <rect key="frame" x="59" y="55" width="120" height="22"/>
+                    <rect key="frame" x="51" y="55" width="120" height="22"/>
                     <constraints>
                         <constraint firstAttribute="width" constant="120" id="G4K-LS-ntu"/>
                         <constraint firstAttribute="height" constant="22" id="pIg-61-zmA"/>
@@ -60,17 +60,30 @@
                     <color key="textColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="calibratedRGB"/>
                     <nil key="highlightedColor"/>
                 </label>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9Ch-4E-l3g">
+                    <rect key="frame" x="8" y="44" width="44" height="44"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="44" id="4ej-m6-zms"/>
+                        <constraint firstAttribute="width" constant="44" id="KTy-4x-P2Z"/>
+                    </constraints>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <connections>
+                        <action selector="toUseCenter:" destination="iN0-l3-epB" eventType="touchUpInside" id="x9k-on-BOB"/>
+                    </connections>
+                </button>
             </subviews>
             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <constraints>
                 <constraint firstItem="omR-9c-WQ1" firstAttribute="top" secondItem="xYy-Ue-YZl" secondAttribute="top" constant="8" id="3LP-Cf-UOB"/>
+                <constraint firstAttribute="bottom" secondItem="xYy-Ue-YZl" secondAttribute="bottom" constant="5" id="GLZ-UC-GBm"/>
                 <constraint firstItem="V09-v5-ugm" firstAttribute="leading" secondItem="q8T-4X-XH1" secondAttribute="trailing" constant="5" id="HMR-Zb-eYg"/>
                 <constraint firstAttribute="trailing" secondItem="omR-9c-WQ1" secondAttribute="trailing" constant="21" id="MxY-he-eWw"/>
                 <constraint firstAttribute="trailing" secondItem="xYy-Ue-YZl" secondAttribute="trailing" constant="15" id="NQ0-wf-rrB"/>
+                <constraint firstItem="9Ch-4E-l3g" firstAttribute="centerY" secondItem="q8T-4X-XH1" secondAttribute="centerY" id="TWf-lZ-rE9"/>
                 <constraint firstItem="q8T-4X-XH1" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="WOM-ee-yRZ"/>
                 <constraint firstItem="V09-v5-ugm" firstAttribute="centerY" secondItem="q8T-4X-XH1" secondAttribute="centerY" id="jWy-Il-BUG"/>
                 <constraint firstItem="xYy-Ue-YZl" firstAttribute="centerY" secondItem="q8T-4X-XH1" secondAttribute="centerY" id="n1m-Dh-PuS"/>
-                <constraint firstAttribute="bottom" secondItem="q8T-4X-XH1" secondAttribute="bottom" constant="5" id="v1f-PT-046"/>
+                <constraint firstItem="q8T-4X-XH1" firstAttribute="centerX" secondItem="9Ch-4E-l3g" secondAttribute="centerX" id="pFZ-KT-emk"/>
             </constraints>
             <nil key="simulatedTopBarMetrics"/>
             <nil key="simulatedBottomBarMetrics"/>

+ 28 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/View/PublicNoticeView.h

@@ -0,0 +1,28 @@
+//
+//  PublicNoticeView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/29.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^NoticeMoreCallback)(void);
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface PublicNoticeView : UIView
+
++ (instancetype)shareInstance;
+
+@property (weak, nonatomic) IBOutlet UIView *adView;
+
+- (void)moreCallback:(NoticeMoreCallback)callback;
+
+- (CGFloat)getViewHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 47 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/View/PublicNoticeView.m

@@ -0,0 +1,47 @@
+//
+//  PublicNoticeView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2022/4/29.
+//
+
+#import "PublicNoticeView.h"
+
+@interface PublicNoticeView ()
+
+@property (nonatomic, copy) NoticeMoreCallback callback;
+
+@end
+
+@implementation PublicNoticeView
+
++ (instancetype)shareInstance {
+    PublicNoticeView *view = [[[NSBundle mainBundle] loadNibNamed:@"PublicNoticeView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)moreCallback:(NoticeMoreCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (IBAction)moreAction:(id)sender {
+    if (self.callback) {
+        self.callback();
+    }
+}
+
+
+- (CGFloat)getViewHeight {
+    return 50.0f;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 94 - 0
KulexiuForStudent/KulexiuForStudent/Module/Home/View/PublicNoticeView.xib

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="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"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="PublicNoticeView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="94"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="18s-Im-HaS">
+                    <rect key="frame" x="14" y="25" width="386" height="44"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="notice_icon" translatesAutoresizingMaskIntoConstraints="NO" id="Emb-yN-fCJ">
+                            <rect key="frame" x="10" y="11" width="23" height="22"/>
+                        </imageView>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FYH-Km-v6L">
+                            <rect key="frame" x="38" y="0.0" width="299" height="44"/>
+                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        </view>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="l4x-1S-fJR">
+                            <rect key="frame" x="342" y="0.0" width="44" height="44"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="44" id="fbW-78-wuS"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" image="notice_more"/>
+                            <connections>
+                                <action selector="moreAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="ISe-v7-tmR"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstAttribute="bottom" secondItem="l4x-1S-fJR" secondAttribute="bottom" id="1Jd-Qb-ShD"/>
+                        <constraint firstItem="Emb-yN-fCJ" firstAttribute="centerY" secondItem="18s-Im-HaS" secondAttribute="centerY" id="Cfw-Em-J6j"/>
+                        <constraint firstAttribute="bottom" secondItem="FYH-Km-v6L" secondAttribute="bottom" id="GJE-Ly-ZYN"/>
+                        <constraint firstItem="l4x-1S-fJR" firstAttribute="top" secondItem="18s-Im-HaS" secondAttribute="top" id="WxH-ZG-AoU"/>
+                        <constraint firstItem="FYH-Km-v6L" firstAttribute="leading" secondItem="Emb-yN-fCJ" secondAttribute="trailing" constant="5" id="fso-hL-wNN"/>
+                        <constraint firstItem="Emb-yN-fCJ" firstAttribute="leading" secondItem="18s-Im-HaS" secondAttribute="leading" constant="10" id="g2l-c1-CMw"/>
+                        <constraint firstItem="l4x-1S-fJR" firstAttribute="leading" secondItem="FYH-Km-v6L" secondAttribute="trailing" constant="5" id="ipb-KG-e20"/>
+                        <constraint firstAttribute="trailing" secondItem="l4x-1S-fJR" secondAttribute="trailing" id="tbz-Oe-Qqu"/>
+                        <constraint firstItem="FYH-Km-v6L" firstAttribute="top" secondItem="18s-Im-HaS" secondAttribute="top" id="yd3-Yp-Kko"/>
+                        <constraint firstAttribute="height" constant="44" id="ygi-dp-jdw"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="size" keyPath="shadowOffset">
+                            <size key="value" width="0.0" height="2"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowOpacity">
+                            <real key="value" value="1"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="shadowUIColor">
+                            <color key="value" red="0.61568627450000002" green="0.61568627450000002" blue="0.61568627450000002" alpha="0.11" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowRadius">
+                            <real key="value" value="2"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="boolean" keyPath="maskToBounces" value="NO"/>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="18s-Im-HaS" secondAttribute="trailing" constant="14" id="2VW-dV-Qen"/>
+                <constraint firstItem="18s-Im-HaS" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="KB3-aY-BCZ"/>
+                <constraint firstItem="18s-Im-HaS" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="ujd-aT-oAW"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="adView" destination="FYH-Km-v6L" id="0Wo-bl-ahs"/>
+            </connections>
+            <point key="canvasLocation" x="131.8840579710145" y="-67.633928571428569"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="notice_icon" width="23" height="22"/>
+        <image name="notice_more" width="18" height="18"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 3 - 32
KulexiuForStudent/KulexiuForStudent/Module/Home/View/TeacherShowCell.m

@@ -48,40 +48,11 @@
     self.descLabel.text = [NSString returnNoNullStringWithString:sourceModel.describe];
     [self.teacherAvatar sd_setImageWithURL:[NSURL URLWithString:[sourceModel.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
     self.teacherNameLabel.text = [NSString returnNoNullStringWithString:sourceModel.username];
-    self.watchCount.text = [NSString stringWithFormat:@"%@已观看",sourceModel.browse];
+    self.watchCount.text = [NSString stringWithFormat:@"%@已观看",sourceModel.browse];
     
-//    if (![NSString isEmptyString:sourceModel.browse] && ![sourceModel.browse isEqualToString:@"0"]) {
-//        self.watchCount.text = [NSString stringWithFormat:@"%@已观看",sourceModel.browse];
-//    }
-//    else {
-//        self.watchCount.text = @"";
-//    }
-    NSInteger duration = [KSVideoHelper getVideoDuration:sourceModel.videoUrl];
-    NSString *durationString = @"00:00";
-    if (duration / 60 > 0) {
-        NSInteger secondTime = duration % 60;
-        NSString *secondStr = @"";
-        if (secondTime < 10) {
-            secondStr = [NSString stringWithFormat:@"0%zd",secondTime];
-        } else {
-            secondStr = [NSString stringWithFormat:@"%zd",secondTime];
-        }
-        durationString = [NSString stringWithFormat:@"%2ld:%@", duration / 60, secondStr];
-    }
-    else {
-        NSInteger secondTime = duration % 60;
-        NSString *secondStr = @"";
-        if (secondTime < 10) {
-            secondStr = [NSString stringWithFormat:@"0%zd",secondTime];
-        } else {
-            secondStr = [NSString stringWithFormat:@"%zd",secondTime];
-        }
-        durationString = [NSString stringWithFormat:@"00:%@", secondStr];
-    }
-    self.durationLabel.text = durationString;
-}
-
 
+    [KSVideoHelper getVideoDuration:sourceModel.videoUrl displayInLabel:self.durationLabel];
+}
 
 - (IBAction)playButtonAction:(id)sender {
     if (self.callback) {

+ 5 - 9
KulexiuForStudent/KulexiuForStudent/Module/Home/View/TeacherShowCell.xib

@@ -5,7 +5,6 @@
         <deployment identifier="iOS"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -61,10 +60,10 @@
                                 <nil key="highlightedColor"/>
                             </label>
                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hhc-kx-51J">
-                                <rect key="frame" x="121" y="80" width="59" height="20"/>
+                                <rect key="frame" x="119.5" y="80" width="60.5" height="20"/>
                                 <subviews>
-                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="12:30" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ueX-N8-LMM">
-                                        <rect key="frame" x="19" y="0.0" width="30" height="20"/>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ueX-N8-LMM">
+                                        <rect key="frame" x="19" y="0.0" width="31.5" height="20"/>
                                         <fontDescription key="fontDescription" type="system" pointSize="11"/>
                                         <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                         <nil key="highlightedColor"/>
@@ -77,7 +76,7 @@
                                         </constraints>
                                     </imageView>
                                     <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KQK-OM-u6P">
-                                        <rect key="frame" x="0.0" y="0.0" width="59" height="20"/>
+                                        <rect key="frame" x="0.0" y="0.0" width="60.5" height="20"/>
                                         <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                                         <connections>
                                             <action selector="playButtonAction:" destination="gTV-IL-0wX" eventType="touchUpInside" id="FQ3-UU-y89"/>
@@ -105,7 +104,7 @@
                                 </userDefinedRuntimeAttributes>
                             </view>
                         </subviews>
-                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                         <constraints>
                             <constraint firstItem="mwL-ai-act" firstAttribute="centerY" secondItem="9jq-kZ-bi9" secondAttribute="centerY" id="1d2-j3-oWy"/>
                             <constraint firstAttribute="trailing" secondItem="EFx-Mc-ddD" secondAttribute="trailing" id="2yD-0O-HEb"/>
@@ -154,8 +153,5 @@
         <image name="introduce_play" width="10" height="10"/>
         <image name="user_default_avatal" width="52" height="52"/>
         <image name="video_placeholder" width="103" height="72"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
     </resources>
 </document>

+ 10 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.h

@@ -46,6 +46,16 @@ NS_ASSUME_NONNULL_BEGIN
 /// 是否在黑名单中
 @property (nonatomic, assign) BOOL blacklistFlag;
 
+@property (nonatomic, assign) BOOL hideCartButton;
+
+// 是否禁止连麦
+@property (nonatomic, assign) BOOL enableSeat;
+// 是否禁止聊天
+@property (nonatomic, assign) BOOL enableChat;
+// 是否允许点赞
+@property (nonatomic, assign) BOOL enableLike;
+
+
 - (void)quitAction;
 
 @end

File diff suppressed because it is too large
+ 479 - 129
KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.m


+ 4 - 1
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSChatroomMessageCenter.h

@@ -22,7 +22,10 @@
 #import "KSLiveChatroomKickOut.h"
 #import "KSLiveBlockUser.h"
 #import "KSLiveUnBlockUser.h"
-
+#import "RCChatroomLikeCount.h"
+#import "KSRCPauseLiveMessage.h"
+#import "KSRCShopRushMessage.h"
+#import "RCChatroomSeatsControl.h"
 typedef void(^RCChatroomMessageSuccess)(long messageId);
 typedef void(^RCChatroomMessageError)(RCErrorCode errorCode, long messageId);
 

+ 5 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSChatroomMessageCenter.m

@@ -40,6 +40,11 @@
     [[RCIM sharedRCIM] registerMessageType:[KSLiveChatroomMemberUp class]];
     [[RCIM sharedRCIM] registerMessageType:[KSLiveBlockUser class]];
     [[RCIM sharedRCIM] registerMessageType:[KSLiveUnBlockUser class]];
+    [[RCIM sharedRCIM] registerMessageType:[RCChatroomLikeCount class]];
+    [[RCIM sharedRCIM] registerMessageType:[KSRCPauseLiveMessage class]];
+    [[RCIM sharedRCIM] registerMessageType:[KSRCShopRushMessage class]];
+    [[RCIM sharedRCIM] registerMessageType:[RCChatroomSeatsControl class]];
+    
 }
 
 + (void)sendChatMessage:(NSString *)roomId content:(RCMessageContent *)content

+ 17 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCPauseLiveMessage.h

@@ -0,0 +1,17 @@
+//
+//  KSRCPauseLiveMessage.h
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/23.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <RongIMLibCore/RongIMLibCore.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSRCPauseLiveMessage : RCMessageContent
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 38 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCPauseLiveMessage.m

@@ -0,0 +1,38 @@
+//
+//  KSRCPauseLiveMessage.m
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/23.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "KSRCPauseLiveMessage.h"
+
+@implementation KSRCPauseLiveMessage
+- (NSData *)encode {
+    NSMutableDictionary *multableDict = [NSMutableDictionary dictionary];
+    
+    return [NSJSONSerialization dataWithJSONObject:multableDict options:kNilOptions error:nil];
+}
+
+- (void)decodeWithData:(NSData *)data {
+    if (data == nil) return;
+    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
+    NSDictionary *json = [[NSDictionary alloc] initWithDictionary:dictionary];
+    if (json == nil) return;
+}
+
+
++ (NSString *)getObjectName {
+  return @"RC:Chatroom:PauseLive";
+}
+
+- (NSArray<NSString *> *)getSearchableWords {
+  return nil;
+}
+
++ (RCMessagePersistent)persistentFlag {
+  return MessagePersistent_NONE;
+}
+
+@end

+ 27 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCShopRushMessage.h

@@ -0,0 +1,27 @@
+//
+//  KSRCShopRushMessage.h
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/24.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <RongIMLibCore/RongIMLibCore.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSRCShopRushMessage : RCMessageContent
+
+/**
+ 用户id
+*/
+@property(nonatomic, copy, nonnull) NSString *userId;
+
+/**
+ 用户名称
+*/
+@property(nonatomic, copy, nonnull) NSString *userName;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 49 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/KSRCShopRushMessage.m

@@ -0,0 +1,49 @@
+//
+//  KSRCShopRushMessage.m
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/24.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "KSRCShopRushMessage.h"
+
+@implementation KSRCShopRushMessage
+
+- (NSData *)encode {
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    if (self.userId) {
+        [mutableDict setObject:self.userId forKey:@"userId"];
+    } else {
+        [mutableDict setObject:@"" forKey:@"userId"];
+    }
+    if (self.userName) {
+        [mutableDict setObject:self.userName forKey:@"userName"];
+    } else {
+        [mutableDict setObject:@"" forKey:@"userName"];
+    }
+    return [NSJSONSerialization dataWithJSONObject:mutableDict options:kNilOptions error:nil];
+}
+
+- (void)decodeWithData:(NSData *)data {
+    if (data == nil) return;
+    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
+    NSDictionary *json = [[NSDictionary alloc] initWithDictionary:dictionary];
+    if (json == nil) return;
+    self.userId = [json stringValueForKey:@"userId"];
+    self.userName = [json stringValueForKey:@"userName"];
+}
+
++ (NSString *)getObjectName {
+  return @"RC:Chatroom:SnapUp";
+}
+
+- (NSArray<NSString *> *)getSearchableWords {
+  return nil;
+}
+
++ (RCMessagePersistent)persistentFlag {
+  return MessagePersistent_NONE;
+}
+
+@end

+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomLikeCount.h

@@ -0,0 +1,22 @@
+//
+//  RCChatroomLikeCount.h
+//  StudentDaya
+//
+//  Created by 王智 on 2022/4/14.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <RongIMLibCore/RongIMLibCore.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RCChatroomLikeCount : RCMessageContent
+
+/**
+    当前点赞数量
+*/
+@property(nonatomic, assign) NSInteger count;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 39 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomLikeCount.m

@@ -0,0 +1,39 @@
+//
+//  RCChatroomLikeCount.m
+//  StudentDaya
+//
+//  Created by 王智 on 2022/4/14.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "RCChatroomLikeCount.h"
+
+@implementation RCChatroomLikeCount
+
+- (NSData *)encode {
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setObject:@(self.count) forKey:@"count"];
+    return [NSJSONSerialization dataWithJSONObject:mutableDict options:kNilOptions error:nil];
+}
+
+- (void)decodeWithData:(NSData *)data {
+    if (data == nil) return;
+    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
+    NSDictionary *json = [[NSDictionary alloc] initWithDictionary:dictionary];
+    if (json == nil) return;
+    self.count = [[json stringValueForKey:@"count"] intValue];
+}
+
++ (NSString *)getObjectName {
+    return @"RC:Chatroom:LikeCount";
+}
+
+- (NSArray<NSString *> *)getSearchableWords {
+    return nil;
+}
+
++ (RCMessagePersistent)persistentFlag {
+    return MessagePersistent_NONE;
+}
+
+@end

+ 33 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomSeatsControl.h

@@ -0,0 +1,33 @@
+//
+//  RCChatroomSeatsControl.h
+//  StudentDaya
+//
+//  Created by Kyle on 2022/2/21.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <RongIMLibCore/RongIMLibCore.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RCChatroomSeatsControl : RCMessageContent
+
+/**
+ 用户id
+*/
+@property(nonatomic, copy, nonnull) NSString *userId;
+
+/**
+ 用户名称
+*/
+@property(nonatomic, copy, nonnull) NSString *userName;
+
+/**
+ 是否禁止连麦 YES 禁止 NO 开启
+ */
+@property(nonatomic, assign) BOOL seatBan;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 50 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/LiveRoomMessage/RCChatroomSeatsControl.m

@@ -0,0 +1,50 @@
+//
+//  RCChatroomSeatsControl.m
+//  StudentDaya
+//
+//  Created by Kyle on 2022/2/21.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "RCChatroomSeatsControl.h"
+
+@implementation RCChatroomSeatsControl
+
+- (NSData *)encode {
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    if (self.userId) {
+        [mutableDict setObject:self.userId forKey:@"userId"];
+    } else {
+        [mutableDict setObject:@"" forKey:@"userId"];
+    }
+    if (self.userName) {
+        [mutableDict setObject:self.userName forKey:@"userName"];
+    } else {
+        [mutableDict setObject:@"" forKey:@"userName"];
+    }
+    [mutableDict setObject:@(self.seatBan) forKey:@"seatBan"];
+    return [NSJSONSerialization dataWithJSONObject:mutableDict options:kNilOptions error:nil];
+}
+
+- (void)decodeWithData:(NSData *)data {
+    if (data == nil) return;
+    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
+    NSDictionary *json = [[NSDictionary alloc] initWithDictionary:dictionary];
+    if (json == nil) return;
+    self.userId = [json stringValueForKey:@"userId"];
+    self.userName = [json stringValueForKey:@"userName"];
+    self.seatBan = [[json stringValueForKey:@"seatBan"] boolValue];
+}
+
++ (NSString *)getObjectName {
+    return @"RC:Chatroom:SeatsCtrl";
+}
+
+- (NSArray<NSString *> *)getSearchableWords {
+  return nil;
+}
+
++ (RCMessagePersistent)persistentFlag {
+  return MessagePersistent_NONE;
+}
+@end

+ 6 - 2
KulexiuForStudent/KulexiuForStudent/Module/Live/Model/KSLiveStreamVideo.h

@@ -15,7 +15,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, strong) NSString *userId;
 
-@property(nonatomic, copy) NSString *streamId;
+@property (nonatomic, copy) NSString *streamId;
+
+@property (nonatomic, strong) NSString *streamTag;
 
 /*!
  包含子类的 RCRTCLocalVideoView 和 RCRTCRemoteVideoView
@@ -25,8 +27,10 @@ NS_ASSUME_NONNULL_BEGIN
 /*!
  RCRTCRemoteVideoView 初始化
  @param streamId  音视频流 Id
+ @param userId 流所属用户
+ @param tag 流类型标识
  */
-- (instancetype)initWithStreamId:(NSString *)streamId;
+- (instancetype)initWithStreamId:(NSString *)streamId streamUserId:(NSString *)userId streamTag:(NSString *)tag;
 
 /*!
  本地 RCRTCLocalVideoView 初始化

+ 11 - 3
KulexiuForStudent/KulexiuForStudent/Module/Live/Model/KSLiveStreamVideo.m

@@ -11,9 +11,17 @@ static NSString *zero = @"0";
 @implementation KSLiveStreamVideo
 
 // 根据 streamId 创建并设置远端视频预览视图
-- (instancetype)initWithStreamId:(nonnull NSString *)stream {
+/*!
+ RCRTCRemoteVideoView 初始化
+ @param streamId  音视频流 Id
+ @param userId 流所属用户
+ @param tag 流类型标识
+ */
+- (instancetype)initWithStreamId:(NSString *)streamId streamUserId:(NSString *)userId streamTag:(NSString *)tag {
     if (self = [super init]) {
-        self.streamId = stream;
+        self.streamId = streamId;
+        self.userId = userId;
+        self.streamTag = tag;
         self.canvesView = [[RCRTCVideoView alloc] init];
         self.canvesView.frameAnimated = NO;
         self.canvesView.translatesAutoresizingMaskIntoConstraints = NO;
@@ -26,7 +34,7 @@ static NSString *zero = @"0";
     KSLiveStreamVideo *localStreamVideo = [[KSLiveStreamVideo alloc] init];
     // 初始化 这里的 streamId 推荐 0
     localStreamVideo.streamId = zero;
-    localStreamVideo.canvesView = [[RCRTCVideoView alloc] init];
+    localStreamVideo.canvesView = [[RCRTCVideoView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
     localStreamVideo.canvesView.frameAnimated = NO;
     localStreamVideo.canvesView.translatesAutoresizingMaskIntoConstraints = NO;
     localStreamVideo.canvesView.fillMode = RCRTCVideoFillModeAspectFill;

+ 30 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/AnimationView/LiveAnimationView.h

@@ -0,0 +1,30 @@
+//
+//  LiveAnimationView.h
+//  TeacherDaya
+//
+//  Created by 王智 on 2022/6/20.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSInteger, ANIMATIONTYPE) {
+    ANIMATIONTYPE_JOIN,
+    ANIMATIONTYPE_RUSH,
+};
+
+typedef void(^AnimationEndCallback)(void);
+
+@interface LiveAnimationView : UIView
+
+@property (nonatomic, assign) BOOL isShow;
+
+- (instancetype)initWithTitle:(NSString *)tipsTitle animationType:(ANIMATIONTYPE)type;
+
+- (void)startAnimationEndCallback:(AnimationEndCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 147 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/AnimationView/LiveAnimationView.m

@@ -0,0 +1,147 @@
+//
+//  LiveAnimationView.m
+//  TeacherDaya
+//
+//  Created by 王智 on 2022/6/20.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "LiveAnimationView.h"
+
+@interface LiveAnimationView ()
+
+@property (nonatomic, strong) UIImageView *cartImgView;
+
+@property (nonatomic, strong) UILabel *tipLabel;
+
+@property (nonatomic, assign) ANIMATIONTYPE animationType;
+
+@property (nonatomic, strong) NSString *tipsTitle;
+
+@property (nonatomic, strong) UIView *colorBgView;
+
+@property (nonatomic, copy) AnimationEndCallback callback;
+
+@property (nonatomic, assign) CGFloat colorViewWidth;
+@end
+
+@implementation LiveAnimationView
+
+- (instancetype)initWithTitle:(NSString *)tipsTitle animationType:(ANIMATIONTYPE)type {
+    self = [super init];
+    if (self) {
+        self.tipsTitle = tipsTitle;
+        self.animationType = type;
+        [self configUI];
+    }
+    return self;
+}
+
+- (void)configUI {
+    [self addSubview:self.colorBgView];
+    self.colorViewWidth = [self getViewWidth];
+    self.colorBgView.frame = CGRectMake(-self.colorViewWidth + 10, 0, self.colorViewWidth, 24);
+    [self.colorBgView addSubview:self.tipLabel];
+    self.tipLabel.text = self.tipsTitle;
+    if (self.animationType == ANIMATIONTYPE_RUSH) {
+        
+        [self.colorBgView addSubview:self.cartImgView];
+        self.cartImgView.frame = CGRectMake(8.0f, 3.0f, 18.0f, 18.0f);
+        self.tipLabel.frame = CGRectMake(CGRectGetMaxX(self.cartImgView.frame) + 5, 3.0f, self.colorViewWidth - 39, 18.0f);
+        
+        CAGradientLayer *layer = [self createGradientLayerFromColor:HexRGB(0xffb300) startPoint:CGPointMake(1, 0.5) endColor:HexRGB(0xff6500) endPoint:CGPointMake(0, 0.5) bounds:CGRectMake(0, 0, self.colorViewWidth, 24)];
+        layer.cornerRadius = 12.0f;
+        layer.masksToBounds = YES;
+        [self.colorBgView.layer addSublayer:layer];
+        [self.colorBgView bringSubviewToFront:self.cartImgView];
+        [self.colorBgView bringSubviewToFront:self.tipLabel];
+    }
+    else {
+        self.tipLabel.frame = CGRectMake(10, 3.0f, self.colorViewWidth - 19.0f, 18.0f);
+
+        CAGradientLayer *layer = [self createGradientLayerFromColor:HexRGB(0x60fff7) startPoint:CGPointMake(1, 0.5) endColor:HexRGB(0x00bf85) endPoint:CGPointMake(0, 0.5) bounds:CGRectMake(0, 0, self.colorViewWidth, 24)];
+        layer.cornerRadius = 12.0f;
+        layer.masksToBounds = YES;
+        [self.colorBgView.layer addSublayer:layer];
+        [self.colorBgView bringSubviewToFront:self.tipLabel];
+    }
+}
+
+- (CGFloat)getViewWidth {
+    CGFloat width = 0.0f;
+    if (self.animationType == ANIMATIONTYPE_RUSH) {
+        width = [self.tipsTitle boundingRectWithSize:CGSizeMake(KPortraitWidth - 60, CGFLOAT_MAX) options:(NSStringDrawingTruncatesLastVisibleLine |NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13.0f weight:UIFontWeightMedium],NSForegroundColorAttributeName:HexRGB(0x666666)} context:nil].size.width + 40;
+    }
+    else {
+        width = [self.tipsTitle boundingRectWithSize:CGSizeMake(KPortraitWidth - 39, CGFLOAT_MAX) options:(NSStringDrawingTruncatesLastVisibleLine |NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13.0f weight:UIFontWeightMedium],NSForegroundColorAttributeName:HexRGB(0x666666)} context:nil].size.width + 20;
+    }
+    return width;
+}
+
+- (void)startAnimationEndCallback:(AnimationEndCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    self.isShow = YES;
+
+    [UIView animateWithDuration:1.0f animations:^{
+        self.colorBgView.frame = CGRectMake(10, 0, self.colorViewWidth, 24);
+    } completion:^(BOOL finished) {
+            [self hideAnimation];
+
+    }];
+}
+
+- (void)hideAnimation {
+    [UIView animateWithDuration:1.0f animations:^{
+        self.alpha = 0.0f;
+    } completion:^(BOOL finished) {
+        self.callback();
+    }];
+}
+
+- (CAGradientLayer *)createGradientLayerFromColor:(UIColor *)fromColor startPoint:(CGPoint)startPoint endColor:(UIColor *)endColor endPoint:(CGPoint)endPoint bounds:(CGRect)bounds {
+    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
+    gradientLayer.colors = @[(__bridge id)fromColor.CGColor, (__bridge id)endColor.CGColor];
+    gradientLayer.startPoint = startPoint;
+    gradientLayer.endPoint = endPoint;
+    gradientLayer.frame = bounds;
+    gradientLayer.locations = @[@(0),@(1.0f)];
+    return gradientLayer;
+}
+
+- (UIView *)colorBgView {
+    if (!_colorBgView) {
+        _colorBgView = [[UIView alloc] initWithFrame:CGRectZero];
+        _colorBgView.backgroundColor = [UIColor clearColor];
+        _colorBgView.layer.cornerRadius = 12.0f;
+        
+    }
+    return _colorBgView;
+}
+
+- (UIImageView *)cartImgView {
+    if (!_cartImgView) {
+        _cartImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cart_logo"]];
+    }
+    return _cartImgView;
+}
+
+- (UILabel *)tipLabel {
+    if (!_tipLabel) {
+        _tipLabel = [[UILabel alloc] init];
+        _tipLabel.textColor = HexRGB(0xffffff);
+        _tipLabel.font = [UIFont systemFontOfSize:13.0f weight:UIFontWeightMedium];
+    }
+    return _tipLabel;
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 29 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveBadNetView.h

@@ -0,0 +1,29 @@
+//
+//  KSLiveBadNetView.h
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/19.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^BadNetCallback)(void);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSLiveBadNetView : UIView
+
+@property (nonatomic, strong) UIImageView *emptyImageView;
+
+@property (nonatomic, strong) UILabel *descLabel;
+
+@property (nonatomic, strong) UIButton *refreshButton;
+
+- (void)configViewWithImageName:(NSString *)imageName desc:(NSString *)desc callback:(BadNetCallback)callback;
+
+- (void)dispPlayViewIsPhoneLive:(BOOL)isPhoneLive;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 144 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveBadNetView.m

@@ -0,0 +1,144 @@
+//
+//  KSLiveBadNetView.m
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/19.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "KSLiveBadNetView.h"
+
+@interface KSLiveBadNetView ()
+
+@property (nonatomic, copy) BadNetCallback callback;
+
+@end
+
+
+@implementation KSLiveBadNetView
+
+- (instancetype)init {
+    self = [super init];
+    if (self) {
+        [self configUI];
+    }
+    return self;
+}
+
+- (void)configUI {
+    self.backgroundColor = HexRGB(0x1a1a1a);
+    [self addSubview:self.emptyImageView];
+    [self.emptyImageView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.centerX.mas_equalTo(self.mas_centerX);
+        make.centerY.mas_equalTo(self.mas_centerY).offset(-18);
+        make.width.mas_equalTo(123);
+        make.height.mas_equalTo(74);
+    }];
+    
+    UIView *contentView = [[UIView alloc] init];
+    contentView.backgroundColor = HexRGBAlpha(0xffffff, 0.05f);
+    contentView.layer.cornerRadius = 12.5f;
+    [self addSubview:contentView];
+    [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.mas_equalTo(self.emptyImageView.mas_bottom).offset(7);
+        make.centerX.mas_equalTo(self.mas_centerX);
+        make.height.mas_equalTo(25);
+        make.left.mas_greaterThanOrEqualTo(self.mas_left).offset(10);
+    }];
+    
+    [contentView addSubview:self.descLabel];
+    [self.descLabel mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.centerX.mas_equalTo(contentView.mas_centerX);
+        make.centerY.mas_equalTo(contentView.mas_centerY);
+        make.left.mas_equalTo(contentView.mas_left).offset(8);
+    }];
+    
+    [self addSubview:self.refreshButton];
+    self.refreshButton.layer.cornerRadius = 18.0f;
+    self.refreshButton.layer.borderColor = HexRGB(0x999999).CGColor;
+    self.refreshButton.layer.borderWidth = 1.0f;
+    [self.refreshButton mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.centerX.mas_equalTo(self.mas_centerX);
+        make.top.mas_equalTo(contentView.mas_bottom).offset(5);
+        make.width.mas_equalTo(80);
+        make.height.mas_equalTo(36);
+    }];
+}
+
+- (void)dispPlayViewIsPhoneLive:(BOOL)isPhoneLive {
+    if (isPhoneLive) {
+        [self.emptyImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
+            if (@available(iOS 11.0, *)) {
+                make.top.mas_equalTo(self.mas_safeAreaLayoutGuideTop).offset(142);
+            } else {
+                // Fallback on earlier versions
+                make.top.mas_equalTo(self.mas_top).offset(142);
+            }
+            make.centerX.mas_equalTo(self.mas_centerX);
+            make.width.mas_equalTo(123);
+            make.height.mas_equalTo(74);
+        }];
+    }
+    else {
+        [self.emptyImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
+            make.centerX.mas_equalTo(self.mas_centerX);
+            make.centerY.mas_equalTo(self.mas_centerY).offset(-18);
+            make.width.mas_equalTo(123);
+            make.height.mas_equalTo(74);
+        }];
+
+    }
+}
+
+- (void)configViewWithImageName:(NSString *)imageName desc:(NSString *)desc callback:(BadNetCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    [self.emptyImageView setImage:[UIImage imageNamed:imageName]];
+    self.descLabel.text = desc;
+}
+
+- (void)refreshAction {
+    if (self.callback) {
+        self.callback();
+    }
+}
+
+#pragma mark --- lazying
+- (UIImageView *)emptyImageView {
+    if (!_emptyImageView) {
+        _emptyImageView = [[UIImageView alloc] init];
+    }
+    return _emptyImageView;
+}
+
+- (UILabel *)descLabel {
+    if (!_descLabel) {
+        _descLabel = [[UILabel alloc] init];
+        _descLabel.textColor = HexRGB(0x999999);
+        _descLabel.textAlignment = NSTextAlignmentCenter;
+        _descLabel.font = [UIFont systemFontOfSize:12.0f];
+    }
+    return _descLabel;
+}
+
+- (UIButton *)refreshButton {
+    if (!_refreshButton) {
+        _refreshButton = [UIButton buttonWithType:UIButtonTypeCustom];
+        [_refreshButton setBackgroundColor:[UIColor clearColor]];
+        [_refreshButton addTarget:self action:@selector(refreshAction) forControlEvents:UIControlEventTouchUpInside];
+        [_refreshButton setTitle:@"刷新一下" forState:UIControlStateNormal];
+        [_refreshButton.titleLabel setFont:[UIFont systemFontOfSize:13.0f]];
+        [_refreshButton setTitleColor:HexRGB(0x999999) forState:UIControlStateNormal];
+    }
+    return _refreshButton;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 2 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEmptyView.h

@@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, strong) UILabel *descLabel;
 
+- (void)dispPlayViewIsPhoneLive:(BOOL)isPhoneLive;
+
 - (void)configViewWithImageName:(NSString *)imageName desc:(NSString *)desc;
 
 @end

+ 24 - 1
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEmptyView.m

@@ -43,10 +43,33 @@
         make.centerX.mas_equalTo(contentView.mas_centerX);
         make.centerY.mas_equalTo(contentView.mas_centerY);
         make.left.mas_equalTo(contentView.mas_left).offset(8);
-        make.right.mas_equalTo(contentView.mas_right).offset(-7);
     }];
 }
 
+- (void)dispPlayViewIsPhoneLive:(BOOL)isPhoneLive {
+    if (isPhoneLive) {
+        [self.emptyImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
+            if (@available(iOS 11.0, *)) {
+                make.top.mas_equalTo(self.mas_safeAreaLayoutGuideTop).offset(160);
+            } else {
+                // Fallback on earlier versions
+                make.top.mas_equalTo(self.mas_top).offset(160);
+            }
+            make.centerX.mas_equalTo(self.mas_centerX);
+            make.width.mas_equalTo(123);
+            make.height.mas_equalTo(74);
+        }];
+    }
+    else {
+        [self.emptyImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
+            make.center.mas_equalTo(self);
+            make.width.mas_equalTo(123);
+            make.height.mas_equalTo(74);
+        }];
+    }
+}
+
+
 - (void)configViewWithImageName:(NSString *)imageName desc:(NSString *)desc {
     [self.emptyImageView setImage:[UIImage imageNamed:imageName]];
     self.descLabel.text = desc;

+ 21 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEndView.h

@@ -0,0 +1,21 @@
+//
+//  KSLiveEndView.h
+//  StudentDaya
+//
+//  Created by 王智 on 2022/6/7.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSLiveEndView : UIView
+
+
+- (void)dispPlayViewIsPhoneLive:(BOOL)isPhoneLive;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 98 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSLiveEndView.m

@@ -0,0 +1,98 @@
+//
+//  KSLiveEndView.m
+//  StudentDaya
+//
+//  Created by 王智 on 2022/6/7.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "KSLiveEndView.h"
+
+@interface KSLiveEndView ()
+
+@property (nonatomic, strong) UIImageView *closeImageView;
+
+@property (nonatomic, strong) UILabel *tipsLabel;
+
+@end
+
+@implementation KSLiveEndView
+
+- (instancetype)init {
+    self = [super init];
+    if (self) {
+        [self configUI];
+    }
+    return self;
+}
+
+- (void)configUI {
+    [self addSubview:self.closeImageView];
+    [self addSubview:self.tipsLabel];
+}
+
++ (instancetype)shareInstance {
+    KSLiveEndView *view = [[[NSBundle mainBundle] loadNibNamed:@"KSLiveEndView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)dispPlayViewIsPhoneLive:(BOOL)isPhoneLive {
+    if (isPhoneLive) {
+        [self.closeImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
+            if (@available(iOS 11.0, *)) {
+                make.top.mas_equalTo(self.mas_safeAreaLayoutGuideTop).offset(160);
+            } else {
+                // Fallback on earlier versions
+                make.top.mas_equalTo(self.mas_top).offset(160);
+            }
+            make.centerX.mas_equalTo(self.mas_centerX);
+            make.width.mas_equalTo(123);
+            make.height.mas_equalTo(74);
+        }];
+        
+    }
+    else {
+        [self.closeImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
+            make.center.mas_equalTo(self);
+            make.width.mas_equalTo(123);
+            make.height.mas_equalTo(74);
+        }];
+    }
+    
+    [self.tipsLabel mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.centerX.mas_equalTo(self.mas_centerX);
+        make.height.mas_equalTo(20);
+        make.top.mas_equalTo(self.closeImageView.mas_bottom).offset(11);
+        make.left.mas_equalTo(self.mas_left).offset(10);
+    }];
+}
+
+- (UIImageView *)closeImageView {
+    if (!_closeImageView) {
+        _closeImageView = [[UIImageView alloc] init];
+        [_closeImageView setImage:[UIImage imageNamed:@"liveroom_close"]];
+    }
+    return _closeImageView;
+}
+
+- (UILabel *)tipsLabel {
+    if (!_tipsLabel) {
+        _tipsLabel = [[UILabel alloc] init];
+        _tipsLabel.text = @"直播已结束!";
+        _tipsLabel.font = [UIFont systemFontOfSize:14.0f weight:UIFontWeightMedium];
+        _tipsLabel.textColor = HexRGB(0x999999);
+        _tipsLabel.textAlignment = NSTextAlignmentCenter;
+        
+    }
+    return _tipsLabel;
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 3 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomBottomView.h

@@ -21,12 +21,15 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface LiveRoomBottomView : UIView
 
+@property (weak, nonatomic) IBOutlet UILabel *tipsLabel;
+
 @property (nonatomic, assign) BOOL hideChatView;
 
 @property (weak, nonatomic) IBOutlet UIView *likeButton;
 
 @property (weak, nonatomic) IBOutlet UIButton *seatButton;
 
+@property (nonatomic, assign) BOOL hideCartVButton;
 
 + (instancetype)shareInstance;
 

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Mine/Controller/MineViewController.m

@@ -81,7 +81,7 @@
     [_bodyView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.top.mas_equalTo(headView.mas_bottom);
         make.left.right.mas_equalTo(self.view);
-        make.height.mas_equalTo(viewHeight);    
+        make.height.mas_equalTo(viewHeight);
         make.bottom.mas_equalTo(self.scrollView.mas_bottom);
     }];
     MJWeakSelf;

+ 10 - 0
KulexiuForStudent/KulexiuForStudent/Module/Mine/Homework/Controller/HomeworkDetailViewController.m

@@ -43,6 +43,8 @@
 
 @property (nonatomic, strong) HomeworkBottomView *bottomView;
 
+@property (nonatomic, assign) BOOL isModify; // 是否修改作业
+
 @end
 
 @implementation HomeworkDetailViewController
@@ -53,6 +55,7 @@
     [self allocTitle:@"作业详情"];
     [self setupUI];
     [self requestCourseMessage];
+    _isModify = NO;
 }
 
 - (void)setupUI {
@@ -204,6 +207,7 @@
     } successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
         [self hudTipWillShow:NO];
         NSString *fileUrl = [fileUrlArray lastObject];
+        self.isModify = YES;
         // 删除文件
         [self removeVideoWithPath:videoUrl];
         [self.fileArray addObject:fileUrl];
@@ -236,6 +240,7 @@
         [self.fileArray removeObjectAtIndex:index];
         [self.tableView reloadData];
     }
+    self.isModify = YES;
 }
 
 #pragma mark ------ WMPlayer
@@ -292,6 +297,10 @@
 }
 
 - (void)submitHomeworkAction {
+    if (self.isModify == NO) {
+        [self MBPShow:@"请先选择视频文件"];
+        return;
+    }
     if (self.fileArray.count == 0) {
         [self MBPShow:@"请选择作业视频"];
         return;
@@ -303,6 +312,7 @@
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             [self MBPShow:@"作业提交成功"];
             [self requestCourseMessage];
+            self.isModify = NO;
         }
         else {
             [self MBPShow:MESSAGEKEY];

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

@@ -244,7 +244,7 @@
             KSChoosePicker *picker = [[KSChoosePicker alloc] initWithTitle:@"声部筛选" sourceData:nameArray chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
                 if (chooseIndex == 0) {
                     [weakSelf.sortView.thirdButton setTitle:@"全部声部" forState:UIControlStateNormal];
-                    weakSelf.subjectId = @"";
+                    weakSelf.subjectId = nil;
                 }
                 else {
                     [weakSelf.sortView.thirdButton setTitle:returnValue forState:UIControlStateNormal];

+ 6 - 0
KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/Classroom/ClassroomService.m

@@ -239,6 +239,12 @@
         return;
     }
     
+    if (type == DeviceTypeHandup) {
+        if (self.currentRoom.currentDisplayType == DisplayTypeStudent && [self.currentRoom.currentDisplayURI isEqualToString:UserDefault(UIDKey)]) {
+            return;
+        }
+    }
+    
     NSString *deviceType = [self getDeviceTypeDesc:type];
     
     [KSNetworkingManager roomDeviceSync:KS_POST deviceType:deviceType roomId:self.currentRoom.roomId enable:enable success:^(NSDictionary * _Nonnull dic) {

+ 17 - 5
KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/Classroom/Message/MemberChangeMessage.m

@@ -16,11 +16,23 @@
 - (void)decodeWithData:(NSData *)data {
     NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
     if(dic) {
-        self.userId = dic[@"userId"];
-        self.userName = dic[@"userName"];
-        self.role = [dic[@"role"] intValue];
-        self.action = [dic[@"action"] integerValue];
-        self.timestamp = [dic[@"timestamp"] longValue];
+        NSDictionary *member = [dic dictionaryValueForKey:@"roomMember"];
+        self.userId = [member stringValueForKey:@"userId"];
+        self.userName = [member stringValueForKey:@"username"];
+        self.role = [member intValueForKey:@"role"];
+        NSString *roleString = [dic stringValueForKey:@"changedEnum"];
+        if ([roleString isEqualToString:@"LEAVE"]) {
+            self.action = MemberChangeActionLeave;
+        }
+        else if ([roleString isEqualToString:@"JOIN"]) {
+            self.action = MemberChangeActionJoin;
+        }
+        else {
+            self.action = MemberChangeActionKick;
+        }
+        
+        
+        self.timestamp = [member longValueForKey:@"joinTime"];
     }
 }
 + (NSString *)getObjectName {

+ 3 - 0
KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/Classroom/Model/Classroom.m

@@ -91,6 +91,9 @@
 }
 
 - (void)updateMember:(NSString *)userId forHandsUp:(BOOL)enable {
+    if ([userId isEqualToString:self.currentDisplayURI]) {
+        return;
+    }
     RoomMember *member = [self getMember:userId];
     member.handUpOn = enable;
     [self updateMemeber:member];

+ 29 - 23
KulexiuForStudent/KulexiuForStudent/Module/SealClass/Services/RTC/RTCService.m

@@ -12,10 +12,10 @@
 
 #define SharedScreenStreamTag @"screenshare"
 
-@interface RTCService ()<RCRTCVideoInputStreamDelegate>
+@interface RTCService ()<RCRTCVideoInputStreamEventDelegate,RCRTCVideoOutputStreamEventDelegate>
 @property (nonatomic, strong) RCRTCRoom *rtcRoom;
 @property (nonatomic, strong) RCRTCCameraOutputStream *capturer;
-@property (nonatomic, strong) RCRTCLocalVideoView *localView;
+@property (nonatomic, strong) RCRTCVideoView *localView;
 @property (nonatomic, strong) RCRTCMicOutputStream *audioCapturer;
 @property (nonatomic, strong) NSMutableDictionary *cachedVideoBufferDic;
 @property (nonatomic, strong) UIImage *currentUserImage;
@@ -146,8 +146,11 @@
             for (RCRTCInputStream *stream in remoteUser.remoteStreams) {
                 if (RTCMediaTypeVideo == stream.mediaType && [stream.tag isEqualToString:SharedScreenStreamTag]) {
                     RCRTCVideoInputStream *videoStream = (RCRTCVideoInputStream *)stream;
-                    RCRTCRemoteVideoView *remoteView = [[RCRTCRemoteVideoView alloc] initWithFrame:view.bounds];
+                    RCRTCVideoView *remoteView = [[RCRTCVideoView alloc] init];
+                    remoteView.frame = view.bounds;
                     remoteView.backgroundColor = [UIColor colorWithHexString:@"3D4041" alpha:1];
+                    remoteView.frameAnimated = NO;
+                    remoteView.translatesAutoresizingMaskIntoConstraints = NO;
                     [view insertSubview:remoteView atIndex:0];
                     [videoStream setVideoView:remoteView];
                     
@@ -170,16 +173,6 @@
         BOOL micOn = [ClassroomService sharedService].currentRoom.currentMember.microphoneEnable;
         [self setMicrophoneDisable:!micOn];
         
-        __weak typeof(self) ws = self;
-#pragma mark   ---- 此处可以使用美颜处理数据
-        [self.capturer setVideoSendBufferCallback:^CMSampleBufferRef _Nullable(BOOL valid, CMSampleBufferRef  _Nullable sampleBuffer) {
-            if(ws.needRefreshCurrentUserImage) {
-                CVPixelBufferRef pixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer);
-                ws.currentUserImage = [ws imageForPixelBufferRef:pixelBufferRef];
-                ws.needRefreshCurrentUserImage = NO;
-            }
-            return sampleBuffer;
-        }];
         if (enable) {
             [self.capturer startCapture];
         }
@@ -197,9 +190,11 @@
     }
     
     if (!self.localView) {
-        self.localView = [[RCRTCLocalVideoView alloc] initWithFrame:view.bounds];
+        self.localView = [[RCRTCVideoView alloc] init];
+        self.localView.frame= view.bounds;
         self.localView.backgroundColor = [UIColor colorWithHexString:@"3D4041" alpha:1];
         self.localView.fillMode = RCRTCVideoFillModeAspectFill;
+        self.localView.translatesAutoresizingMaskIntoConstraints = NO;
         self.localView.frameAnimated = NO;
 //        self.localView.isPreviewMirror = NO;
         [self.capturer setVideoView:self.localView];
@@ -214,7 +209,7 @@
     BOOL canceled = NO;
     UIView *renderedView = nil;
     for(UIView * v in view.subviews) {
-        if([v isKindOfClass:[RCRTCLocalVideoView class]] || [v isKindOfClass:[RCRTCRemoteVideoView class]]) {
+        if([v isKindOfClass:[RCRTCVideoView class]]) {
             renderedView = v;
             break;
         }
@@ -260,7 +255,7 @@
     // 没有订阅用户才去订阅
     if (![[KSRemoteUserManager shareInstance] isContentUser:remoteUser.userId]) {
                 
-        [self.rtcRoom.localUser subscribeStream:nil tinyStreams:remoteUser.remoteStreams completion:^(BOOL isSuccess, RCRTCCode desc) {
+        [self.rtcRoom.localUser subscribeStream:@[] tinyStreams:remoteUser.remoteStreams completion:^(BOOL isSuccess, RCRTCCode desc) {
             if (isSuccess) {
                 [[KSRemoteUserManager shareInstance] addUser:remoteUser.userId];
                 // 在播放节拍器状态下 不播放进入房间学生的信息
@@ -334,7 +329,7 @@
     }
     
     if (streamArray.count > 0) {
-        [self.rtcRoom.localUser subscribeStream:nil tinyStreams:streamArray completion:^(BOOL isSuccess, RCRTCCode desc) {
+        [self.rtcRoom.localUser subscribeStream:@[] tinyStreams:streamArray completion:^(BOOL isSuccess, RCRTCCode desc) {
             if (isSuccess) {
                 NSLog(@"订阅音频流成功");
             }
@@ -400,7 +395,7 @@
                 }];
             }
             else { // 订阅小流
-                [self.rtcRoom.localUser subscribeStream:nil tinyStreams:remoteUser.remoteStreams completion:^(BOOL isSuccess, RCRTCCode desc) {
+                [self.rtcRoom.localUser subscribeStream:@[] tinyStreams:remoteUser.remoteStreams completion:^(BOOL isSuccess, RCRTCCode desc) {
                     if (isSuccess) {
                         [[KSRemoteUserManager shareInstance] addUser:remoteUser.userId];
                         // 在播放节拍器状态下 不播放进入房间学生的信息
@@ -448,7 +443,7 @@
                     });
                     return;
                 }
-                [self.rtcRoom.localUser subscribeStream:remoteUser.remoteStreams tinyStreams:nil completion:^(BOOL isSuccess, RCRTCCode desc) {
+                [self.rtcRoom.localUser subscribeStream:remoteUser.remoteStreams tinyStreams:@[] completion:^(BOOL isSuccess, RCRTCCode desc) {
                     if (isSuccess) {
                         [[KSRemoteUserManager shareInstance] addUser:remoteUser.userId];
                         completeBlock();
@@ -470,11 +465,13 @@
     for(RCRTCInputStream *stream in remoteUser.remoteStreams) {
         if(RTCMediaTypeVideo == stream.mediaType && ![stream.tag isEqualToString:SharedScreenStreamTag]) {
             RCRTCVideoInputStream *videoStream = (RCRTCVideoInputStream *)stream;
-            RCRTCRemoteVideoView *remoteView = [[RCRTCRemoteVideoView alloc] initWithFrame:view.bounds];
+            RCRTCVideoView *remoteView = [[RCRTCVideoView alloc] init];
             remoteView.backgroundColor = [UIColor colorWithHexString:@"3D4041" alpha:1];
             remoteView.frame = view.bounds;
             remoteView.fillMode = RCRTCVideoFillModeAspectFill;
-            videoStream.delegate = self;
+            remoteView.frameAnimated = NO;
+            remoteView.translatesAutoresizingMaskIntoConstraints = NO;
+            videoStream.streamEventDelegate = self;
             [view insertSubview:remoteView atIndex:0];
             [videoStream setVideoView:remoteView];
             return;
@@ -523,8 +520,8 @@
     self.needRefreshCurrentUserImage = YES;
 }
 
--(void)willRenderCVPixelBufferRef:(CVPixelBufferRef)ref stream:(RCRTCInputStream *)stream {
-    [self.cachedVideoBufferDic setValue:(__bridge id _Nullable)(ref) forKey:stream.userId];
+- (void)inputVideoStream:(RCRTCVideoInputStream *)stream willRenderVideoFrame:(nullable RCRTCVideoFrame *)videoFrame {
+    [self.cachedVideoBufferDic setValue:(__bridge id _Nullable)(videoFrame.pixelBuffer) forKey:stream.userId];
 }
 
 - (UIImage *)imageForPixelBufferRef:(CVPixelBufferRef)sampleBuffer {
@@ -580,11 +577,20 @@
     return image;
 }
 
+// 摄像头输出
+- (void)outputVideoStream:(RCRTCVideoOutputStream *)stream willRenderVideoFrame:(RCRTCVideoFrame *)videoFrame {
+    if(self.needRefreshCurrentUserImage) {
+        CVPixelBufferRef pixelBufferRef = videoFrame.pixelBuffer;
+        self.currentUserImage = [self imageForPixelBufferRef:pixelBufferRef];
+        self.needRefreshCurrentUserImage = NO;
+    }
+}
 #pragma mark - getter
 - (RCRTCCameraOutputStream *)capturer {
     if(!_capturer) {
         _capturer = [RCRTCEngine sharedInstance].defaultVideoStream;
         _capturer.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
+        _capturer.streamEventDelegate = self;
 //        _capturer.isPreviewMirror = YES;
     }
     return _capturer;

BIN
KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_group_portrait@2x.png


BIN
KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_group_portrait@3x.png


BIN
KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait@2x.png


BIN
KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait@3x.png


BIN
KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait_msg@2x.png


BIN
KulexiuForStudent/Pods/RongCloudIM/RongCloudIM/RongCloud.bundle/default_portrait_msg@3x.png


Some files were not shown because too many files changed in this diff