Parcourir la source

直播课进入路径

Steven il y a 2 ans
Parent
commit
76a7b53c39
25 fichiers modifiés avec 1090 ajouts et 38 suppressions
  1. 40 0
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. BIN
      KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/UserInterfaceState.xcuserstate
  3. 22 6
      KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  4. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/course_bg.imageset/Contents.json
  5. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/course_bg.imageset/course_bg@2x.png
  6. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/course_bg.imageset/course_bg@3x.png
  7. 44 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/liveCart_AlertBg.imageset/Contents.json
  8. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/liveCart_AlertBg.imageset/liveCart_AlertBg@2x.png
  9. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/liveCart_AlertBg.imageset/liveCart_AlertBg@3x.png
  10. 34 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSBaseWKWebViewController.m
  11. 11 10
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h
  12. 1 2
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m
  13. 16 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/KSLiveWebViewController.h
  14. 46 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/KSLiveWebViewController.m
  15. 230 19
      KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.m
  16. 0 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/Model/LiveCard.bundle/cardAnimation.json
  17. 35 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindow.h
  18. 243 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindow.m
  19. 30 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindowManager.h
  20. 71 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindowManager.m
  21. 3 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSChatVideoView.h
  22. 33 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.h
  23. 84 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.m
  24. 121 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.xib
  25. 4 1
      KulexiuForStudent/Podfile

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

@@ -645,6 +645,12 @@
 		BCB908F12850B08D00F5FF69 /* KSChatMusicShareCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB908EB2850B08D00F5FF69 /* KSChatMusicShareCell.m */; };
 		BCB908F22850B08D00F5FF69 /* ShareMusicCellContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCB908EC2850B08D00F5FF69 /* ShareMusicCellContentView.xib */; };
 		BCB908F32850B08D00F5FF69 /* ShareLiveCellContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCB908ED2850B08D00F5FF69 /* ShareLiveCellContentView.xib */; };
+		BCB9090B2852EE9600F5FF69 /* KSLiveWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB9090A2852EE9600F5FF69 /* KSLiveWebViewController.m */; };
+		BCB9090D2852EEBE00F5FF69 /* LiveCard.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BCB9090C2852EEBE00F5FF69 /* LiveCard.bundle */; };
+		BCB909132852EF0000F5FF69 /* KSDragWindowManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB909112852EF0000F5FF69 /* KSDragWindowManager.m */; };
+		BCB909142852EF0000F5FF69 /* KSDragWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB909122852EF0000F5FF69 /* KSDragWindow.m */; };
+		BCB9091728530E9C00F5FF69 /* KSShopCardView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB9091628530E9C00F5FF69 /* KSShopCardView.m */; };
+		BCB9091928530EA500F5FF69 /* KSShopCardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCB9091828530EA500F5FF69 /* KSShopCardView.xib */; };
 		BCBFDF3728110C660052AFE5 /* HomeNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCBFDF3628110C660052AFE5 /* HomeNavView.m */; };
 		BCBFDF3928110C6F0052AFE5 /* HomeNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCBFDF3828110C6F0052AFE5 /* HomeNavView.xib */; };
 		BCBFDF3C281156430052AFE5 /* HomeBannerView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCBFDF3B281156430052AFE5 /* HomeBannerView.m */; };
@@ -1869,6 +1875,16 @@
 		BCB908EB2850B08D00F5FF69 /* KSChatMusicShareCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSChatMusicShareCell.m; sourceTree = "<group>"; };
 		BCB908EC2850B08D00F5FF69 /* ShareMusicCellContentView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareMusicCellContentView.xib; sourceTree = "<group>"; };
 		BCB908ED2850B08D00F5FF69 /* ShareLiveCellContentView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareLiveCellContentView.xib; sourceTree = "<group>"; };
+		BCB909092852EE9600F5FF69 /* KSLiveWebViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KSLiveWebViewController.h; sourceTree = "<group>"; };
+		BCB9090A2852EE9600F5FF69 /* KSLiveWebViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KSLiveWebViewController.m; sourceTree = "<group>"; };
+		BCB9090C2852EEBE00F5FF69 /* LiveCard.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = LiveCard.bundle; sourceTree = "<group>"; };
+		BCB9090F2852EF0000F5FF69 /* KSDragWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSDragWindow.h; sourceTree = "<group>"; };
+		BCB909102852EF0000F5FF69 /* KSDragWindowManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSDragWindowManager.h; sourceTree = "<group>"; };
+		BCB909112852EF0000F5FF69 /* KSDragWindowManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSDragWindowManager.m; sourceTree = "<group>"; };
+		BCB909122852EF0000F5FF69 /* KSDragWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSDragWindow.m; sourceTree = "<group>"; };
+		BCB9091528530E9C00F5FF69 /* KSShopCardView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KSShopCardView.h; sourceTree = "<group>"; };
+		BCB9091628530E9C00F5FF69 /* KSShopCardView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KSShopCardView.m; sourceTree = "<group>"; };
+		BCB9091828530EA500F5FF69 /* KSShopCardView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KSShopCardView.xib; sourceTree = "<group>"; };
 		BCBFDF3528110C660052AFE5 /* HomeNavView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeNavView.h; sourceTree = "<group>"; };
 		BCBFDF3628110C660052AFE5 /* HomeNavView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeNavView.m; sourceTree = "<group>"; };
 		BCBFDF3828110C6F0052AFE5 /* HomeNavView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeNavView.xib; sourceTree = "<group>"; };
@@ -4005,6 +4021,8 @@
 			children = (
 				BCB6342A27F6D29500ACFDCF /* LiveVideoRoomViewController.h */,
 				BCB6342727F6D29500ACFDCF /* LiveVideoRoomViewController.m */,
+				BCB909092852EE9600F5FF69 /* KSLiveWebViewController.h */,
+				BCB9090A2852EE9600F5FF69 /* KSLiveWebViewController.m */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -4020,6 +4038,7 @@
 				BCB6343427F6D29500ACFDCF /* LiveroomTimeManager.m */,
 				BCB6343127F6D29500ACFDCF /* LiveSeatMember.h */,
 				BCB6343527F6D29500ACFDCF /* LiveSeatMember.m */,
+				BCB9090C2852EEBE00F5FF69 /* LiveCard.bundle */,
 			);
 			path = Model;
 			sourceTree = "<group>";
@@ -4027,6 +4046,7 @@
 		BCB6343627F6D29500ACFDCF /* View */ = {
 			isa = PBXGroup;
 			children = (
+				BCB9090E2852EF0000F5FF69 /* DragWindow */,
 				BCB635A827F6D93300ACFDCF /* KSChatVideoView.h */,
 				BCB635A727F6D93300ACFDCF /* KSChatVideoView.m */,
 				BCB635A527F6D90600ACFDCF /* KSLiveEmptyView.h */,
@@ -4050,6 +4070,9 @@
 				BCB6345827F6D29600ACFDCF /* LiveSeatApplyView.xib */,
 				BCB6344627F6D29500ACFDCF /* SeatContentView.h */,
 				BCB6345627F6D29600ACFDCF /* SeatContentView.m */,
+				BCB9091528530E9C00F5FF69 /* KSShopCardView.h */,
+				BCB9091628530E9C00F5FF69 /* KSShopCardView.m */,
+				BCB9091828530EA500F5FF69 /* KSShopCardView.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -4549,6 +4572,17 @@
 			path = MainToolbar;
 			sourceTree = "<group>";
 		};
+		BCB9090E2852EF0000F5FF69 /* DragWindow */ = {
+			isa = PBXGroup;
+			children = (
+				BCB9090F2852EF0000F5FF69 /* KSDragWindow.h */,
+				BCB909122852EF0000F5FF69 /* KSDragWindow.m */,
+				BCB909102852EF0000F5FF69 /* KSDragWindowManager.h */,
+				BCB909112852EF0000F5FF69 /* KSDragWindowManager.m */,
+			);
+			path = DragWindow;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -4678,6 +4712,7 @@
 				BCFE53F728128A9600AD6786 /* TeacherShowCell.xib in Resources */,
 				2723B5BF27F157B100E0B90B /* GroupCreateView.xib in Resources */,
 				BC8C2C5E2823F57100FBA5D5 /* AddressDetailBodyView.xib in Resources */,
+				BCB9090D2852EEBE00F5FF69 /* LiveCard.bundle in Resources */,
 				2723B63727F157D500E0B90B /* ApplyBottomView.xib in Resources */,
 				BC542E5928409EC900633781 /* InstrumentChooseCell.xib in Resources */,
 				2723B62F27F157D500E0B90B /* ChatComplainBodyView.xib in Resources */,
@@ -4731,6 +4766,7 @@
 				BC8A45A4283DC33400094BBB /* KSCloudSettingView.xib in Resources */,
 				2723B62D27F157D500E0B90B /* GroupApplyMemberCell.xib in Resources */,
 				BCB6347427F6D29600ACFDCF /* BaseEmoji.plist in Resources */,
+				BCB9091928530EA500F5FF69 /* KSShopCardView.xib in Resources */,
 				BC40BA252812560100DEC0D1 /* HomeCourseTipsView.xib in Resources */,
 				27F9032E27E87C2E00C08A19 /* DeviceCheckView.xib in Resources */,
 				275FA23727E7356B00CFEA2E /* LoginBodyView.xib in Resources */,
@@ -4978,6 +5014,7 @@
 				2723B67F27F15D3D00E0B90B /* AboutUsViewController.m in Sources */,
 				BCB6355027F6D2A300ACFDCF /* WhiteUtils.m in Sources */,
 				2779356127E324A70010E277 /* KSAudioRecordManager.m in Sources */,
+				BCB909132852EF0000F5FF69 /* KSDragWindowManager.m in Sources */,
 				2779359827E324A80010E277 /* TZAssetModel.m in Sources */,
 				277935A027E324A80010E277 /* UIView+TZLayout.m in Sources */,
 				2779351227E324A50010E277 /* KSNetworkAccessibleManager.m in Sources */,
@@ -5027,6 +5064,7 @@
 				2779352627E324A60010E277 /* UIAlertController+Extend.m in Sources */,
 				BC11925E280FA89A00A716F7 /* HomeworkBodyView.m in Sources */,
 				275FA1EB27E7351900CFEA2E /* KSBaseWKWebViewController.m in Sources */,
+				BCB909142852EF0000F5FF69 /* KSDragWindow.m in Sources */,
 				BCB6356727F6D2A300ACFDCF /* MemberChangeMessage.m in Sources */,
 				2779353B27E324A60010E277 /* UrlDecode.m in Sources */,
 				BC40BA23281255F700DEC0D1 /* HomeCourseTipsView.m in Sources */,
@@ -5060,6 +5098,7 @@
 				2779351627E324A60010E277 /* NSMutableArray+KSSafe.m in Sources */,
 				BC119247280EDA5800A716F7 /* kSJXCollectionView.m in Sources */,
 				2779358927E324A80010E277 /* CoinModel.m in Sources */,
+				BCB9091728530E9C00F5FF69 /* KSShopCardView.m in Sources */,
 				275FA1EA27E7351900CFEA2E /* KSRCIMDataSource.m in Sources */,
 				BC27A071280FF56C00F91E27 /* AccompanyEvaluateCell.m in Sources */,
 				BC119241280ED9E000A716F7 /* AccompanyDetailViewController.m in Sources */,
@@ -5338,6 +5377,7 @@
 				BCB6359C27F6D2AB00ACFDCF /* ClassVideoListCell.m in Sources */,
 				2723B61B27F157D500E0B90B /* KSSearchRCLabel.m in Sources */,
 				275FA23B27E7356B00CFEA2E /* PasswordBodyView.m in Sources */,
+				BCB9090B2852EE9600F5FF69 /* KSLiveWebViewController.m in Sources */,
 				277935C527E324A90010E277 /* UIView+SDExtension.m in Sources */,
 				2779356E27E324A70010E277 /* UITextField_Toolbar.m in Sources */,
 				BCEBB8E82840B87100A76BE8 /* KSLiveChatroomMemberUp.m in Sources */,

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


+ 22 - 6
KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -78,8 +78,8 @@
             filePath = "KulexiuForStudent/Common/Base/KSBaseWKWebViewController.m"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "555"
-            endingLineNumber = "555"
+            startingLineNumber = "589"
+            endingLineNumber = "589"
             landmarkName = "-refreshUrl:"
             landmarkType = "7">
          </BreakpointContent>
@@ -94,8 +94,8 @@
             filePath = "KulexiuForStudent/Common/Base/KSBaseWKWebViewController.m"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "548"
-            endingLineNumber = "548"
+            startingLineNumber = "582"
+            endingLineNumber = "582"
             landmarkName = "-refreshUrl:"
             landmarkType = "7">
          </BreakpointContent>
@@ -110,8 +110,8 @@
             filePath = "KulexiuForStudent/Common/Base/KSBaseWKWebViewController.m"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "345"
-            endingLineNumber = "345"
+            startingLineNumber = "346"
+            endingLineNumber = "346"
             landmarkName = "-handleScriptMessageSource:"
             landmarkType = "7">
          </BreakpointContent>
@@ -176,5 +176,21 @@
             landmarkType = "7">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "C6ED8B61-E00C-44BE-ACF9-0239E944E9B6"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "KulexiuForStudent/Module/Live/View/KSShopCardView.m"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "47"
+            endingLineNumber = "47"
+            landmarkName = "-showViewInView:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/course_bg.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/course_bg.imageset/course_bg@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/course_bg.imageset/course_bg@3x.png


+ 44 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/liveCart_AlertBg.imageset/Contents.json

@@ -0,0 +1,44 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "liveCart_AlertBg@2x.png",
+      "idiom" : "universal",
+      "resizing" : {
+        "cap-insets" : {
+          "bottom" : 33,
+          "top" : 21
+        },
+        "center" : {
+          "height" : 1,
+          "mode" : "tile"
+        },
+        "mode" : "3-part-vertical"
+      },
+      "scale" : "2x"
+    },
+    {
+      "filename" : "liveCart_AlertBg@3x.png",
+      "idiom" : "universal",
+      "resizing" : {
+        "cap-insets" : {
+          "bottom" : 51,
+          "top" : 33
+        },
+        "center" : {
+          "height" : 1,
+          "mode" : "tile"
+        },
+        "mode" : "3-part-vertical"
+      },
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/liveCart_AlertBg.imageset/liveCart_AlertBg@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Live/liveCart_AlertBg.imageset/liveCart_AlertBg@3x.png


+ 34 - 0
KulexiuForStudent/KulexiuForStudent/Common/Base/KSBaseWKWebViewController.m

@@ -21,6 +21,7 @@
 #import "KSOrderManager.h"
 #import "AddressListViewController.h"
 #import "KSEnterLiveroomManager.h"
+#import "TZImageManager.h"
 
 @interface KSBaseWKWebViewController ()
 
@@ -459,6 +460,39 @@
             [self removehub];
         }];
     }
+    else if ([[parm stringValueForKey:@"api"] isEqualToString:@"savePicture"]) { // 保存图片到相册
+        // 判断相册权限
+        PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable:NO showInView:nil];
+        if (albumEnable == PREMISSIONTYPE_YES) { // 如果有权限
+            NSDictionary *valueDic = [parm dictionaryValueForKey:@"content"];
+            NSString *base64String = [valueDic stringValueForKey:@"base64"];
+            UIImage *saveImage = [self imageWithBase64String:base64String];
+            [[TZImageManager manager] savePhotoWithImage:saveImage completion:^(PHAsset *asset, NSError *error) {
+                if (!error) {
+                    [self savePicCallback:[valueDic stringValueForKey:@"uuid"] isSuccess:YES];
+                }
+                else {
+                    [self savePicCallback:[valueDic stringValueForKey:@"uuid"] isSuccess:NO];
+                }
+            }];
+        }
+        else {
+            if (albumEnable == PREMISSIONTYPE_NO) {
+                [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
+            }
+        }
+    }
+}
+
+- (void)savePicCallback:(NSString *)uuid isSuccess:(BOOL)isSuccess {
+    NSString *status = isSuccess ? @"success" : @"fail";
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:@"savePicture" forKey:@"api"];
+    NSMutableDictionary *content = [NSMutableDictionary dictionary];
+    [content setValue:status forKey:@"status"];
+    [content setValue:uuid forKey:@"uuid"];
+    [parm setValue:content forKey:@"content"];
+    [self postMessage:parm];
 }
 
 - (void)sendAddressAction:(AddressListModel *)model {

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

@@ -8,6 +8,7 @@
 #import <Foundation/Foundation.h>
 #import "VoNetWorking.h"
 #import "UIImage+ResizeImage.h"
+#import "CustomNavViewController.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -377,16 +378,16 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param faliure 失败
 + (void)liveRoomJoinRoomRequest:(NSString *)get roomUid:(NSString *)roomUid success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
-// 进入直播间通知
-// /api-student/imLiveBroadcastRoom/joinRoom
-
-/// 进入直播间通知
-/// @param get get
-/// @param roomId 房间号
-/// @param userId 用户id
-/// @param success 成功
-/// @param faliure 失败
-+ (void)LiveroomJoinRequest:(NSString *)get roomId:(NSString *)roomId userId:(NSString *)userId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+//// 进入直播间通知
+//// /api-student/imLiveBroadcastRoom/joinRoom
+//
+///// 进入直播间通知
+///// @param get get
+///// @param roomId 房间号
+///// @param userId 用户id
+///// @param success 成功
+///// @param faliure 失败
+//+ (void)LiveroomJoinRequest:(NSString *)get roomId:(NSString *)roomId userId:(NSString *)userId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
 // 退出直播间通知
 // /api-student/liveRoom/syncUserStatus

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

@@ -12,7 +12,6 @@
 #import <RongIMKit/RongIMKit.h>
 #import "JPUSHService.h"
 #import "RCConnectionManager.h"
-#import "CustomNavViewController.h"
 
 @implementation KSNetworkingManager
 
@@ -877,7 +876,7 @@
 /// @param faliure 失败
 + (void)LiveroomQuit:(NSString *)post success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
-    NSString *url = [NSString stringWithFormat:@"%@%@", SEALCLASSHOST, @"/liveRoom/syncUserStatus"];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/liveRoom/syncUserStatus"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:@"iOS" forKey:@"os"];
     [parm setValue:@"3" forKey:@"status"];

+ 16 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/KSLiveWebViewController.h

@@ -0,0 +1,16 @@
+//
+//  KSLiveWebViewController.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/6/10.
+//
+
+#import "KSBaseWKWebViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSLiveWebViewController : KSBaseWKWebViewController
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 46 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/KSLiveWebViewController.m

@@ -0,0 +1,46 @@
+//
+//  KSLiveWebViewController.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/6/10.
+//
+
+#import "KSLiveWebViewController.h"
+
+@interface KSLiveWebViewController ()
+
+@end
+
+@implementation KSLiveWebViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomClose) name:@"LiveroomClose" object:nil];
+}
+
+- (void)liveroomClose {
+    [self MBPShow:@"直播已结束"];
+//    [self.navigationController popToRootViewControllerAnimated:YES];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+    [super viewWillDisappear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = 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

+ 230 - 19
KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.m

@@ -21,6 +21,11 @@
 #import "KSLiveEmptyView.h"
 #import "KSChatVideoView.h"
 #import "LiveRoomLikeLayer.h"
+#import "KSDragWindowManager.h"
+//#import <Lottie/Lottie.h>
+#import "KSShopCardView.h"
+#import "KSLiveWebViewController.h"
+
 
 typedef NS_ENUM(NSInteger, MICSTATUS) {
     MICSTATUS_NOMAL,      // 正常状态
@@ -42,6 +47,9 @@ typedef NS_ENUM(NSInteger, MICSTATUS) {
 
 @property (nonatomic) NSMutableArray <KSLiveStreamVideo *>*streamVideos;
 
+// 视频主窗口容器
+@property (nonatomic, strong) UIView *videoContainerView;
+
 @property (nonatomic, strong) KSChatVideoView *videoView;
 
 @property (nonatomic, strong) LiveRoomHeadView *headView;
@@ -101,6 +109,26 @@ typedef NS_ENUM(NSInteger, MICSTATUS) {
 /// 是否在切换身份
 @property (nonatomic, assign) BOOL isTransferRole;
 
+@property (nonatomic, assign) BOOL hasSendWelcomeMessage;
+
+@property (nonatomic, assign) BOOL hasShowSuspendView;
+
+@property (nonatomic, assign) BOOL isPackageLostTips;
+
+@property (nonatomic, assign) NSTimeInterval lostStartTime; // 开始丢包事件
+
+@property (nonatomic, assign) NSTimeInterval bitErrorTime; // video bit zero start
+
+@property (nonatomic, assign) BOOL isLostPackage; // 严重丢包
+
+@property (nonatomic, assign) BOOL isBitError;  // bit error
+
+//@property (nonatomic, strong) LOTAnimationView *animationView;
+
+@property (nonatomic, assign) BOOL isCloseRoom; // 是否直播结束
+
+@property (nonatomic, strong) KSShopCardView *cardView;
+
 @end
 
 //  用于记录点赞消息连续点击的次数
@@ -120,6 +148,7 @@ static int clickPraiseBtnTimes  = 0;
     self.micStatus = MICSTATUS_NOMAL;
     self.isCreaterInRoom = NO; // 默认主讲人不在房间
     self.isImConnected = [USER_MANAGER checkIMConnected];
+    self.isCloseRoom = NO;
 }
 
 - (void)viewDidLoad {
@@ -140,13 +169,52 @@ static int clickPraiseBtnTimes  = 0;
         }];
     }
     
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomLogOut) name:@"liveroomLogout" object:nil];
-    
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomQuit) name:@"liveroomQuit" object:nil];
-    
     [self judgeAutoClose];
 }
 
+- (void)muteAllAudio {
+    if (self.room) {
+        [self.room muteAllRemoteAudio:YES];
+    }
+}
+
+- (void)IMConnetedCallback {
+    dispatch_main_async_safe(^{
+        // IM 连接成功回调
+        if (self.hasSendWelcomeMessage) { // 如果已经发送了进入消息
+            // 查询是否直播间开启
+            [KSNetworkingManager liveRoomJoinRoomRequest:KS_GET roomUid:self.roomId success:^(NSDictionary * _Nonnull dic) {
+                if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
+                    // 回调信息
+                    MJWeakSelf;
+                    [self notiferJoinSuccessToServiceCallback:^{
+                        [self MBPShow:@"IM连接成功"];
+                        [weakSelf sendWelcomeMessage];
+                    }];
+                }
+                else {
+                    [self MBPShow:MESSAGEKEY];
+                    [self quitRoom];
+                }
+            } faliure:^(NSError * _Nonnull error) {
+                
+            }];
+        }
+    });
+}
+
+- (void)sendWelcomeMessage {
+    [[RCIMClient sharedRCIMClient] joinExistChatRoom:self.roomId messageCount:-1 success:^{
+        KSLiveChatroomWelcome *joinChatroomMessage = [[KSLiveChatroomWelcome alloc] init];
+        [joinChatroomMessage setMsgId:[RCIM sharedRCIM].currentUserInfo.userId];
+        [self sendMessage:joinChatroomMessage displayMessage:YES callback:^(BOOL success) {
+            
+        }];
+    } error:^(RCErrorCode status) {
+        NSLog(@"error code %zd" ,status);
+    }];
+}
+
 - (void)judgeAutoClose {
     if (self.isTempRoom == NO) {
         self.timeManager.autoCloseNetworkRoomTime = [self getCloseTime];
@@ -169,13 +237,27 @@ static int clickPraiseBtnTimes  = 0;
 - (void)registerNotification {
     [KSChatroomMessageCenter registerMessageTypes];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMessageNotification:) name:OnReceiveChatroomMessageNotification object:nil];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomLogOut) name:@"liveroomLogout" object:nil];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomQuit) name:@"liveroomQuit" object:nil];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(IMConnetedCallback) name:@"RongIMConnected" object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(muteAllAudio) name:@"muteLiveAudio" object:nil];
 }
 
 - (void)setupUI {
     CGSize size = self.view.bounds.size;
     self.view.backgroundColor = HexRGB(0x25292e);
     
-    [self.view addSubview:self.videoView];
+    // 视图主容器
+    [self.view addSubview:self.videoContainerView];
+    [self.videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.top.bottom.right.mas_equalTo(self.view);
+    }];
+    
+    [self.videoContainerView addSubview:self.videoView];
+    
     [self.videoView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.top.bottom.right.mas_equalTo(self.view);
     }];
@@ -249,8 +331,9 @@ static int clickPraiseBtnTimes  = 0;
         });
         KSLiveChatroomWelcome *joinChatroomMessage = [[KSLiveChatroomWelcome alloc] init];
         [joinChatroomMessage setMsgId:[RCIM sharedRCIM].currentUserInfo.userId];
+        MJWeakSelf;
         [self sendMessage:joinChatroomMessage displayMessage:YES callback:^(BOOL success) {
-            
+            weakSelf.hasSendWelcomeMessage = YES;
         }];
         // 加入成功发送消息
     } error:^(RCErrorCode status) {
@@ -268,6 +351,32 @@ static int clickPraiseBtnTimes  = 0;
     [IQKeyboardManager sharedManager].enableAutoToolbar = NO;
     [IQKeyboardManager sharedManager].enable = NO;
     [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
+    // 重新渲染view
+    KSDragWindowManager *manager = [KSDragWindowManager sharedManager];
+    if (manager.hasShowWindow) {
+        [manager resignDragWindow];
+    }
+    if (self.hasShowSuspendView) {
+        KSLiveStreamVideo *mainVideo = nil;
+        if (self.videoView.streamId) {
+            for (KSLiveStreamVideo *streamVideo in self.streamVideos) {
+                if ([streamVideo.streamId isEqualToString:self.videoView.streamId]) {
+                    mainVideo = streamVideo;
+                    break;
+                }
+            }
+        }
+        if (mainVideo) {
+            [self.videoView addSubview:mainVideo.canvesView];
+            [mainVideo.canvesView mas_updateConstraints:^(MASConstraintMaker *make) {
+                make.left.right.bottom.top.mas_equalTo(self.videoView);
+            }];
+        }
+        _hasShowSuspendView = NO;
+    }
+    if (self.room) {
+        [self.room muteAllRemoteAudio:NO];
+    }
 }
 
 - (void)viewWillDisappear:(BOOL)animated {
@@ -281,6 +390,8 @@ static int clickPraiseBtnTimes  = 0;
         // Fallback on earlier versions
         [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
     }
+    
+    // 退出房间才停止定时器
     if (_timeManager) {
         [_timeManager stopDurationTimer];
     }
@@ -288,30 +399,44 @@ static int clickPraiseBtnTimes  = 0;
 
 // 刷新seatView
 - (void)renderSeatView {
+    
     NSMutableArray *seatArray = [NSMutableArray array];
-    for (RCRTCRemoteUser *user in self.remoteMemberArray) {
+    NSArray *remoteUserArray = [self.room.remoteUsers mutableCopy];
+    for (RCRTCRemoteUser *user in remoteUserArray) {
         if (![user.userId isEqualToString:self.videoView.streamUserId] && ![user.userId isEqualToString:self.createrId]) {
             [seatArray addObject:user.userId];
         }
     }
-    if (self.micStatus == MICSTATUS_CONNECTING) {
+    if (self.micStatus == MICSTATUS_CONNECTING && ![seatArray containsObject:UserDefault(UIDKey)]) {
         [seatArray addObject:UserDefault(UIDKey)];
     }
     
     if (seatArray.count) {
-        [self.view addSubview:self.seatContainer];
-        [self.seatContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
-            make.left.right.mas_equalTo(self.view);
-            make.top.mas_equalTo(self.headView.mas_bottom).offset(10);
-            make.height.mas_equalTo(80);
-        }];
+        if (![self.videoContainerView.subviews containsObject:self.seatContainer]) {
+            [self.videoContainerView addSubview:self.seatContainer];
+        }
+        [self updateSeatContainerConstraint];
+        
         self.seatContainer.seatMemberArray = [NSMutableArray arrayWithArray:seatArray];
         [self.seatContainer refreshSeatUI];
     }
     else {
-        if ([self.view.subviews containsObject:self.seatContainer]) {
-            [self.seatContainer removeFromSuperview];
-        }
+        [self removeSeatContainer];
+    }
+}
+
+- (void)updateSeatContainerConstraint {
+    [self.seatContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.videoContainerView);
+        make.top.mas_equalTo(self.headView.mas_bottom).offset(0);
+        make.height.mas_equalTo(70);
+    }];
+}
+
+// 移除连麦视图
+- (void)removeSeatContainer {
+    if ([self.videoContainerView.subviews containsObject:self.seatContainer]) {
+        [self.seatContainer removeFromSuperview];
     }
 }
 
@@ -845,6 +970,16 @@ static int clickPraiseBtnTimes  = 0;
     }
 }
 
+#pragma mark -- 加入直播间和退出直播间回到服务
+- (void)notiferJoinSuccessToServiceCallback:(void(^)(void))callback {
+    callback();
+//    [KSNetworkingManager LiveroomJoinRequest:KS_GET roomId:self.roomId userId:UserDefault(UIDKey) success:^(NSDictionary * _Nonnull dic) {
+//        callback();
+//    } faliure:^(NSError * _Nonnull error) {
+//        callback();
+//    }];
+}
+
 #pragma mark -- 退出直播间回掉服务
 - (void)quitNotiferService {
     [KSNetworkingManager LiveroomQuit:KS_POST success:^(NSDictionary * _Nonnull dic) {
@@ -1276,6 +1411,14 @@ static int clickPraiseBtnTimes  = 0;
     return _videoView;
 }
 
+- (UIView *)videoContainerView {
+    if (!_videoContainerView) {
+        _videoContainerView = [[UIView alloc] initWithFrame:CGRectZero];
+        _videoContainerView.backgroundColor = [UIColor clearColor];
+    }
+    return _videoContainerView;
+}
+
 - (LiveRoomHeadView *)headView {
     if (!_headView) {
         _headView = [LiveRoomHeadView shareInstance];
@@ -1341,9 +1484,9 @@ static int clickPraiseBtnTimes  = 0;
             }
         }
             break;
-        case LIVEROOMACTION_SHOP: // 商店
+        case LIVEROOMACTION_SHOP:
         {
-            
+            [self showCartAlert];
         }
             break;
         case LIVEROOMACTION_LIKE:
@@ -1361,6 +1504,9 @@ static int clickPraiseBtnTimes  = 0;
     }
 }
 
+- (void)showCartAlert {
+    [self.cardView showViewInView:self.view];
+}
 
 - (void)quitAction {
     if (self.micStatus == MICSTATUS_CONNECTING) {
@@ -1490,6 +1636,71 @@ static int clickPraiseBtnTimes  = 0;
     return self.expiredMinute * 60 + timeInterval;
 }
 
+- (KSShopCardView *)cardView {
+    if (!_cardView) {
+        _cardView = [KSShopCardView shareInstance];
+        MJWeakSelf;
+        [_cardView clickAction:^(CART_TYPE type) {
+            [weakSelf displayTeacherInfo:type];
+        }];
+    }
+    return _cardView;
+}
+// tabs=  practice | 陪练课 live | 直播课 video | 视频课 music | 乐谱 跳转到对应tab页
+
+- (void)displayTeacherInfo:(CART_TYPE)type {
+    
+    RCRTCVideoView *videoView = nil;
+    for (UIView *view in self.videoView.subviews) {
+        if ([view isKindOfClass:[RCRTCVideoView class]]) {
+            videoView = (RCRTCVideoView *)view;
+        }
+    }
+    if (videoView) {
+        _hasShowSuspendView = YES;
+        KSDragWindowManager *manager = [KSDragWindowManager sharedManager];
+        [manager initDragWindow];
+        manager.rootVC = (CustomNavViewController *)self.navigationController;
+        
+        [videoView removeFromSuperview];
+        [manager.dragWindow.containerView addSubview:videoView];
+        [videoView mas_updateConstraints:^(MASConstraintMaker *make) {
+            make.left.right.top.bottom.mas_equalTo(manager.dragWindow.containerView);
+        }];
+        [manager.dragWindow bringSubviewToFront:manager.dragWindow.cancelButton];
+    }
+    
+    NSString *tabs = @"";
+    switch (type) {
+        case CART_TYPE_ACCOMPANY:
+        {
+            tabs = @"practice";
+        }
+            break;
+        case CART_TYPE_LIVE:
+        {
+            tabs = @"live";
+        }
+            break;
+        case CART_TYPE_VIDEO:
+        {
+            tabs = @"video";
+        }
+            break;
+        case CART_TYPE_MUSIC:
+        {
+            tabs = @"music";
+        }
+            break;
+        default:
+            break;
+    }
+    NSString *url = [NSString stringWithFormat:@"%@%@%@&tabs=%@", WEBHOST,@"/#/teacherHome?teacherId=",self.createrId,tabs];
+    KSLiveWebViewController *ctrl = [[KSLiveWebViewController alloc] init];
+    ctrl.url = url;
+    [self.navigationController pushViewController:ctrl animated:YES];
+}
+
 - (void)dealloc {
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/Model/LiveCard.bundle/cardAnimation.json


+ 35 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindow.h

@@ -0,0 +1,35 @@
+//
+//  KSDragWindow.h
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/16.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+#define KSDragWindowWidth (KPortraitWidth / 4.0f)
+#define KSDragWindowHeight (KPortraitHeight / 4.0f)
+#define KSDragWindowHeightBottomSpace 40.0f
+#define KSDragWindowHeightRightSpace 0
+
+typedef NS_ENUM(NSInteger, DRAG_ACTION) {
+    DRAG_ACTION_CLICK,  // 返回详情
+    DRAG_ACTION_CANCEL, // 取消
+};
+
+typedef void(^DragClickAction)(DRAG_ACTION action);
+
+@interface KSDragWindow : UIWindow
+
+@property (nonatomic, strong) UIView *containerView;
+
+@property (nonatomic, strong) UIButton *cancelButton;
+
+- (void)clickAction:(DragClickAction)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 243 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindow.m

@@ -0,0 +1,243 @@
+//
+//  KSDragWindow.m
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/16.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "KSDragWindow.h"
+#define WIDTH (self.frame.size.width)
+#define HEIGHT (self.frame.size.height)
+
+@interface KSDragWindow ()<UIGestureRecognizerDelegate>
+
+@property (nonatomic, assign) UIInterfaceOrientation currentOrientation;
+
+@property (nonatomic, copy) DragClickAction callback;
+
+@end
+
+@implementation KSDragWindow
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    if (self = [super initWithFrame:frame]) {
+        self.backgroundColor  = [UIColor clearColor];
+        self.windowLevel = UIWindowLevelAlert;
+        [self makeKeyAndVisible];
+        [self addSubview:self.containerView];
+        self.containerView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
+        
+        
+        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(locationChange:)];
+        pan.delaysTouchesBegan = YES;
+        [self addGestureRecognizer:pan];
+        self.currentOrientation = UIInterfaceOrientationPortrait;
+        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(click:)];
+        [self addGestureRecognizer:tap];
+        tap.delegate = self;
+        [self addSubview:self.cancelButton];
+        self.cancelButton.frame = CGRectMake(frame.size.width-30, 0, 30, 30);
+        
+        [self setRootViewController:[UIViewController new]];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
+        
+    }
+    return self;
+}
+
+- (void)clickAction:(DragClickAction)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+#define KDEAISellDegreesToRadians(degrees) (degrees * M_PI / 180)
+- (void)statusBarOrientationChange:(NSNotification*)notification{
+    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
+    
+    [self setTransform:[self transformForOrientation:orientation]];
+    self.currentOrientation = orientation;
+    
+    CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
+    CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
+    if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
+        self.frame = CGRectMake(KSDragWindowHeight+KSDragWindowHeightBottomSpace, screenWidth - KSDragWindowWidth , KSDragWindowWidth, KSDragWindowHeight);
+    }else{
+        self.frame = CGRectMake(screenWidth - KSDragWindowWidth, screenHeight - KSDragWindowHeight - KSDragWindowHeightBottomSpace , KSDragWindowWidth, KSDragWindowHeight);
+    }
+}
+
+- (CGAffineTransform)transformForOrientation:(UIInterfaceOrientation)orientation {
+    
+    switch (orientation) {
+            
+        case UIInterfaceOrientationLandscapeLeft:
+            return CGAffineTransformMakeRotation(-KDEAISellDegreesToRadians(90));
+            
+        case UIInterfaceOrientationLandscapeRight:
+            return CGAffineTransformMakeRotation(KDEAISellDegreesToRadians(90));
+            
+        case UIInterfaceOrientationPortraitUpsideDown:
+            return CGAffineTransformMakeRotation(KDEAISellDegreesToRadians(180));
+            
+        case UIInterfaceOrientationPortrait:
+        default:
+            return CGAffineTransformMakeRotation(KDEAISellDegreesToRadians(0));
+    }
+}
+
+//改变位置
+//横屏之后的坐标系变为左下角坐标系,其中x轴向上,y轴向右,在这样的坐标系中计算即可
+-(void)locationChange:(UIPanGestureRecognizer*)pan {
+    
+    if  (self.currentOrientation == UIInterfaceOrientationLandscapeRight || self.currentOrientation == UIInterfaceOrientationLandscapeLeft) {//如果是横屏
+        [self springToBoundsOnLandscape:pan];
+        
+    } else{ //如果是竖屏
+        [self springToBoundsOnPortrait:pan];
+    }
+}
+
+- (void)springToBoundsOnPortrait:(UIPanGestureRecognizer*)panGesture {
+    CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
+    CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
+    
+    CGPoint panPoint = [panGesture locationInView:[[UIApplication sharedApplication] windows][0]];
+    if(panGesture.state == UIGestureRecognizerStateBegan) {
+        
+    } else if (panGesture.state == UIGestureRecognizerStateChanged) {
+        self.center = CGPointMake(panPoint.x,  panPoint.y);
+    } else if(panGesture.state == UIGestureRecognizerStateEnded || panGesture.state == UIGestureRecognizerStateCancelled) {
+        NSLog(@"ss");
+        if(panPoint.x <= screenWidth/2) {
+            if(panPoint.y >= screenHeight-HEIGHT/2-40 ) { //左下边界判断
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(WIDTH/2, screenHeight-HEIGHT/2);
+                }];
+                
+            } else if (panPoint.y < (HEIGHT/2 + STATUS_BAR_HEIGHT)) {
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(WIDTH/2, HEIGHT/2 + STATUS_BAR_HEIGHT);
+                    
+                }];
+            } else {
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(WIDTH/2, panPoint.y);
+                }];
+            }
+        }
+        else if(panPoint.x > screenWidth/2) {
+            if(panPoint.y <= (HEIGHT/2 + STATUS_BAR_HEIGHT)) {//向右越过上边界
+                
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(screenWidth-WIDTH/2, HEIGHT/2 + STATUS_BAR_HEIGHT);
+                }];
+                
+            }
+            else if (panPoint.y > screenHeight-HEIGHT/2) { //右下边界
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(screenWidth-WIDTH/2, screenHeight-HEIGHT/2);
+                }];
+                
+            }else { //正常拖动
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(screenWidth-WIDTH/2, panPoint.y);
+                }];
+            }
+        }
+    }
+}
+
+- (void)springToBoundsOnLandscape:(UIPanGestureRecognizer*)panGesture {
+    CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
+    CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
+    
+    CGPoint panPoint = [panGesture locationInView:[[UIApplication sharedApplication] windows][0]];
+    panPoint = CGPointMake(screenHeight - panPoint.y, panPoint.x);
+    
+    NSLog(@"screenWidth:%f, panPoint:%@", screenWidth, NSStringFromCGPoint(panPoint));
+    
+    if(panGesture.state == UIGestureRecognizerStateBegan) {
+    } else if (panGesture.state == UIGestureRecognizerStateChanged) {
+        self.center = CGPointMake(panPoint.x,  panPoint.y);
+    } else if(panGesture.state == UIGestureRecognizerStateEnded || panGesture.state == UIGestureRecognizerStateCancelled) {
+        if(panPoint.y <= screenWidth/2) {
+            if (panPoint.x <= HEIGHT/2 + STATUS_BAR_HEIGHT) {
+                [UIView animateWithDuration:0.2 animations:^{//左下角
+                    self.center = CGPointMake(WIDTH/2, HEIGHT/2 + STATUS_BAR_HEIGHT);
+                }];
+            }else if (panPoint.x >= screenHeight - HEIGHT/2){//左上角
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(screenHeight - HEIGHT/2, HEIGHT/2 + STATUS_BAR_HEIGHT);
+                }];
+            }else{
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(panPoint.x, HEIGHT/2 + STATUS_BAR_HEIGHT);
+                }];
+            }
+        }
+        else if(panPoint.y > screenWidth/2)
+        {
+            if (panPoint.x <= HEIGHT/2) {//右下角
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(HEIGHT/2,  screenWidth - WIDTH/2);
+                }];
+            }else if (panPoint.x >= screenHeight - HEIGHT/2){//右上角
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(screenHeight - HEIGHT/2, screenWidth - WIDTH/2);
+                }];
+            }else{
+                [UIView animateWithDuration:0.2 animations:^{
+                    self.center = CGPointMake(panPoint.x , screenWidth - WIDTH/2);
+                }];
+            }
+        }
+    }
+}
+
+//点击事件
+-(void)click:(UITapGestureRecognizer*)tapGesture {
+    if (self.callback) {
+        self.callback(DRAG_ACTION_CLICK);
+    }
+}
+
+- (void)cancelVideoAction {
+    if (self.callback) {
+        self.callback(DRAG_ACTION_CANCEL);
+    }
+}
+
+- (UIView *)containerView {
+    if (!_containerView) {
+        _containerView = [[UIView alloc] init];
+        _containerView.backgroundColor = [UIColor blackColor];
+    }
+    return _containerView;
+}
+//delete_white_image
+- (UIButton *)cancelButton {
+    if (!_cancelButton) {
+        _cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
+        [_cancelButton setImage:[UIImage imageNamed:@"delete_white_image"] forState:UIControlStateNormal];
+        [_cancelButton addTarget:self action:@selector(cancelVideoAction) forControlEvents:UIControlEventTouchUpInside];
+    }
+    return _cancelButton;
+}
+
+-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
+    if ([touch.view isDescendantOfView:self.cancelButton]) {
+        return NO;
+    }
+    return YES;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 30 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindowManager.h

@@ -0,0 +1,30 @@
+//
+//  KSDragWindowManager.h
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/16.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "KSDragWindow.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSDragWindowManager : NSObject
+
+@property (nonatomic, strong) KSDragWindow *dragWindow;
+
+@property (nonatomic, weak) CustomNavViewController *rootVC;
+
+@property (nonatomic, assign) BOOL hasShowWindow;
+
++ (instancetype)sharedManager;
+
+- (void)initDragWindow;
+
+- (void)resignDragWindow;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 71 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/DragWindow/KSDragWindowManager.m

@@ -0,0 +1,71 @@
+//
+//  KSDragWindowManager.m
+//  StudentDaya
+//
+//  Created by 王智 on 2022/5/16.
+//  Copyright © 2022 DayaMusic. All rights reserved.
+//
+
+#import "KSDragWindowManager.h"
+
+@implementation KSDragWindowManager
+
++ (instancetype)sharedManager {
+    static KSDragWindowManager *manager;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        manager = [[KSDragWindowManager alloc] init];
+    });
+    return manager;
+}
+
+- (void)initDragWindow {
+    _hasShowWindow = YES;
+    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
+    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
+    self.dragWindow = [[KSDragWindow alloc] initWithFrame:CGRectMake(screenWidth - KSDragWindowWidth, screenHeight - KSDragWindowHeight - KSDragWindowHeightBottomSpace , KSDragWindowWidth, KSDragWindowHeight)];
+    MJWeakSelf;
+    [self.dragWindow clickAction:^(DRAG_ACTION action) {
+        [weakSelf dragAction:action];
+    }];
+   
+    if (@available(iOS 13.0, *)) {
+        NSSet* windowScene = [UIApplication sharedApplication].connectedScenes;
+        self.dragWindow.windowScene = windowScene.anyObject;
+    }
+}
+
+
+- (void)dragAction:(DRAG_ACTION)action {
+    switch (action) {
+        case DRAG_ACTION_CANCEL:
+        {
+            [self resignDragWindow];
+            // 静音所有的声音
+            [[NSNotificationCenter defaultCenter] postNotificationName:@"muteLiveAudio" object:nil];
+        }
+            break;
+        case DRAG_ACTION_CLICK: // 返回到指定页面
+        {
+            // 返回到对应的页面
+            // 获取当前页面的层级
+            [self resignDragWindow];
+            // 回到登录界面
+            [self.rootVC popToRootViewControllerAnimated:YES];
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)resignDragWindow {
+    _hasShowWindow = NO;
+    [self.dragWindow.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
+    self.dragWindow.rootViewController = nil;
+    [self.dragWindow resignKeyWindow];
+    [self.dragWindow removeFromSuperview];
+    _dragWindow = nil;
+}
+
+@end

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

@@ -14,6 +14,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, strong) NSString *streamUserId;
 
+@property (nonatomic, strong) NSString *streamId; // 流id
+
+@property (nonatomic, strong) NSString *streamTag; // 视频流tag
 @end
 
 NS_ASSUME_NONNULL_END

+ 33 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.h

@@ -0,0 +1,33 @@
+//
+//  KSShopCardView.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/6/10.
+//
+
+#import <UIKit/UIKit.h>
+typedef NS_ENUM(NSInteger, CART_TYPE) {
+    CART_TYPE_ACCOMPANY = 2,
+    CART_TYPE_LIVE,
+    CART_TYPE_VIDEO,
+    CART_TYPE_MUSIC,
+};
+typedef void(^CartClickAction)(CART_TYPE type);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSShopCardView : UIView
+
+@property (nonatomic, assign) BOOL isShow;
+
++ (instancetype)shareInstance;
+
+- (void)showViewInView:(UIView *)displayView;
+
+- (void)hideView;
+
+- (void)clickAction:(CartClickAction)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 84 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.m

@@ -0,0 +1,84 @@
+//
+//  KSShopCardView.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/6/10.
+//
+
+#import "KSShopCardView.h"
+
+@interface KSShopCardView ()<UIGestureRecognizerDelegate>
+
+@property (weak, nonatomic) IBOutlet UIView *containerView;
+
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *containerBottomSpace;
+
+@property (nonatomic, copy) CartClickAction callback;
+
+@end
+
+@implementation KSShopCardView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.containerBottomSpace.constant = iPhoneXSafeBottomMargin + 60;
+}
+
++ (instancetype)shareInstance {
+    KSShopCardView *view = [[[NSBundle mainBundle] loadNibNamed:@"KSShopCardView" owner:nil options:nil] firstObject];
+    view.frame = CGRectMake(0, 0, KPortraitWidth, KPortraitHeight);
+    [view configUIDisplay];
+    return view;
+}
+
+- (void)configUIDisplay {
+    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideViewAction:)];
+    tapGesture.delegate = self;
+    [self addGestureRecognizer:tapGesture];
+}
+
+- (void)clickAction:(CartClickAction)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (void)showViewInView:(UIView *)displayView {
+    [displayView addSubview:self];
+    self.isShow = YES;
+}
+
+- (void)hideViewAction:(UITapGestureRecognizer *)gesture {
+    [self hideView];
+}
+
+- (void)hideView {
+    if (self.isShow) {
+        [self removeFromSuperview];
+        self.isShow = NO;
+    }
+}
+
+- (IBAction)chooseAction:(UIButton *)sender {
+    NSInteger index = sender.tag - 1000;
+    if (self.callback) {
+        self.callback(index);
+    }
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
+    
+    if ([touch.view isDescendantOfView:self.containerView]) {
+        return NO;
+    }
+    return YES;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 121 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.xib

@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="KSShopCardView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="836"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ufy-tg-Q9c">
+                    <rect key="frame" x="297" y="615" width="86" height="181"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="liveCart_AlertBg" translatesAutoresizingMaskIntoConstraints="NO" id="3lN-YD-l1m">
+                            <rect key="frame" x="0.0" y="0.0" width="86" height="181"/>
+                        </imageView>
+                        <button opaque="NO" tag="1002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LzX-ss-QR3">
+                            <rect key="frame" x="13" y="12" width="60" height="32"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="60" id="SkV-ZH-Lz9"/>
+                                <constraint firstAttribute="height" constant="32" id="pLd-3Z-mFf"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="陪练课" backgroundImage="course_bg">
+                                <color key="titleColor" red="0.25490196078431371" green="0.43529411764705883" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="chooseAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="hlv-oC-zAR"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" tag="1003" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="D77-vR-GET">
+                            <rect key="frame" x="13" y="51" width="60" height="32"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="32" id="loQ-2S-47S"/>
+                                <constraint firstAttribute="width" constant="60" id="xPF-Dw-XZR"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="直播课" backgroundImage="course_bg">
+                                <color key="titleColor" red="0.25490196079999999" green="0.43529411759999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="chooseAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="Gjg-ik-AYI"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" tag="1004" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZZq-UP-OkF">
+                            <rect key="frame" x="13" y="90" width="60" height="32"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="60" id="cDj-Sn-wdz"/>
+                                <constraint firstAttribute="height" constant="32" id="iIY-lM-qo1"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="视频课" backgroundImage="course_bg">
+                                <color key="titleColor" red="0.25490196079999999" green="0.43529411759999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="chooseAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="5wJ-bP-54B"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" tag="1005" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="AYN-JT-FVH">
+                            <rect key="frame" x="13" y="129" width="60" height="32"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="32" id="YE6-Od-QrD"/>
+                                <constraint firstAttribute="width" constant="60" id="hsb-cq-EZj"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="乐谱" backgroundImage="course_bg">
+                                <color key="titleColor" red="0.25490196079999999" green="0.43529411759999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="chooseAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="ryc-nT-j7g"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="3lN-YD-l1m" firstAttribute="leading" secondItem="Ufy-tg-Q9c" secondAttribute="leading" id="5bp-tj-iSz"/>
+                        <constraint firstItem="LzX-ss-QR3" firstAttribute="centerX" secondItem="Ufy-tg-Q9c" secondAttribute="centerX" id="6WR-FE-6Iu"/>
+                        <constraint firstItem="D77-vR-GET" firstAttribute="top" secondItem="LzX-ss-QR3" secondAttribute="bottom" constant="7" id="Dzn-fM-Xq0"/>
+                        <constraint firstItem="D77-vR-GET" firstAttribute="centerX" secondItem="LzX-ss-QR3" secondAttribute="centerX" id="LOO-ID-KTg"/>
+                        <constraint firstItem="AYN-JT-FVH" firstAttribute="centerX" secondItem="LzX-ss-QR3" secondAttribute="centerX" id="PAg-Bm-atQ"/>
+                        <constraint firstAttribute="bottom" secondItem="3lN-YD-l1m" secondAttribute="bottom" id="UA1-Zq-YfH"/>
+                        <constraint firstItem="3lN-YD-l1m" firstAttribute="top" secondItem="Ufy-tg-Q9c" secondAttribute="top" id="Vh9-wy-xce"/>
+                        <constraint firstAttribute="trailing" secondItem="3lN-YD-l1m" secondAttribute="trailing" id="WXy-DS-zbW"/>
+                        <constraint firstItem="ZZq-UP-OkF" firstAttribute="centerX" secondItem="LzX-ss-QR3" secondAttribute="centerX" id="aPs-Rm-bqB"/>
+                        <constraint firstItem="ZZq-UP-OkF" firstAttribute="top" secondItem="D77-vR-GET" secondAttribute="bottom" constant="7" id="cWz-am-9yD"/>
+                        <constraint firstItem="LzX-ss-QR3" firstAttribute="top" secondItem="Ufy-tg-Q9c" secondAttribute="top" constant="12" id="gZF-z8-kQh"/>
+                        <constraint firstAttribute="bottom" secondItem="AYN-JT-FVH" secondAttribute="bottom" constant="20" id="h0f-gC-bhN"/>
+                        <constraint firstItem="AYN-JT-FVH" firstAttribute="top" secondItem="ZZq-UP-OkF" secondAttribute="bottom" constant="7" id="nkr-sm-QVM"/>
+                        <constraint firstAttribute="width" constant="86" id="rUV-0a-GzK"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="Ufy-tg-Q9c" secondAttribute="bottom" constant="40" id="Jmv-DU-eUq"/>
+                <constraint firstAttribute="trailing" secondItem="Ufy-tg-Q9c" secondAttribute="trailing" constant="31" id="Ohd-SR-NBM"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="containerBottomSpace" destination="Jmv-DU-eUq" id="skB-Gy-Rgh"/>
+                <outlet property="containerView" destination="Ufy-tg-Q9c" id="Ret-ed-UCF"/>
+            </connections>
+            <point key="canvasLocation" x="131.8840579710145" y="116.51785714285714"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="course_bg" width="60" height="32"/>
+        <image name="liveCart_AlertBg" width="86" height="27.5"/>
+    </resources>
+</document>

+ 4 - 1
KulexiuForStudent/Podfile

@@ -35,11 +35,14 @@ target 'KulexiuForStudent' do
   pod 'RongCloudIM/IMLib',  '~> 5.2.0'
   pod 'RongCloudIM/IMKit',  '~> 5.2.0'
   pod 'RongCloudIM/Sight',  '~> 5.2.0'
-  pod 'RongCloudRTC/RongRTCLib','~> 5.2.1'
+  pod 'RongCloudRTC/RongRTCLib', '~> 5.2.3'
 
   pod "iOS-KS3SDK", "~>1.0.5"
   pod "WechatOpenSDK"
   pod 'AlipaySDK-iOS'
+  #lottie 动画库
+  pod 'lottie-ios', '~> 2.5'
+  
   # Pods for KulexiuForStudent
 
   target 'KulexiuForStudentTests' do

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff