ソースを参照

主考和助考老师身份

Steven 5 年 前
コミット
d080f8ea9a
46 ファイル変更1122 行追加79 行削除
  1. 52 0
      MusicGradeExam/MusicGradeExam.xcodeproj/project.pbxproj
  2. 6 0
      MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/Contents.json
  3. 22 0
      MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/count_image.imageset/Contents.json
  4. BIN
      MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/count_image.imageset/count_image@2x.png
  5. BIN
      MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/count_image.imageset/count_image@3x.png
  6. 22 0
      MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/record_bg.imageset/Contents.json
  7. BIN
      MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/record_bg.imageset/record_bg@2x.png
  8. BIN
      MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/record_bg.imageset/record_bg@3x.png
  9. 8 8
      MusicGradeExam/MusicGradeExam/Define/PrefixHeader.pch
  10. 33 2
      MusicGradeExam/MusicGradeExam/KSRequestManager.h
  11. 50 3
      MusicGradeExam/MusicGradeExam/KSRequestManager.m
  12. 17 5
      MusicGradeExam/MusicGradeExam/UI/Classroom/Controller/ClassroomViewController.m
  13. 6 6
      MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/ClassroomDefine.h
  14. 15 15
      MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/ClassroomService.m
  15. 2 2
      MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/Model/Classroom.m
  16. 3 0
      MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/Util/Macro.h
  17. 2 2
      MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/Util/Portrait/RolePortraitView.m
  18. 2 2
      MusicGradeExam/MusicGradeExam/UI/Classroom/View/MainContainer/EmptyView.m
  19. 1 1
      MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListCell.h
  20. 10 5
      MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListCell.m
  21. 0 4
      MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListView.h
  22. 11 8
      MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListView.m
  23. 18 2
      MusicGradeExam/MusicGradeExam/UI/Exam/Controller/WaitExamViewController.m
  24. 5 0
      MusicGradeExam/MusicGradeExam/UI/Exam/View/WaitExamBodyView.h
  25. 20 3
      MusicGradeExam/MusicGradeExam/UI/Exam/View/WaitExamBodyView.m
  26. 2 0
      MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Controller/ExamLibraryController.h
  27. 3 2
      MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Controller/ExamLibraryController.m
  28. 26 5
      MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Controller/ExamViewController.m
  29. 21 0
      MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Model/BaseExamModel.h
  30. 102 0
      MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Model/BaseExamModel.m
  31. 3 2
      MusicGradeExam/MusicGradeExam/UI/ExamLibrary/View/ExamListCell.h
  32. 7 2
      MusicGradeExam/MusicGradeExam/UI/ExamLibrary/View/ExamListCell.m
  33. 17 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/Controller/RecordExamViewController.h
  34. 158 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/Controller/RecordExamViewController.m
  35. 28 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBodyView.h
  36. 45 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBodyView.m
  37. 119 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBodyView.xib
  38. 23 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBottomView.h
  39. 43 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBottomView.m
  40. 45 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBottomView.xib
  41. 17 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordListCell.h
  42. 25 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordListCell.m
  43. 40 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordListCell.xib
  44. 19 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordTipsView.h
  45. 28 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordTipsView.m
  46. 46 0
      MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordTipsView.xib

+ 52 - 0
MusicGradeExam/MusicGradeExam.xcodeproj/project.pbxproj

@@ -17,6 +17,16 @@
 		2729F7DF24C81FB000E1F3C4 /* LibraryTipsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2729F7DE24C81FB000E1F3C4 /* LibraryTipsView.xib */; };
 		2729F7E324C8244100E1F3C4 /* ExamListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2729F7E124C8244100E1F3C4 /* ExamListCell.m */; };
 		2729F7E424C8244100E1F3C4 /* ExamListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2729F7E224C8244100E1F3C4 /* ExamListCell.xib */; };
+		2729F7E724C8326900E1F3C4 /* RecordExamViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2729F7E624C8326900E1F3C4 /* RecordExamViewController.m */; };
+		2729F7EA24C8328700E1F3C4 /* RecordBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2729F7E924C8328700E1F3C4 /* RecordBodyView.m */; };
+		2729F7EC24C8329700E1F3C4 /* RecordBodyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2729F7EB24C8329700E1F3C4 /* RecordBodyView.xib */; };
+		2729F7F024C8379D00E1F3C4 /* RecordListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2729F7EE24C8379D00E1F3C4 /* RecordListCell.m */; };
+		2729F7F124C8379D00E1F3C4 /* RecordListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2729F7EF24C8379D00E1F3C4 /* RecordListCell.xib */; };
+		2729F7F424C8395300E1F3C4 /* RecordBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2729F7F324C8395300E1F3C4 /* RecordBottomView.m */; };
+		2729F7F624C8398B00E1F3C4 /* RecordBottomView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2729F7F524C8398B00E1F3C4 /* RecordBottomView.xib */; };
+		2729F7F924C8425E00E1F3C4 /* RecordTipsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2729F7F824C8425E00E1F3C4 /* RecordTipsView.m */; };
+		2729F7FB24C8427200E1F3C4 /* RecordTipsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2729F7FA24C8427100E1F3C4 /* RecordTipsView.xib */; };
+		2729F7FE24C851FA00E1F3C4 /* BaseExamModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 2729F7FC24C851F900E1F3C4 /* BaseExamModel.m */; };
 		27476F4824BBFB5900181362 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 27476F4724BBFB5900181362 /* AppDelegate.m */; };
 		27476F4E24BBFB5900181362 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 27476F4D24BBFB5900181362 /* ViewController.m */; };
 		27476F5124BBFB5900181362 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 27476F4F24BBFB5900181362 /* Main.storyboard */; };
@@ -392,6 +402,22 @@
 		2729F7E024C8244100E1F3C4 /* ExamListCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExamListCell.h; sourceTree = "<group>"; };
 		2729F7E124C8244100E1F3C4 /* ExamListCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExamListCell.m; sourceTree = "<group>"; };
 		2729F7E224C8244100E1F3C4 /* ExamListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ExamListCell.xib; sourceTree = "<group>"; };
+		2729F7E524C8326900E1F3C4 /* RecordExamViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordExamViewController.h; sourceTree = "<group>"; };
+		2729F7E624C8326900E1F3C4 /* RecordExamViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordExamViewController.m; sourceTree = "<group>"; };
+		2729F7E824C8328700E1F3C4 /* RecordBodyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordBodyView.h; sourceTree = "<group>"; };
+		2729F7E924C8328700E1F3C4 /* RecordBodyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordBodyView.m; sourceTree = "<group>"; };
+		2729F7EB24C8329700E1F3C4 /* RecordBodyView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RecordBodyView.xib; sourceTree = "<group>"; };
+		2729F7ED24C8379D00E1F3C4 /* RecordListCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordListCell.h; sourceTree = "<group>"; };
+		2729F7EE24C8379D00E1F3C4 /* RecordListCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordListCell.m; sourceTree = "<group>"; };
+		2729F7EF24C8379D00E1F3C4 /* RecordListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RecordListCell.xib; sourceTree = "<group>"; };
+		2729F7F224C8395300E1F3C4 /* RecordBottomView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordBottomView.h; sourceTree = "<group>"; };
+		2729F7F324C8395300E1F3C4 /* RecordBottomView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordBottomView.m; sourceTree = "<group>"; };
+		2729F7F524C8398B00E1F3C4 /* RecordBottomView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RecordBottomView.xib; sourceTree = "<group>"; };
+		2729F7F724C8425E00E1F3C4 /* RecordTipsView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordTipsView.h; sourceTree = "<group>"; };
+		2729F7F824C8425E00E1F3C4 /* RecordTipsView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordTipsView.m; sourceTree = "<group>"; };
+		2729F7FA24C8427100E1F3C4 /* RecordTipsView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RecordTipsView.xib; sourceTree = "<group>"; };
+		2729F7FC24C851F900E1F3C4 /* BaseExamModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseExamModel.m; sourceTree = "<group>"; };
+		2729F7FD24C851FA00E1F3C4 /* BaseExamModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseExamModel.h; sourceTree = "<group>"; };
 		27476F4324BBFB5900181362 /* 酷乐秀.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "酷乐秀.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		27476F4624BBFB5900181362 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
 		27476F4724BBFB5900181362 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -1089,6 +1115,8 @@
 		2729F7D524C81CA200E1F3C4 /* Controller */ = {
 			isa = PBXGroup;
 			children = (
+				2729F7E524C8326900E1F3C4 /* RecordExamViewController.h */,
+				2729F7E624C8326900E1F3C4 /* RecordExamViewController.m */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -1103,6 +1131,18 @@
 		2729F7D724C81CA300E1F3C4 /* View */ = {
 			isa = PBXGroup;
 			children = (
+				2729F7E824C8328700E1F3C4 /* RecordBodyView.h */,
+				2729F7E924C8328700E1F3C4 /* RecordBodyView.m */,
+				2729F7EB24C8329700E1F3C4 /* RecordBodyView.xib */,
+				2729F7F724C8425E00E1F3C4 /* RecordTipsView.h */,
+				2729F7F824C8425E00E1F3C4 /* RecordTipsView.m */,
+				2729F7FA24C8427100E1F3C4 /* RecordTipsView.xib */,
+				2729F7ED24C8379D00E1F3C4 /* RecordListCell.h */,
+				2729F7EE24C8379D00E1F3C4 /* RecordListCell.m */,
+				2729F7EF24C8379D00E1F3C4 /* RecordListCell.xib */,
+				2729F7F224C8395300E1F3C4 /* RecordBottomView.h */,
+				2729F7F324C8395300E1F3C4 /* RecordBottomView.m */,
+				2729F7F524C8398B00E1F3C4 /* RecordBottomView.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -2313,6 +2353,8 @@
 		2748F8ED24C05F30003F8E11 /* Model */ = {
 			isa = PBXGroup;
 			children = (
+				2729F7FD24C851FA00E1F3C4 /* BaseExamModel.h */,
+				2729F7FC24C851F900E1F3C4 /* BaseExamModel.m */,
 				2729F7C824C6EB4900E1F3C4 /* SubjectNameModel.h */,
 				2729F7C924C6EB4A00E1F3C4 /* SubjectNameModel.m */,
 				2729F7CB24C6F3F300E1F3C4 /* SongListModel.h */,
@@ -2708,9 +2750,11 @@
 				2747718A24BC0C0500181362 /* WMPlayer.bundle in Resources */,
 				27476F5624BBFB5C00181362 /* LaunchScreen.storyboard in Resources */,
 				2747727F24BC0C7C00181362 /* RCColor.plist in Resources */,
+				2729F7EC24C8329700E1F3C4 /* RecordBodyView.xib in Resources */,
 				27EF3EF824BEF1E8002068A2 /* TicketBodyView.xib in Resources */,
 				27A008F924BDB6310002452B /* UserBodyView.xib in Resources */,
 				2794D1C424BD60E900BAF6F3 /* UserCenterBodyView.xib in Resources */,
+				2729F7FB24C8427200E1F3C4 /* RecordTipsView.xib in Resources */,
 				2794D1B224BC605600BAF6F3 /* VefiBodyView.xib in Resources */,
 				2747728324BC0C7D00181362 /* RongCloud.bundle in Resources */,
 				27A008A724BD96C50002452B /* NetworkBodyView.xib in Resources */,
@@ -2720,6 +2764,8 @@
 				27A008FE24BECDFC0002452B /* HomeBodyView.xib in Resources */,
 				274771AC24BC0C0500181362 /* mss_browseLoading@3x.png in Resources */,
 				274771ED24BC0C0500181362 /* LoginBodyView.xib in Resources */,
+				2729F7F624C8398B00E1F3C4 /* RecordBottomView.xib in Resources */,
+				2729F7F124C8379D00E1F3C4 /* RecordListCell.xib in Resources */,
 				2794D1BA24BC69A400BAF6F3 /* RegisterBodyView.xib in Resources */,
 				2747719624BC0C0500181362 /* TZImagePickerController.bundle in Resources */,
 				27A008DE24BDA6950002452B /* PhoneCheckBodyView.xib in Resources */,
@@ -2862,6 +2908,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				2729F7F924C8425E00E1F3C4 /* RecordTipsView.m in Sources */,
 				2747722A24BC0C0500181362 /* KSHoldButton.m in Sources */,
 				2747719A24BC0C0500181362 /* TZPhotoPreviewCell.m in Sources */,
 				274771E324BC0C0500181362 /* KSIMService.m in Sources */,
@@ -2937,10 +2984,12 @@
 				274771E024BC0C0500181362 /* Classroom.m in Sources */,
 				2747719F24BC0C0500181362 /* SCIndexViewConfiguration.m in Sources */,
 				2747720D24BC0C0500181362 /* UIView+AddConstraints.m in Sources */,
+				2729F7EA24C8328700E1F3C4 /* RecordBodyView.m in Sources */,
 				274771BC24BC0C0500181362 /* ALCalendarCollectionView.m in Sources */,
 				27EF3EF224BEE885002068A2 /* NotifyMessageCell.m in Sources */,
 				274771F424BC0C0500181362 /* KSLRUManager.m in Sources */,
 				2747718C24BC0C0500181362 /* FastForwardView.m in Sources */,
+				2729F7FE24C851FA00E1F3C4 /* BaseExamModel.m in Sources */,
 				2747718724BC0C0500181362 /* JYEqualCellSpaceFlowLayout.m in Sources */,
 				274771E624BC0C0500181362 /* LoginViewController.m in Sources */,
 				2747726424BC0C0500181362 /* LLPhoto.m in Sources */,
@@ -2967,6 +3016,7 @@
 				2747720924BC0C0500181362 /* UIAlertController+Extend.m in Sources */,
 				27A008C624BD99BD0002452B /* UserViewController.m in Sources */,
 				27A008EE24BDA7100002452B /* AboutBodyView.m in Sources */,
+				2729F7F424C8395300E1F3C4 /* RecordBottomView.m in Sources */,
 				27476F4E24BBFB5900181362 /* ViewController.m in Sources */,
 				274771DC24BC0C0500181362 /* TurnPageMessage.m in Sources */,
 				2747721124BC0C0500181362 /* NSArray+ks_SafeAccess.m in Sources */,
@@ -2987,6 +3037,7 @@
 				2747725D24BC0C0500181362 /* KSMessageInputView.m in Sources */,
 				274771CB24BC0C0500181362 /* RTCService.m in Sources */,
 				274771CD24BC0C0500181362 /* RolePortraitView.m in Sources */,
+				2729F7E724C8326900E1F3C4 /* RecordExamViewController.m in Sources */,
 				2747722024BC0C0500181362 /* UIImage+Property.m in Sources */,
 				274771C624BC0C0500181362 /* KSTabBarController.m in Sources */,
 				27EF3F2A24C02DE9002068A2 /* EmptyView.m in Sources */,
@@ -3105,6 +3156,7 @@
 				274771EF24BC0C0500181362 /* KSRCIMDataSource.m in Sources */,
 				274771EB24BC0C0500181362 /* UserInfoManager.m in Sources */,
 				2747723224BC0C0500181362 /* JXPagerListContainerView.m in Sources */,
+				2729F7F024C8379D00E1F3C4 /* RecordListCell.m in Sources */,
 				27A008C324BD99B10002452B /* SettingViewController.m in Sources */,
 				2747725724BC0C0500181362 /* UITextView_Toolbar.m in Sources */,
 				274771DA24BC0C0500181362 /* MemberChangeMessage.m in Sources */,

+ 6 - 0
MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/Contents.json

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

+ 22 - 0
MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/count_image.imageset/Contents.json

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

BIN
MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/count_image.imageset/count_image@2x.png


BIN
MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/count_image.imageset/count_image@3x.png


+ 22 - 0
MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/record_bg.imageset/Contents.json

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

BIN
MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/record_bg.imageset/record_bg@2x.png


BIN
MusicGradeExam/MusicGradeExam/Assets.xcassets/RecordExam/record_bg.imageset/record_bg@3x.png


+ 8 - 8
MusicGradeExam/MusicGradeExam/Define/PrefixHeader.pch

@@ -85,17 +85,17 @@
 
 //#ifdef DEBUG
 
-//#define hostURL (@"http://kjtest.dayaedu.com")
-//#define SEALCLASSHOST (@"http://kjtest.dayaedu.com/api-im")
-//#define WEBHOST (@"http://mstudev.dayaedu.com")
-//#define JSPUSH_ENVIRONMENT (NO)
-//#define RCIM_KEY (@"8luwapkv84g3l")
-
-#define hostURL (@"http://192.168.3.28:8000")
-#define SEALCLASSHOST (@"http://192.168.3.28:8000/api-im")
+#define hostURL (@"http://kjtest.dayaedu.com")
+#define SEALCLASSHOST (@"http://kjtest.dayaedu.com/api-im")
 #define WEBHOST (@"http://mstudev.dayaedu.com")
 #define JSPUSH_ENVIRONMENT (NO)
 #define RCIM_KEY (@"8luwapkv84g3l")
+
+//#define hostURL (@"http://192.168.3.28:8000")
+//#define SEALCLASSHOST (@"http://192.168.3.28:8000/api-im")
+//#define WEBHOST (@"http://mstudev.dayaedu.com")
+//#define JSPUSH_ENVIRONMENT (NO)
+//#define RCIM_KEY (@"8luwapkv84g3l")
 //#else    // 线上
 
 //#define hostURL (@"https://online.dayaedu.com")

+ 33 - 2
MusicGradeExam/MusicGradeExam/KSRequestManager.h

@@ -317,25 +317,56 @@ NS_ASSUME_NONNULL_BEGIN
 + (void)signInRequest:(NSString *)post examRegistrationId:(NSString *)examRegistrationId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
 #pragma mark ---- 曲库
+// /api-user/examRegistration/studentBaseExams
+
+/// 获取考级项目
+/// @param get get
+/// @param success 成功
+/// @param faliure 失败
++ (void)studentBaseExamsRequest:(NSString *)get success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 // /api-user/subject/studentQueryPage
 
 /// 获取学生曲库科目
 /// @param get get
+/// @param tenantId 考试编号
 /// @param success 成功
 /// @param faliure 失败
-+ (void)musicLibraryPageRequest:(NSString *)get success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
++ (void)musicLibraryPageRequest:(NSString *)get tenantId:(NSString *)tenantId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
 // /api-user/examSong/queryPage
 
 /// 分页查询曲目
 /// @param get get
+/// @param tenantId 考试编号
 /// @param subjectList 专业
 /// @param level 级别
 /// /// @param page 分页
 /// @param rows 条数
 /// @param success 成功
 /// @param faliure 失败
-+ (void)musicSongListRequest:(NSString *)get subjectList:(NSString *)subjectList level:(NSString *)level page:(NSString *)page rows:(NSString *)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
++ (void)musicSongListRequest:(NSString *)get tenantId:(NSString *)tenantId subjectList:(NSString *)subjectList level:(NSString *)level page:(NSString *)page rows:(NSString *)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+#pragma mark ----- 录播考试
+// examRoomStudentRelation/stuRecordDetail
+
+/// 录播详情页查询
+/// @param get get
+/// @param examRegistrationId 报名编号
+/// @param success 成功
+/// @param faliure 失败
++ (void)stuRecordDetailRequest:(NSString *)get examRegistrationId:(NSString *)examRegistrationId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+// examRoomStudentRelation/stuEndRecord
+
+/// 完成录播
+/// @param post post
+/// @param examRegistrationId 报名编号
+/// @param videoUrl 链接
+/// @param success 成功
+/// @param faliure 失败
++ (void)stuEndRecordFinishRequest:(NSString *)post examRegistrationId:(NSString *)examRegistrationId videoUrl:(NSString *)videoUrl success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 50 - 3
MusicGradeExam/MusicGradeExam/KSRequestManager.m

@@ -712,32 +712,47 @@
 }
 
 #pragma mark ---- 曲库
+// /api-user/examRegistration/studentBaseExams
+
+/// 获取考级项目
+/// @param get get
+/// @param success 成功
+/// @param faliure 失败
++ (void)studentBaseExamsRequest:(NSString *)get success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-user/examRegistration/studentBaseExams"];
+    [self request:get url:url parm:nil success:success faliure:faliure];
+}
+
 // /api-user/subject/studentQueryPage
 
 /// 获取学生曲库科目
 /// @param get get
+/// @param tenantId 考试编号
 /// @param success 成功
 /// @param faliure 失败
-+ (void)musicLibraryPageRequest:(NSString *)get success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
++ (void)musicLibraryPageRequest:(NSString *)get tenantId:(NSString *)tenantId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-user/subject/studentQueryPage"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:@"0" forKey:@"parentId"];
-    [self request:get url:url parm:nil success:success faliure:faliure];
+    [parm setValue:tenantId forKey:@"tenantId"];
+    [self request:get url:url parm:parm success:success faliure:faliure];
 }
 
 // /api-user/examSong/queryPage
 
 /// 分页查询曲目
 /// @param get get
+/// @param tenantId 考试编号
 /// @param subjectList 专业
 /// @param level 级别
 /// /// @param page 分页
 /// @param rows 条数
 /// @param success 成功
 /// @param faliure 失败
-+ (void)musicSongListRequest:(NSString *)get subjectList:(NSString *)subjectList level:(NSString *)level page:(NSString *)page rows:(NSString *)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
++ (void)musicSongListRequest:(NSString *)get tenantId:(NSString *)tenantId subjectList:(NSString *)subjectList level:(NSString *)level page:(NSString *)page rows:(NSString *)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure  {
     NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-user/examSong/queryPage"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:tenantId forKey:@"tenantId"];
     [parm setValue:subjectList forKey:@"subjectList"];
     [parm setValue:level forKey:@"level"];
     [parm setValue:page forKey:@"page"];
@@ -745,4 +760,36 @@
     [self request:get url:url parm:nil success:success faliure:faliure];
 }
 
+#pragma mark ----- 录播考试
+// examRoomStudentRelation/stuRecordDetail
+
+/// 录播详情页查询
+/// @param get get
+/// @param examRegistrationId 报名编号
+/// @param success 成功
+/// @param faliure 失败
++ (void)stuRecordDetailRequest:(NSString *)get examRegistrationId:(NSString *)examRegistrationId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-user/examRoomStudentRelation/stuRecordDetail"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:examRegistrationId forKey:@"examRegistrationId"];
+    [self request:get url:url parm:parm success:success faliure:faliure];
+}
+
+// examRoomStudentRelation/stuEndRecord
+
+/// 完成录播
+/// @param post post
+/// @param examRegistrationId 报名编号
+/// @param videoUrl 链接
+/// @param success 成功
+/// @param faliure 失败
++ (void)stuEndRecordFinishRequest:(NSString *)post examRegistrationId:(NSString *)examRegistrationId videoUrl:(NSString *)videoUrl success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodForm];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-user/examRoomStudentRelation/stuEndRecord"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:examRegistrationId forKey:@"examRegistrationId"];
+    [parm setValue:videoUrl forKey:@"videoUrl"];
+    [self request:post url:url parm:parm success:success faliure:faliure];
+}
+
 @end

+ 17 - 5
MusicGradeExam/MusicGradeExam/UI/Classroom/Controller/ClassroomViewController.m

@@ -338,10 +338,10 @@
 
 - (void)memberDidJoin:(RoomMember *)member {
     NSLog(@"memberDidJoin %@",member);
-    if(member.role == RoleTeacher) {
+    if(member.role == RoleMainTeacher || member.role == RoleAssistantTeacher) {
         [self.videoListView reloadVideoList];
     }
-    if (member.role == RoleTeacher || member.role == RoleAssistant) {
+    if (member.role == RoleMainTeacher || member.role == RoleAssistantTeacher) {
         [self.tipsView showTipsMessage:[NSString stringWithFormat:@"老师%@已经进入教室", member.name] inView:self.view];
     }
 }
@@ -351,15 +351,26 @@
     // 此处移除
     [[KSRemoteUserManager shareInstance] removeUser:member.userId];
     
-    if(member.role == RoleTeacher) {
+    if(member.role == RoleMainTeacher || member.role == RoleAssistantTeacher) {
         [self.videoListView reloadVideoList];
     }
 }
 
 - (void)memberDidKick:(RoomMember *)member {
     NSLog(@"memberDidKick %@",member);
+    RoomMember *curMember = [ClassroomService sharedService].currentRoom.currentMember;
+    [[ClassroomService sharedService].currentRoom removeMemeber:member];
+    if ([curMember.userId isEqualToString:member.userId]) {
+        [KSNormalAlertView ks_showAlertWithTitle:@"恭喜您,考试已结束,请耐心等待考试结果。" confirmTitle:@"退出考场" confirm:^{
+            [self roomDidLeave];
+        }];
+        return;
+    }
+    
+    
     [[KSRemoteUserManager shareInstance] removeUser:member.userId];
-    if ([ClassroomService sharedService].currentRoom.currentMember.role == RoleTeacher) {
+    Role curRole = [ClassroomService sharedService].currentRoom.currentMember.role;
+    if (curRole == RoleMainTeacher || curRole == RoleAssistantTeacher) {
         [self.tipsView showTipsMessage:[NSString stringWithFormat:@"你已将%@移出课堂", member.name] inView:self.view];
     }
     [self.videoListView reloadVideoList];
@@ -389,6 +400,7 @@
             } error:^(RongRTCCode code) {
                 [self.hud hideAnimated:YES];
             }];
+            [[NSNotificationCenter defaultCenter] postNotificationName:RecordExamNotification object:nil];
         }];
     }
 }
@@ -410,7 +422,7 @@
     RoomMember *curMember = [ClassroomService sharedService].currentRoom.currentMember;
     NSString *hudMessage = @"";
     //只有老师和自己才有提示
-    if (curMember.role == RoleTeacher && ![curMember.userId isEqualToString:operatorId]) {
+    if ((curMember.role == RoleMainTeacher || curMember.role == RoleAssistantTeacher) && ![curMember.userId isEqualToString:operatorId]) {
         if (type == DeviceTypeCamera) {
             hudMessage = !enable ? [NSString stringWithFormat:NSLocalizedStringFromTable(@"SetCameraClose", @"SealClass", nil),member.name] : [NSString stringWithFormat:NSLocalizedStringFromTable(@"SetCameraOpen", @"SealClass", nil),member.name];
         } else if (type == DeviceTypeMicrophone) {

+ 6 - 6
MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/ClassroomDefine.h

@@ -10,13 +10,13 @@
 #define ClassroomDefine_h
 
 typedef NS_ENUM(NSUInteger, Role) {
-    //助教
-    RoleAssistant = 1,
-    //老师
-    RoleTeacher = 2,
-    //学生
+    // 主考
+    RoleMainTeacher = 1,
+    // 助考
+    RoleAssistantTeacher = 2,
+    // 学生
     RoleStudent = 3,
-    //旁观者
+    // 旁观者
     RoleAudience = 4,
 };
 

+ 15 - 15
MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/ClassroomService.m

@@ -271,7 +271,7 @@
     NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
     [dic setObject:self.currentRoom.roomId forKey:@"roomId"];
     [dic setObject:userId forKey:@"userId"];
-    [dic setObject:@(RoleTeacher) forKey:@"role"];
+    [dic setObject:@(RoleAssistantTeacher) forKey:@"role"];
     [HTTPUtility requestWithHTTPMethod:HTTPMethodPost URLString:@"/room/change-role" parameters:dic response:^(HTTPResult *result) {
         if(result.success){
         }else {
@@ -707,17 +707,16 @@
                 }
             }
         } else if(msg.action == MemberChangeActionKick) {
-            if ([msg.userId isEqualToString:self.currentRoom.currentMember.userId]) {
-                if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) {
-                    [self.classroomDelegate roomDidLeave];
-                }
-            } else {
+//            if ([msg.userId isEqualToString:self.currentRoom.currentMember.userId]) {
+//                if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) {
+//                    [self.classroomDelegate roomDidLeave];
+//                }
+//            } else {
                 RoomMember *mem = [self.currentRoom getMember:msg.userId];
-                [self.currentRoom removeMemeber:mem];
                 if([self.classroomDelegate respondsToSelector:@selector(memberDidKick:)]) {
                     [self.classroomDelegate memberDidKick:mem];
                 }
-            }
+//            }
         }
         else if (msg.action == MemberChangeActionRecord) { // 去录制
             RoomMember *mem = [self.currentRoom getMember:msg.userId];
@@ -726,6 +725,7 @@
             }
         }
         else if (msg.action == MemberChangeActionRefresh) { // 刷新列表
+            
             [[NSNotificationCenter defaultCenter] postNotificationName:RefreshWaitListNotification object:nil];
         }
     });
@@ -816,7 +816,7 @@
 
 - (void)onReceiveApplySpeechMessage:(ApplySpeechMessage *)msg {
     dispatch_main_async_safe(^{
-        if (self.currentRoom.currentMember.role == RoleAssistant) {
+        if (self.currentRoom.currentMember.role == RoleMainTeacher) {
             if ([self.classroomDelegate respondsToSelector:@selector(upgradeDidApply:ticket:overMaxCount:)]) {
                 RoomMember *mem = [self.currentRoom getMember:msg.requestUserId];
                 if(!mem) {
@@ -867,9 +867,9 @@
 - (void)onReceiveAssistantTransferMessage:(AssistantTransferMessage *)msg {
     dispatch_main_async_safe(^{
         if([self.classroomDelegate respondsToSelector:@selector(roleDidChange:forUser:)]) {
-            [self.currentRoom updateMemeber:msg.toUserId forRole:RoleAssistant];
+            [self.currentRoom updateMemeber:msg.toUserId forRole:RoleMainTeacher];
             [self.currentRoom updateMemeber:msg.operatorId forRole:RoleStudent];
-            [self.classroomDelegate roleDidChange:RoleAssistant forUser:[self.currentRoom getMember:msg.toUserId]];
+            [self.classroomDelegate roleDidChange:RoleMainTeacher forUser:[self.currentRoom getMember:msg.toUserId]];
 //            [self.classroomDelegate roleDidChange:RoleStudent forUser:[self.currentRoom getMember:msg.operatorId]];
         }
         if ([self.classroomDelegate respondsToSelector:@selector(assistantDidTransfer:newAssistant:)]){
@@ -895,7 +895,7 @@
                 }
             }
         } else if (msg.action == InviteUpgradeActionApprove) {
-            if (self.currentRoom.currentMember.role == RoleAssistant) {
+            if (self.currentRoom.currentMember.role == RoleMainTeacher) {
                 if ([self.classroomDelegate respondsToSelector:@selector(inviteDidApprove:)]) {
                     RoomMember *mem = [self.currentRoom getMember:msg.operatorId];
                     if(!mem) {
@@ -908,7 +908,7 @@
                 }
             }
         } else if (msg.action == InviteUpgradeActionReject) {
-            if (self.currentRoom.currentMember.role == RoleAssistant) {
+            if (self.currentRoom.currentMember.role == RoleMainTeacher) {
                 if ([self.classroomDelegate respondsToSelector:@selector(inviteDidReject:)]) {
                     RoomMember *mem = [self.currentRoom getMember:msg.operatorId];
                     if(!mem) {
@@ -930,14 +930,14 @@
                 [self.classroomDelegate deviceDidInviteEnable:msg.type ticket:msg.ticket];
             }
         } else if (msg.action == ControlDeviceActionApprove) {
-            if (self.currentRoom.currentMember.role == RoleAssistant) {
+            if (self.currentRoom.currentMember.role == RoleMainTeacher) {
                 if ([self.classroomDelegate respondsToSelector:@selector(deviceInviteEnableDidApprove:type:)]) {
                     RoomMember *mem = [self.currentRoom getMember:msg.opUserId];
                     [self.classroomDelegate deviceInviteEnableDidApprove:mem type:msg.type];
                 }
             }
         } else if (msg.action == ControlDeviceActionReject) {
-            if (self.currentRoom.currentMember.role == RoleAssistant) {
+            if (self.currentRoom.currentMember.role == RoleMainTeacher) {
                 if ([self.classroomDelegate respondsToSelector:@selector(deviceInviteEnableDidReject:type:)]) {
                     RoomMember *mem = [self.currentRoom getMember:msg.opUserId];
                     [self.classroomDelegate deviceInviteEnableDidReject:mem type:msg.type];

+ 2 - 2
MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/Model/Classroom.m

@@ -154,7 +154,7 @@
 
 - (RoomMember *)teacher {
     for(RoomMember *mem in self.memberList) {
-        if(mem.role == RoleTeacher) {
+        if(mem.role == RoleAssistantTeacher) {
             return mem;
         }
     }
@@ -163,7 +163,7 @@
 
 - (RoomMember *)assistant {
     for(RoomMember *mem in self.memberList) {
-        if(mem.role == RoleAssistant) {
+        if(mem.role == RoleMainTeacher) {
             return mem;
         }
     }

+ 3 - 0
MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/Util/Macro.h

@@ -22,4 +22,7 @@ NSLog(@"[SealClassLog] desc: %@", [NSString stringWithFormat:(s), ##__VA_ARGS__]
 #define OnReceiveMessageNotification @"OnReceiveMessageNotification"
 
 #define RefreshWaitListNotification @"RefreshWaitListNotification"
+
+#define RecordExamNotification @"RecordExamNotification"
+
 #endif /* Macro_h */

+ 2 - 2
MusicGradeExam/MusicGradeExam/UI/Classroom/Service/Classroom/Util/Portrait/RolePortraitView.m

@@ -39,10 +39,10 @@
 - (CAGradientLayer *)getRoleHeaderGradientLayer:(RoomMember *)member{
     CAGradientLayer *gradientLayer;
     switch (member.role) {
-        case RoleAssistant:
+        case RoleMainTeacher:
             gradientLayer = [self createGradientLayerWithColors:@[(__bridge id)[UIColor colorWithHexString:@"FCCF31" alpha:1].CGColor,(__bridge id)[UIColor colorWithHexString:@"F56352" alpha:1].CGColor]];
             break;
-        case RoleTeacher:
+        case RoleAssistantTeacher:
             gradientLayer = [self createGradientLayerWithColors:@[(__bridge id)[UIColor colorWithHexString:@"FBA276" alpha:1].CGColor,(__bridge id)[UIColor colorWithHexString:@"EB5756" alpha:1].CGColor]];
             break;
         case RoleStudent:

+ 2 - 2
MusicGradeExam/MusicGradeExam/UI/Classroom/View/MainContainer/EmptyView.m

@@ -44,8 +44,8 @@
 - (void)changeRole:(Role)role {
     self.currentRole = role;
     switch (role) {
-        case RoleAssistant:
-        case RoleTeacher:
+        case RoleMainTeacher:
+        case RoleAssistantTeacher:
             self.emptyImageView.image = [UIImage imageNamed:@"empty_teacher"];
             self.emptyLabel.text = @"当前无共享内容,您可以新建共享内容";
             break;

+ 1 - 1
MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListCell.h

@@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, assign) CGSize cellSize;
 
-- (void)setModel:(RoomMember *)member showTeacherPrompt:(BOOL)teacherPrompt;
+- (void)setModel:(RoomMember *)member;
 
 - (void)renderVideo:(RoomMember *)member;
 

+ 10 - 5
MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListCell.m

@@ -87,7 +87,7 @@
     self.videoView.size = cellSize;
 }
 
-- (void)setModel:(RoomMember *)member showTeacherPrompt:(BOOL)teacherPrompt {
+- (void)setModel:(RoomMember *)member {
     [self resetDefaultStyle];
     if (member == nil) {
         return;
@@ -108,10 +108,15 @@
         else {
             [self remakeNameLable:member];
             if (![member.userId isEqualToString:[ClassroomService sharedService].currentRoom.currentMember.userId]) {
-                if (teacherPrompt) {
-                    self.promptLable.hidden = NO;
-                }
                 self.roleLable.hidden = NO;
+                if (member.role == RoleMainTeacher) {
+                    self.roleLable.text = @"主考";
+                    self.roleLable.backgroundColor = HexRGB(0xF5A623);
+                }
+                else {
+                    self.roleLable.text = @"助考";
+                    self.roleLable.backgroundColor = HexRGB(0xFF5500);
+                }
             }
             else {
                 self.roleLable.hidden = YES;
@@ -190,7 +195,7 @@
         _roleLable.textAlignment = NSTextAlignmentCenter;
         _roleLable.textColor = [UIColor colorWithHexString:@"FFFFFF" alpha:1];
         _roleLable.backgroundColor = HexRGB(0xFF5500);
-        _roleLable.text = @"老师";
+        _roleLable.text = @"助考";
         _roleLable.layer.cornerRadius = 4;
         _roleLable.layer.masksToBounds = YES;
     }

+ 0 - 4
MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListView.h

@@ -19,16 +19,12 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface ClassVideoListView : UIView
 
-@property (nonatomic, assign) BOOL showTeacherPrompt;
-
 @property (nonatomic, weak) id<ClassVideoListViewDelegate> delegate;
 
 - (void)updateUserVideo:(NSString *)userId;
 
 - (void)reloadVideoList;
 
-- (void)showTeacherPrompt:(BOOL)showTeacherPrompt;
-
 @end
 
 NS_ASSUME_NONNULL_END

+ 11 - 8
MusicGradeExam/MusicGradeExam/UI/Classroom/View/VideoList/ClassVideoListView.m

@@ -29,7 +29,6 @@
         self.backgroundColor = [UIColor clearColor];
         [self addSubview:self.videoListTableView];
         [self getDataSource];
-        self.showTeacherPrompt = NO;
     }
     return self;
 }
@@ -46,16 +45,26 @@
         NSMutableArray *lastArray = [sortArray mutableCopy];
         
         NSMutableArray *removeArray = [NSMutableArray array];
+        NSInteger mainTeacherIndex = -1;
         for (int i = 0; i < [lastArray count]; i++) {
             RoomMember *member = (RoomMember *)[sortArray objectAtIndex:i];
+            if (member.role == RoleMainTeacher) {
+                mainTeacherIndex = i;
+            }
             if (member.role == RoleStudent) {
                 [removeArray addObject:member];
             }
         }
+        // 将主考老师放在第一位
+        if (mainTeacherIndex > 0) {
+            [lastArray exchangeObjectAtIndex:0 withObjectAtIndex:mainTeacherIndex];
+        }
+        
         // 移除列表上的学生
         if (removeArray.count) {
             [lastArray removeObjectsInArray:removeArray];
         }
+        
         dispatch_async(dispatch_get_main_queue(), ^{
             self.videoDataSource = [lastArray mutableCopy];
             [self.videoListTableView reloadData];
@@ -84,12 +93,6 @@
     [self getDataSource];
 }
 
-- (void)showTeacherPrompt:(BOOL)showTeacherPrompt {
-    self.showTeacherPrompt = showTeacherPrompt;
-    [self reloadVideoList];
-}
-
-
 #pragma mark - tableViewDelegate
 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     static NSString * cellName = @"VideoListCell";
@@ -99,7 +102,7 @@
     }
     cell.cellSize = CGSizeMake(CGRectGetWidth(self.frame), (CGRectGetWidth(self.frame) - 20) / 4.0 * 3);
     if (self.videoDataSource.count > 0) {
-        [cell setModel:[self.videoDataSource objectAtIndex:indexPath.row] showTeacherPrompt:self.showTeacherPrompt];
+        [cell setModel:[self.videoDataSource objectAtIndex:indexPath.row]];
     }
     return cell;
 }

+ 18 - 2
MusicGradeExam/MusicGradeExam/UI/Exam/Controller/WaitExamViewController.m

@@ -10,6 +10,7 @@
 #import "WaitExamBodyView.h"
 #import "TicketDetailModel.h"
 #import "OnlineRoomManager.h"
+#import "RecordExamViewController.h"
 
 @interface WaitExamViewController ()
 
@@ -33,8 +34,16 @@
     [self configUI];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backLoginView) name:@"backLoginView" object:nil];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshWaitList) name:RefreshWaitListNotification object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toRecordExam) name:RecordExamNotification object:nil];
 }
 
+// 去录播
+- (void)toRecordExam {
+    RecordExamViewController *ctrl = [[RecordExamViewController alloc] init];
+    [self.navigationController pushViewController:ctrl animated:YES];
+}
+
+
 - (void)refreshWaitList {
     [self requestDataWithHub:NO];
 }
@@ -111,8 +120,14 @@
             break;
         case JOINROOMACTION_JOIN:  // 加入房间
         {
-            NSString *roomId = [NSString stringWithFormat:@"%.0f", source.examRegistrationId];
-            [self joinRoomAction:roomId];
+//            if (self.sourceModel.openFlag == 1) { // 去录播
+//                RecordExamViewController *ctrl = [[RecordExamViewController alloc] init];
+//                [self.navigationController pushViewController:ctrl animated:YES];
+//            }
+//            else {
+                NSString *roomId = [NSString stringWithFormat:@"%.0f", source.examRegistrationId];
+                [self joinRoomAction:roomId];
+//            }
         }
             break;
         default:
@@ -128,6 +143,7 @@
         [self removehub];
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             self.bodyView.isSign = YES;
+            // 判断是否能进入教室
         }
         else {
             [self MBPShow:MESSAGEKEY];

+ 5 - 0
MusicGradeExam/MusicGradeExam/UI/Exam/View/WaitExamBodyView.h

@@ -21,6 +21,11 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, assign) BOOL isSign;
 
+@property (nonatomic, assign) BOOL canJoinRoom;
+
+@property (weak, nonatomic) IBOutlet UIButton *joinButton;
+
+
 + (instancetype)shareInstance;
 
 - (void)configMessageSource:(TicketDetailModel *)source;

+ 20 - 3
MusicGradeExam/MusicGradeExam/UI/Exam/View/WaitExamBodyView.m

@@ -22,7 +22,6 @@
 
 @property (weak, nonatomic) IBOutlet UILabel *waitLabel;
 
-@property (weak, nonatomic) IBOutlet UIButton *joinButton;
 
 @property (nonatomic, copy) JoinRoomAction callback;
 
@@ -63,6 +62,15 @@
         self.signDescLabel.text = @"您已签到,请点击下方按钮进入教室";
     }
     
+    if (self.sourceModel.openFlag == 1) {
+        [self.joinButton setTitle:@"录播考试" forState:UIControlStateNormal];
+    }
+    else {
+        [self.joinButton setTitle:@"进入教室" forState:UIControlStateNormal];
+    }
+    
+    self.canJoinRoom = self.sourceModel.classroomSwitch;
+    
     self.classDate.text = [[self.sourceModel.examStartTime componentsSeparatedByString:@" "] firstObject];
     self.subjectLabel.text = [NSString returnNoNullStringWithString:self.sourceModel.baseExamName];
 
@@ -87,18 +95,27 @@
         _gradientLayer = nil;
         self.signButton.userInteractionEnabled = NO;
         [self.signButton setTitle:@"已签到" forState:UIControlStateNormal];
-        self.joinButton.userInteractionEnabled = YES;
-        [self.joinButton setBackgroundColor:THEMECOLOR];
     }
     else {
         [self.signButton.layer insertSublayer:self.gradientLayer atIndex:0];
         self.signButton.userInteractionEnabled = YES;
         [self.signButton setTitle:@"签到" forState:UIControlStateNormal];
+    }
+}
+
+- (void)setCanJoinRoom:(BOOL)canJoinRoom {
+    _canJoinRoom = canJoinRoom;
+    if (canJoinRoom) {
+        self.joinButton.userInteractionEnabled = YES;
+        [self.joinButton setBackgroundColor:THEMECOLOR];
+    }
+    else {
         self.joinButton.userInteractionEnabled = NO;
         [self.joinButton setBackgroundColor:HexRGB(0xcccccc)];
     }
 }
 
+
 - (void)operationCallback:(JoinRoomAction)callback {
     if (callback) {
         self.callback = callback;

+ 2 - 0
MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Controller/ExamLibraryController.h

@@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface ExamLibraryController : KSBaseViewController
 
+@property (nonatomic, strong) NSString *tenantId;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 3 - 2
MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Controller/ExamLibraryController.m

@@ -40,7 +40,7 @@
 
 - (void)querySubjectMessage {
     [self showhud];
-    [KSRequestManager musicLibraryPageRequest:KS_GET success:^(NSDictionary * _Nonnull dic) {
+    [KSRequestManager musicLibraryPageRequest:KS_GET tenantId:self.tenantId success:^(NSDictionary * _Nonnull dic) {
         [self removehub];
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
             NSArray *source = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"rows"];
@@ -129,7 +129,7 @@
 }
 
 - (void)requestData {
-    [KSRequestManager musicSongListRequest:KS_GET subjectList:self.subjectId level:self.levelString page:[NSString stringWithFormat:@"%zd", self.pages] rows:[NSString stringWithFormat:@"%zd", self.rows] success:^(NSDictionary * _Nonnull dic) {
+    [KSRequestManager musicSongListRequest:KS_GET tenantId:self.tenantId subjectList:self.subjectId level:self.levelString page:[NSString stringWithFormat:@"%zd", self.pages] rows:[NSString stringWithFormat:@"%zd", self.rows] success:^(NSDictionary * _Nonnull dic) {
         [self.tableView.mj_header endRefreshing];
         [self.tableView.mj_footer endRefreshing];
         if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
@@ -196,6 +196,7 @@
 //        return;
         model.fileUrlList = @"https://www.tutorialspoint.com/ios/ios_tutorial.pdf";
     }
+//    model.fileUrlList = @"https://www.tutorialspoint.com/ios/ios_tutorial.pdf";
     OpenFileViewController *readCtrl = [[OpenFileViewController alloc] init];
     readCtrl.urlString = model.fileUrlList;
     readCtrl.fileName = model.songName;

+ 26 - 5
MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Controller/ExamViewController.m

@@ -10,6 +10,7 @@
 #import "LibraryTipsView.h"
 #import "ExamListCell.h"
 #import "ExamLibraryController.h"
+#import "BaseExamModel.h"
 
 @interface ExamViewController ()<UITableViewDelegate, UITableViewDataSource>
 
@@ -38,7 +39,25 @@
 }
 
 - (void)requestData {
-    [self.tableView reloadData];
+    [self showhud];
+    [KSRequestManager studentBaseExamsRequest:KS_GET success:^(NSDictionary * _Nonnull dic) {
+        [self removehub];
+        if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+            NSArray *source = [[dic dictionaryValueForKey:@"data"] arrayValueForKey:@"rows"];
+            NSMutableArray *sourceArray = [NSMutableArray array];
+            for (NSDictionary *parm in source) {
+                BaseExamModel *model = [[BaseExamModel alloc] initWithDictionary:parm];
+                [sourceArray addObject:model];
+            }
+            self.dataArray = [NSMutableArray arrayWithArray:sourceArray];
+            [self.tableView reloadData];
+        }
+        else {
+            [self MBPShow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        [self removehub];
+    }];
 }
 
 - (void)configUI {
@@ -50,21 +69,23 @@
 
 #pragma mark ---- table data source
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
-//    return self.dataArray.count;
-    return 3;
+    return self.dataArray.count;
 }
 
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     ExamListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ExamListCell"];
+    BaseExamModel *model = self.dataArray[indexPath.row];
     MJWeakSelf;
-    [cell configCellWithSource:@"" callback:^(id source) {
+    [cell configCellWithSource:model callback:^(BaseExamModel * _Nonnull source) {
         [weakSelf examLibraryView:source];
     }];
+
     return cell;
 }
 
-- (void)examLibraryView:(id)source {
+- (void)examLibraryView:(BaseExamModel *)source {
     ExamLibraryController *libraryVC = [[ExamLibraryController alloc] init];
+    libraryVC.tenantId = [NSString stringWithFormat:@"%.0f",source.tenantId];
     [self.navigationController pushViewController:libraryVC animated:YES];
 }
 

+ 21 - 0
MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Model/BaseExamModel.h

@@ -0,0 +1,21 @@
+//
+//  BaseExamModel.h
+//
+//  Created by   on 2020/7/22
+//  Copyright (c) 2020 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface BaseExamModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, assign) double tenantId;
+@property (nonatomic, strong) NSString *baseExamName;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 102 - 0
MusicGradeExam/MusicGradeExam/UI/ExamLibrary/Model/BaseExamModel.m

@@ -0,0 +1,102 @@
+//
+//  BaseExamModel.m
+//
+//  Created by   on 2020/7/22
+//  Copyright (c) 2020 __MyCompanyName__. All rights reserved.
+//
+
+#import "BaseExamModel.h"
+
+
+NSString *const kBaseExamModelTenantId = @"tenantId";
+NSString *const kBaseExamModelBaseExamName = @"baseExamName";
+
+
+@interface BaseExamModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation BaseExamModel
+
+@synthesize tenantId = _tenantId;
+@synthesize baseExamName = _baseExamName;
+
+
++ (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.tenantId = [[self objectOrNilForKey:kBaseExamModelTenantId fromDictionary:dict] doubleValue];
+            self.baseExamName = [self objectOrNilForKey:kBaseExamModelBaseExamName fromDictionary:dict];
+
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.tenantId] forKey:kBaseExamModelTenantId];
+    [mutableDict setValue:self.baseExamName forKey:kBaseExamModelBaseExamName];
+
+    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];
+    return [object isEqual:[NSNull null]] ? nil : object;
+}
+
+
+#pragma mark - NSCoding Methods
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super init];
+
+    self.tenantId = [aDecoder decodeDoubleForKey:kBaseExamModelTenantId];
+    self.baseExamName = [aDecoder decodeObjectForKey:kBaseExamModelBaseExamName];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeDouble:_tenantId forKey:kBaseExamModelTenantId];
+    [aCoder encodeObject:_baseExamName forKey:kBaseExamModelBaseExamName];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    BaseExamModel *copy = [[BaseExamModel alloc] init];
+    
+    if (copy) {
+
+        copy.tenantId = self.tenantId;
+        copy.baseExamName = [self.baseExamName copyWithZone:zone];
+    }
+    
+    return copy;
+}
+
+
+@end

+ 3 - 2
MusicGradeExam/MusicGradeExam/UI/ExamLibrary/View/ExamListCell.h

@@ -7,14 +7,15 @@
 //
 
 #import <UIKit/UIKit.h>
+#import "BaseExamModel.h"
 
-typedef void(^CheckCallback)(id source);
+typedef void(^CheckCallback)(BaseExamModel * _Nonnull source);
 
 NS_ASSUME_NONNULL_BEGIN
 
 @interface ExamListCell : UITableViewCell
 
-- (void)configCellWithSource:(id)source callback:(CheckCallback)callback;
+- (void)configCellWithSource:(BaseExamModel *)source callback:(CheckCallback)callback;
 
 @end
 

+ 7 - 2
MusicGradeExam/MusicGradeExam/UI/ExamLibrary/View/ExamListCell.m

@@ -13,6 +13,8 @@
 @property (weak, nonatomic) IBOutlet UILabel *examName;
 
 @property (nonatomic, copy) CheckCallback callback;
+
+@property (nonatomic, strong) BaseExamModel *sourceModel;
 @end
 
 @implementation ExamListCell
@@ -23,15 +25,18 @@
     self.selectionStyle = UITableViewCellSelectionStyleNone;
 }
 
-- (void)configCellWithSource:(id)source callback:(CheckCallback)callback {
+- (void)configCellWithSource:(BaseExamModel *)source callback:(CheckCallback)callback {
     if (callback) {
         self.callback = callback;
     }
     // 赋值
+    self.sourceModel = source;
+    self.examName.text = [NSString returnNoNullStringWithString:self.sourceModel.baseExamName];
 }
+
 - (IBAction)checkLibrary:(id)sender {
     if (self.callback) {
-        self.callback(@"");
+        self.callback(self.sourceModel);
     }
 }
 

+ 17 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/Controller/RecordExamViewController.h

@@ -0,0 +1,17 @@
+//
+//  RecordExamViewController.h
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import "KSBaseViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RecordExamViewController : KSBaseViewController
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 158 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/Controller/RecordExamViewController.m

@@ -0,0 +1,158 @@
+//
+//  RecordExamViewController.m
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import "RecordExamViewController.h"
+#import "RecordBodyView.h"
+#import "RecordListCell.h"
+#import "RecordBottomView.h"
+#import "RecordTipsView.h"
+
+@interface RecordExamViewController ()<UITableViewDelegate, UITableViewDataSource>
+
+@property (nonatomic, strong) RecordBodyView *topView;
+
+@property (nonatomic, strong) RecordTipsView *tipsView;
+
+@property (nonatomic, strong) UITableView *tableView;
+
+@property (nonatomic, strong) RecordBottomView *bottomView;
+
+@end
+
+@implementation RecordExamViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    self.ks_prefersNavigationBarHidden = YES;
+    [self configUI];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
+}
+
+- (void)viewDidDisappear:(BOOL)animated {
+    [super viewDidDisappear:animated];
+    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
+    if(@available(iOS 13.0, *)){
+        [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDarkContent;
+    }
+}
+
+- (void)configUI {
+    
+    [self.view addSubview:self.topView];
+    [self.topView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.left.right.mas_equalTo(self.view);
+        make.height.mas_equalTo(self.view.mas_width).multipliedBy(79.0 / 207).offset(11);
+    }];
+    [self.view addSubview:self.bottomView];
+    [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.bottom.mas_equalTo(self.view.mas_bottomMargin);
+        make.height.mas_equalTo(90);
+    }];
+    
+    [self.view addSubview:self.tableView];
+    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.topView.mas_bottom);
+        make.bottom.mas_equalTo(self.bottomView.mas_top);
+    }];
+}
+
+
+#pragma mark ----- table data source
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+//    return self.dataArray.count;
+    return 3;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    RecordListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"RecordListCell"];
+    return cell;
+}
+
+#pragma mark --- lazying
+- (RecordBodyView *)topView {
+    if (!_topView) {
+        _topView = [RecordBodyView shareInstance];
+        
+        MJWeakSelf;
+        [_topView topviewAction:^(RECORDTOPACTION action) {
+            [weakSelf backOrEndAction:action];
+        }];
+    }
+    return _topView;
+}
+
+
+- (void)backOrEndAction:(RECORDTOPACTION)action {
+    if (action == RECORDTOPACTION_BACK) {
+        [self.navigationController popViewControllerAnimated:YES];
+    }
+    else { // 时间结束
+        
+    }
+}
+
+- (RecordTipsView *)tipsView {
+    if (!_tipsView) {
+        _tipsView = [RecordTipsView shareInstance];
+    }
+    return _tipsView;
+}
+
+- (UITableView *)tableView {
+    if (!_tableView) {
+//        CGFloat yPosition = kScreenWidth / 207 * 79 + 11;
+        _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
+        _tableView.delegate = self;
+        _tableView.dataSource = self;
+        _tableView.rowHeight = 130;
+        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        _tableView.backgroundColor = HexRGB(0xf5f5f5);
+        _tableView.showsVerticalScrollIndicator = NO;
+        [_tableView registerNib:[UINib nibWithNibName:@"RecordListCell" bundle:nil] forCellReuseIdentifier:@"RecordListCell"];
+        _tableView.tableHeaderView = self.tipsView;
+        
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 10)];
+        bottomView.backgroundColor = HexRGB(0xf3f4f8);
+        _tableView.tableFooterView = bottomView;
+    }
+    return _tableView;
+}
+
+- (RecordBottomView *)bottomView {
+    if (!_bottomView) {
+        _bottomView = [RecordBottomView shareInstance];
+        MJWeakSelf;
+        [_bottomView submitMediaAction:^{
+            [weakSelf submitAction];
+        }];
+    }
+    return _bottomView;
+}
+
+- (void)submitAction {
+    // 提交 完成考试
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+    // Get the new view controller using [segue destinationViewController].
+    // Pass the selected object to the new view controller.
+}
+*/
+
+@end

+ 28 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBodyView.h

@@ -0,0 +1,28 @@
+//
+//  RecordBodyView.h
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, RECORDTOPACTION) {
+    RECORDTOPACTION_BACK = 1,
+    RECORDTOPACTION_OVER,
+};
+
+typedef void(^RecordTopBlock)(RECORDTOPACTION action);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RecordBodyView : UIView
+
++ (instancetype)shareInstance;
+
+- (void)topviewAction:(RecordTopBlock)block;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 45 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBodyView.m

@@ -0,0 +1,45 @@
+//
+//  RecordBodyView.m
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import "RecordBodyView.h"
+
+@interface RecordBodyView ()
+
+@property (nonatomic, copy) RecordTopBlock block;
+
+@end
+
+@implementation RecordBodyView
+
++ (instancetype)shareInstance {
+    RecordBodyView *view = [[[NSBundle mainBundle] loadNibNamed:@"RecordBodyView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)topviewAction:(RecordTopBlock)block {
+    if (block) {
+        self.block = block;
+    }
+}
+
+- (IBAction)backAction:(id)sender {
+    if (self.block) {
+        self.block(RECORDTOPACTION_BACK);
+    }
+}
+
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 119 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBodyView.xib

@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="RecordBodyView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_top" translatesAutoresizingMaskIntoConstraints="NO" id="u8d-f2-rBu">
+                    <rect key="frame" x="0.0" y="0.0" width="414" height="158"/>
+                    <constraints>
+                        <constraint firstAttribute="width" secondItem="u8d-f2-rBu" secondAttribute="height" multiplier="207:79" id="m5U-8d-lRP"/>
+                    </constraints>
+                </imageView>
+                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="login_back" translatesAutoresizingMaskIntoConstraints="NO" id="7Jy-vB-KnL">
+                    <rect key="frame" x="17" y="64" width="11" height="20"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="20" id="MI7-Wm-8GB"/>
+                        <constraint firstAttribute="width" constant="11" id="YyT-xH-TdU"/>
+                    </constraints>
+                </imageView>
+                <button opaque="NO" tag="1001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4H7-md-Jk7">
+                    <rect key="frame" x="0.0" y="54" width="40" height="40"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="40" id="hOj-IE-Pas"/>
+                        <constraint firstAttribute="width" constant="40" id="okQ-qz-9nC"/>
+                    </constraints>
+                    <connections>
+                        <action selector="backAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="agH-sv-5sK"/>
+                    </connections>
+                </button>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="68b-I8-Bmr">
+                    <rect key="frame" x="16" y="123" width="382" height="46"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="count_image" translatesAutoresizingMaskIntoConstraints="NO" id="LaT-YJ-L52">
+                            <rect key="frame" x="15" y="13" width="20" height="20"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="20" id="LSK-fV-WHd"/>
+                                <constraint firstAttribute="width" constant="20" id="Nhh-u8-6pK"/>
+                            </constraints>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="剩余时间:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="76t-dO-T3V">
+                            <rect key="frame" x="45" y="12" width="87" height="22"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="22" id="Jgd-Zm-3sV"/>
+                                <constraint firstAttribute="width" constant="87" id="UD6-cn-C28"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                            <color key="textColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="calibratedRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="20分45秒" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q8k-CG-YKq">
+                            <rect key="frame" x="132" y="13" width="235" height="20"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                            <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="46" id="DC6-cS-Jye"/>
+                        <constraint firstItem="Q8k-CG-YKq" firstAttribute="leading" secondItem="76t-dO-T3V" secondAttribute="trailing" id="DVU-KZ-PJP"/>
+                        <constraint firstItem="76t-dO-T3V" firstAttribute="centerY" secondItem="LaT-YJ-L52" secondAttribute="centerY" id="LKC-Ka-aXT"/>
+                        <constraint firstItem="LaT-YJ-L52" firstAttribute="leading" secondItem="68b-I8-Bmr" secondAttribute="leading" constant="15" id="MIL-wZ-eyk"/>
+                        <constraint firstItem="76t-dO-T3V" firstAttribute="centerY" secondItem="68b-I8-Bmr" secondAttribute="centerY" id="VbH-dr-0YQ"/>
+                        <constraint firstItem="76t-dO-T3V" firstAttribute="leading" secondItem="LaT-YJ-L52" secondAttribute="trailing" constant="10" id="a1U-td-RWr"/>
+                        <constraint firstItem="Q8k-CG-YKq" firstAttribute="centerY" secondItem="68b-I8-Bmr" secondAttribute="centerY" id="ojk-fn-B9H"/>
+                        <constraint firstAttribute="trailing" secondItem="Q8k-CG-YKq" secondAttribute="trailing" constant="15" id="pX6-2y-p7a"/>
+                        <constraint firstItem="LaT-YJ-L52" firstAttribute="centerY" secondItem="68b-I8-Bmr" secondAttribute="centerY" id="t1T-Ai-LDC"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="8"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="录播考试" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hAD-kA-qss">
+                    <rect key="frame" x="170" y="61.5" width="74" height="25"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="25" id="Ecf-cv-JnF"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
+                    <color key="textColor" red="0.95294117649999999" green="0.95686274510000002" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" red="0.96078431372549022" green="0.96078431372549022" blue="0.96078431372549022" alpha="1" colorSpace="calibratedRGB"/>
+            <constraints>
+                <constraint firstItem="u8d-f2-rBu" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="3Ip-x5-kYQ"/>
+                <constraint firstItem="hAD-kA-qss" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="BLL-np-5Yn"/>
+                <constraint firstItem="u8d-f2-rBu" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="LfA-AT-YDL"/>
+                <constraint firstItem="4H7-md-Jk7" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="NgB-LZ-eD1"/>
+                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="u8d-f2-rBu" secondAttribute="trailing" id="QUO-lM-bI4"/>
+                <constraint firstItem="68b-I8-Bmr" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="16" id="ane-u7-mmI"/>
+                <constraint firstItem="7Jy-vB-KnL" firstAttribute="centerY" secondItem="4H7-md-Jk7" secondAttribute="centerY" id="czg-er-qIQ"/>
+                <constraint firstItem="7Jy-vB-KnL" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="20" id="hEE-KT-Ben"/>
+                <constraint firstItem="7Jy-vB-KnL" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="17" id="hVZ-z7-Ml3"/>
+                <constraint firstItem="hAD-kA-qss" firstAttribute="centerY" secondItem="4H7-md-Jk7" secondAttribute="centerY" id="i5D-6p-4Rt"/>
+                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="68b-I8-Bmr" secondAttribute="trailing" constant="16" id="rWe-qe-faA"/>
+                <constraint firstItem="68b-I8-Bmr" firstAttribute="bottom" secondItem="u8d-f2-rBu" secondAttribute="bottom" constant="11" id="sHM-ZD-pDL"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
+            <point key="canvasLocation" x="163.768115942029" y="71.651785714285708"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="count_image" width="22" height="25"/>
+        <image name="home_top" width="375" height="158"/>
+        <image name="login_back" width="12" height="21"/>
+    </resources>
+</document>

+ 23 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBottomView.h

@@ -0,0 +1,23 @@
+//
+//  RecordBottomView.h
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^SureCallback)(void);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RecordBottomView : UIView
+
++ (instancetype)shareInstance;
+
+- (void)submitMediaAction:(SureCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 43 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBottomView.m

@@ -0,0 +1,43 @@
+//
+//  RecordBottomView.m
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import "RecordBottomView.h"
+
+@interface RecordBottomView ()
+
+@property (nonatomic, copy) SureCallback callback;
+
+@end
+
+@implementation RecordBottomView
+
++ (instancetype)shareInstance {
+    RecordBottomView *view = [[[NSBundle mainBundle] loadNibNamed:@"RecordBottomView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)submitMediaAction:(SureCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+- (IBAction)submitAction:(id)sender {
+    if (self.callback) {
+        self.callback();
+    }
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 45 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordBottomView.xib

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097.2" 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="16087"/>
+        <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="RecordBottomView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="90"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OVk-6l-fwy">
+                    <rect key="frame" x="17" y="20" width="380" height="50"/>
+                    <color key="backgroundColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="calibratedRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="50" id="7kz-FV-ii6"/>
+                    </constraints>
+                    <state key="normal" title="完成考试"/>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="25"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="submitAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="J6j-ED-Zt9"/>
+                    </connections>
+                </button>
+            </subviews>
+            <color key="backgroundColor" red="0.96078431372549022" green="0.96078431372549022" blue="0.96078431372549022" alpha="1" colorSpace="calibratedRGB"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="OVk-6l-fwy" secondAttribute="trailing" constant="17" id="04m-SB-3QC"/>
+                <constraint firstItem="OVk-6l-fwy" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="j7O-3y-VXI"/>
+                <constraint firstItem="OVk-6l-fwy" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="17" id="kSV-uH-DT0"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="252" y="148"/>
+        </view>
+    </objects>
+</document>

+ 17 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordListCell.h

@@ -0,0 +1,17 @@
+//
+//  RecordListCell.h
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RecordListCell : UITableViewCell
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 25 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordListCell.m

@@ -0,0 +1,25 @@
+//
+//  RecordListCell.m
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import "RecordListCell.h"
+
+@implementation RecordListCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 40 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordListCell.xib

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="RecordListCell">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="130"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
+                <rect key="frame" x="0.0" y="0.0" width="375" height="130"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="record_bg" translatesAutoresizingMaskIntoConstraints="NO" id="zrO-5f-aoY">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="130"/>
+                    </imageView>
+                </subviews>
+                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                <constraints>
+                    <constraint firstItem="zrO-5f-aoY" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="ZF4-0d-pe2"/>
+                    <constraint firstItem="zrO-5f-aoY" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="k0V-d3-rh5"/>
+                    <constraint firstAttribute="bottom" secondItem="zrO-5f-aoY" secondAttribute="bottom" id="sdX-xS-xan"/>
+                    <constraint firstAttribute="trailing" secondItem="zrO-5f-aoY" secondAttribute="trailing" id="tcQ-Vf-BkK"/>
+                </constraints>
+            </tableViewCellContentView>
+            <color key="backgroundColor" red="0.96078431372549022" green="0.96078431372549022" blue="0.96078431372549022" alpha="1" colorSpace="calibratedRGB"/>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <point key="canvasLocation" x="132" y="119"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="record_bg" width="351" height="120"/>
+    </resources>
+</document>

+ 19 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordTipsView.h

@@ -0,0 +1,19 @@
+//
+//  RecordTipsView.h
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RecordTipsView : UIView
+
++ (instancetype)shareInstance;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 28 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordTipsView.m

@@ -0,0 +1,28 @@
+//
+//  RecordTipsView.m
+//  MusicGradeExam
+//
+//  Created by Kyle on 2020/7/22.
+//  Copyright © 2020 DayaMusic. All rights reserved.
+//
+
+#import "RecordTipsView.h"
+
+@implementation RecordTipsView
+
+
++ (instancetype)shareInstance {
+    RecordTipsView *view = [[[NSBundle mainBundle] loadNibNamed:@"RecordTipsView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 46 - 0
MusicGradeExam/MusicGradeExam/UI/RecordExam/View/RecordTipsView.xib

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097.2" 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="16087"/>
+        <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="RecordTipsView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="119"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="录播考试说明" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hf0-qG-qs5">
+                    <rect key="frame" x="20" y="17" width="98" height="22"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="22" id="N2T-0l-Uge"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请于2020-05-20 9:30:59前依次完成考级曲目的提交,规定时间后,未提交完成,则视为缺考。" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0KC-iu-RW4">
+                    <rect key="frame" x="20" y="49" width="374" height="33.5"/>
+                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                    <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" red="0.96078431369999995" green="0.96078431369999995" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
+            <constraints>
+                <constraint firstItem="0KC-iu-RW4" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" id="M2a-Nq-7rx"/>
+                <constraint firstItem="Hf0-qG-qs5" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" id="SNd-PR-wqq"/>
+                <constraint firstItem="Hf0-qG-qs5" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="17" id="cxg-AT-Izz"/>
+                <constraint firstItem="0KC-iu-RW4" firstAttribute="top" secondItem="Hf0-qG-qs5" secondAttribute="bottom" constant="10" id="ihL-nu-17A"/>
+                <constraint firstAttribute="trailing" secondItem="0KC-iu-RW4" secondAttribute="trailing" constant="20" id="jEa-L6-JCm"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="131.8840579710145" y="-71.986607142857139"/>
+        </view>
+    </objects>
+</document>