Browse Source

扫一扫登录乐教通

Steven 6 months ago
parent
commit
61016c98e2
35 changed files with 1168 additions and 25 deletions
  1. 43 1
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj
  2. 1 1
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/xcshareddata/xcschemes/KulexiuForTeacher.xcscheme
  3. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scanAlert_bg.imageset/Contents.json
  4. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scanAlert_bg.imageset/scanAlert_bg@2x.png
  5. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scanAlert_bg.imageset/scanAlert_bg@3x.png
  6. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_alert.imageset/Contents.json
  7. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_alert.imageset/scan_alert@2x.png
  8. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_alert.imageset/scan_alert@3x.png
  9. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_authError.imageset/Contents.json
  10. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_authError.imageset/scan_authError@2x.png
  11. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_authError.imageset/scan_authError@3x.png
  12. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_codeExpired.imageset/Contents.json
  13. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_codeExpired.imageset/scan_codeExpired@2x.png
  14. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_codeExpired.imageset/scan_codeExpired@3x.png
  15. 20 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.h
  16. 54 12
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m
  17. 2 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Define/KSDomain.h
  18. 90 7
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/KSScanViewController.m
  19. 23 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanFailViewController.h
  20. 109 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanFailViewController.m
  21. 18 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanLoginViewController.h
  22. 92 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanLoginViewController.m
  23. 24 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanFailBodyView.h
  24. 63 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanFailBodyView.m
  25. 87 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanFailBodyView.xib
  26. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanLoginBodyView.h
  27. 64 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanLoginBodyView.m
  28. 98 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanLoginBodyView.xib
  29. 26 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanOpenAlert.h
  30. 73 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanOpenAlert.m
  31. 155 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanOpenAlert.xib
  32. 4 1
      KulexiuForTeacher/KulexiuForTeacher/configuration/Config-debug.xcconfig
  33. 4 1
      KulexiuForTeacher/KulexiuForTeacher/configuration/Config-dev.xcconfig
  34. 4 1
      KulexiuForTeacher/KulexiuForTeacher/configuration/Config-release.xcconfig
  35. 4 1
      KulexiuForTeacher/KulexiuForTeacher/configuration/Config-test.xcconfig

+ 43 - 1
KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj

@@ -1097,6 +1097,14 @@
 		BCF61BEC28042D1A0000ACFE /* InstrumentMessageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF61BEB28042D1A0000ACFE /* InstrumentMessageModel.m */; };
 		BCF61BEF28042F9B0000ACFE /* InstrumentChooseBottonView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF61BEE28042F9B0000ACFE /* InstrumentChooseBottonView.m */; };
 		BCF61BF128042FA90000ACFE /* InstrumentChooseBottonView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCF61BF028042FA90000ACFE /* InstrumentChooseBottonView.xib */; };
+		BCF7EB272C856C31006AA38C /* ScanFailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF7EB232C856C31006AA38C /* ScanFailViewController.m */; };
+		BCF7EB282C856C31006AA38C /* ScanLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF7EB262C856C31006AA38C /* ScanLoginViewController.m */; };
+		BCF7EB322C856C53006AA38C /* ScanFailBodyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCF7EB292C856C52006AA38C /* ScanFailBodyView.xib */; };
+		BCF7EB332C856C53006AA38C /* ScanOpenAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF7EB2B2C856C52006AA38C /* ScanOpenAlert.m */; };
+		BCF7EB342C856C53006AA38C /* ScanLoginBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF7EB2E2C856C52006AA38C /* ScanLoginBodyView.m */; };
+		BCF7EB352C856C53006AA38C /* ScanFailBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF7EB2F2C856C52006AA38C /* ScanFailBodyView.m */; };
+		BCF7EB362C856C53006AA38C /* ScanOpenAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCF7EB302C856C53006AA38C /* ScanOpenAlert.xib */; };
+		BCF7EB372C856C53006AA38C /* ScanLoginBodyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCF7EB312C856C53006AA38C /* ScanLoginBodyView.xib */; };
 		BCFC09DD2C48E4A0009A727F /* UserVip.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFC09DC2C48E4A0009A727F /* UserVip.m */; };
 		BCFE540928168DFF00AD6786 /* KSButtonStatusView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFE540828168DFF00AD6786 /* KSButtonStatusView.m */; };
 		BCFE541028178FF600AD6786 /* MyIncomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFE540F28178FF600AD6786 /* MyIncomeViewController.m */; };
@@ -2924,6 +2932,19 @@
 		BCF61BED28042F9B0000ACFE /* InstrumentChooseBottonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InstrumentChooseBottonView.h; sourceTree = "<group>"; };
 		BCF61BEE28042F9B0000ACFE /* InstrumentChooseBottonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InstrumentChooseBottonView.m; sourceTree = "<group>"; };
 		BCF61BF028042FA90000ACFE /* InstrumentChooseBottonView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InstrumentChooseBottonView.xib; sourceTree = "<group>"; };
+		BCF7EB232C856C31006AA38C /* ScanFailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanFailViewController.m; sourceTree = "<group>"; };
+		BCF7EB242C856C31006AA38C /* ScanLoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanLoginViewController.h; sourceTree = "<group>"; };
+		BCF7EB252C856C31006AA38C /* ScanFailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanFailViewController.h; sourceTree = "<group>"; };
+		BCF7EB262C856C31006AA38C /* ScanLoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanLoginViewController.m; sourceTree = "<group>"; };
+		BCF7EB292C856C52006AA38C /* ScanFailBodyView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ScanFailBodyView.xib; sourceTree = "<group>"; };
+		BCF7EB2A2C856C52006AA38C /* ScanLoginBodyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanLoginBodyView.h; sourceTree = "<group>"; };
+		BCF7EB2B2C856C52006AA38C /* ScanOpenAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanOpenAlert.m; sourceTree = "<group>"; };
+		BCF7EB2C2C856C52006AA38C /* ScanOpenAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanOpenAlert.h; sourceTree = "<group>"; };
+		BCF7EB2D2C856C52006AA38C /* ScanFailBodyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanFailBodyView.h; sourceTree = "<group>"; };
+		BCF7EB2E2C856C52006AA38C /* ScanLoginBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanLoginBodyView.m; sourceTree = "<group>"; };
+		BCF7EB2F2C856C52006AA38C /* ScanFailBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanFailBodyView.m; sourceTree = "<group>"; };
+		BCF7EB302C856C53006AA38C /* ScanOpenAlert.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ScanOpenAlert.xib; sourceTree = "<group>"; };
+		BCF7EB312C856C53006AA38C /* ScanLoginBodyView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ScanLoginBodyView.xib; sourceTree = "<group>"; };
 		BCF880EA2B91C70C0007B8F0 /* Config-dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Config-dev.xcconfig"; sourceTree = "<group>"; };
 		BCF880EC2B91C7200007B8F0 /* Config-test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Config-test.xcconfig"; sourceTree = "<group>"; };
 		BCF880EE2B91C7310007B8F0 /* Config-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Config-debug.xcconfig"; sourceTree = "<group>"; };
@@ -6702,6 +6723,10 @@
 			children = (
 				BCB9FA1A286D537E005D766B /* KSScanViewController.h */,
 				BCB9FA1B286D537E005D766B /* KSScanViewController.m */,
+				BCF7EB242C856C31006AA38C /* ScanLoginViewController.h */,
+				BCF7EB262C856C31006AA38C /* ScanLoginViewController.m */,
+				BCF7EB252C856C31006AA38C /* ScanFailViewController.h */,
+				BCF7EB232C856C31006AA38C /* ScanFailViewController.m */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -6712,6 +6737,15 @@
 				BCB9FA1D286D539A005D766B /* ScanNavView.h */,
 				BCB9FA1E286D539A005D766B /* ScanNavView.m */,
 				BCB9FA20286D53A1005D766B /* ScanNavView.xib */,
+				BCF7EB2D2C856C52006AA38C /* ScanFailBodyView.h */,
+				BCF7EB2F2C856C52006AA38C /* ScanFailBodyView.m */,
+				BCF7EB292C856C52006AA38C /* ScanFailBodyView.xib */,
+				BCF7EB2A2C856C52006AA38C /* ScanLoginBodyView.h */,
+				BCF7EB2E2C856C52006AA38C /* ScanLoginBodyView.m */,
+				BCF7EB312C856C53006AA38C /* ScanLoginBodyView.xib */,
+				BCF7EB2C2C856C52006AA38C /* ScanOpenAlert.h */,
+				BCF7EB2B2C856C52006AA38C /* ScanOpenAlert.m */,
+				BCF7EB302C856C53006AA38C /* ScanOpenAlert.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -7328,7 +7362,7 @@
 			isa = PBXProject;
 			attributes = {
 				BuildIndependentTargetsInParallel = 1;
-				LastUpgradeCheck = 1530;
+				LastUpgradeCheck = 1540;
 				TargetAttributes = {
 					275E8A6327E18F2300DD3F6E = {
 						CreatedOnToolsVersion = 13.2.1;
@@ -7596,6 +7630,7 @@
 				BC513E7E28A4D874003F58C4 /* live_animation.json in Resources */,
 				BC106BA32A8F45AA000759A9 /* TXLiveRoomHeadView.xib in Resources */,
 				BC9EFEB62C0480A500CFA7B1 /* GroupBanNavView.xib in Resources */,
+				BCF7EB362C856C53006AA38C /* ScanOpenAlert.xib in Resources */,
 				BCC408DA2AFCE0D700C60249 /* VideoCropImageViewCell.xib in Resources */,
 				27D83F5927F4225D00062476 /* LivePreviewBodyView.xib in Resources */,
 				BC41104A2806706800800BD9 /* HomeworkListCell.xib in Resources */,
@@ -7744,7 +7779,9 @@
 				BC9AA0D02ABC3D3A00CD954D /* KSComplainImageDisplayView.xib in Resources */,
 				BCECE2152B3D5F0800C0D555 /* FeedbackBodyView.xib in Resources */,
 				BC1263AA28FF98C300509E90 /* HomeRecommendMusicView.xib in Resources */,
+				BCF7EB322C856C53006AA38C /* ScanFailBodyView.xib in Resources */,
 				BC71D2042887FDD40010F14B /* img_26.png in Resources */,
+				BCF7EB372C856C53006AA38C /* ScanLoginBodyView.xib in Resources */,
 				27F9CAFC27EC1AF3003E0FE4 /* ContractListCell.xib in Resources */,
 				BC31BF9F2B219C5700F7D538 /* WidgetFunctionView.xib in Resources */,
 				BC71D2032887FDD40010F14B /* img_24.png in Resources */,
@@ -7854,6 +7891,7 @@
 				BCA1135728A2439D007FAFB9 /* HomeBannerCell.m in Sources */,
 				BC2888522A80DB990064B773 /* AppDelegate+AppService.m in Sources */,
 				BC85A9D32C6B4D4A003C1ABE /* KSRealtimeAnalyzer.m in Sources */,
+				BCF7EB272C856C31006AA38C /* ScanFailViewController.m in Sources */,
 				BC106B7A2A8F4586000759A9 /* TXLiveMessageLikeCount.m in Sources */,
 				BCA9CE3927FD93EB00D558C6 /* AccompanyStudentEvaCell.m in Sources */,
 				2723B68C27F1685600E0B90B /* HomeNavView.m in Sources */,
@@ -7918,6 +7956,7 @@
 				BC76146A280D4F670080FD1F /* HomeworkDetailModel.m in Sources */,
 				BC5EB5B22804027500B4A3B0 /* MyStyleViewController.m in Sources */,
 				BCFE54182817BDFD00AD6786 /* IncomeHeaderView.m in Sources */,
+				BCF7EB282C856C31006AA38C /* ScanLoginViewController.m in Sources */,
 				BC8B641C28F3E8D800A08D16 /* KSAwardAlertView.m in Sources */,
 				BC106B7D2A8F4586000759A9 /* TXLiveMessageOpenLive.m in Sources */,
 				275B16FD27EB083C0081FDEF /* ChatAddressViewController.m in Sources */,
@@ -7977,6 +8016,7 @@
 				BCC9F43327F69BD200647449 /* KSRemoteUserManager.m in Sources */,
 				BC106B862A8F4586000759A9 /* TXLiveMessageKickOut.m in Sources */,
 				2779361B27E32C3A0010E277 /* MineViewController.m in Sources */,
+				BCF7EB342C856C53006AA38C /* ScanLoginBodyView.m in Sources */,
 				BC2888652A8100EA0064B773 /* KSConversationListController.m in Sources */,
 				BCC03F95280562F700461B7C /* MyLessonBodyView.m in Sources */,
 				BCE6A09027F823BE00C97704 /* LiveCourseCell.m in Sources */,
@@ -8044,6 +8084,7 @@
 				BCC9F44727F69BD200647449 /* ClassSongMessage.m in Sources */,
 				BC38C4802AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.m in Sources */,
 				2728086A27E6C12000DB71EA /* FirstSettingBodyView.m in Sources */,
+				BCF7EB352C856C53006AA38C /* ScanFailBodyView.m in Sources */,
 				BC58E7D3281B9630004B0893 /* PublicNoticeView.m in Sources */,
 				2779322627E30FC30010E277 /* KSMessageInputView.m in Sources */,
 				BCDB09402805C0EF00D0BDAD /* NewClassPopView.m in Sources */,
@@ -8469,6 +8510,7 @@
 				BC28886C2A8101310064B773 /* KSChatSearchBar.m in Sources */,
 				277931EF27E30FC20010E277 /* NSObject+Parse.m in Sources */,
 				BCD6D15F281950F2009A773E /* UserBankCard.m in Sources */,
+				BCF7EB332C856C53006AA38C /* ScanOpenAlert.m in Sources */,
 				BC56C95D2923412800AF301F /* CoursewareViewModel.m in Sources */,
 				BC1191ED280E55CB00A716F7 /* EvaluateDetailModel.m in Sources */,
 				BC1E28502C77218A0063E0A1 /* KSDeleteFailedAlertView.m in Sources */,

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

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1530"
+   LastUpgradeVersion = "1540"
    version = "1.7">
    <BuildAction
       parallelizeBuildables = "YES"

+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scanAlert_bg.imageset/Contents.json

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scanAlert_bg.imageset/scanAlert_bg@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scanAlert_bg.imageset/scanAlert_bg@3x.png


+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_alert.imageset/Contents.json

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_alert.imageset/scan_alert@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_alert.imageset/scan_alert@3x.png


+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_authError.imageset/Contents.json

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_authError.imageset/scan_authError@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_authError.imageset/scan_authError@3x.png


+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_codeExpired.imageset/Contents.json

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_codeExpired.imageset/scan_codeExpired@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/scan_codeExpired.imageset/scan_codeExpired@3x.png


+ 20 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.h

@@ -1535,5 +1535,25 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param success 成功
 /// @param faliure 失败
 + (void)updateUserCustomerServiceRequest:(NSString *)get success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+#pragma mark ----- 二维码
+// /open/qrcode/scan
+
+/// 扫描二维码事件
+/// @param post post
+/// @param uuid uuid
+/// @param success 成功
+/// @param faliure 失败
++ (void)scanQrCodeRequest:(NSString *)post uuid:(NSString *)uuid success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+// /open/qrcode/verify
+
+/// 认证二维码
+/// @param post post
+/// @param uuid uuid
+/// @param success 成功
+/// @param faliure 失败
++ (void)verifyQrcode:(NSString *)post uuid:(NSString *)uuid success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 @end
 NS_ASSUME_NONNULL_END

+ 54 - 12
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m

@@ -107,19 +107,23 @@
         } successBlock:^(id response) {
             NSLog(@"success call back---- %@", myUrl);
             dic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
-            
-            if ([dic ks_integerValueForKey:@"code"] == 403) { // token验证失败
-                [self logOutWithType:YES];
-                [dic setValue:@"" forKey:@"msg"];
-                success(dic);
-                return;
-            }
-            else if ([dic ks_integerValueForKey:@"code"] == 401) {
-                [self logOutWithType:NO];
-                [dic setValue:@"" forKey:@"msg"];
-                success(dic);
-                return;
+            // open  不需要校验失效
+            BOOL isOpenUrl = [myUrl hasPrefix:OPEN_URL];
+            if (isOpenUrl == NO) {
+                if ([dic ks_integerValueForKey:@"code"] == 403) { // token验证失败
+                    [self logOutWithType:YES];
+                    [dic setValue:@"" forKey:@"msg"];
+                    success(dic);
+                    return;
+                }
+                else if ([dic ks_integerValueForKey:@"code"] == 401) {
+                    [self logOutWithType:NO];
+                    [dic setValue:@"" forKey:@"msg"];
+                    success(dic);
+                    return;
+                }
             }
+            
             success(dic);
             return;
             
@@ -2810,4 +2814,42 @@
     [self request:get andWithUrl:url and:parm success:success faliure:faliure];
 }
 
+#pragma mark ----- 二维码
+// /open/qrcode/scan
+
+/// 扫描二维码事件
+/// @param post post
+/// @param uuid uuid
+/// @param success 成功
+/// @param faliure 失败
++ (void)scanQrCodeRequest:(NSString *)post uuid:(NSString *)uuid success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSONWithToken:nil];
+    NSString *url = [NSString stringWithFormat:@"%@%@", OPEN_URL, @"/cbs-app/open/qrcode/scan"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:uuid forKey:@"uuid"];
+    [parm setValue:@"KLX" forKey:@"appKey"];
+    [parm setValue:@"TEACHER" forKey:@"clientType"];
+    [parm setValue:UserDefault(TokenKey) forKey:@"token"];
+
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
+
+// /open/qrcode/verify
+
+/// 认证二维码
+/// @param post post
+/// @param uuid uuid
+/// @param success 成功
+/// @param faliure 失败
++ (void)verifyQrcode:(NSString *)post uuid:(NSString *)uuid success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure  {
+    [self configRequestMethodJSONWithToken:nil];
+    NSString *url = [NSString stringWithFormat:@"%@%@", OPEN_URL, @"/cbs-app/open/qrcode/verify"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:uuid forKey:@"uuid"];
+    [parm setValue:@"KLX" forKey:@"appKey"];
+    [parm setValue:@"TEACHER" forKey:@"clientType"];
+    [parm setValue:UserDefault(TokenKey) forKey:@"token"];
+
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
 @end

+ 2 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Define/KSDomain.h

@@ -29,4 +29,6 @@
 // 白板
 #define WhiteBoardHostURL ([NSString stringWithFormat:@"https://%@",WHITE_BOARD])
 
+#define OPEN_URL ([NSString stringWithFormat:@"https://%@",OPEN_DOMAIN])
+
 #endif /* KSDomain_h */

+ 90 - 7
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/KSScanViewController.m

@@ -13,6 +13,10 @@
 #import "KSPremissionAlert.h"
 #import <KSToolLibrary/RecordCheckManager.h>
 
+#import "ScanLoginViewController.h"
+#import "ScanFailViewController.h"
+#import "ScanOpenAlert.h"
+
 @interface KSScanViewController ()
 
 @property (nonatomic, strong) KSMediaManager *mediaManager;
@@ -27,6 +31,7 @@
 
 @property (nonatomic, strong) UIView *maskView;
 
+@property (nonatomic, strong) ScanOpenAlert *openAlert;
 
 @end
 
@@ -43,7 +48,11 @@
 - (void)viewWillAppear:(BOOL)animated {
     [super viewWillAppear:animated];
     [self startScan];
+}
 
+- (void)viewWillDisappear:(BOOL)animated {
+    [super viewWillDisappear:animated];
+    [self.scanManager stopScanning];
 }
 
 - (void)configUI {
@@ -100,28 +109,70 @@
 
 - (void)dealWithCheckSource:(NSString *)result {
     if (result) {
-        if ([result containsString:hostURL]) {
+        if ([result containsString:hostURL]) { // 如果是本端链接
             result = [result getUrlEndcodeString];
             KSBaseWKWebViewController *webCtrl = [[KSBaseWKWebViewController alloc] init];
             webCtrl.url = result;
             [self.navigationController pushViewController:webCtrl animated:YES];
         }
+        else if ([result hasPrefix:@"http://"] || [result hasPrefix:@"https://"]) { // 如果非本端链接
+            result = [result getUrlEndcodeString];
+            [self.openAlert configWithLinkUrl:result];
+            [self.openAlert showAlertInView:self.view];
+        }
         else {
-            [self backPreView];
+            NSData *jsonData = [result mj_JSONData];
+            NSError *error;
+            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
+            if (!error) {
+                NSString *action = [dict ks_stringValueForKey:@"action"];
+                if ([action isEqualToString:@"login"]) { // 登录乐教通
+                    NSString *uuid = [dict ks_stringValueForKey:@"uuid"];
+                    [self scanAuthCodeRequest:uuid];
+                }
+            }
+            else {
+                // 无法识别
+                [self showScanFailedPage];
+            }
         }
+
     }
     else {
-        [self backPreView];
+        // 无法识别
+        [self showScanFailedPage];
     }
 }
 
-- (void)backPreView {
-    [LOADING_MANAGER KSShowMsg:@"请扫描酷乐秀二维码" promptCompletion:^{
 
-        [self.navigationController popViewControllerAnimated:YES];
-    }];
+- (void)showScanFailedPage {
+    ScanFailViewController *ctrl = [[ScanFailViewController alloc] init];
+    ctrl.failType = SCANFAIL_UNRECOGNIZE;
+    [self.navigationController pushViewController:ctrl animated:YES];
 }
 
+- (void)scanAuthCodeRequest:(NSString *)uuid {
+    [KSNetworkingManager scanQrCodeRequest:KS_POST uuid:uuid success:^(NSDictionary * _Nonnull dic) {
+        
+        if ([dic ks_integerValueForKey:@"code"] == 200) { // 正常
+            ScanLoginViewController *ctrl = [[ScanLoginViewController alloc] init];
+            ctrl.uuid = uuid;
+            [self.navigationController pushViewController:ctrl animated:YES];
+        }
+        else if ([dic ks_integerValueForKey:@"code"] == 5440) { // 过期
+            ScanFailViewController *ctrl = [[ScanFailViewController alloc] init];
+            ctrl.failType = SCANFAIL_EXPIRED;
+            [self.navigationController pushViewController:ctrl animated:YES];
+        }
+        else {
+            [LOADING_MANAGER KSShowMsg:MESSAGEKEY promptCompletion:^{
+                [self startScan];
+            }];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        [self startScan];
+    }];
+}
 
 - (GRScanManager *)scanManager {
     if (!_scanManager) {
@@ -132,6 +183,38 @@
     return _scanManager;
 }
 
+- (ScanOpenAlert *)openAlert {
+    if (!_openAlert) {
+        _openAlert = [ScanOpenAlert shareInstance];
+        MJWeakSelf;
+        [_openAlert alertActionCallback:^(BOOL openLink, NSString * _Nullable linkUrl) {
+            [weakSelf scanAlertAction:openLink linkUrl:linkUrl];
+        }];
+    }
+    return _openAlert;
+}
+
+- (void)scanAlertAction:(BOOL)isOpen linkUrl:(NSString *)linkUrl {
+    if (isOpen) { // 关闭页面, 打开外部页面
+        if (![NSString isEmptyString:linkUrl]) {
+            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkUrl] options: @{} completionHandler: nil];
+        }
+        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+            [self backAction];
+        });
+    }
+    else { // 重新开启扫码
+        [self startScan];
+    }
+}
+
+- (void)backAction {
+    [self.view endEditing:YES];
+    // 根据需要返回到不同页面
+    
+    [self.navigationController popViewControllerAnimated:YES];
+}
+
 - (ScanNavView *)navView {
     if (!_navView) {
         _navView = [ScanNavView shareInstance];

+ 23 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanFailViewController.h

@@ -0,0 +1,23 @@
+//
+//  ScanFailViewController.h
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/13.
+//
+
+#import "KSBaseViewController.h"
+
+typedef NS_ENUM(NSInteger, SCANFAIL) {
+    SCANFAIL_EXPIRED,     // 过期
+    SCANFAIL_AUTHFAILED,  // 授权失败
+    SCANFAIL_UNRECOGNIZE, // 无法识别
+};
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ScanFailViewController : KSBaseViewController
+
+@property (nonatomic, assign) SCANFAIL failType;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 109 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanFailViewController.m

@@ -0,0 +1,109 @@
+//
+//  ScanFailViewController.m
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/13.
+//
+
+#import "ScanFailViewController.h"
+#import "ScanFailBodyView.h"
+
+
+@interface ScanFailViewController ()
+
+@property (nonatomic, strong) ScanFailBodyView *bodyView;
+
+@end
+
+@implementation ScanFailViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self configUI];
+}
+
+- (void)configUI {
+    [self.scrollView removeFromSuperview];
+    [self.view addSubview:self.bodyView];
+    [self.bodyView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(self.view);
+    }];
+    
+    [self configBodyView];
+}
+
+- (void)configBodyView {
+    NSString *imageName = @"";
+    NSString *title = @"";
+    NSString *desc = @"";
+    NSString *headTitle = @"扫描结果";
+    if (self.failType == SCANFAIL_EXPIRED) {
+        imageName = @"scan_codeExpired";
+        title = @"二维码已过期";
+        desc = @"请在乐教通刷新二维码后重新扫码";
+        headTitle = @"授权登录";
+    }
+    else if (self.failType == SCANFAIL_AUTHFAILED) {
+        imageName = @"scan_authError";
+        title = @"授权失败";
+        desc = @"授权失败,请重新扫码授权";
+        headTitle = @"授权登录";
+    }
+    else if (self.failType == SCANFAIL_UNRECOGNIZE) { // 无法识别
+        imageName = @"scan_codeExpired";
+        title = @"无法识别";
+        desc = @"当前二维码无法识别";
+        headTitle = @"扫描结果";
+    }
+    
+    [self allocTitle:headTitle];
+
+    [self.bodyView configWithImageName:imageName title:title desc:desc];
+}
+
+- (void)backAction {
+    [self.navigationController popToRootViewControllerAnimated:YES];
+}
+
+
+#pragma mark ------- lazying
+- (ScanFailBodyView *)bodyView {
+    if (!_bodyView) {
+        _bodyView = [ScanFailBodyView shareIntance];
+        MJWeakSelf;
+        [_bodyView reScanAction:^{
+            [weakSelf reScanCode];
+        }];
+    }
+    return _bodyView;
+}
+
+- (void)reScanCode {
+    // 返回扫码页面
+    UIViewController *ctrl = nil;
+    for (UIViewController *controller in self.navigationController.viewControllers) {
+        if ([controller isKindOfClass:NSClassFromString(@"HomeScanViewController")]) {
+            ctrl = controller;
+            break;
+        }
+    }
+    if (ctrl) {
+        [self.navigationController popToViewController:ctrl animated:YES];
+    }
+    else {
+        [self.navigationController popToRootViewControllerAnimated:YES];
+    }
+}
+
+/*
+#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

+ 18 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanLoginViewController.h

@@ -0,0 +1,18 @@
+//
+//  ScanLoginViewController.h
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/12.
+//
+
+#import "KSBaseViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ScanLoginViewController : KSBaseViewController
+
+@property (nonatomic, strong) NSString *uuid;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 92 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/Controller/ScanLoginViewController.m

@@ -0,0 +1,92 @@
+//
+//  ScanLoginViewController.m
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/12.
+//
+
+#import "ScanLoginViewController.h"
+#import "ScanLoginBodyView.h"
+#import "ScanFailViewController.h"
+
+@interface ScanLoginViewController ()
+
+@property (nonatomic, strong) ScanLoginBodyView *bodyView;
+
+@end
+
+@implementation ScanLoginViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self allocTitle:@"授权登录"];
+    [self configUI];
+}
+
+
+
+- (void)configUI {
+    [self.scrollView removeFromSuperview];
+    [self.view addSubview:self.bodyView];
+    [self.bodyView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(self.view);
+    }];
+}
+
+
+- (ScanLoginBodyView *)bodyView {
+    if (!_bodyView) {
+        _bodyView = [ScanLoginBodyView shareInstance];
+        MJWeakSelf;
+        [_bodyView authActionCallback:^(BOOL isAuth) {
+            [weakSelf authAction:isAuth];
+        }];
+    }
+    return _bodyView;
+}
+
+- (void)authAction:(BOOL)isAuth {
+    if (isAuth) {
+        [LOADING_MANAGER showCustomLoading:@"登录中.."];
+        [KSNetworkingManager verifyQrcode:KS_POST uuid:self.uuid success:^(NSDictionary * _Nonnull dic) {
+            [LOADING_MANAGER removeCustomLoading];
+            if ([dic ks_integerValueForKey:@"code"] == 200) {
+                [LOADING_MANAGER KSShowMsg:@"授权成功" promptCompletion:^{
+                    [self.navigationController popToRootViewControllerAnimated:YES];
+                }];
+            }
+            else {
+                ScanFailViewController *ctrl = [[ScanFailViewController alloc] init];
+                if ([dic ks_integerValueForKey:@"code"] == 5440) { // 过期
+                    ctrl.failType = SCANFAIL_EXPIRED;
+                }
+                else {
+                    ctrl.failType = SCANFAIL_AUTHFAILED;
+                }
+                [self.navigationController pushViewController:ctrl animated:YES];
+            }
+        } faliure:^(NSError * _Nonnull error) {
+            [LOADING_MANAGER removeCustomLoading];
+            
+        }];
+    }
+    else {
+        [self.navigationController popToRootViewControllerAnimated:YES];
+    }
+}
+
+- (void)backAction {
+    [self.navigationController popToRootViewControllerAnimated:YES];
+}
+/*
+#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

+ 24 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanFailBodyView.h

@@ -0,0 +1,24 @@
+//
+//  ScanFailBodyView.h
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/13.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^ReScanCallback)(void);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ScanFailBodyView : UIView
+
++ (instancetype)shareIntance;
+
+- (void)reScanAction:(ReScanCallback)callback;
+
+- (void)configWithImageName:(NSString *)imgName title:(NSString *)title desc:(NSString *)desc;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 63 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanFailBodyView.m

@@ -0,0 +1,63 @@
+//
+//  ScanFailBodyView.m
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/13.
+//
+
+#import "ScanFailBodyView.h"
+
+
+@interface ScanFailBodyView ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *imageView;
+
+@property (weak, nonatomic) IBOutlet UILabel *errorTitle;
+
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+
+@property (weak, nonatomic) IBOutlet UIButton *backButton;
+
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpace;
+
+@property (nonatomic, copy) ReScanCallback callback;
+
+@end
+
+@implementation ScanFailBodyView
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.bottomSpace.constant = iPhoneXSafeBottomMargin + 44;
+}
+
++ (instancetype)shareIntance {
+    ScanFailBodyView *view = [[[NSBundle mainBundle] loadNibNamed:@"ScanFailBodyView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)reScanAction:(ReScanCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (void)configWithImageName:(NSString *)imgName title:(NSString *)title desc:(NSString *)desc {
+    [self.imageView setImage:[UIImage imageNamed:imgName]];
+    self.errorTitle.text = title;
+    self.descLabel.text = desc;
+}
+
+- (IBAction)backScan:(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

+ 87 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanFailBodyView.xib

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
+        <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="ScanFailBodyView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ovn-7d-fib">
+                    <rect key="frame" x="38" y="766" width="317" height="42"/>
+                    <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="42" id="oeI-TN-HsT"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <state key="normal" title="重新扫码">
+                        <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </state>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="21"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="backScan:" destination="iN0-l3-epB" eventType="touchUpInside" id="Trv-8R-Usf"/>
+                    </connections>
+                </button>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="二维码已过期" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NR0-je-xVF">
+                    <rect key="frame" x="141" y="150" width="111" height="25"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="25" id="V1E-FZ-plL"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
+                    <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="scan_codeExpired" translatesAutoresizingMaskIntoConstraints="NO" id="1ts-Cu-fpc">
+                    <rect key="frame" x="166.66666666666666" y="60" width="60" height="60"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="60" id="FqQ-lS-Bj7"/>
+                        <constraint firstAttribute="height" constant="60" id="tgx-fa-iJB"/>
+                    </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="WVb-iT-d5l">
+                    <rect key="frame" x="74" y="190" width="245" height="19.333333333333343"/>
+                    <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                    <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstItem="WVb-iT-d5l" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="47F-xV-C4x"/>
+                <constraint firstAttribute="bottom" secondItem="ovn-7d-fib" secondAttribute="bottom" constant="44" id="AMI-1x-QaR"/>
+                <constraint firstItem="1ts-Cu-fpc" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="60" id="TED-mm-eMO"/>
+                <constraint firstItem="NR0-je-xVF" firstAttribute="top" secondItem="1ts-Cu-fpc" secondAttribute="bottom" constant="30" id="VKr-dX-zzE"/>
+                <constraint firstItem="NR0-je-xVF" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="Vhc-ku-Ibz"/>
+                <constraint firstAttribute="trailing" secondItem="ovn-7d-fib" secondAttribute="trailing" constant="38" id="mhT-Bg-GD9"/>
+                <constraint firstItem="WVb-iT-d5l" firstAttribute="top" secondItem="NR0-je-xVF" secondAttribute="bottom" constant="15" id="nHd-0B-CHq"/>
+                <constraint firstItem="ovn-7d-fib" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="38" id="wFN-Uc-ZZC"/>
+                <constraint firstItem="1ts-Cu-fpc" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="zAt-Zo-aO3"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="backButton" destination="ovn-7d-fib" id="cni-AZ-uHf"/>
+                <outlet property="bottomSpace" destination="AMI-1x-QaR" id="tKX-Sc-0Hc"/>
+                <outlet property="descLabel" destination="WVb-iT-d5l" id="on4-5K-1HW"/>
+                <outlet property="errorTitle" destination="NR0-je-xVF" id="0LP-0o-aOy"/>
+                <outlet property="imageView" destination="1ts-Cu-fpc" id="vSc-rQ-Gnb"/>
+            </connections>
+            <point key="canvasLocation" x="-40.458015267175568" y="19.718309859154932"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="scan_codeExpired" width="60" height="60"/>
+    </resources>
+</document>

+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanLoginBodyView.h

@@ -0,0 +1,22 @@
+//
+//  ScanLoginBodyView.h
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/13.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^AuthCallback)(BOOL isAuth);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ScanLoginBodyView : UIView
+
++ (instancetype)shareInstance;
+
+- (void)authActionCallback:(AuthCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 64 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanLoginBodyView.m

@@ -0,0 +1,64 @@
+//
+//  ScanLoginBodyView.m
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/13.
+//
+
+#import "ScanLoginBodyView.h"
+
+@interface ScanLoginBodyView ()
+
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+
+@property (weak, nonatomic) IBOutlet UIButton *sureButton;
+
+@property (nonatomic, copy) AuthCallback callback;
+
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpace;
+@end
+
+@implementation ScanLoginBodyView
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.bottomSpace.constant = iPhoneXSafeBottomMargin + 44;
+ 
+    NSString *text = @"使用酷乐秀学院端账号授权登录「乐教通」";
+    NSMutableAttributedString *desc = [[NSMutableAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14.0f], NSForegroundColorAttributeName:HexRGB(0x777777)}];
+    [desc addAttributes:@{NSForegroundColorAttributeName:THEMECOLOR} range:[text rangeOfString:@"「乐教通」"]];
+    self.descLabel.attributedText = desc;
+}
+
+
++ (instancetype)shareInstance {
+    ScanLoginBodyView *view = [[[NSBundle mainBundle] loadNibNamed:@"ScanLoginBodyView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)authActionCallback:(AuthCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (IBAction)authLogin:(id)sender {
+    if (self.callback) {
+        self.callback(YES);
+    }
+}
+
+- (IBAction)cancelAuth:(id)sender {
+    if (self.callback) {
+        self.callback(NO);
+    }
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 98 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanLoginBodyView.xib

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
+        <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="ScanLoginBodyView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Kbv-wB-GWj">
+                    <rect key="frame" x="38" y="766" width="317" height="42"/>
+                    <color key="backgroundColor" red="0.94901960784313721" green="0.96078431372549022" blue="0.98039215686274506" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="42" id="YAW-vx-IMO"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <state key="normal" title="取消授权">
+                        <color key="titleColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                    </state>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="21"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="cancelAuth:" destination="iN0-l3-epB" eventType="touchUpInside" id="5Ev-DD-uTo"/>
+                    </connections>
+                </button>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="37f-Bu-I2X">
+                    <rect key="frame" x="38" y="708" width="317" height="42"/>
+                    <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="42" id="VfP-ey-Rd0"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <state key="normal" title="授权登录">
+                        <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </state>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="21"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="authLogin:" destination="iN0-l3-epB" eventType="touchUpInside" id="cp1-Cp-z2T"/>
+                    </connections>
+                </button>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="aboutUs_icon" translatesAutoresizingMaskIntoConstraints="NO" id="eso-Gq-pVd">
+                    <rect key="frame" x="126.66666666666669" y="60" width="140" height="140"/>
+                </imageView>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="使用管乐团伴学端账号授权登录「乐教通」" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XDb-uv-cBU">
+                    <rect key="frame" x="66" y="230" width="261" height="20"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="20" id="gdB-Rb-2kP"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                    <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+            <constraints>
+                <constraint firstItem="XDb-uv-cBU" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="3m6-Oj-2Nd"/>
+                <constraint firstItem="eso-Gq-pVd" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="G1e-A9-5xZ"/>
+                <constraint firstItem="Kbv-wB-GWj" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="38" id="HNB-nr-QiU"/>
+                <constraint firstAttribute="bottom" secondItem="Kbv-wB-GWj" secondAttribute="bottom" constant="44" id="KYP-pi-Otr"/>
+                <constraint firstItem="eso-Gq-pVd" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="60" id="Yfm-Tc-J4H"/>
+                <constraint firstAttribute="trailing" secondItem="Kbv-wB-GWj" secondAttribute="trailing" constant="38" id="jfX-cd-SVR"/>
+                <constraint firstItem="Kbv-wB-GWj" firstAttribute="top" secondItem="37f-Bu-I2X" secondAttribute="bottom" constant="16" id="lAL-mS-Ebw"/>
+                <constraint firstItem="Kbv-wB-GWj" firstAttribute="trailing" secondItem="37f-Bu-I2X" secondAttribute="trailing" id="my8-yl-u8i"/>
+                <constraint firstItem="XDb-uv-cBU" firstAttribute="top" secondItem="eso-Gq-pVd" secondAttribute="bottom" constant="30" id="ra2-ze-XDs"/>
+                <constraint firstItem="Kbv-wB-GWj" firstAttribute="leading" secondItem="37f-Bu-I2X" secondAttribute="leading" id="wdK-Nf-n5w"/>
+            </constraints>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="bottomSpace" destination="KYP-pi-Otr" id="2a8-NU-aZN"/>
+                <outlet property="descLabel" destination="XDb-uv-cBU" id="cXF-n7-Kih"/>
+                <outlet property="sureButton" destination="37f-Bu-I2X" id="nJC-fe-h9z"/>
+            </connections>
+            <point key="canvasLocation" x="-19" y="20"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="aboutUs_icon" width="140" height="140"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 26 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanOpenAlert.h

@@ -0,0 +1,26 @@
+//
+//  ScanOpenAlert.h
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/14.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^ScanOutLinkCallback)(BOOL openLink, NSString * _Nullable linkUrl);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ScanOpenAlert : UIView
+
++ (instancetype)shareInstance;
+
+- (void)alertActionCallback:(ScanOutLinkCallback)callback;
+
+- (void)configWithLinkUrl:(NSString *)linkUrl;
+
+- (void)showAlertInView:(UIView *)displayView;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 73 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanOpenAlert.m

@@ -0,0 +1,73 @@
+//
+//  ScanOpenAlert.m
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2024/3/14.
+//
+
+#import "ScanOpenAlert.h"
+
+@interface ScanOpenAlert ()
+
+@property (nonatomic, strong) NSString *linkUrl;
+
+@property (nonatomic, copy) ScanOutLinkCallback callback;
+
+@property (weak, nonatomic) IBOutlet UILabel *linkLabel;
+
+@end
+
+@implementation ScanOpenAlert
+
++ (instancetype)shareInstance {
+    ScanOpenAlert *view = [[[NSBundle mainBundle] loadNibNamed:@"ScanOpenAlert" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)alertActionCallback:(ScanOutLinkCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (void)configWithLinkUrl:(NSString *)linkUrl {
+    self.linkUrl = linkUrl;
+    self.linkLabel.text = linkUrl;
+}
+
+- (void)showAlertInView:(UIView *)displayView {
+    if (displayView == nil) {
+        displayView = [NSObject getKeyWindow];
+    }
+    [displayView addSubview:self];
+    [self mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(displayView);
+    }];
+}
+
+- (void)removeAlert {
+    [self removeFromSuperview];
+}
+- (IBAction)cancelAlert:(id)sender {
+    [self removeAlert];
+    if (self.callback) {
+        self.callback(NO, nil);
+    }
+}
+
+- (IBAction)openLink:(id)sender {
+    [self removeAlert];
+    if (self.callback) {
+        self.callback(YES, self.linkUrl);
+    }
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 155 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/ScanView/View/ScanOpenAlert.xib

@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
+        <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="ScanOpenAlert">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jXB-mR-C4u">
+                    <rect key="frame" x="59" y="304" width="275" height="244"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="scanAlert_bg" translatesAutoresizingMaskIntoConstraints="NO" id="MUz-Cl-nqc">
+                            <rect key="frame" x="0.0" y="0.0" width="275" height="115"/>
+                        </imageView>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="q8g-DC-NIM">
+                            <rect key="frame" x="0.0" y="194" width="275" height="1"/>
+                            <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="JCv-4f-83H"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="U7H-IF-ndO">
+                            <rect key="frame" x="137" y="195" width="1" height="49"/>
+                            <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="1" id="aGa-Qc-7Ap"/>
+                            </constraints>
+                        </view>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" usesAttributedText="YES" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dgb-DR-Ik9">
+                            <rect key="frame" x="22" y="93" width="232" height="46"/>
+                            <attributedString key="attributedText">
+                                <fragment content="下个页面不受我们控制哦,使用时请注意安全">
+                                    <attributes>
+                                        <color key="NSColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <font key="NSFont" metaFont="system" size="15"/>
+                                        <font key="NSOriginalFont" metaFont="system" size="16"/>
+                                        <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" minimumLineHeight="23" maximumLineHeight="23" tighteningFactorForTruncation="0.0"/>
+                                    </attributes>
+                                </fragment>
+                            </attributedString>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qaS-zw-d7N">
+                            <rect key="frame" x="22" y="141" width="232" height="23"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="23" id="qRQ-bS-cbY"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="温馨提示" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="caP-kU-zjG">
+                            <rect key="frame" x="100.66666666666666" y="53" width="74" height="25"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="25" id="c5U-2s-eZ9"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
+                            <color key="textColor" red="0.23137254901960785" green="0.13725490196078433" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kEp-h3-Qgh">
+                            <rect key="frame" x="0.0" y="195" width="137" height="49"/>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="取消">
+                                <color key="titleColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="cancelAlert:" destination="iN0-l3-epB" eventType="touchUpInside" id="11I-9n-w2P"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xsF-dB-N9M">
+                            <rect key="frame" x="138" y="195" width="137" height="49"/>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="浏览器打开">
+                                <color key="titleColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="openLink:" destination="iN0-l3-epB" eventType="touchUpInside" id="ipE-0x-NwY"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="kEp-h3-Qgh" firstAttribute="leading" secondItem="jXB-mR-C4u" secondAttribute="leading" id="1Ha-9w-F0B"/>
+                        <constraint firstItem="xsF-dB-N9M" firstAttribute="top" secondItem="q8g-DC-NIM" secondAttribute="bottom" id="3P5-At-SJL"/>
+                        <constraint firstItem="MUz-Cl-nqc" firstAttribute="leading" secondItem="jXB-mR-C4u" secondAttribute="leading" id="6F2-Pa-sbg"/>
+                        <constraint firstAttribute="width" constant="275" id="6H1-nh-Owm"/>
+                        <constraint firstItem="kEp-h3-Qgh" firstAttribute="top" secondItem="q8g-DC-NIM" secondAttribute="bottom" id="9jl-vi-f9o"/>
+                        <constraint firstAttribute="trailing" secondItem="Dgb-DR-Ik9" secondAttribute="trailing" constant="21" id="C1w-CY-2zk"/>
+                        <constraint firstItem="qaS-zw-d7N" firstAttribute="leading" secondItem="jXB-mR-C4u" secondAttribute="leading" constant="22" id="CCd-Ky-LKd"/>
+                        <constraint firstItem="MUz-Cl-nqc" firstAttribute="top" secondItem="jXB-mR-C4u" secondAttribute="top" id="Gn9-Ws-kJE"/>
+                        <constraint firstAttribute="bottom" secondItem="U7H-IF-ndO" secondAttribute="bottom" id="Gun-ep-ELv"/>
+                        <constraint firstAttribute="bottom" secondItem="kEp-h3-Qgh" secondAttribute="bottom" id="H1z-go-wcO"/>
+                        <constraint firstItem="caP-kU-zjG" firstAttribute="centerX" secondItem="jXB-mR-C4u" secondAttribute="centerX" id="Hry-vJ-W89"/>
+                        <constraint firstItem="U7H-IF-ndO" firstAttribute="top" secondItem="q8g-DC-NIM" secondAttribute="bottom" id="LMh-oq-dwd"/>
+                        <constraint firstItem="caP-kU-zjG" firstAttribute="top" secondItem="jXB-mR-C4u" secondAttribute="top" constant="53" id="Oxf-CZ-lsH"/>
+                        <constraint firstItem="Dgb-DR-Ik9" firstAttribute="leading" secondItem="jXB-mR-C4u" secondAttribute="leading" constant="22" id="Ref-7v-iMv"/>
+                        <constraint firstAttribute="bottom" secondItem="q8g-DC-NIM" secondAttribute="bottom" constant="49" id="S8Q-g6-ZK7"/>
+                        <constraint firstItem="Dgb-DR-Ik9" firstAttribute="top" secondItem="caP-kU-zjG" secondAttribute="bottom" constant="15" id="SYg-IX-U6u"/>
+                        <constraint firstItem="U7H-IF-ndO" firstAttribute="leading" secondItem="kEp-h3-Qgh" secondAttribute="trailing" id="YiZ-EA-if1"/>
+                        <constraint firstAttribute="trailing" secondItem="xsF-dB-N9M" secondAttribute="trailing" id="Ylc-3a-bVl"/>
+                        <constraint firstItem="xsF-dB-N9M" firstAttribute="leading" secondItem="U7H-IF-ndO" secondAttribute="trailing" id="by9-HA-aXp"/>
+                        <constraint firstAttribute="bottom" secondItem="xsF-dB-N9M" secondAttribute="bottom" id="dwH-66-ceI"/>
+                        <constraint firstItem="q8g-DC-NIM" firstAttribute="top" secondItem="qaS-zw-d7N" secondAttribute="bottom" constant="30" id="exg-nY-vgG"/>
+                        <constraint firstItem="qaS-zw-d7N" firstAttribute="top" secondItem="Dgb-DR-Ik9" secondAttribute="bottom" constant="2" id="jOl-QZ-gmD"/>
+                        <constraint firstItem="U7H-IF-ndO" firstAttribute="centerX" secondItem="jXB-mR-C4u" secondAttribute="centerX" id="l8w-Uj-Xfc"/>
+                        <constraint firstAttribute="trailing" secondItem="qaS-zw-d7N" secondAttribute="trailing" constant="21" id="lS3-kc-Xpp"/>
+                        <constraint firstItem="q8g-DC-NIM" firstAttribute="leading" secondItem="jXB-mR-C4u" secondAttribute="leading" id="n1M-G8-Jho"/>
+                        <constraint firstAttribute="trailing" secondItem="MUz-Cl-nqc" secondAttribute="trailing" id="wbz-m9-wAr"/>
+                        <constraint firstAttribute="trailing" secondItem="q8g-DC-NIM" secondAttribute="trailing" id="ybr-Lp-pDX"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="scan_alert" translatesAutoresizingMaskIntoConstraints="NO" id="bGk-TQ-TtF">
+                    <rect key="frame" x="146.66666666666666" y="280" width="100" height="60"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="60" id="ZgD-Kc-i8g"/>
+                        <constraint firstAttribute="width" constant="100" id="bDq-ry-W2n"/>
+                    </constraints>
+                </imageView>
+            </subviews>
+            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="bGk-TQ-TtF" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="Qzf-1p-w86"/>
+                <constraint firstItem="jXB-mR-C4u" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="Vlb-w1-X2A"/>
+                <constraint firstItem="jXB-mR-C4u" firstAttribute="top" secondItem="bGk-TQ-TtF" secondAttribute="top" constant="24" id="fW5-Dk-byM"/>
+                <constraint firstItem="jXB-mR-C4u" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="zXo-eW-Sh2"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="linkLabel" destination="qaS-zw-d7N" id="kBM-Rf-sMG"/>
+            </connections>
+            <point key="canvasLocation" x="-37.404580152671755" y="19.718309859154932"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="scanAlert_bg" width="275" height="115"/>
+        <image name="scan_alert" width="101" height="77"/>
+    </resources>
+</document>

+ 4 - 1
KulexiuForTeacher/KulexiuForTeacher/configuration/Config-debug.xcconfig

@@ -13,6 +13,8 @@ ACCOMPANY_DOMAIN = @"test.colexiu.com"
 SOCKET_DOMAIN = @"test.colexiu.com/audioAnalysis"
 WHITE_BOARD = @"test.gym.lexiaoya.cn"
 
+OPEN_DOMAIN = @"test.resource.colexiu.com"
+
 JSPUSH_ENVIRONMENT = NO
 SUBMIT_UUID = NO
 CONFIG_TXSDKAPPID = 1400805079
@@ -22,4 +24,5 @@ APP_BUNDLE_ID = com.Colexiu.KulexiuForTeacher
 CONFIG_FLAG = DEBUG
 SSL_AUTH = YES
 
-GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' OPEN_DOMAIN='${OPEN_DOMAIN}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'
+

+ 4 - 1
KulexiuForTeacher/KulexiuForTeacher/configuration/Config-dev.xcconfig

@@ -13,6 +13,9 @@ ACCOMPANY_DOMAIN = @"dev.colexiu.com"
 SOCKET_DOMAIN = @"dev.colexiu.com/audioAnalysis"
 WHITE_BOARD = @"test.dayaedu.com"
 
+OPEN_DOMAIN = @"dev.resource.colexiu.com"
+
+
 JSPUSH_ENVIRONMENT = NO
 SUBMIT_UUID = NO
 CONFIG_TXSDKAPPID = 1400805079
@@ -22,4 +25,4 @@ APP_BUNDLE_ID = com.Colexiu.KulexiuForTeacher-dev
 CONFIG_FLAG = DEV
 SSL_AUTH = YES
 
-GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' OPEN_DOMAIN='${OPEN_DOMAIN}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'

+ 4 - 1
KulexiuForTeacher/KulexiuForTeacher/configuration/Config-release.xcconfig

@@ -13,6 +13,8 @@ ACCOMPANY_DOMAIN = @"online.colexiu.com"
 SOCKET_DOMAIN = @"online.colexiu.com/audioAnalysis"
 WHITE_BOARD = @"gym.lexiaoya.cn"
 
+OPEN_DOMAIN = @"mec.colexiu.com"
+
 JSPUSH_ENVIRONMENT = YES
 SUBMIT_UUID = YES
 CONFIG_TXSDKAPPID = 1400799837
@@ -22,4 +24,5 @@ APP_BUNDLE_ID = com.Colexiu.KulexiuForTeacher
 CONFIG_FLAG = RELEASE
 SSL_AUTH = YES
 
-GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' OPEN_DOMAIN='${OPEN_DOMAIN}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'
+

+ 4 - 1
KulexiuForTeacher/KulexiuForTeacher/configuration/Config-test.xcconfig

@@ -13,6 +13,8 @@ ACCOMPANY_DOMAIN = @"test.colexiu.com"
 SOCKET_DOMAIN = @"test.colexiu.com/audioAnalysis"
 WHITE_BOARD = @"test.gym.lexiaoya.cn"
 
+OPEN_DOMAIN = @"test.resource.colexiu.com"
+
 JSPUSH_ENVIRONMENT = NO
 SUBMIT_UUID = NO
 CONFIG_TXSDKAPPID = 1400805079
@@ -22,4 +24,5 @@ APP_BUNDLE_ID = com.Colexiu.KulexiuForTeacher-test
 CONFIG_FLAG = TEST
 SSL_AUTH = YES
 
-GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) REQUEST_DOMAIN='${REQUEST_DOMAIN}' ACCOMPANY_DOMAIN='${ACCOMPANY_DOMAIN}' SOCKET_DOMAIN='${SOCKET_DOMAIN}' WHITE_BOARD='${WHITE_BOARD}' OPEN_DOMAIN='${OPEN_DOMAIN}' JSPUSH_ENVIRONMENT='${JSPUSH_ENVIRONMENT}' SUBMIT_UUID='${SUBMIT_UUID}' CONFIG_TXSDKAPPID='${CONFIG_TXSDKAPPID}' TXOfflinePushCertificateIDForAPNS='${TXOfflinePushCertificateIDForAPNS}' APP_NAME='${APP_NAME}' APP_BUNDLE_ID='${APP_BUNDLE_ID}' SSL_AUTH='${SSL_AUTH}'
+