ganzf před 5 měsíci
rodič
revize
39eb74de6c
100 změnil soubory, kde provedl 8293 přidání a 377 odebrání
  1. 94 13
      AIIM/AIIM/AppDelegate.m
  2. 23 0
      AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/Contents.json
  3. binární
      AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/xiazai 1.png
  4. binární
      AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/xiazai 2.png
  5. binární
      AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/xiazai.png
  6. 7 9
      AIIM/AIIM/Base.lproj/Main.storyboard
  7. 64 3
      AIIM/AIIM/Common/CommonUI/FilePreviewer.m
  8. 2 0
      AIIM/AIIM/Common/CommonUI/HistoryPreloader.h
  9. 7 1
      AIIM/AIIM/Common/CommonUI/HistoryPreloader.m
  10. 1 1
      AIIM/AIIM/Common/CommonUI/Util/FileInfoUtils.m
  11. 85 0
      AIIM/AIIM/Common/CommonUI/Util/UILabel+YBAttributeTextTapAction.h
  12. 540 0
      AIIM/AIIM/Common/CommonUI/Util/UILabel+YBAttributeTextTapAction.m
  13. 22 12
      AIIM/AIIM/Common/CommonUI/Util/config.h
  14. 6 2
      AIIM/AIIM/Common/Defaults/CryptoAES.m
  15. 3 0
      AIIM/AIIM/Common/Defaults/UDManager.h
  16. 7 1
      AIIM/AIIM/Common/Network/FileNetApi.h
  17. 27 2
      AIIM/AIIM/Common/Network/FileNetApi.m
  18. 11 1
      AIIM/AIIM/Common/Network/GBaseNetApi.h
  19. 186 14
      AIIM/AIIM/Common/Network/GBaseNetApi.m
  20. 3 0
      AIIM/AIIM/Common/Network/GDBManager.h
  21. 57 23
      AIIM/AIIM/Common/Network/GDBManager.m
  22. 27 19
      AIIM/AIIM/Common/Network/GWebSocket.m
  23. 32 0
      AIIM/AIIM/Common/Network/aliOSS/OSSManager.h
  24. 190 0
      AIIM/AIIM/Common/Network/aliOSS/OSSManager.m
  25. 19 0
      AIIM/AIIM/Common/Network/aliOSS/OssNetApi.h
  26. 21 0
      AIIM/AIIM/Common/Network/aliOSS/OssNetApi.m
  27. 117 32
      AIIM/AIIM/Common/Store/ChatListStore.m
  28. 27 9
      AIIM/AIIM/Common/Store/ChatsStore.m
  29. 329 120
      AIIM/AIIM/Controller/chat/ChatController.m
  30. 3 2
      AIIM/AIIM/Controller/chat/ChatHistoryController.m
  31. 3 0
      AIIM/AIIM/Controller/chat/ChatIndexController.h
  32. 17 3
      AIIM/AIIM/Controller/chat/ChatIndexController.m
  33. 29 15
      AIIM/AIIM/Controller/chat/ChatListCell.m
  34. 5 5
      AIIM/AIIM/Controller/chat/ChatListCell.xib
  35. 2 1
      AIIM/AIIM/Controller/chat/chetCell/ChatLongPressMenuView.m
  36. 12 1
      AIIM/AIIM/Controller/chat/chetCell/ChatMessageModel.h
  37. 128 18
      AIIM/AIIM/Controller/chat/chetCell/ChatMessageModel.m
  38. 299 45
      AIIM/AIIM/Controller/chat/chetCell/chatCellView.m
  39. 6 0
      AIIM/AIIM/Controller/friend/FriendListController.m
  40. 6 1
      AIIM/AIIM/Controller/group/GroupListController.m
  41. 10 1
      AIIM/AIIM/Controller/login/GSignController.m
  42. 3 0
      AIIM/AIIM/Controller/mine/UserConterController.m
  43. 67 23
      AIIM/AIIM/Controller/webRTC/JSGController.m
  44. 44 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/Info.plist
  45. binární
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/AliyunOSSiOS
  46. 22 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/AliyunOSSiOS.h
  47. 19 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/NSDate+OSS.h
  48. 15 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/NSMutableData+OSS_CRC.h
  49. 15 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/NSMutableDictionary+OSS.h
  50. 33 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSAllRequestNeededMessage.h
  51. 26 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSBolts.h
  52. 42 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCancellationToken.h
  53. 29 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCancellationTokenRegistration.h
  54. 60 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCancellationTokenSource.h
  55. 527 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSClient.h
  56. 75 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCocoaLumberjack.h
  57. 85 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCompat.h
  58. 133 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSConstants.h
  59. 860 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDDLog.h
  60. 85 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDefine.h
  61. 31 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteMultipleObjectsRequest.h
  62. 17 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteMultipleObjectsResult.h
  63. 23 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteObjectTaggingRequest.h
  64. 17 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteObjectTaggingResult.h
  65. 62 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSExecutor.h
  66. 509 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSFileLogger.h
  67. 15 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetBucketInfoRequest.h
  68. 57 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetBucketInfoResult.h
  69. 26 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectACLRequest.h
  70. 19 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectACLResult.h
  71. 23 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectTaggingRequest.h
  72. 19 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectTaggingResult.h
  73. 17 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetSymlinkRequest.h
  74. 13 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetSymlinkResult.h
  75. 39 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSHttpResponseParser.h
  76. 16 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSHttpdns.h
  77. 114 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSIPv6Adapter.h
  78. 23 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSIPv6PrefixResolver.h
  79. 54 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSLog.h
  80. 82 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSLogMacros.h
  81. 1520 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSModel.h
  82. 14 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSNSLogger.h
  83. 47 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSNetworking.h
  84. 79 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSNetworkingRequestDelegate.h
  85. 27 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutObjectTaggingRequest.h
  86. 17 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutObjectTaggingResult.h
  87. 25 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutSymlinkRequest.h
  88. 13 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutSymlinkResult.h
  89. 64 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSReachability.h
  90. 41 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSRequest.h
  91. 17 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSRestoreObjectRequest.h
  92. 13 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSRestoreObjectResult.h
  93. 42 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSResult.h
  94. 46 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSService.h
  95. 295 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSTask.h
  96. 89 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSTaskCompletionSource.h
  97. 36 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSURLRequestRetryHandler.h
  98. 77 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSUtil.h
  99. 88 0
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSXMLDictionary.h
  100. binární
      AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Info.plist

+ 94 - 13
AIIM/AIIM/AppDelegate.m

@@ -26,6 +26,11 @@
 #import "ChatListStore.h"
 #import "ChatsStore.h"
 
+#import "OSSManager.h"
+
+#import <Bugly/Bugly.h>
+
+
 @import JitsiMeetSDK;
 
 @interface AppDelegate ()<UNUserNotificationCenterDelegate,PKPushRegistryDelegate,CXProviderDelegate>
@@ -33,6 +38,8 @@
 @property (nonatomic) NSUUID *uuid;
 @property (nonatomic) NSDictionary *msg;
 @property (strong, nonatomic) NSTimer *timer;
+@property (nonatomic) NSInteger timerActCount;
+@property (strong, nonatomic) NSString *bgMark;
 
 @property (nonatomic) BOOL isTokenCleared;
 
@@ -40,6 +47,8 @@
 @property (nonatomic, strong) JSGController * _Nullable jsyuyinctr;
 
 
+
+
 @property (nonatomic) BOOL isNotification;
 
 @end
@@ -50,19 +59,27 @@
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     // Override point for customization after application launch.
     app = self;
+    BuglyConfig *config = [[BuglyConfig alloc] init];
+    config.reportLogLevel = BuglyLogLevelVerbose;
+    [Bugly startWithAppId:@"1d9e6b546a" config:config];
     self.isJitsiMeet=false;
     _isNotification=false;
     self.shouldShowLock = YES;
+    self.bgMark=@"";
+    
+    
     [self initJSMSDK];
     [self setupListener];
     [self checkLoginState:launchOptions];
     [self registerPushright];
     [self setupCallProvider];
+    [self initAliyunOss];
     
     _isTokenCleared=YES;
     
     _floatWindow = [[FloatingWindow alloc] initWithFrame:self.window.bounds];
     [_floatWindow hide];
+    self.bgMark = @"";
     
     NSLog(@"didFinishLaunchingWithOptions------");
     
@@ -74,8 +91,12 @@
     return YES;
 }
 
+
+
+
 -(void)applicationDidBecomeActive:(UIApplication *)application{
     NSLog(@"applicationDidBecomeActive");
+   
     if(self.isLogin){
         [self sartWebsocket];
         if(self.isJitsiMeet){
@@ -83,13 +104,25 @@
         }
         [self showLockScreen];
         if(!_isNotification){
-            if ([[self.window jk_currentViewController] isKindOfClass:ChatController.class]) {
-                ChatController * currentChatVc = (ChatController *)[self.window jk_currentViewController];
-                [currentChatVc reloadAllData];
+            if ([[self.window jk_currentViewController] isKindOfClass:UITabBarController.class]){
+                UITabBarController * tabbarVc= (UITabBarController *)[self.window jk_currentViewController];
+                if (tabbarVc.selectedIndex==0) {
+                    ChatIndexController * chatListVc = tabbarVc.viewControllers[0];
+                    if (chatListVc) {
+                        [chatListVc reloadList];
+                    }
+                }
+            }
+            else{
+                [Bugly reportException:[NSException exceptionWithName:@"applicationDidBecomeActive1" reason:@"1" userInfo:nil]];
+                if ([[self.window jk_currentViewController] isKindOfClass:ChatController.class]) {
+                    ChatController * currentChatVc = (ChatController *)[self.window jk_currentViewController];
+                    [currentChatVc reloadAllData];
+                    [Bugly reportException:[NSException exceptionWithName:@"applicationDidBecomeActive2" reason:@"2" userInfo:nil]];
+                }
             }
         }
     }
-    
     [self startTimer];
     // 应用从后台返回前台时检查是否需要显示锁屏
 }
@@ -124,6 +157,7 @@
 }
 
 -(void)initJSMSDK{
+    
     JitsiMeetConferenceOptions *defaultOptions
         = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
             builder.serverURL = [NSURL URLWithString:JitsiMeetSV];
@@ -142,7 +176,9 @@
             [builder setFeatureFlag:@"recording.enabled" withBoolean:NO];
             [builder setFeatureFlag:@"kick-out.enabled" withBoolean:NO];
             [builder setFeatureFlag:@"security-options.enabled" withBoolean:NO];
-//            
+            
+
+//
 //            //网络传输层加速
 //            [builder setConfigOverride:@"disableSimulcast" withBoolean:YES];
 //            [builder setFeatureFlag:@"reconnect.enabled" withBoolean:YES];
@@ -173,6 +209,15 @@
     NSLog(@"Failed to get token, error: %@", error);
 }
 
+//阿里云oss:https://abtimoss.oss-ap-southeast-1.aliyuncs.com
+//AccessKey ID
+//LTAI5tNoRjDRMuvnKBcop3hL
+//AccessKey Secret
+//kUoR7zqLafRYpcz3vJk1JHTvkRaaSl
+-(void)initAliyunOss{
+    [[OSSManager sharedManager] getOSSInfo];
+}
+
 
 
 #pragma mark push token voip token
@@ -218,6 +263,8 @@
     NSLog(@"%@",token);
     // 将token发送到你的服务器或其他需要的地方
     [UDManager.shareInstance setSDManager:token key:dkpushtoken];
+    NSString *bgMark = [NSString stringWithFormat:@"推送token:%ld",token.length];
+    [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
     if(self.isLogin){
         [self updivicetoken];
     }
@@ -257,7 +304,8 @@
         @"userId":usinfo[@"id"]?:@"",
         @"platformType":@"i"
     };
-    
+    NSString *bgMark = [NSString stringWithFormat:@"上传推送token:%ld",token.length];
+    [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
     [UserNetApi setUserinfo:ud succ:^(int code, NSDictionary * res) {
         self->_isTokenCleared=NO;
         NSData *jsonData = [NSJSONSerialization dataWithJSONObject:res options:0 error:nil];
@@ -275,6 +323,8 @@
     NSString *token =[UDManager.shareInstance getSDManager:dkvoiptoken];
     NSDictionary *usinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
     NSLog(@"dkvoiptoken:%@",token);
+    NSString *bgMark = [NSString stringWithFormat:@"上传 voip 推送token:%ld",token.length];
+    [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
     if([token isKindOfClass:[NSNull class]]){
         return;
     }
@@ -320,6 +370,7 @@
             if(self.uuid!=nil){
                 NSString *fromId = self.msg[@"fromId"];
                 if ( [fromId isEqualToString:msg[@"fromId"]]) {
+                    
                     [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
                     self.uuid = nil;
                     self.msg =nil;
@@ -349,6 +400,8 @@
     NSString *token = [NSString stringWithFormat:@"%@%@",token1,token2];
     NSLog(@"%@",token);
      //将token发送到你的服务器或其他需要的地方
+    NSString *bgMark = [NSString stringWithFormat:@"voip token:%ld",token.length];
+    [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
     [UDManager.shareInstance setSDManager:token key:dkvoiptoken];
     if(self.isLogin){
         [self updiviceVoIPtoken];
@@ -357,6 +410,8 @@
  
 - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion{
     
+    
+    
     NSDictionary * temp =payload.dictionaryPayload;
     temp =temp[@"business"];
     temp=temp[@"incomingCallParams"];
@@ -389,6 +444,7 @@
 }
 
 -(void)isBUSYNow:(NSDictionary *)msg{
+    
     NSDate *now = [NSDate date];
     NSTimeInterval trt = [now timeIntervalSince1970];
     NSInteger time = trt*1000;
@@ -418,6 +474,7 @@
 #pragma mark - CXProviderDelegate Methods
 
 - (void)setupCallProvider {
+    
     // 创建配置对象
     CXProviderConfiguration *config = [[CXProviderConfiguration alloc] init];
     config.supportsVideo = YES; // 是否支持视频通话
@@ -447,6 +504,7 @@
 
 -(void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action{
     
+    
     [self reciveVoip];
     
     //使用GCD创建一个在3秒后执行的定时器
@@ -455,6 +513,7 @@
         if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
             // 应用已经解锁并且在前台
             if(self.uuid){
+                
                 [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
                 self.msg = nil;
                 self.uuid = nil;
@@ -468,7 +527,10 @@
     if (!self.uuid) {
         return;
     }
+    
     [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
+    self.msg = nil;
+    self.uuid = nil;
     NSLog(@"timedOutPerformingAction:%@",action);
 }
 - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action {
@@ -516,12 +578,14 @@
         else{
             audioOnly = YES;
         }
+        
         [self startJSCall:self.msg[@"fromId"] room:self.msg[@"payload"] isCaller:NO audioOnly:audioOnly];
     }
 }
 
 //开启悬浮窗拨打方式
 -(void)startJSCall:(NSString *_Nonnull)chatId room:(NSString *_Nonnull)roomId isCaller:(BOOL)isCaller audioOnly:(BOOL)audioOnly{
+    
     self.isJitsiMeet = YES;
     if(_jsyuyinctr){
         _jsyuyinctr.chatId = chatId.copy;
@@ -538,9 +602,10 @@
         _jsyuyinctr.audioOnly = audioOnly;
         _jsyuyinctr.isCaller = isCaller;
     }
-    NSLog(@"roomId:%@",roomId);
+    NSLog(@"startJSCall roomId:%@",roomId);
     [_floatWindow showView:_jsyuyinctr.view];
     [_jsyuyinctr startJitsiMeetCall];
+    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
 }
 
 -(void)floadinSmWindow:(NSInteger )type{
@@ -632,8 +697,8 @@
         NSString *avatar = mutablemsg[@"fromAvatar"]?:@"";
         
         
-        NSLog(@"top className:%@",[[self.window jk_topMostController] class]);
-        NSLog(@"current className:%@",[[self.window jk_currentViewController] class]);
+//        NSLog(@"top className:%@",[[self.window jk_topMostController] class]);
+//        NSLog(@"current className:%@",[[self.window jk_currentViewController] class]);
         if ([[self.window jk_currentViewController] isKindOfClass:ChatController.class]) {
             ChatController * currentChatVc = (ChatController *)[self.window jk_currentViewController];
             if (![currentChatVc.chatId isEqualToString:mutablemsg[@"chatId"]]) {
@@ -654,7 +719,6 @@
             }
         }
         
-        
         UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
         ChatController *chatctr = [board instantiateViewControllerWithIdentifier:@"ChatController"];
         UINavigationController *uiNavC = [[UINavigationController alloc] initWithRootViewController:chatctr];
@@ -683,7 +747,7 @@
 }
 -(void)onLogoutSucc{
     self.isLogin =false;
-    
+    NSLog(@"1-----------------1");
 //        [GDBManager.shareInstance delLocalmsglistTable:userid];
 //        [GDBManager.shareInstance delchatlistTable:nil fail:nil];
 //        [GDBManager.shareInstance deleteDB];
@@ -903,10 +967,11 @@
 
 #pragma mark 定时服务
 -(void)startTimer{
+    _timerActCount=0;
     if(self.timer){
         return;
     }
-    self.timer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(TimerAction) userInfo:nil repeats:YES];
+    self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(TimerAction) userInfo:nil repeats:YES];
     [self.timer setFireDate:[NSDate distantPast]];
     [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
 }
@@ -917,7 +982,11 @@
 }
 
 -(void)TimerAction{
-    //处理重发事件
+    _timerActCount=_timerActCount+1;
+    if(_timerActCount<3){
+        return;
+    }
+    _timerActCount=0;
 //    NSLog(@"111222222");
     if(![self isNetworkAvailable]){
         if(self.isLogin){
@@ -942,9 +1011,20 @@
     SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
     if (reachability != NULL) {
         SCNetworkReachabilityFlags flags;
+        
         if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
             BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
             BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
+            
+            BOOL isWWAN = (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0;
+            if(isWWAN){
+                NSLog(@"isWWAN:1----------");
+            }
+            else{
+                NSLog(@"isWWAN:2----------");
+            }
+            
+            
             if ((isReachable && !needsConnection)) {
                 // 网络是可用的,无需连接
 //                NSLog(@"网络是可用的,无需连接");
@@ -985,6 +1065,7 @@
     if (self.shouldShowLock && [[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
         NSLog(@"showLockScreen--------------1");
         if (self.isJitsiMeet) {
+            [_floatWindow viewInFload:0];
             return;
         }
         else{

+ 23 - 0
AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/Contents.json

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

binární
AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/xiazai 1.png


binární
AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/xiazai 2.png


binární
AIIM/AIIM/Assets.xcassets/xiazaibendi.imageset/xiazai.png


+ 7 - 9
AIIM/AIIM/Base.lproj/Main.storyboard

@@ -188,9 +188,7 @@
                         </subviews>
                         <viewLayoutGuide key="safeArea" id="Lr7-kH-XF3"/>
                     </view>
-                    <tabBarItem key="tabBarItem" title="聊天" image="index" selectedImage="index_cur" id="V2y-ee-B7h">
-                        <color key="badgeColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    </tabBarItem>
+                    <tabBarItem key="tabBarItem" title="聊天" image="index" selectedImage="index_cur" id="V2y-ee-B7h"/>
                     <connections>
                         <outlet property="_tableView" destination="eEg-r1-9YX" id="BSf-wm-F0U"/>
                     </connections>
@@ -35322,7 +35320,7 @@ gaMAAAAAAAAEAQAAAAAAAABYAAAAAAAAAAAAAAAAAA+Bpg
         <image name="index_cur" width="32" height="32"/>
         <image name="launch" width="375" height="812"/>
         <image name="loginBG" width="375" height="812"/>
-        <image name="logo512" width="523" height="512"/>
+        <image name="logo512" width="1024" height="1024"/>
         <image name="qunzu" width="32" height="32"/>
         <image name="qunzu_cur" width="32" height="32"/>
         <image name="rightdian" width="20" height="20"/>
@@ -35337,22 +35335,22 @@ gaMAAAAAAAAEAQAAAAAAAABYAAAAAAAAAAAAAAAAAA+Bpg
             <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
         </systemColor>
         <systemColor name="opaqueSeparatorColor">
-            <color red="0.77647058820000003" green="0.77647058820000003" blue="0.7843137255" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <color red="0.77647058823529413" green="0.77647058823529413" blue="0.78431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
         <systemColor name="systemBackgroundColor">
             <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
         </systemColor>
         <systemColor name="systemGray2Color">
-            <color red="0.68235294120000001" green="0.68235294120000001" blue="0.69803921570000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <color red="0.68235294117647061" green="0.68235294117647061" blue="0.69803921568627447" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
         <systemColor name="systemGreenColor">
-            <color red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <color red="0.20392156862745098" green="0.7803921568627451" blue="0.34901960784313724" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
         <systemColor name="systemPinkColor">
-            <color red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <color red="1" green="0.17647058823529413" blue="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
         <systemColor name="tertiarySystemGroupedBackgroundColor">
-            <color red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
     </resources>
 </document>

+ 64 - 3
AIIM/AIIM/Common/CommonUI/FilePreviewer.m

@@ -15,6 +15,7 @@
 @property (nonatomic, strong) UIViewController *webPreviewController;
 @property (nonatomic, weak) UIViewController *currentParentViewController;
 @property (nonatomic, strong) UIActivityIndicatorView *loadingIndicator;
+@property (nonatomic, strong) UIImage *showimge;
 @end
 
 @implementation FilePreviewer
@@ -41,11 +42,13 @@
     self.currentParentViewController = parentViewController;
     // 优先尝试本地路径
     if (localPath && [[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
+        NSLog(@"本地路径");
         [self previewFileAtPath:localPath];
     }
     // 如果本地路径不存在或无效,尝试远程URL
     else if (remoteURL) {
 //        [self showLoadingIndicator];
+        NSLog(@"尝试远程URL");
         [self previewRemoteFileAtURL:remoteURL];
     }
     else {
@@ -126,6 +129,21 @@
     [closeButton addTarget:self action:@selector(dismissPreviewController) forControlEvents:UIControlEventTouchUpInside];
     [previewController.view addSubview:closeButton];
     
+    
+    
+    // 添加保存 本地按钮
+    UIButton *saveButton = [UIButton buttonWithType:UIButtonTypeSystem];
+    [saveButton setBackgroundColor:globalColor(GCTypeDark1)];
+    [saveButton setImage:kImageMake(@"xiazaibendi") forState:UIControlStateNormal];
+    CGFloat width = previewController.view.frame.size.width;
+    saveButton.frame = CGRectMake(width-60, 60, 40, 40);
+    saveButton.layer.cornerRadius = 5;
+    saveButton.tag = 101; // 用于稍后隐藏/显示
+    [saveButton addTarget:self action:@selector(saveImg) forControlEvents:UIControlEventTouchUpInside];
+    [previewController.view addSubview:saveButton];
+    
+    
+    
     // 添加加载指示器
     UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
     indicator.center = previewController.view.center;
@@ -138,7 +156,6 @@
     __weak typeof(self) weakSelf = self;
     __weak typeof(zoomableView) weakZoomableView = zoomableView;
     __weak typeof(indicator) weakIndicator = indicator;
-    __weak typeof(closeButton) weakCloseButton = closeButton;
     
     // 使用SDWebImage加载图片
     [zoomableView.imageView sd_setImageWithURL:imageURL
@@ -167,6 +184,7 @@
                 // 添加单击手势隐藏/显示控制按钮
                 UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:weakSelf action:@selector(toggleControls:)];
                 [previewController.view addGestureRecognizer:singleTap];
+                self->_showimge =image;
             }
         });
     }];
@@ -177,10 +195,34 @@
 - (void)previewVideoAtURL:(NSURL *)videoURL {
     
     AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
-    playerViewController.player = [AVPlayer playerWithURL:videoURL];
+    AVPlayer *player = [AVPlayer playerWithURL:videoURL];
+    playerViewController.player = player;
     playerViewController.showsPlaybackControls = YES;
-    
     [self presentViewController:playerViewController];
+    // 尝试切换到耳机输出(如果可用)或扬声器(默认)
+    NSError *error = nil;
+    
+    
+    AVAudioSession *session = [AVAudioSession sharedInstance];
+    // 设置音频会话的类别为播放
+    [session setCategory:AVAudioSessionCategoryPlayback error:&error];
+    if (error) {
+        NSLog(@"设置音频会话类别失败: %@", error.localizedDescription);
+    } else {
+        // 尝试将输出端口覆盖为扬声器
+        [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];// 或者AVAudioSessionPortOverrideSpeaker AVAudioSessionPortOverrideNone 保持默认行为
+        if (error) {
+            NSLog(@"设置输出端口为扬声器失败: %@", error.localizedDescription);
+        } else {
+            NSLog(@"已成功设置为扬声器播放模式");
+        }
+    }
+    // 激活音频会话
+    [session setActive:YES error:&error];
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+        [player play];
+    });
+    
     
 //    __weak AVPlayerViewController *weakPlayerVC = playerViewController;
 //    [playerViewController.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
@@ -285,6 +327,22 @@
     [self hideLoadingIndicator];
 }
 
+
+- (void)saveImg {
+    if(_showimge){
+        UIImageWriteToSavedPhotosAlbum(_showimge, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
+    }
+}
+- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
+    if (error) {
+        // 保存失败,输出错误信息
+        NSLog(@"Error saving image: %@", error);
+    } else {
+        // 保存成功
+        NSLog(@"Image saved successfully!");
+        [MBProgressHUD showWithText:@"图片已保存到相册"];
+    }
+}
 #pragma mark - Gesture Handlers
 
 - (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer {
@@ -308,8 +366,11 @@
     UIViewController *previewController = (UIViewController *)gesture.view.nextResponder;
     UIButton *closeButton = [previewController.view viewWithTag:100];
     
+    UIButton *saveButton = [previewController.view viewWithTag:101];
+    
     [UIView animateWithDuration:0.3 animations:^{
         closeButton.alpha = (closeButton.alpha == 0) ? 1 : 0;
+        saveButton.alpha = (saveButton.alpha == 0) ? 1 : 0;
     }];
     
 }

+ 2 - 0
AIIM/AIIM/Common/CommonUI/HistoryPreloader.h

@@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 /// 预加载触发回调
 @property (nonatomic, copy) void (^loadBlock)(void);
+/// 预加载触发回调
+@property (nonatomic, copy) void (^toofast)(void);
 
 /// 是否已经检测到用户滑动(只读)
 @property (nonatomic, assign, readonly) BOOL isUserInitiatedScroll;

+ 7 - 1
AIIM/AIIM/Common/CommonUI/HistoryPreloader.m

@@ -106,7 +106,13 @@
 - (void)tryTriggerPreload {
     // 冷却时间检查(至少间隔1秒)
     NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
-    if (now - _lastTriggerTime < 1.0) return;
+    if (now - _lastTriggerTime < 1.0){
+        // 触发过快加载加载回调
+        if (self.toofast) {
+            self.toofast();
+        }
+        return;
+    }
     
     _lastTriggerTime = now;
     

+ 1 - 1
AIIM/AIIM/Common/CommonUI/Util/FileInfoUtils.m

@@ -92,7 +92,7 @@
 
 + (BOOL)isFileGreaterThan100MB:(NSURL *)fileURL error:(NSError **)error {
     // 定义200MB的字节数
-    const unsigned long long oneHundredMB = 200 * 1024 * 1024; // 100MB = 100*1024*1024 bytes
+    const unsigned long long oneHundredMB = 2024 * 1024 * 1024; // 100MB = 100*1024*1024 bytes
     
     // 检查URL是否有效
     if (![fileURL isFileURL]) {

+ 85 - 0
AIIM/AIIM/Common/CommonUI/Util/UILabel+YBAttributeTextTapAction.h

@@ -0,0 +1,85 @@
+//
+//  UILabel+YBAttributeTextTapAction.h
+//
+//  Created by LYB on 16/7/1.
+//  Copyright © 2016年 LYB. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@protocol YBAttributeTapActionDelegate <NSObject>
+@optional
+/**
+ *  YBAttributeTapActionDelegate
+ *
+ *  @param string  点击的字符串
+ *  @param range   点击的字符串range
+ *  @param index 点击的字符在数组中的index
+ */
+- (void)yb_tapAttributeInLabel:(UILabel *)label
+                        string:(NSString *)string
+                         range:(NSRange)range
+                         index:(NSInteger)index;
+@end
+
+
+@interface UILabel (YBAttributeTextTapAction)
+
+/**
+ *  是否打开点击效果,默认是打开
+ */
+@property (nonatomic, assign) BOOL enabledTapEffect;
+
+/**
+ *  点击高亮色 默认是[UIColor lightGrayColor] 需打开enabledTapEffect才有效
+ */
+@property (nonatomic, strong) UIColor * tapHighlightedColor;
+
+/**
+ *  是否扩大点击范围,默认是打开
+ */
+@property (nonatomic, assign) BOOL enlargeTapArea;
+
+/**
+ *  给文本添加点击事件Block回调
+ *
+ *  @param strings  需要添加的字符串数组
+ *  @param tapClick 点击事件回调
+ */
+- (void)yb_addAttributeTapActionWithStrings:(NSArray <NSString *> *)strings
+                                 tapClicked:(void (^) (UILabel * label, NSString *string, NSRange range, NSInteger index))tapClick;
+
+/**
+ *  给文本添加点击事件delegate回调
+ *
+ *  @param strings  需要添加的字符串数组
+ *  @param delegate delegate
+ */
+- (void)yb_addAttributeTapActionWithStrings:(NSArray <NSString *> *)strings
+                                   delegate:(id <YBAttributeTapActionDelegate> )delegate;
+
+/**
+ *  根据range给文本添加点击事件Block回调
+ *
+ *  @param ranges  需要添加的Range字符串数组
+ *  @param tapClick 点击事件回调
+ */
+- (void)yb_addAttributeTapActionWithRanges:(NSArray <NSString *> *)ranges
+                                 tapClicked:(void (^) (UILabel * label, NSString *string, NSRange range, NSInteger index))tapClick;
+
+/**
+ *  根据range给文本添加点击事件delegate回调
+ *
+ *  @param ranges  需要添加的Range字符串数组
+ *  @param delegate delegate
+ */
+- (void)yb_addAttributeTapActionWithRanges:(NSArray <NSString *> *)ranges
+                                   delegate:(id <YBAttributeTapActionDelegate> )delegate;
+
+/**
+ *  删除label上的点击事件
+ */
+- (void)yb_removeAttributeTapActions;
+
+@end
+

+ 540 - 0
AIIM/AIIM/Common/CommonUI/Util/UILabel+YBAttributeTextTapAction.m

@@ -0,0 +1,540 @@
+//
+//  UILabel+YBAttributeTextTapAction.m
+//
+//  Created by LYB on 16/7/1.
+//  Copyright © 2016年 LYB. All rights reserved.
+//
+
+#import "UILabel+YBAttributeTextTapAction.h"
+#import <objc/runtime.h>
+#import <CoreText/CoreText.h>
+#import <Foundation/Foundation.h>
+
+@interface YBAttributeModel : NSObject
+
+@property (nonatomic, copy) NSString *str;
+
+@property (nonatomic) NSRange range;
+
+@end
+
+@implementation YBAttributeModel
+
+@end
+
+@implementation UILabel (YBAttributeTextTapAction)
+
+#pragma mark - AssociatedObjects
+
+- (NSMutableArray *)attributeStrings
+{
+    return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)setAttributeStrings:(NSMutableArray *)attributeStrings
+{
+    objc_setAssociatedObject(self, @selector(attributeStrings), attributeStrings, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (NSMutableDictionary *)effectDic
+{
+    return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)setEffectDic:(NSMutableDictionary *)effectDic
+{
+    objc_setAssociatedObject(self, @selector(effectDic), effectDic, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (BOOL)isTapAction
+{
+    return [objc_getAssociatedObject(self, _cmd) boolValue];
+}
+
+- (void)setIsTapAction:(BOOL)isTapAction
+{
+    objc_setAssociatedObject(self, @selector(isTapAction), @(isTapAction), OBJC_ASSOCIATION_ASSIGN);
+}
+
+- (void (^)(UILabel *, NSString *, NSRange, NSInteger))tapBlock
+{
+    return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)setTapBlock:(void (^)(UILabel *, NSString *, NSRange, NSInteger))tapBlock
+{
+    objc_setAssociatedObject(self, @selector(tapBlock), tapBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
+}
+
+- (id<YBAttributeTapActionDelegate>)delegate
+{
+    return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)setDelegate:(id<YBAttributeTapActionDelegate>)delegate
+{
+    objc_setAssociatedObject(self, @selector(delegate), delegate, OBJC_ASSOCIATION_ASSIGN);
+}
+
+- (BOOL)enabledTapEffect
+{
+    return [objc_getAssociatedObject(self, _cmd) boolValue];
+}
+
+- (void)setEnabledTapEffect:(BOOL)enabledTapEffect
+{
+    objc_setAssociatedObject(self, @selector(enabledTapEffect), @(enabledTapEffect), OBJC_ASSOCIATION_ASSIGN);
+    self.isTapEffect = enabledTapEffect;
+}
+
+- (BOOL)enlargeTapArea
+{
+    NSNumber * number = objc_getAssociatedObject(self, _cmd);
+    if (!number) {
+        number = @(YES);
+        objc_setAssociatedObject(self, _cmd, number, OBJC_ASSOCIATION_ASSIGN);
+    }
+    return [number boolValue];
+}
+
+- (void)setEnlargeTapArea:(BOOL)enlargeTapArea
+{
+    objc_setAssociatedObject(self, @selector(enlargeTapArea), @(enlargeTapArea), OBJC_ASSOCIATION_ASSIGN);
+}
+
+- (UIColor *)tapHighlightedColor
+{
+    UIColor * color = objc_getAssociatedObject(self, _cmd);
+    if (!color) {
+        color = [UIColor lightGrayColor];
+        objc_setAssociatedObject(self, _cmd, color, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
+    return color;
+}
+
+- (void)setTapHighlightedColor:(UIColor *)tapHighlightedColor
+{
+    objc_setAssociatedObject(self, @selector(tapHighlightedColor), tapHighlightedColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (BOOL)isTapEffect
+{
+    return [objc_getAssociatedObject(self, _cmd) boolValue];
+}
+
+- (void)setIsTapEffect:(BOOL)isTapEffect
+{
+    objc_setAssociatedObject(self, @selector(isTapEffect), @(isTapEffect), OBJC_ASSOCIATION_ASSIGN);
+}
+
+#pragma mark - mainFunction
+- (void)yb_addAttributeTapActionWithStrings:(NSArray <NSString *> *)strings tapClicked:(void (^) (UILabel * label, NSString *string, NSRange range, NSInteger index))tapClick
+{
+    [self yb_removeAttributeTapActions];
+    [self yb_getRangesWithStrings:strings];
+    self.userInteractionEnabled = YES;
+    
+    if (self.tapBlock != tapClick) {
+        self.tapBlock = tapClick;
+    }
+}
+
+- (void)yb_addAttributeTapActionWithStrings:(NSArray <NSString *> *)strings
+                                   delegate:(id <YBAttributeTapActionDelegate> )delegate
+{
+    [self yb_removeAttributeTapActions];
+    [self yb_getRangesWithStrings:strings];
+    self.userInteractionEnabled = YES;
+    
+    if (self.delegate != delegate) {
+        self.delegate = delegate;
+    }
+}
+
+- (void)yb_addAttributeTapActionWithRanges:(NSArray<NSString *> *)ranges tapClicked:(void (^)(UILabel *, NSString *, NSRange, NSInteger))tapClick
+{
+    [self yb_removeAttributeTapActions];
+    [self yb_getRangesWithRanges:ranges];
+    self.userInteractionEnabled = YES;
+    
+    if (self.tapBlock != tapClick) {
+        self.tapBlock = tapClick;
+    }
+}
+
+- (void)yb_addAttributeTapActionWithRanges:(NSArray<NSString *> *)ranges delegate:(id<YBAttributeTapActionDelegate>)delegate
+{
+    [self yb_removeAttributeTapActions];
+    [self yb_getRangesWithRanges:ranges];
+    self.userInteractionEnabled = YES;
+    
+    if (self.delegate != delegate) {
+        self.delegate = delegate;
+    }
+}
+
+- (void)yb_removeAttributeTapActions
+{
+    self.tapBlock = nil;
+    self.delegate = nil;
+    self.effectDic = nil;
+    self.isTapAction = NO;
+    self.attributeStrings = [NSMutableArray array];
+}
+
+#pragma mark - touchAction
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
+{
+    if (!self.isTapAction) {
+        [super touchesBegan:touches withEvent:event];
+        return;
+    }
+    
+    if (objc_getAssociatedObject(self, @selector(enabledTapEffect))) {
+        self.isTapEffect = self.enabledTapEffect;
+    }
+    
+    UITouch *touch = [touches anyObject];
+    
+    CGPoint point = [touch locationInView:self];
+    
+    __weak typeof(self) weakSelf = self;
+    
+    BOOL ret = [self yb_getTapFrameWithTouchPoint:point result:^(NSString *string, NSRange range, NSInteger index) {
+        
+        if (weakSelf.isTapEffect) {
+            
+            [weakSelf yb_saveEffectDicWithRange:range];
+            
+            [weakSelf yb_tapEffectWithStatus:YES];
+        }
+        
+    }];
+    if (!ret) {
+        [super touchesBegan:touches withEvent:event];
+    }
+}
+
+- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
+{
+    if (!self.isTapAction) {
+        [super touchesEnded:touches withEvent:event];
+        return;
+    }
+    if (self.isTapEffect) {
+        [self performSelectorOnMainThread:@selector(yb_tapEffectWithStatus:) withObject:nil waitUntilDone:NO];
+    }
+    
+    UITouch *touch = [touches anyObject];
+    
+    CGPoint point = [touch locationInView:self];
+    
+    __weak typeof(self) weakSelf = self;
+    
+    BOOL ret = [self yb_getTapFrameWithTouchPoint:point result:^(NSString *string, NSRange range, NSInteger index) {
+        if (weakSelf.tapBlock) {
+            weakSelf.tapBlock (weakSelf, string, range, index);
+        }
+        
+        if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(yb_tapAttributeInLabel:string:range:index:)]) {
+            [weakSelf.delegate yb_tapAttributeInLabel:weakSelf string:string range:range index:index];
+        }
+    }];
+    if (!ret) {
+        [super touchesEnded:touches withEvent:event];
+    }
+}
+
+- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
+{
+    if (!self.isTapAction) {
+        [super touchesCancelled:touches withEvent:event];
+        return;
+    }
+    if (self.isTapEffect) {
+        [self performSelectorOnMainThread:@selector(yb_tapEffectWithStatus:) withObject:nil waitUntilDone:NO];
+    }
+    UITouch *touch = [touches anyObject];
+    
+    CGPoint point = [touch locationInView:self];
+    
+    __weak typeof(self) weakSelf = self;
+    
+    BOOL ret = [self yb_getTapFrameWithTouchPoint:point result:^(NSString *string, NSRange range, NSInteger index) {
+        if (weakSelf.tapBlock) {
+            weakSelf.tapBlock (weakSelf, string, range, index);
+        }
+        
+        if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(yb_tapAttributeInLabel:string:range:index:)]) {
+            [weakSelf.delegate yb_tapAttributeInLabel:weakSelf string:string range:range index:index];
+        }
+    }];
+    if (!ret) {
+        [super touchesCancelled:touches withEvent:event];
+    }
+}
+
+#pragma mark - getTapFrame
+- (BOOL)yb_getTapFrameWithTouchPoint:(CGPoint)point result:(void (^) (NSString *string , NSRange range , NSInteger index))resultBlock
+{
+    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attributedText);
+    
+    CGMutablePathRef Path = CGPathCreateMutable();
+    
+    CGPathAddRect(Path, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height + 20));
+    
+    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL);
+    
+    CFArrayRef lines = CTFrameGetLines(frame);
+    
+    CGFloat total_height =  [self yb_textSizeWithAttributedString:self.attributedText width:self.bounds.size.width numberOfLines:0].height;
+    
+    if (!lines) {
+        CFRelease(frame);
+        CFRelease(framesetter);
+        CGPathRelease(Path);
+        return NO;
+    }
+    
+    CFIndex count = CFArrayGetCount(lines);
+    
+    CGPoint origins[count];
+    
+    CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins);
+    
+    CGAffineTransform transform = [self yb_transformForCoreText];
+    
+    for (CFIndex i = 0; i < count; i++) {
+        CGPoint linePoint = origins[i];
+        
+        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
+        
+        CGRect flippedRect = [self yb_getLineBounds:line point:linePoint];
+        
+        CGRect rect = CGRectApplyAffineTransform(flippedRect, transform);
+        
+        CGFloat lineOutSpace = (self.bounds.size.height - total_height) / 2;
+        
+        rect.origin.y = lineOutSpace + [self yb_getLineOrign:line];
+        
+        if (self.enlargeTapArea) {
+            rect.origin.y -= 5;
+            rect.size.height += 10;
+        }
+        
+        if (CGRectContainsPoint(rect, point)) {
+            
+            CGPoint relativePoint = CGPointMake(point.x - CGRectGetMinX(rect), point.y - CGRectGetMinY(rect));
+
+            CFIndex index = CTLineGetStringIndexForPosition(line, relativePoint);
+            
+            CGFloat offset;
+            
+            CTLineGetOffsetForStringIndex(line, index, &offset);
+            
+            if (offset > relativePoint.x) {
+                index = index - 1;
+            }
+            
+            NSInteger link_count = self.attributeStrings.count;
+            
+            for (int j = 0; j < link_count; j++) {
+                
+                YBAttributeModel *model = self.attributeStrings[j];
+                
+                NSRange link_range = model.range;
+                if (NSLocationInRange(index, link_range)) {
+                    if (resultBlock) {
+                        resultBlock (model.str , model.range , (NSInteger)j);
+                    }
+                    CFRelease(frame);
+                    CFRelease(framesetter);
+                    CGPathRelease(Path);
+                    return YES;
+                }
+            }
+        }
+    }
+    CFRelease(frame);
+    CFRelease(framesetter);
+    CGPathRelease(Path);
+    return NO;
+}
+
+- (CGAffineTransform)yb_transformForCoreText
+{
+    return CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f);
+}
+
+- (CGRect)yb_getLineBounds:(CTLineRef)line point:(CGPoint)point
+{
+    CGFloat ascent = 0.0f;
+    CGFloat descent = 0.0f;
+    CGFloat leading = 0.0f;
+    CGFloat width = (CGFloat)CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
+    CGFloat height = 0.0f;
+    
+    CFRange range = CTLineGetStringRange(line);
+    NSAttributedString * attributedString = [self.attributedText attributedSubstringFromRange:NSMakeRange(range.location, range.length)];
+    if ([attributedString.string hasSuffix:@"\n"] && attributedString.string.length > 1) {
+        attributedString = [attributedString attributedSubstringFromRange:NSMakeRange(0, attributedString.length - 1)];
+    }
+    height = [self yb_textSizeWithAttributedString:attributedString width:self.bounds.size.width numberOfLines:0].height;
+    return CGRectMake(point.x, point.y , width, height);
+}
+
+- (CGFloat)yb_getLineOrign:(CTLineRef)line
+{
+    CFRange range = CTLineGetStringRange(line);
+    if (range.location == 0) {
+        return 0.;
+    }else {
+        NSAttributedString * attributedString = [self.attributedText attributedSubstringFromRange:NSMakeRange(0, range.location)];
+        if ([attributedString.string hasSuffix:@"\n"] && attributedString.string.length > 1) {
+            attributedString = [attributedString attributedSubstringFromRange:NSMakeRange(0, attributedString.length - 1)];
+        }
+        return [self yb_textSizeWithAttributedString:attributedString width:self.bounds.size.width numberOfLines:0].height;
+    }
+}
+
+- (CGSize)yb_textSizeWithAttributedString:(NSAttributedString *)attributedString width:(float)width numberOfLines:(NSInteger)numberOfLines
+{
+    @autoreleasepool {
+        UILabel *sizeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+        sizeLabel.numberOfLines = numberOfLines;
+        sizeLabel.attributedText = attributedString;
+        CGSize fitSize = [sizeLabel sizeThatFits:CGSizeMake(width, MAXFLOAT)];
+        return fitSize;
+    }
+}
+
+#pragma mark - tapEffect
+- (void)yb_tapEffectWithStatus:(BOOL)status
+{
+    if (self.isTapEffect) {
+        NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
+        
+        NSMutableAttributedString *subAtt = [[NSMutableAttributedString alloc] initWithAttributedString:[[self.effectDic allValues] firstObject]];
+        
+        NSRange range = NSRangeFromString([[self.effectDic allKeys] firstObject]);
+        
+        if (status) {
+            [subAtt addAttribute:NSBackgroundColorAttributeName value:self.tapHighlightedColor range:NSMakeRange(0, subAtt.string.length)];
+            
+            [attStr replaceCharactersInRange:range withAttributedString:subAtt];
+        }else {
+            
+            [attStr replaceCharactersInRange:range withAttributedString:subAtt];
+        }
+        self.attributedText = attStr;
+    }
+}
+
+- (void)yb_saveEffectDicWithRange:(NSRange)range
+{
+    self.effectDic = [NSMutableDictionary dictionary];
+    
+    NSAttributedString *subAttribute = [self.attributedText attributedSubstringFromRange:range];
+    
+    [self.effectDic setObject:subAttribute forKey:NSStringFromRange(range)];
+}
+
+#pragma mark - getRange
+- (void)yb_getRangesWithStrings:(NSArray <NSString *>  *)strings
+{
+    if (self.attributedText == nil) {
+        self.isTapAction = NO;
+        return;
+    }
+    self.isTapAction = YES;
+    self.isTapEffect = YES;
+    __block  NSString *totalStr = self.attributedText.string;
+    self.attributeStrings = [NSMutableArray array];
+    __weak typeof(self) weakSelf = self;
+    
+    [strings enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        
+        NSRange range = [totalStr rangeOfString:obj];
+        
+        if (range.length != 0) {
+            
+            totalStr = [totalStr stringByReplacingCharactersInRange:range withString:[weakSelf yb_getStringWithRange:range]];
+            
+            YBAttributeModel *model = [YBAttributeModel new];
+            model.range = range;
+            model.str = obj;
+            [weakSelf.attributeStrings addObject:model];
+            
+        }
+        
+    }];
+}
+
+- (void)yb_getRangesWithRanges:(NSArray <NSString *>  *)ranges
+{
+    if (self.attributedText == nil) {
+        self.isTapAction = NO;
+        return;
+    }
+    
+    self.isTapAction = YES;
+    self.isTapEffect = YES;
+    __block  NSString *totalStr = self.attributedText.string;
+    self.attributeStrings = [NSMutableArray array];
+    __weak typeof(self) weakSelf = self;
+    
+    [ranges enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        NSRange range = NSRangeFromString(obj);
+        NSAssert(totalStr.length >= range.location + range.length, @"NSRange(%ld,%ld) is out of bounds",range.location,range.length);
+        NSString * string = [totalStr substringWithRange:range];
+        
+        YBAttributeModel *model = [YBAttributeModel new];
+        model.range = range;
+        model.str = string;
+        [weakSelf.attributeStrings addObject:model];
+    }];
+}
+
+- (NSString *)yb_getStringWithRange:(NSRange)range
+{
+    NSMutableString *string = [NSMutableString string];
+    
+    for (int i = 0; i < range.length ; i++) {
+        
+        [string appendString:@" "];
+    }
+    return string;
+}
+
+#pragma mark - KVO
+- (void)yb_addObserver
+{
+    [self addObserver:self forKeyPath:@"attributedText" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
+}
+
+- (void)yb_removeObserver
+{
+    id info = self.observationInfo;
+    NSString * key = @"attributedText";
+    NSArray *array = [info valueForKey:@"_observances"];
+    for (id objc in array) {
+        id Properties = [objc valueForKeyPath:@"_property"];
+        NSString *keyPath = [Properties valueForKeyPath:@"_keyPath"];
+        if ([key isEqualToString:keyPath]) {
+            [self removeObserver:self forKeyPath:@"attributedText" context:nil];
+        }
+    }
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
+{
+    if ([keyPath isEqualToString:@"attributedText"]) {
+        if (self.isTapAction) {
+            if (![change[NSKeyValueChangeNewKey] isEqual: change[NSKeyValueChangeOldKey]]) {
+               
+            }
+        }
+    }
+}
+
+@end

+ 22 - 12
AIIM/AIIM/Common/CommonUI/Util/config.h

@@ -9,21 +9,29 @@
 #define config_h
 #import <UIKit/UIKit.h>
 
+
+//#ifdef DEBUG
+//static NSString *WebSocketUrl = @"ws://abt1.my-im.com:9326?";
+//#else
+//static NSString *WebSocketUrl = @"wss://aiim.my-im.com/wss?";
+//#endif
 //
-#ifdef DEBUG
-static NSString *WebSocketUrl = @"ws://abt1.my-im.com:9326?";
-#else
-static NSString *WebSocketUrl = @"ws://aiim.my-im.com:9326?";
-#endif
+//#ifdef DEBUG
+//static NSString *httphost = @"http://abt1.my-im.com:8080";
+//#else
+//static NSString *httphost = @"https://aiim.my-im.com";
+//#endif
+
+static NSString *WebSocketUrl = @"wss://aiim.my-im.com/wss?";
+static NSString *httphost = @"https://aiim.my-im.com";
 
-#ifdef DEBUG
-static NSString *httphost = @"http://abt1.my-im.com:8080";
-#else
-static NSString *httphost = @"http://aiim.my-im.com";
-#endif
+//static NSString *WebSocketUrl = @"wss://aliaiim.my-im.com/wss?";
+//static NSString *httphost = @"https://aliaiim.my-im.com";
+
+//
+//static NSString *WebSocketUrl = @"wss://web.my-im.com/wss?";
+//static NSString *httphost = @"https://web.my-im.com";
 
-//static NSString *WebSocketUrl = @"ws://aiim.my-im.com:9326?";
-//static NSString *httphost = @"http://aiim.my-im.com";
 
 //static NSString *WebSocketUrl = @"ws://192.168.1.7:9326?";
 //static NSString *httphost = @"http://192.168.1.7:8080";
@@ -44,6 +52,8 @@ static NSString *JitsiMeetSV = @"https://rtc2.my-im.com/";
 //旧地址 @"https://rtc.my-im.com/"
 
 static NSString *filehttphost = @"http://upload.my-im.com";//生产文件服务器
+static NSString *ossfilehttphost = @"http://newweb.abtim-my.com/api/oss/uploadPart";//生产文件服务器
+
 static NSString * privacyPolicy = @"https://download.gobuy99.com/ynszc.html";//隐私政策
 
 

+ 6 - 2
AIIM/AIIM/Common/Defaults/CryptoAES.m

@@ -50,9 +50,13 @@ static NSString *RSAprivateKey2 = @"-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgk
 -(NSString *_Nullable)decryptDataL:(NSString *_Nullable)str{
 //    NSLog(@"decryptDataL str:%lu",(unsigned long)str.length);
     if([str isKindOfClass:[NSString class]]&&str.length>30){
-//        NSString *decWithPrivKey = [RSA decryptString:str privateKey:RSAprivateKey2];
         NSString *decWithPrivKey = [GRSA decryptString:str privateKey:RSAprivateKey2];
-        return decWithPrivKey;
+        if(decWithPrivKey&&decWithPrivKey.length>0){
+            return decWithPrivKey;
+        }
+        else{
+            return str;
+        }
     }
     else{
         if([str isKindOfClass:[NSString class]]){

+ 3 - 0
AIIM/AIIM/Common/Defaults/UDManager.h

@@ -29,6 +29,9 @@ static NSString * _Nonnull nkonNewMessageNote = @"nkonNewMessageNote";
 static NSString * _Nonnull nkonAddFriendNote = @"nkonAddFriendNote";
 static NSString * _Nonnull nkonEXGroupdNote = @"nkonEXGroupdNote";
 
+//oss
+static NSString * _Nonnull nkOSSinfo = @"nkOSSinfo";
+
 
 
 @interface UDManager : NSObject

+ 7 - 1
AIIM/AIIM/Common/Network/FileNetApi.h

@@ -24,11 +24,17 @@
 ///上传文件(带上传进度)
 +(void)uploadWithFilePath:(NSURL * _Nonnull)filePath thrid:(NSString *_Nullable)thrid progress:(FUploadProgress _Nullable)progress succ:(FSucc _Nullable )succ fail:(FFail _Nullable )fail;
 
+
+///上传文件(带上传进度)
++(void)OSSuploadWithFilePath:(NSURL * _Nonnull)filePath thrid:(NSString *_Nullable)thrid progress:(FUploadProgress _Nullable)progress succ:(FSucc _Nullable )succ fail:(FFail _Nullable )fail;
+
+
+
 ///批量上传文件
 +(void)uploadWithFilePaths:(NSArray <NSURL *>*_Nonnull)filePaths thrid:(NSString *_Nullable)thrid succ:(FSucc _Nullable )succ fail:(FFail _Nullable )fail;
 
 //下载保存文件
-+(void)downLoadWToken:(NSURL *_Nonnull)filePath succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail;
++(void)downLoadWToken:(NSURL *_Nonnull)filePath thrid:(NSString *_Nullable)thrid succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail;
 //取消上传
 +(void)stopUploadTanck:(NSString *_Nullable)thrid;
 @end

+ 27 - 2
AIIM/AIIM/Common/Network/FileNetApi.m

@@ -7,6 +7,7 @@
 
 #import <Foundation/Foundation.h>
 #import "FileNetApi.h"
+#import <Bugly/Bugly.h>
 
 @implementation FileNetApi
 
@@ -30,10 +31,34 @@
         }
         
     } succ:^(int code, NSString * _Nullable thrid, NSDictionary * sdic) {
+        [Bugly reportException:[NSException exceptionWithName:@"文件传输成功" reason:[NSString stringWithFormat:@"%@",sdic] userInfo:nil]];
         if(succ){
             succ(code,thrid,sdic);
         }
     } fail:^(NSString * _Nullable thrid, NSError * _Nonnull error) {
+        [Bugly reportException:[NSException exceptionWithName:@"文件传输失败:" reason:[NSString stringWithFormat:@"%@",error] userInfo:nil]];
+        if(fail){
+            fail(thrid,error);
+        }
+    }];
+//    [GBaseNetApi.shareInstance uploadWithFilePath:filePath thrid:thrid progress:
+//                                             succ:succ fail:fail];
+}
+
+///上传文件(返回上传进度)
++(void)OSSuploadWithFilePath:(NSURL * _Nonnull)filePath thrid:(NSString *_Nullable)thrid progress:(FUploadProgress _Nullable)progress succ:(FSucc _Nullable )succ fail:(FFail _Nullable )fail{
+    [GBaseNetApi.shareInstance uploadWithFilePathOSS:filePath thrid:thrid progress:^(NSString * _Nullable thrid, NSProgress * _Nullable uploadProgress) {
+        NSLog(@"uploadWithFilePath: %lld %@", 100 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount, @" %");
+        if(progress){
+            progress(thrid,uploadProgress);
+        }
+    } succ:^(int code, NSString * _Nullable thrid, NSDictionary * sdic) {
+        [Bugly reportException:[NSException exceptionWithName:@"文件传输成功" reason:[NSString stringWithFormat:@"%@",sdic] userInfo:nil]];
+        if(succ){
+            succ(code,thrid,sdic);
+        }
+    } fail:^(NSString * _Nullable thrid, NSError * _Nonnull error) {
+        [Bugly reportException:[NSException exceptionWithName:@"文件传输失败:" reason:[NSString stringWithFormat:@"%@",error] userInfo:nil]];
         if(fail){
             fail(thrid,error);
         }
@@ -46,8 +71,8 @@
     [GBaseNetApi.shareInstance uploadWithFilePath:filePaths thrid:thrid succ:succ fail:fail];
 }
 
-+(void)downLoadWToken:(NSURL *_Nonnull)filePath succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail{
-    [GBaseNetApi.shareInstance downLoadFileWToken:filePath succ:succ fail:fail];
++(void)downLoadWToken:(NSURL *_Nonnull)filePath thrid:(NSString *_Nullable)thrid succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail{
+    [GBaseNetApi.shareInstance downLoadFileWToken:filePath thrid:thrid succ:succ fail:fail];
 }
 
 //取消上传

+ 11 - 1
AIIM/AIIM/Common/Network/GBaseNetApi.h

@@ -23,11 +23,13 @@ typedef void (^FUploadProgress)(NSString * _Nullable thrid,NSProgress * _Nullabl
 //#define host @"http://192.168.1.21:8080"//测试服务器
 #define host httphost//生产服务器
 #define filehost filehttphost//生产服务器
+#define OSSfilehost ossfilehttphost//生产服务器
 //#import "ReactiveObjC.h"
 
 @interface GBaseNetApi : NSObject
 
 @property (nonatomic,strong) NSMutableArray * _Nullable uploadTanck;
+@property (nonatomic,strong) NSMutableArray * _Nullable downloadTanck;
 
 + (GBaseNetApi *_Nonnull)shareInstance;
 
@@ -50,7 +52,15 @@ typedef void (^FUploadProgress)(NSString * _Nullable thrid,NSProgress * _Nullabl
 ///批量上传
 - (void)uploadWithFilePath:(NSArray <NSURL *>*_Nullable)filePaths thrid:(NSString *_Nullable)thrid succ:(FSucc _Nullable )succ fail:(FFail _Nullable )fail;
 
--(void)downLoadFileWToken:(NSURL *_Nonnull)url succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail;
+
+
+//OSS返回上传进度的上传方法
+- (void)uploadWithFilePathOSS:(NSURL *_Nullable)filePath thrid:(NSString *_Nullable)thrid progress:(FUploadProgress _Nullable )progress succ:(FSucc _Nullable )succ fail:(FFail _Nullable )fail;
+
+
+
+
+-(void)downLoadFileWToken:(NSURL *_Nonnull)url thrid:(NSString *_Nullable)thrid succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail;
 
 //取消上传
 -(void)stopUploadTanck:(NSString *_Nullable)thrid;

+ 186 - 14
AIIM/AIIM/Common/Network/GBaseNetApi.m

@@ -26,6 +26,7 @@
 - (instancetype)init {
     if (self = [super init]) {
         _uploadTanck = [NSMutableArray new];
+        _downloadTanck =[NSMutableArray new];
     }
     return self;
 }
@@ -35,7 +36,13 @@
 -(void)httpGet:(nullable id)parameters url:(NSString *)url succ:(GSucc)succ fail:(GFail)fail{
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     manager.requestSerializer = [AFJSONRequestSerializer serializer];
-    NSString *acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    NSString *acUrl=@"";
+    if([url containsString:@"http"]){
+        acUrl =url;
+    }
+    else{
+        acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    }
     NSLog(@"%@",acUrl);
     [manager GET:acUrl parameters:parameters  headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
         //
@@ -53,7 +60,13 @@
 -(void)httpPost:(nullable id)parameters url:(NSString *)url succ:(GSucc)succ fail:(GFail)fail{
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     manager.requestSerializer = [AFJSONRequestSerializer serializer];
-    NSString *acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    NSString *acUrl=@"";
+    if([url containsString:@"http"]){
+        acUrl =url;
+    }
+    else{
+        acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    }
 //    NSLog(@"%@",acUrl);
 //    NSLog(@"%@",parameters);
     [manager POST:acUrl parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
@@ -74,7 +87,13 @@
     NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
     [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",token] forHTTPHeaderField:@"Authorization"];
     
-    NSString *acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    NSString *acUrl=@"";
+    if([url containsString:@"http"]){
+        acUrl =url;
+    }
+    else{
+        acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    }
     NSLog(@"%@",acUrl);
     [manager GET:acUrl parameters:parameters  headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
         //
@@ -97,7 +116,13 @@
     NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
     [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",token] forHTTPHeaderField:@"Authorization"];
     
-    NSString *acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    NSString *acUrl=@"";
+    if([url containsString:@"http"]){
+        acUrl =url;
+    }
+    else{
+        acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    }
     NSLog(@"%@",acUrl);
     NSLog(@"%@",parameters);
     [manager POST:acUrl parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
@@ -119,7 +144,13 @@
     NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
     [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",token] forHTTPHeaderField:@"Authorization"];
     
-    NSString *acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    NSString *acUrl=@"";
+    if([url containsString:@"http"]){
+        acUrl =url;
+    }
+    else{
+        acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    }
 //    NSLog(@"%@",acUrl);
 //    NSLog(@"%@",parameters);
 //    
@@ -141,7 +172,13 @@
     NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
     [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",token] forHTTPHeaderField:@"Authorization"];
     
-    NSString *acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    NSString *acUrl=@"";
+    if([url containsString:@"http"]){
+        acUrl =url;
+    }
+    else{
+        acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    }
     NSLog(@"%@",acUrl);
     NSLog(@"%@",parameters);
     
@@ -163,7 +200,13 @@
     NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
     [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",token] forHTTPHeaderField:@"Authorization"];
     
-    NSString *acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    NSString *acUrl=@"";
+    if([url containsString:@"http"]){
+        acUrl =url;
+    }
+    else{
+        acUrl=[NSString stringWithFormat:@"%@%@",host,url];
+    }
     NSLog(@"%@",acUrl);
     NSLog(@"%@",parameters);
 
@@ -227,8 +270,6 @@
         return;
     }
     
-    
-    
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // 确保服务器返回的是原始数据,而非自动解析为JSON等
     NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
@@ -236,6 +277,7 @@
     //[manager.requestSerializer setValue:[NSString stringWithFormat:@"multipart/form-data"] forHTTPHeaderField:@"Content-Type"];
     
     NSString *acUrl=[NSString stringWithFormat:@"%@%@",filehost,@"/common/upload"];
+    NSLog(@"acUrl:%@",acUrl);
     NSURLSessionDataTask *uploadTack;
     // 上传文件,使用multipart/form-data类型(通常用于文件上传)
     uploadTack = [manager POST:acUrl parameters:nil headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
@@ -272,6 +314,67 @@
     [self addUploadTanckobj:uploadTack thrid:thrid];
 }
 
+
+//OSS返回上传进度的上传方法
+- (void)uploadWithFilePathOSS:(NSURL *_Nullable)filePath thrid:(NSString *_Nullable)thrid progress:(FUploadProgress _Nullable )progress succ:(FSucc _Nullable )succ fail:(FFail _Nullable )fail{
+    
+    
+    if([self isuploadTanck:thrid]){
+        NSLog(@"---------isuploadTanck:%@",filePath);
+        return;
+    }
+    
+    NSData *fileData = [NSData dataWithContentsOfURL:filePath];
+    
+    if (!fileData) {
+        [MBProgressHUD showWithText:@"獲取本地檔案失敗,請重新選擇檔案"];
+        return;
+    }
+    
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // 确保服务器返回的是原始数据,而非自动解析为JSON等
+    NSString *token = (NSString *)[UDManager.shareInstance getSDManager:gkeytoken];
+    [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",token] forHTTPHeaderField:@"Authorization"];
+    //[manager.requestSerializer setValue:[NSString stringWithFormat:@"multipart/form-data"] forHTTPHeaderField:@"Content-Type"];
+    
+    NSString *acUrl=OSSfilehost;
+    NSLog(@"acUrl:%@",acUrl);
+    NSURLSessionDataTask *uploadTack;
+    // 上传文件,使用multipart/form-data类型(通常用于文件上传)
+    uploadTack = [manager POST:acUrl parameters:nil headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
+            // 参数名称,服务器用来识别是哪个文件被上传
+            [formData appendPartWithFileData:fileData name:@"file" fileName:filePath.lastPathComponent mimeType:@"multipart/form-data"];
+        } progress:^(NSProgress * _Nonnull uploadProgress) {
+            // 上传进度处理
+            NSLog(@"Percent Done: %lld %@", 100 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount, @" %");
+            if (progress) {
+                progress(thrid,uploadProgress);
+            }
+            
+        } success:^(NSURLSessionTask * _Nonnull task, id  _Nullable responseObject) {
+            // 上传成功处理
+            [self removeUploadTanckobj:thrid];
+            NSString *str =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
+            NSLog(@"Success: %@", str);
+            NSMutableDictionary *jsonDict = [NSMutableDictionary dictionaryWithDictionary:[NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil]];
+            [jsonDict jk_setObj:[self calculateFileSizeFromData:fileData] forKey:@"size"];
+//            NSLog(@"jsonDict:%@",jsonDict);
+            if (succ) {
+                succ(200,thrid,jsonDict);
+            }
+        } failure:^(NSURLSessionTask * _Nullable task, NSError * _Nonnull error) {
+            // 上传失败处理
+            [self removeUploadTanckobj:thrid];
+            if (fail) {
+                fail(thrid,error);
+            }
+            NSLog(@"Error: %@", error);
+        }];
+    
+    uploadTack.priority = NSURLSessionTaskPriorityLow;
+    [self addUploadTanckobj:uploadTack thrid:thrid];
+}
+
 -(void)upLoaddataWToken:(NSData *_Nonnull)data fileName:(NSString *_Nullable)fileName succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail{
     
   
@@ -397,21 +500,32 @@
     }
 }
 
--(void)downLoadFileWToken:(NSURL *_Nonnull)url succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail{
+-(void)downLoadFileWToken:(NSURL *_Nonnull)url thrid:(NSString *_Nullable)thrid succ:(GSucc _Nullable )succ fail:(GFail _Nullable )fail{
+    
+    if([self isDownloadTanck:thrid]){
+       
+        return;
+    }
+    
     NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
     AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:config];
     NSURLRequest *request = [NSURLRequest requestWithURL:url];
     NSURLSessionTask *task = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
-        CGFloat progres = downloadProgress.completedUnitCount/downloadProgress.totalUnitCount;
-        NSLog(@"1111:%f",progres);
+//        NSLog(@"%lld:%lld",downloadProgress.completedUnitCount,downloadProgress.totalUnitCount);
+        CGFloat progres = downloadProgress.completedUnitCount/(double)downloadProgress.totalUnitCount;
+//        NSLog(@"1111:%f",progres);
         if(succ){
-            succ(progres,nil);
+//            NSLog(@"222222:%f",progres);
+            CGFloat Pcode =progres*100;
+//            NSLog(@"222222:%d",(int)Pcode);
+            succ(Pcode,nil);
         }
     } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
         NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
             return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
     } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
-        NSLog(@"333:%@",filePath);
+//        NSLog(@"333:%@",filePath);
+        [self removeDownloadTanckobj:thrid];
         if(error){//失败
             if(fail){
                 fail(error);
@@ -430,6 +544,8 @@
             }
         }
     }];
+    task.priority = NSURLSessionTaskPriorityLow;
+    [self addDownloadTanckobj:task thrid:thrid];
     [task resume];
 }
 
@@ -461,6 +577,23 @@
     [_uploadTanck addObject:item];
 }
 
+
+
+-(BOOL)isuploadTanck:(NSString *)thrid{
+    NSLog(@"stopUploadTanck-------------2");
+    if(_uploadTanck.count>0){
+        for (NSDictionary *item in _uploadTanck) {
+            NSString *th = item[@"thrid"];
+            NSLog(@"stopUploadTanck-------------3");
+            if([th isEqualToString:thrid]){
+                NSLog(@"stopUploadTanck-------------4");
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 -(void)removeUploadTanckobj:(NSString *)thrid{
     if(_uploadTanck.count>0){
         for (NSDictionary *item in _uploadTanck) {
@@ -490,5 +623,44 @@
     }
 }
 
+
+-(void)addDownloadTanckobj:(NSURLSessionTask *)task thrid:(NSString *)thrid{
+    NSDictionary *item = @{
+        @"task":task,
+        @"thrid":thrid
+    };
+    [_downloadTanck addObject:item];
+}
+
+
+-(void)removeDownloadTanckobj:(NSString *)thrid{
+    if(_downloadTanck.count>0){
+        for (NSDictionary *item in _downloadTanck) {
+            NSString *th = item[@"thrid"];
+            if([th isEqualToString:thrid]){
+                [_downloadTanck removeObject:item];
+                return;
+            }
+        }
+    }
+}
+
+
+
+-(BOOL)isDownloadTanck:(NSString *)thrid{
+    NSLog(@"stopUploadTanck-------------2");
+    if(_downloadTanck.count>0){
+        for (NSDictionary *item in _downloadTanck) {
+            NSString *th = item[@"thrid"];
+            NSLog(@"stopUploadTanck-------------3");
+            if([th isEqualToString:thrid]){
+                NSLog(@"stopUploadTanck-------------4");
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 @end
 

+ 3 - 0
AIIM/AIIM/Common/Network/GDBManager.h

@@ -48,6 +48,9 @@ typedef void (^DBSucc)(NSArray * _Nullable array);
 //删除数据指定消息
 -(void)deleteLocalmsg:(NSDictionary *_Nullable)msg;
 
+//删除数据指定聊天窗消息
+-(void)deletechatLocalmsg:(NSString *_Nullable)chatId;
+
 //按分类查询消息
 -(void)selectLocalmsgType:(NSString *_Nullable)chatId messageType:(NSString *_Nullable)messageType succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail;
 

+ 57 - 23
AIIM/AIIM/Common/Network/GDBManager.m

@@ -95,7 +95,7 @@
     int lowerBound = 10;
     int upperBound = 30;
     int randomInt = lowerBound + arc4random() % (upperBound - lowerBound + 1);
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     
     for (NSInteger i = 0; i<randomInt; i++) {
         [self delLocalmsglistTable:userid];
@@ -178,7 +178,7 @@
 -(void)createLocalMSGtable:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail;{
    
     // 创建表语句
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *sql1=@"create table if not exists lcmsglist_";
     NSString *tablejg = @"(id CHAR PRIMARY KEY,chatId CHAR,type CHAR,messageType CHAR,timestamp BIGINT,localtime BIGINT,Message TEXT)";
     NSString *sql = [NSString stringWithFormat:@"%@%@ %@",sql1,userid,tablejg];
@@ -209,7 +209,7 @@
 }
 -(void)insertLocalmsg:(NSDictionary *_Nonnull)msg succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{//插入消息
     NSString *vstr = @"insert into lcmsglist_";
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSDictionary * safeDict = [self replaceNullsWithEmptyStringInDictionary:msg];
     
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" ('id','chatId','type','messageType','timestamp','localtime','Message') values ("];
@@ -255,7 +255,7 @@
         return;
     }
     
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     if (userid.length == 0) {
         if (fail) fail(@"用户ID获取失败");
         return;
@@ -308,14 +308,14 @@
         }
         
         if(urlMark){//删除旧数据,以便更新信息
-//            NSLog(@"删除旧数据(2localtime=%@)", localtime);
+            NSLog(@"删除旧数据(2localtime=%@)", localtime);
             // 4. 删除相同localtime的旧数据
             NSString *deleteSQL = [NSString stringWithFormat:
                                    @"DELETE FROM %@ WHERE localtime = ?",
                                    tableName];
             
             if (![self.db executeUpdate:deleteSQL, localtime]) {
-//                NSLog(@"删除旧数据失败(localtime=%@): %@", localtime, [self.db lastErrorMessage]);
+                NSLog(@"删除旧数据失败(localtime=%@): %@", localtime, [self.db lastErrorMessage]);
                 // 不终止,继续尝试插入
             }
         }
@@ -369,7 +369,7 @@
         return;
     }
     
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *tableName = [NSString stringWithFormat:@"lcmsglist_%@", userid];
     
     // 开启事务
@@ -473,7 +473,7 @@
 -(void)selectLocalmsg:(NSString *_Nonnull)chatId page:(NSInteger)page succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{//查询消息
     
     // 查询数据
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"select * from lcmsglist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" where chatId = "];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,chatId];
@@ -502,7 +502,7 @@
 
 -(void)selectnextmsg:(NSString *_Nonnull)chatId timestp:(NSInteger)timestp succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{//查询消息
     // 查询数据
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"select * from lcmsglist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" where chatId = "];
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,chatId,@" AND timestamp < "];
@@ -532,7 +532,7 @@
 
 -(void)deleteMyLocalmsg:(NSDictionary *)msg{//删除单个消息 DELETE FROM users WHERE id IN (100, 101);
     
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"DELETE FROM lcmsglist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" WHERE id=="];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,msg[@"localtime"]];
@@ -545,7 +545,7 @@
 }
 
 -(void)deleteLocalmsg:(NSDictionary *_Nullable)msg{
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"DELETE FROM lcmsglist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" WHERE id=="];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,msg[@"id"]];
@@ -557,11 +557,45 @@
     }
 }
 
+//删除数据指定聊天窗消息
+-(void)deletechatLocalmsg:(NSString *_Nullable)chatId{
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
+    // 开启事务
+    [self.db beginTransaction];
+    @try {
+        NSString *updataSQL =[NSString stringWithFormat:@"UPDATE lcmsglist_%@ SET Message=? WHERE chatId = ?",userid];
+        // 执行插入(使用参数化查询)
+        NSUUID *uid = [NSUUID UUID];
+        BOOL success = [self.db executeUpdate:updataSQL,
+                        uid.UUIDString,
+                        chatId];
+        // 提交事务
+        [self.db commit];
+        if (!success) {
+            NSLog(@"更新数据失败: %@", [self.db lastErrorMessage]);
+        } else {
+            NSLog(@"更新数据成功");
+        }
+        NSString *vstr = [NSString stringWithFormat:@"DELETE FROM lcmsglist_%@ WHERE chatId=%@",userid,chatId];
+        success = [self.db executeUpdate:vstr];
+        if (!success) {
+            NSLog(@"删除指定消息: %@", [self.db lastErrorMessage]);
+        } else {
+            NSLog(@"删除指定消息成功");
+        }
+    }
+    @catch (NSException *exception) {
+        [self.db rollback];
+        NSString *error = [NSString stringWithFormat:@"lcUserServer插入本地异常: %@", exception.reason];
+        NSLog(@"%@", error);
+    }
+}
+
 
 -(void)selectLocalmsgType:(NSString *)chatId messageType:(NSString *)messageType succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{//按分类查询消息
     
     // 查询数据
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"select * from lcmsglist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" where chatId = "];
     vstr=[NSString stringWithFormat:@"%@%@ AND messageType=",vstr,chatId];
@@ -591,7 +625,7 @@
 
 -(void)selectNextmsgType:(NSString *_Nullable)chatId messageType:(NSString *_Nullable)messageType timestp:(NSInteger)timestp succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
     // 查询数据
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"select * from lcmsglist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" where chatId = "];
     vstr=[NSString stringWithFormat:@"%@%@ AND messageType=",vstr,chatId];
@@ -623,7 +657,7 @@
 //根据本地时间查询本地消息
 -(void)selectLocalmsgWithLocaltime:(NSString *_Nullable)localtime succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
     // 查询数据
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"select * from lcmsglist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" where localtime = "];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,localtime];;
@@ -653,7 +687,7 @@
 //聊天窗表lcChatlist_
 -(void)createChattable:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
     // 创建表语句
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *sql1=@"create table if not exists lcChatlist_";
     NSString *tablejg = @"(id CHAR PRIMARY KEY,name CHAR,avatar CHAR,type CHAR,lastMessage TEXT,lastTime BIGINT,unreadCount int,loaded int,loading int,top int)";
     NSString *sql = [NSString stringWithFormat:@"%@%@ %@",sql1,userid,tablejg];
@@ -673,7 +707,7 @@
 }
 
 -(void)delchatlistTable:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{//删除聊天窗表lcChatlist_
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *sql1=@"DROP TABLE lcChatlist_";
     NSString *sql = [NSString stringWithFormat:@"%@%@",sql1,userid];
     BOOL success = [self.db executeUpdate:sql];
@@ -694,7 +728,7 @@
     
     
     NSString *vstr = @"INSERT OR REPLACE INTO lcChatlist_";
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" ('id','name','avatar','type','lastMessage','lastTime','unreadCount','loaded','loading','top') values ("];
     NSDictionary * safeDict = [self replaceNullsWithEmptyStringInDictionary:msg];
@@ -728,7 +762,7 @@
 -(void)selectLocalchats:(NSString *)top succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
     // 查询数据
     NSString *vstr = @"select * from lcChatlist_";
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,userid];
     vstr=[NSString stringWithFormat:@"%@ %@",vstr,@"where top="];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,top];
@@ -760,7 +794,7 @@
 
 
 - (void)deleteChatListItem:(NSDictionary *_Nonnull)item succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *vstr = @"DELETE FROM lcChatlist_";
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" WHERE id="];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,item[@"id"]];
@@ -786,7 +820,7 @@
 
 //聊天窗最后已读时间表
 -(void)createLastreadtimetable:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *sql1=@"create table if not exists lcChatlasttime_";
     NSString *tablejg = @"(chatId CHAR PRIMARY KEY,userId CHAR,timestamp BIGINT,type CHAR)";
     NSString *sql = [NSString stringWithFormat:@"%@%@ %@",sql1,userid,tablejg];
@@ -808,7 +842,7 @@
 
 -(void)deleatLastreadtimetable{
     
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     NSString *sql1=@"DROP TABLE lcChatlasttime_";
     NSString *sql = [NSString stringWithFormat:@"%@%@",sql1,userid];
     BOOL success = [self.db executeUpdate:sql];
@@ -824,7 +858,7 @@
 
 -(void)insertLastreadtime:(NSDictionary *_Nonnull)msg succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
     NSString *vstr = @"INSERT OR REPLACE INTO lcChatlasttime_";
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     
     vstr=[NSString stringWithFormat:@"%@%@%@",vstr,userid,@" ('chatId','userId','timestamp','type') values ("];
     
@@ -850,7 +884,7 @@
 -(void)selectchatLastreadtime:(NSString *_Nonnull)chatId succ:(DBSucc _Nullable )succ fail:(DBFail _Nullable )fail{
     // 查询数据
     NSString *vstr = @"select * from lcChatlasttime_";
-    NSString *userid = [UDManager.shareInstance getSDManager:dkuserloginId];
+    NSString *userid = [UDManager.shareInstance getSDManager:dkuserId];
     vstr=[NSString stringWithFormat:@"%@%@",vstr,userid];
     vstr=[NSString stringWithFormat:@"%@ %@%@",vstr,@"where userId=",chatId];
     

+ 27 - 19
AIIM/AIIM/Common/Network/GWebSocket.m

@@ -33,6 +33,7 @@ static NSString *redeady = @"{\"code\":1}";
 
 @property (nonatomic,assign) BOOL autoReconnect;
 @property (nonatomic,assign) NSInteger pingCount;
+@property (nonatomic,assign) NSInteger reconnetCount;
 @property (nonatomic,assign) BOOL isFirstload;
 @property (nonatomic,strong) NSString *UUID;
 @end
@@ -52,6 +53,7 @@ static NSString *redeady = @"{\"code\":1}";
 - (instancetype)init {
     if (self = [super init]) {
         self.pingCount = 0;
+        self.reconnetCount = 0;
         NSUUID *uid = [NSUUID UUID];
         _UUID=uid.UUIDString;
         NSLog(@"_UUID:%@",_UUID);
@@ -80,7 +82,7 @@ static NSString *redeady = @"{\"code\":1}";
     if (self.socket && self.socket.readyState == SR_OPEN) {
         // 只有在socket状态为SR_OPEN 时,才可以发送消息
         // 在socket状态不为SR_OPEN,可以将消息放进队列里,在websocket连上时,再发送
-//        NSLog(@"sendMsg:%@",msg);
+        NSLog(@"sendMsg:%@",msg);
         [self.socket sendString:msg error:nil];
     }
     else{
@@ -155,6 +157,7 @@ static NSString *redeady = @"{\"code\":1}";
     if (self.socket.readyState == SR_OPEN) {
 //        NSLog(@"heartbeatAction1111");
         self.pingCount = self.pingCount+1;
+        self.reconnetCount = self.reconnetCount+1;
         if(self.pingCount>5){//连续多次发送ping 没有收到回复,发起重连;
             [self.socket close];
             self.socket = nil;
@@ -168,6 +171,7 @@ static NSString *redeady = @"{\"code\":1}";
     else{
 //        NSLog(@"heartbeatAction222");
         self.pingCount = self.pingCount+1;
+        self.reconnetCount = self.reconnetCount+1;
         if(self.pingCount>5){//连续多次发送ping 没有收到回复,发起重连;
             [self.socket close];
             self.socket = nil;
@@ -183,25 +187,28 @@ static NSString *redeady = @"{\"code\":1}";
     if (!self.autoReconnect) {
         return;
     }
-    NSLog(@"reConnect1111---------");
-    NSString *token = [UDManager.shareInstance getSDManager:gkeytoken];
-    if([token isKindOfClass:[NSString class]]&&token.length>10){
-        [UserNetApi getUserinfo:^(int code, NSDictionary * res) {
-            NSNumber *gcode=res[@"code"];
-            NSLog(@"gcode11");
-            if([gcode intValue]==401){//token有效
-                [self logoutAct];
-            }
-            else{
+//    NSLog(@"reConnect1111---------:%ld",(long)self.reconnetCount);
+    if(self.reconnetCount>15){
+        NSString *token = [UDManager.shareInstance getSDManager:gkeytoken];
+        if([token isKindOfClass:[NSString class]]&&token.length>10){
+            [UserNetApi getUserinfo:^(int code, NSDictionary * res) {
+                NSNumber *gcode=res[@"code"];
+                NSLog(@"gcode11");
+                if([gcode intValue]==401){//token有效
+                    [self logoutAct];
+                }
+                else{
+                    self.socket = nil;
+                    [self initWebSocket];
+                }
+            } fail:^(NSError * _Nonnull error) {
+                NSLog(@"11%@", error);
                 self.socket = nil;
                 [self initWebSocket];
-            }
-        } fail:^(NSError * _Nonnull error) {
-            NSLog(@"11%@", error);
-            self.socket = nil;
-            [self initWebSocket];
-        }];
+            }];
+        }
     }
+    
 }
 
 
@@ -220,6 +227,7 @@ static NSString *redeady = @"{\"code\":1}";
         NSString *msg = (NSString *)message;
         NSError *error;
         self.pingCount = 0;
+        self.reconnetCount = 0;
         if([msg isEqual:ping]){
             if(self.isFirstload){//第一次打开socket数据加载完成需要执行的
                 
@@ -374,9 +382,8 @@ static NSString *redeady = @"{\"code\":1}";
             [mutablemsg setObject:msg[@"fromId"] forKey:@"chatId"];
         }
     }
-    
     [ChatsStore.shareInstance reciveMsg:mutablemsg];//聊天窗信息
-    [ChatListStore.shareInstance reciveMsg:(NSDictionary *)mutablemsg];//聊天窗列表
+    [ChatListStore.shareInstance reciveMsg:[mutablemsg copy]];//聊天窗列表
     [[NSNotificationCenter defaultCenter] postNotificationName:nkonNewMessageNote object:mutablemsg];
 }
 
@@ -411,6 +418,7 @@ static NSString *redeady = @"{\"code\":1}";
 
 //异地登录
 -(void)logoutAct{
+    NSLog(@"logoutAct");
     [UserNetApi logout:nil succ:^(int code, NSDictionary * res) {
 //        NSLog(@"res:%@",res);
         [[NSNotificationCenter defaultCenter] postNotificationName: nkonLogoutSucc object:nil];

+ 32 - 0
AIIM/AIIM/Common/Network/aliOSS/OSSManager.h

@@ -0,0 +1,32 @@
+//
+//  OSSManager.h
+//  AliyunOSSSDK-iOS-Example
+//
+//  Created by huaixu on 2018/10/23.
+//  Copyright © 2018 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <AliyunOSSiOS/AliyunOSSiOS.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSManager : NSObject
+
+@property (nonatomic, strong) OSSClient *defaultClient;
+
+@property (nonatomic, strong) OSSClient *imageClient;
+@property (nonatomic, strong) NSDictionary *OSSInfo;
+
++ (instancetype)sharedManager;
+
+-(void)getOSSInfo;
+//普通上传
+- (void)asyncPutFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime progress:(void (^)(NSInteger,NSString *))progress success:(void (^)(id _Nullable,NSString *))success failure:(void (^)(NSError * _Nonnull,NSString *))failure;
+
+//断点续传
+- (void)asyncResumableUploadFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime progress:(void (^)(NSInteger,NSString *))prgress success:(void (^)(id _Nullable,NSString *))success failure:(void (^)(NSError * _Nonnull,NSString *))failure;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 190 - 0
AIIM/AIIM/Common/Network/aliOSS/OSSManager.m

@@ -0,0 +1,190 @@
+//
+//  OSSManager.m
+//  AliyunOSSSDK-iOS-Example
+//
+//  Created by huaixu on 2018/10/23.
+//  Copyright © 2018 aliyun. All rights reserved.
+//
+
+#import "OSSManager.h"
+#import "OssNetApi.h"
+#import <AliyunOSSiOS/OSSService.h>
+
+// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
+#define endpoint @"https://oss-ap-southeast-1.aliyuncs.com"//生产服务器
+
+
+@interface OSSManager ()
+
+@property (nonatomic, strong) OSSPutObjectRequest *normalUploadRequest;
+
+@property (nonatomic, strong) OSSGetObjectRequest *normalDloadRequest;
+
+@end
+
+
+@implementation OSSManager
+
++ (instancetype)sharedManager {
+    static OSSManager *_manager = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _manager = [[OSSManager alloc] init];
+    });
+    
+    return _manager;
+}
+
+-(void)getOSSInfo{
+    
+    NSDictionary *dic = [UDManager.shareInstance getDDManager:nkOSSinfo];
+    if(dic){
+        self.OSSInfo = dic.copy;
+        [self initmyAliyunOSS];
+    }
+    
+    [OssNetApi getOSSInfo:nil succ:^(int code, NSDictionary * res) {
+        NSLog(@"res:%@",res);
+        NSString *codeV =res[@"code"];
+        if(codeV.intValue==200){
+            self.OSSInfo = res[@"data"];
+            if(self.OSSInfo){
+                [self initmyAliyunOSS];
+                [UDManager.shareInstance setDDManager:self.OSSInfo key:nkOSSinfo];
+            }
+        }
+    } fail:^(NSError * _Nonnull error) {
+        
+    }];
+}
+
+-(void)initmyAliyunOSS{
+    if(self.OSSInfo){
+        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
+        //NSString *endpoint = @"https://oss-ap-southeast-1.aliyuncs.com";
+   
+        // 旧版本图片服务的endpoint
+//        NSString *oldimgendpoint =  @"http://img-ap-southeast-1.aliyuncs.com";
+        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
+        NSString *accessKeyId = self.OSSInfo[@"accessKeyId"];
+        NSString *accessKeySecret = self.OSSInfo[@"accessKeySecret"];
+        // 从STS服务获取的安全令牌(SecurityToken)。
+        NSString *securityToken = self.OSSInfo[@"securityToken"];
+//        NSString *expiration = self.OSSInfo[@"expiration"];
+       
+        
+        id<OSSCredentialProvider> credentialProvider = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:accessKeyId secretKeyId:accessKeySecret securityToken:securityToken];
+        OSSClientConfiguration *cfg = [[OSSClientConfiguration alloc] init];
+        cfg.maxRetryCount = 3;
+        cfg.timeoutIntervalForRequest = 15;
+        cfg.isHttpdnsEnable = NO;
+        cfg.crc64Verifiable = YES;
+        
+        OSSClient *defaultClient = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credentialProvider clientConfiguration:cfg];
+        [OSSManager sharedManager].defaultClient = defaultClient;
+        //旧的图片服务
+//        OSSClient *defaultImgClient = [[OSSClient alloc] initWithEndpoint:oldimgendpoint credentialProvider:credentialProvider clientConfiguration:cfg];
+//        [OSSManager sharedManager].imageClient = defaultImgClient;
+    }
+}
+
+
+//普通上传
+- (void)asyncPutFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime progress:(void (^)(NSInteger,NSString *))prgress success:(void (^)(id _Nullable,NSString *))success failure:(void (^)(NSError * _Nonnull,NSString *))failure{
+    if([OSSManager sharedManager].defaultClient==nil){
+        [MBProgressHUD showWithText:@"OSS文件服务初始化失败!請重試"];
+        [self getOSSInfo];
+        return;
+    }
+    if (![objectKey oss_isNotEmpty]) {
+        NSError *error = [NSError errorWithDomain:NSInvalidArgumentException code:0 userInfo:@{NSLocalizedDescriptionKey: @"objectKey should not be nil"}];
+        failure(error,strtime);
+        return;
+    }
+    
+    NSLog(@"objectKey:%@",objectKey);
+    _normalUploadRequest = [OSSPutObjectRequest new];
+    _normalUploadRequest.bucketName = self.OSSInfo[@"bucket"];
+    _normalUploadRequest.objectKey = objectKey;
+    _normalUploadRequest.uploadingFileURL = [NSURL fileURLWithPath:filePath];
+    _normalUploadRequest.isAuthenticationRequired = YES;
+    _normalUploadRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
+        CGFloat progress = 1.f * totalByteSent / totalBytesExpectedToSend;
+//        NSLog(@"上传文件进度: %f", progress);
+        NSInteger pcent =progress*100;
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+            prgress(pcent,strtime);
+        });
+        
+    };
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        OSSTask * task = [[OSSManager sharedManager].defaultClient putObject:self->_normalUploadRequest];
+        [task continueWithBlock:^id(OSSTask *task) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if (task.error) {
+                    failure(task.error,strtime);
+                } else {
+                    success(task,strtime);
+                    NSLog(@"上传文件完成");
+                }
+            });
+            
+            return nil;
+        }];
+    });
+}
+
+//断点续传
+- (void)asyncResumableUploadFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime progress:(void (^)(NSInteger,NSString *))prgress success:(void (^)(id _Nullable,NSString *))success failure:(void (^)(NSError * _Nonnull,NSString *))failure{
+    
+    if([OSSManager sharedManager].defaultClient==nil){
+        [MBProgressHUD showWithText:@"OSS文件服务初始化失败!請重試"];
+        [self getOSSInfo];
+        return;
+    }
+    
+    // 获取UploadId上传文件。
+    OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];
+    resumableUpload.bucketName = self.OSSInfo[@"bucket"];
+    // objectKey等同于objectName,表示断点上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg
+    resumableUpload.objectKey = objectKey;
+    resumableUpload.partSize = 1024 * 1024;
+    resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
+        NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
+        CGFloat progress = 1.f * totalByteSent / totalBytesExpectedToSend;
+//        NSLog(@"上传文件进度: %f", progress);
+        NSInteger pcent =progress*100;
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+            prgress(pcent,strtime);
+        });
+    };
+    NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
+    // 设置断点记录保存路径。
+    resumableUpload.recordDirectoryPath = cachesDir;
+    // 将参数deleteUploadIdOnCancelling设置为NO,表示不删除断点记录文件,上传失败后将从断点记录处继续上传直到文件上传完成。如果不设置此参数,即保留默认值YES,表示删除断点记录文件,下次再上传同一文件时则重新上传。
+    resumableUpload.deleteUploadIdOnCancelling = NO;
+
+    resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:filePath];
+    OSSTask * resumeTask = [[OSSManager sharedManager].defaultClient resumableUpload:resumableUpload];
+    [resumeTask continueWithBlock:^id(OSSTask *task) {
+        if (task.error) {
+            NSLog(@"error: %@", task.error);
+            if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) {
+                // 此任务无法续传,需获取新的uploadId重新上传。
+                failure(task.error,strtime);
+            }
+        } else {
+            NSLog(@"Upload file success");
+            success(task,strtime);
+        }
+        return nil;
+    }];
+
+    // [resumeTask waitUntilFinished];
+
+    // [resumableUpload cancel];
+}
+
+
+
+@end

+ 19 - 0
AIIM/AIIM/Common/Network/aliOSS/OssNetApi.h

@@ -0,0 +1,19 @@
+//
+//  OssNetApi.h
+//  Pods
+//
+//  Created by gan on 2025/3/24.
+//
+
+#ifndef ChatNetApi_h
+#define ChatNetApi_h
+
+
+#endif /* OssNetApi_h */
+#import "GBaseNetApi.h"
+
+
+@interface OssNetApi : NSObject
+//获取OSS配置信息
++(void)getOSSInfo:(NSDictionary *_Nullable)parameters succ:(nullable GSucc)succ fail:(nullable GFail)fail;
+@end

+ 21 - 0
AIIM/AIIM/Common/Network/aliOSS/OssNetApi.m

@@ -0,0 +1,21 @@
+//
+//  OssNetApi.m
+//  TUIContact
+//
+//  Created by gan on 2025/3/24.
+//
+
+#import <Foundation/Foundation.h>
+#import "OssNetApi.h"
+
+
+@implementation OssNetApi
+
+
+//获取OSS配置信息
++(void)getOSSInfo:(NSDictionary *_Nullable)parameters succ:(nullable GSucc)succ fail:(nullable GFail)fail{
+    [GBaseNetApi.shareInstance httpGet:parameters url:@"http://newweb.abtim-my.com/api/oss/sts" succ:succ fail:fail];
+}
+
+
+@end

+ 117 - 32
AIIM/AIIM/Common/Store/ChatListStore.m

@@ -11,7 +11,8 @@
 #import "ChatNetApi.h"
 #import "UserNetApi.h"
 #import "GroupNetApi.h"
-
+#import <Bugly/Bugly.h>
+#import "CryptoAES.h"
 
 @interface ChatListStore()
 @property(nonatomic, strong) NSArray *toparray;
@@ -48,15 +49,19 @@
             self.chatlist =chats;
             self.toparray =chats;
         }
+        else{
+            self.toparray = @[];
+        }
         [self loadnmData:mark];
     } fail:^(NSString * _Nullable error) {
         [self loadnmData:mark];
     }];
+    
 }
 
 -(void)loadnmData:(BOOL)mark{
     [GDBManager.shareInstance selectLocalchats:@"'false'" succ:^(NSArray * _Nullable array) {
-//        NSLog(@"array:%@",array);
+        NSLog(@"array:%@",array);
         if(array.count>0){
             array = [self saveArray:array];
             NSMutableOrderedSet *orderedSet = [[NSMutableOrderedSet alloc] initWithArray:array];//去重,顺序不变
@@ -72,9 +77,12 @@
             }
             self.chatlist=reschats;
             if(self.delegate){
-                [self.delegate ChatListChange:reschats];
+                [self.delegate ChatListChange:reschats.copy];
             }
         }
+        else{
+            self.nmarray =@[];
+        }
         if(mark){
             [self getnmChatlist];
         }
@@ -107,9 +115,12 @@
 
 
 -(void)getnmChatlist{
+    NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
     [ChatNetApi getchats:nil succ:^(int code, NSDictionary * res) {
-//        NSLog(@"getnmChatlist res:%@",res);
+        NSLog(@"getnmChatlist res:%@",res);
         NSArray *netArray = res[@"data"];
+        
+        [Bugly reportException:[NSException exceptionWithName:[NSString stringWithFormat:@"getnmChatlist:%@",userinfo[@"name"]] reason:[NSString stringWithFormat:@"netArray:%lu",(unsigned long)netArray.count] userInfo:nil]];
         if(netArray.count>0){
             netArray = [self saveArray:netArray];
             netArray=[self arraysort:netArray];
@@ -118,10 +129,13 @@
             [self doWithNewList:chats];
 //            [self updatelcDB:chats top:@"false"];
         }
+        else{
+            [Bugly reportException:[NSException exceptionWithName:@"getchats--空" reason:userinfo[@"name"] userInfo:nil]];
+        }
         //NSLog(@"self.chatlist:%@",self.chatlist);
         
     } fail:^(NSError * _Nonnull error) {
-        
+        [Bugly reportException:[NSException exceptionWithName:@"getchats--失败" reason:[NSString stringWithFormat:@"error:%@",error] userInfo:nil]];
     }];
 }
 
@@ -205,6 +219,7 @@
             NSString *newtime =msg[@"timestamp"];
             NSString *dtime =item[@"lastTime"];
             NSString *count = item[@"unreadCount"];
+            
             if(addcount==0){
             }
             else{
@@ -226,6 +241,7 @@
                         @"top":item[@"top"]?:@"false"
                     };
                     [self updateChat:chatD isreload:YES];
+                    [self updataUserInfo:chatD];
                 }
             }
             else{
@@ -243,9 +259,12 @@
                         @"top":item[@"top"]?:@"false"
                     };
                     [self updateChat:chatD isreload:YES];
+                    [self updataUserInfo:chatD];
                 }
             }
             
+            
+            
             return;
         }
     }
@@ -253,13 +272,19 @@
 }
 
 -(void)updateChat:(NSDictionary *)chat isreload:(BOOL)reload{
+    
+    chat = [self encodingMsg:chat];
+    
 //    NSLog(@"1----------updateChat--------------");
+    NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
     [GDBManager.shareInstance insertLocalchat:chat succ:^(NSArray * _Nullable array) {
+        NSLog(@"111chat");
         if(self.delegate &&reload){
             [self reloadData:false];
         }
     } fail:^(NSString * _Nullable error) {
-        ;
+        NSLog(@"111222chat");
+        [Bugly reportException:[NSException exceptionWithName:[NSString stringWithFormat:@"insertLocalchat fail:%@",userinfo[@"name"]] reason:[NSString stringWithFormat:@"error:%@",chat] userInfo:nil]];
     }];
 }
 
@@ -273,7 +298,7 @@
     }
     NSString *countstr = [NSString stringWithFormat:@"%ld",(long)addcount];
     NSString *lastMsg = [self setLastMsg:msg];
-    if([msg[@"type"] isEqual:@"0"]){//友聊
+    if([msg[@"type"] isEqualToString:@"0"]){//友聊
         [UserNetApi getUserinfo_id:msg[@"chatId"] succ:^(int code, NSDictionary * res) {
             NSDictionary * userinfo=res[@"data"];
             if(userinfo){
@@ -346,6 +371,52 @@
     }
 }
 
+-(void)updataUserInfo:(NSDictionary *)chatDis{
+    NSString *type = chatDis[@"type"];
+    NSString *chatId = chatDis[@"id"];
+    
+    NSString *oldName = chatDis[@"name"];
+    NSString *oldavatar = chatDis[@"avatar"];
+    
+    if([type isEqualToString:@"0"]){//友聊
+        [UserNetApi getUserinfo_id:chatId succ:^(int code, NSDictionary * res) {
+            NSDictionary * userinfo=res[@"data"];
+            if(userinfo){
+                if([oldName isEqualToString:userinfo[@"name"]]&&[oldavatar isEqualToString:userinfo[@"avatar"]]){
+                    return;
+                }else{
+                    NSMutableDictionary *mdic = [chatDis mutableCopy];
+                    [mdic setObject:userinfo[@"name"] forKey:@"name"];
+                    [mdic setObject:userinfo[@"avatar"] forKey:@"avatar"];
+                    [self updateChat:mdic isreload:YES];
+                }
+            }
+        } fail:^(NSError * _Nonnull error) {
+            
+        }];
+    }
+    else{
+        [GroupNetApi getGroupInfo:chatId succ:^(int code, NSDictionary * res) {
+            NSLog(@"getGroupInfo:%@",res);
+            NSDictionary * userinfo=res[@"data"];
+            if(userinfo){
+                if([oldName isEqualToString:userinfo[@"name"]]&&[oldavatar isEqualToString:userinfo[@"avatar"]]){
+                    return;
+                }else{
+                    NSMutableDictionary *mdic = [chatDis mutableCopy];
+                    [mdic setObject:userinfo[@"name"] forKey:@"name"];
+                    [mdic setObject:userinfo[@"avatar"] forKey:@"avatar"];
+                    [self updateChat:mdic isreload:YES];
+                }
+            }
+            else{
+            }
+        } fail:^(NSError * _Nonnull error) {
+           
+        }];
+    }
+}
+
 - (void)deleteChat:(NSDictionary *_Nonnull)chat{
     weakSelf(self);
     [GDBManager.shareInstance deleteChatListItem:chat succ:^(NSArray * _Nullable array) {
@@ -356,6 +427,8 @@
     } fail:^(NSString * _Nullable error) {
         NSLog(@"error:%@",error);
     }];
+    [GDBManager.shareInstance deletechatLocalmsg:chat[@"id"]];
+    
 }
 
 -(NSString *)setLastMsg:(NSDictionary *)msg{
@@ -398,8 +471,8 @@
     BOOL notHadChat=YES;
     NSString *chatid = chatmsg[@"chatId"];
     for (NSDictionary *item in self.chatlist) {
-//        NSLog(@"item:%@",item);
         if([chatid isEqualToString:item[@"id"]]){//窗口已经存在
+            NSLog(@"窗口已经存在:%@",item);
             notHadChat=NO;
             NSString *countstr = @"0";
             NSDictionary *chatD=@{
@@ -424,7 +497,8 @@
 }
 
 -(void)tryToCreateChate:(NSDictionary *_Nonnull)chatmsg{
-    
+    NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
+    [Bugly reportException:[NSException exceptionWithName:@"tryToCreateChate" reason:userinfo[@"name"] userInfo:nil]];
     NSDate *now = [NSDate date];
     NSTimeInterval trt = [now timeIntervalSince1970];
     NSInteger time = trt*1000;
@@ -534,10 +608,10 @@
                     NSString *dtime =oitem[@"lastTime"];
                     if(newtime.longLongValue>=dtime.longLongValue){
                         NSDictionary *chatD=@{
-                            @"id":safeDict[@"id"],
-                            @"name":safeDict[@"name"]?:@"",
-                            @"avatar":safeDict[@"avatar"]?:@"",
-                            @"type":safeDict[@"type"]?:@"",
+                            @"id":oitem[@"id"],
+                            @"name":oitem[@"name"]?:@"",
+                            @"avatar":oitem[@"avatar"]?:@"",
+                            @"type":oitem[@"type"]?:@"",
                             @"lastMessage":safeDict[@"lastMessage"]?:@"",
                             @"lastTime":safeDict[@"lastTime"]?:@"",
                             @"unreadCount":safeDict[@"unreadCount"]?:@"",
@@ -546,6 +620,7 @@
                             @"top":oitem[@"top"]?:@"false",
                         };
                         NSLog(@"chatD:%@",chatD);
+                        chatD = [self encodingMsg:chatD];
                         NSInteger index = [self.toparray indexOfObject:oitem];
                         [topArray replaceObjectAtIndex:index withObject:chatD];
                         [self updateToDBonly:chatD];
@@ -553,20 +628,7 @@
                 }
             }
             if(mark){
-                NSDictionary *chatD=@{
-                    @"id":safeDict[@"id"],
-                    @"name":safeDict[@"name"]?:@"",
-                    @"avatar":safeDict[@"avatar"]?:@"",
-                    @"type":safeDict[@"type"]?:@"",
-                    @"lastMessage":safeDict[@"lastMessage"]?:@"",
-                    @"lastTime":safeDict[@"lastTime"]?:@"",
-                    @"unreadCount":safeDict[@"unreadCount"]?:@"",
-                    @"loaded":@"",
-                    @"loading":@"",
-                    @"top":@"true",
-                };
-                [tempArray addObject:chatD];
-                [self updateToDBonly:chatD];
+                [tempArray addObject:item];
             }
         }
     }
@@ -580,19 +642,22 @@
                 NSDictionary * safeDict = [self replaceNullsWithEmptyStringInDictionary:item];
                 mark=YES;
                 NSString *newtime =safeDict[@"lastTime"];
+                NSLog(@"000000000");
                 if (newtime.intValue==0) {
                     continue;
                 }
                 for(NSDictionary *oitem in self.nmarray){
                     if([safeDict[@"id"] isEqualToString:oitem[@"id"]]){
+                        NSLog(@"1111111111");
                         mark=NO;
                         NSString *dtime =oitem[@"lastTime"];
                         if(newtime.longLongValue>=dtime.longLongValue){
+                            NSLog(@"2222222");
                             NSDictionary *chatD=@{
-                                @"id":safeDict[@"id"],
-                                @"name":safeDict[@"name"]?:@"",
-                                @"avatar":safeDict[@"avatar"]?:@"",
-                                @"type":safeDict[@"type"]?:@"",
+                                @"id":oitem[@"id"],
+                                @"name":oitem[@"name"]?:@"",
+                                @"avatar":oitem[@"avatar"]?:@"",
+                                @"type":oitem[@"type"]?:@"",
                                 @"lastMessage":safeDict[@"lastMessage"]?:@"",
                                 @"lastTime":safeDict[@"lastTime"]?:@"",
                                 @"unreadCount":safeDict[@"unreadCount"]?:@"",
@@ -601,6 +666,7 @@
                                 @"top":oitem[@"top"]?:@"false",
                             };
                             NSLog(@"chatD:%@",chatD);
+                            chatD = [self encodingMsg:chatD];
                             NSInteger index = [self.nmarray indexOfObject:oitem];
                             [nmArray replaceObjectAtIndex:index withObject:chatD];
                             [self updateToDBonly:chatD];
@@ -620,6 +686,7 @@
                         @"loading":@"",
                         @"top":@"false",
                     };
+                    chatD = [self encodingMsg:chatD];
                     [nmArray addObject:chatD];
                     [self updateToDBonly:chatD];
                 }
@@ -629,6 +696,7 @@
             NSArray  *arr= [self replaceNullsWithEmptyStringInArray:tempArray];
 //            nmArray=[arr mutableCopy];
             for (NSDictionary *item in arr) {
+                NSLog(@"3333333");
                 NSString *lastT =item[@"lastTime"];
                 if(lastT.intValue==0){
                     continue;
@@ -645,6 +713,7 @@
                     @"loading":@"",
                     @"top":@"false",
                 };
+                chatD = [self encodingMsg:chatD];
                 [nmArray addObject:chatD.copy];
                 [self updateToDBonly:chatD];
             }
@@ -659,6 +728,7 @@
 }
 
 -(void)updateToDBonly:(NSDictionary *)chat{
+    chat = [self encodingMsg:chat];
     [GDBManager.shareInstance insertLocalchat:chat succ:^(NSArray * _Nullable array) {
     } fail:^(NSString * _Nullable error) {
         ;
@@ -684,8 +754,13 @@
     }
     self.chatlist =reschats.copy;
     if(self.delegate){
-        [self.delegate ChatListChange:reschats];
+        [self.delegate ChatListChange:reschats.copy];
+        [Bugly reportException:[NSException exceptionWithName:@"postdataToView--1" reason:[NSString stringWithFormat:@"reschats:%lu",(unsigned long)reschats.count] userInfo:nil]];
     }
+    else{
+        [Bugly reportException:[NSException exceptionWithName:@"postdataToView--2" reason:[NSString stringWithFormat:@"reschats:%lu",(unsigned long)reschats.count] userInfo:nil]];
+    }
+    
 }
 
 
@@ -730,6 +805,16 @@
     return [NSArray arrayWithArray:mutableArray];
 }
 
+
+//信息解密存储
+-(NSDictionary *)encodingMsg:(NSDictionary *)msg{
+    NSMutableDictionary *temp = [msg mutableCopy];
+    NSString *content = msg[@"lastMessage"];
+    content = [CryptoAES.shareInstance decryptDataL:content?: @""];
+    [temp setObject:content forKey:@"lastMessage"];
+    return [temp copy];
+}
+
 @end
 
 

+ 27 - 9
AIIM/AIIM/Common/Store/ChatsStore.m

@@ -13,6 +13,7 @@
 #import "UDManager.h"
 #import "GWebSocket.h"
 #import "ChatListStore.h"
+#import "CryptoAES.h"
 
 
 @implementation ChatsStore
@@ -36,8 +37,9 @@
 
 -(void)reciveMsg:(NSDictionary *_Nonnull)msg{
     
-    NSString *mine = msg[@"mine"];
+    msg = [self encodingMsg:msg];
     
+    NSString *mine = msg[@"mine"];
     if(mine.boolValue){
         [self deleteMineTmpMsg:msg];
     }
@@ -55,6 +57,9 @@
         if(!m.boolValue){
             [[GWebSocket shareInstance] sendRecNote:msg];
         }
+        else{
+//            [[GWebSocket shareInstance] sendRecNote:msg];
+        }
     } fail:^(NSString * _Nullable error) {
         //插入数据库成功
     }];
@@ -111,22 +116,22 @@
 
 
 -(void)reloadData:(NSString *_Nonnull)chatId type:(NSInteger)type{
-    NSLog(@"chatId:%@,%ld",chatId,(long)type);
+//    NSLog(@"chatId:%@,%ld",chatId,(long)type);
     [self reloadData:chatId];
     [ChatNetApi getOutLineMsg:chatId type:type succ:^(int code, NSDictionary *res) {
         NSArray *array = res[@"data"];
-        NSLog(@"getOutLineMsg2 res:%lu",(unsigned long)array.count);
+//        NSLog(@"getOutLineMsg2 res:%lu",(unsigned long)array.count);
         if(array.count>0){
             NSMutableArray *tempArray = [[NSMutableArray alloc] init];
             for (NSDictionary *msg in array) {
-                
-                NSMutableDictionary *mutablemsg = [msg mutableCopy];
+                NSDictionary *enmsg = [self encodingMsg:msg];
+                NSMutableDictionary *mutablemsg = [enmsg mutableCopy];
                 if([self.userid isEqual:mutablemsg[@"fromId"]]){
                     [mutablemsg setObject:[NSNumber numberWithBool:YES] forKey:@"mine"];
                 }else{
-                    if([@"0" isEqual:msg[@"type"]]){//友聊
-                        [mutablemsg setObject:msg[@"fromId"] forKey:@"chatId"];
-                        NSLog(@"-----1-------友聊:%@",mutablemsg);
+                    if([@"0" isEqual:enmsg[@"type"]]){//友聊
+                        [mutablemsg setObject:enmsg[@"fromId"] forKey:@"chatId"];
+//                        NSLog(@"-----1-------友聊:%@",mutablemsg);
                     }
                 }
                 [tempArray addObject:mutablemsg];
@@ -157,7 +162,8 @@
         if(array.count>0){
             NSMutableArray *tempArray = [[NSMutableArray alloc] init];
             for (NSDictionary *msg in array) {
-                NSMutableDictionary *mutablemsg = [msg mutableCopy];
+                NSDictionary *enmsg = [self encodingMsg:msg];
+                NSMutableDictionary *mutablemsg = [enmsg mutableCopy];
                 if([self.userid isEqual:mutablemsg[@"fromId"]]){
                     [mutablemsg setObject:[NSNumber numberWithBool:YES] forKey:@"mine"];
                 }
@@ -517,4 +523,16 @@
     }
 }
 
+
+//信息解密存储
+-(NSDictionary *)encodingMsg:(NSDictionary *)msg{
+    NSMutableDictionary *temp = [msg mutableCopy];
+    NSString *content = msg[@"content"];
+    content = [CryptoAES.shareInstance decryptDataL:content?: @""];
+    [temp setObject:content forKey:@"content"];
+    return [temp copy];
+}
+
+
+
 @end

+ 329 - 120
AIIM/AIIM/Controller/chat/ChatController.m

@@ -43,6 +43,8 @@
 #import "MentionTextView.h"
 #import "TopPopupView.h"
 
+#import "OSSManager.h"
+
 static const CGFloat kQuoteViewHeight = 46.0f;
 @interface ChatController()<UITextViewDelegate,ChatsStoreDelegate,UITableViewDelegate,UITableViewDataSource,chatpopViewDelegate,PHPickerViewControllerDelegate,UINavigationControllerDelegate,UIDocumentPickerDelegate,UIScrollViewDelegate>
 
@@ -94,6 +96,8 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 @property (nonatomic, strong) NSMutableArray * atSomeoneArray;
 @property (nonatomic, assign) BOOL isBatchMode;
 
+@property (nonatomic, assign) BOOL showLoading;
+
 
 
 @end
@@ -190,6 +194,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
     ChatsStore.shareInstance.userid =self.userId;
     ChatListStore.shareInstance.chatId = self.chatId;
     [ChatsStore.shareInstance getchatReadTime:self.chatId];
+    _showLoading = YES;
     NSString *type=@"";
     if(self.type==0){
         type=@"0";
@@ -216,7 +221,6 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 }
 
 -(void)reloadAllData{
-    
     [self.messageArray removeAllObjects];
     self.msgList = @[];
     [__tableView reloadData];
@@ -349,6 +353,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 
 
 - (IBAction)fanhui:(id)sender {
+    NSLog(@"fanhui-------");
     [self dismissViewControllerAnimated:YES completion:nil];
 }
 - (IBAction)rightBt:(id)sender {
@@ -437,7 +442,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 }
 
 -(void)ChatsChange:(NSArray *)msgList type:(NSInteger)typpe{
-//    NSLog(@"msgList:%@",msgList.lastObject);
+    NSLog(@"msgList:%@",msgList);
     if([msgList count]==0){
         return;
     }
@@ -463,6 +468,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 //    NSLog(@"self.msgList11:%@",self.msgList);
     NSMutableArray * tempArray = [NSMutableArray array];
     for (NSDictionary * msg in self.msgList) {
+//        NSLog(@"msg:%@",msg);
         ChatMessageModel *message = [ChatMessageModel modelWithDictionary:msg];
         if (message.avatar.length==0 && message.isSender) {
             message.avatar = self.useravatar;
@@ -473,13 +479,14 @@ static const CGFloat kQuoteViewHeight = 46.0f;
             [tempArray addObject:message];
         }
     }
-//    NSLog(@"----222---:coun-------");
+//    NSLog(@"----222---:coun-------:%lu",(unsigned long)tempArray.count);
     NSMutableArray * indexPathArray = [NSMutableArray array];
     BOOL isHistoryRecord = NO;
     if (self.messageArray.count == 0) {
-//        NSLog(@"----222---:count == 0");
+        
         [self.messageArray removeAllObjects];
         [self.messageArray addObjectsFromArray:tempArray];
+//        NSLog(@"----222---:count ==%lu",(unsigned long)self.messageArray.count);
         //禁用隐式动画 加载历史消息
         [CATransaction begin];
         [CATransaction setDisableActions:YES];
@@ -495,7 +502,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
         
         for (ChatMessageModel *message in tempArray) {
             BOOL isContain = NO;
-//            NSLog(@"----333---:%@",message.content);
+//            NSLog(@"----333---:%ld",(long)message.localtime);
             for (ChatMessageModel * localMessage in self.messageArray) {
                 if (localMessage.localtime==message.localtime) {
                     isContain = YES;
@@ -565,6 +572,9 @@ static const CGFloat kQuoteViewHeight = 46.0f;
         }
         return;
     }
+    
+//    NSLog(@"----222444---:count ==%lu",(unsigned long)self.messageArray.count);
+    
     if (isHistoryRecord) {
         // 执行插入操作(禁用动画)
         for (NSIndexPath * index in indexPathArray) {
@@ -601,7 +611,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
             CGFloat visibleHeight = self._tableView.bounds.size.height - self._tableView.contentInset.top - self._tableView.contentInset.bottom;
             CGFloat yOffset = self._tableView.contentOffset.y;
             CGFloat threshold = MAX(20, visibleHeight * 0.8); // 距离底部20点或20%可见高度
-            
+//            NSLog(@"threshold:%f,%f",threshold,self._tableView.contentSize.height - yOffset - visibleHeight);
             BOOL shouldScrollToBottom = (self._tableView.contentSize.height - yOffset - visibleHeight) <= threshold;
             if (shouldScrollToBottom) {
                 [CATransaction begin];
@@ -619,6 +629,13 @@ static const CGFloat kQuoteViewHeight = 46.0f;
             _canloadhistory = false;
         }
     }
+    
+    if(self.messageArray.count>20){
+        _showLoading = false;
+    }
+    else{
+        _showLoading = true;
+    }
 
     
 }
@@ -665,22 +682,29 @@ static const CGFloat kQuoteViewHeight = 46.0f;
     NSLog(@"setupPreloader");
     self.preloader = [[HistoryPreloader alloc] init];
     self.preloader.tableView = self._tableView;
-    self.preloader.threshold = 800;
+    self.preloader.threshold = 700;
     weakSelf(self);
     self.preloader.loadBlock = ^{
         
         if (!weakself.canloadhistory) {
-//            NSLog(@"preloader.loadBlock 1");
             return;
         }
-//        NSLog(@"preloader.loadBlock 2");
         [weakself loadhistoryData];
     };
+
+    self.preloader.toofast = ^{
+        if (weakself.showLoading) {
+        }else{
+            weakself.showLoading = YES;
+//            [MBProgressHUD showLoadingWithText:@"數據解密中。。。。"  inView:weakself.view hideAfterDelay:2];
+        }
+    };
+    
 }
 
 -(void)loadhistoryData{
     if(self.messageArray.count>0){
-//        NSLog(@"loadhistoryData-------");
+        NSLog(@"loadhistoryData-------");
         _canloadhistory = false;
         if(self.type==0){
             ChatMessageModel *eldata = self.messageArray[0];
@@ -692,8 +716,6 @@ static const CGFloat kQuoteViewHeight = 46.0f;
             NSInteger time =eldata.timestamp;
             [ChatsStore.shareInstance loadQunNextData:self.chatId timestp:time];
         }
-        
-        
     }
 }
 
@@ -718,6 +740,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
     cell.parentViewController = self;
     cell.isHistory = false;
     ChatMessageModel *message = self.messageArray[indexPath.row];
+//    NSLog(@"---:%ld,%@",(long)message.localtime,message.content);
     weakSelf(self);
     cell.bubbleCellLongPressMenuBlock = ^(NSInteger index) {
         switch (index) {
@@ -752,7 +775,11 @@ static const CGFloat kQuoteViewHeight = 46.0f;
                 break;
             case 7:
                 NSLog(@"------保存------");
-                
+                [weakself saveFile:message];
+                break;
+            case 8:
+                NSLog(@"------文件视频图片重新上传------");
+                [weakself resendFile:message];
                 break;
             case 99:
 //                NSLog(@"------长按开始------");
@@ -765,7 +792,12 @@ static const CGFloat kQuoteViewHeight = 46.0f;
     };
     cell.batchSelectedStateBlock = ^(BOOL isSelected) {
         if (isSelected) {
-            [weakself.forwordMsgArray addObject:message.formerMessage];
+            
+            NSMutableDictionary *dic =message.formerMessage.mutableCopy;
+            NSString *coontent = dic[@"content"]?:@"";
+            coontent =[CryptoAES.shareInstance encryptStringL:coontent];
+            [dic setObject:coontent forKey:@"content"];
+            [weakself.forwordMsgArray addObject:dic];
         }else{
             [weakself.forwordMsgArray removeObject:message.formerMessage];
         }
@@ -846,6 +878,76 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 }
 
 
+-(void)saveFile:(ChatMessageModel *)msgMdl{
+    
+    NSString *localPath =msgMdl.localurl;
+    if (localPath && [[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
+        NSLog(@"本地路径");
+        NSString *fileExtension = [[msgMdl.localurl pathExtension] lowercaseString];
+        if([self isVideoFile:fileExtension]){
+            NSURL *fileURL = [NSURL fileURLWithPath:localPath];
+            [self saveVideoToPhotoLibrary:fileURL];
+        }
+        else{
+            [self saveFileToLibrary:localPath];
+        }
+    }
+    else{
+        [MBProgressHUD showWithText:@"文件尚未加载完成,请稍后重试"];
+    }
+    
+    
+}
+
+- (BOOL)isVideoFile:(NSString *)fileExtension {
+    NSArray *videoExtensions = @[@"mp4", @"mov", @"m4v", @"avi", @"mkv", @"flv", @"wmv"];
+    return [videoExtensions containsObject:fileExtension];
+}
+
+
+- (void)saveVideoToPhotoLibrary:(NSURL *)videoURL {
+    // 检查 PHPhotoLibrary 的授权状态
+    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
+        if (status == PHAuthorizationStatusAuthorized) {
+            // 授权成功,保存视频
+            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
+                // 创建资产更改请求
+                PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:videoURL];
+                // 可以设置其他属性,如位置信息等
+                // [assetChangeRequest setLocation:location];
+            } completionHandler:^(BOOL success, NSError *error) {
+                if (success) {
+                    NSLog(@"视频保存成功");
+                    dispatch_async(dispatch_get_main_queue(), ^{
+                        [self showNot:@"保存到手机成功"];
+                    });
+                    
+                } else {
+                    NSLog(@"视频保存失败: %@", error.localizedDescription);
+                }
+            }];
+        } else {
+            // 授权失败或未授权,处理用户未授权的情况
+            NSLog(@"请在设置中授权访问相册");
+        }
+    }];
+}
+
+-(void)showNot:(NSString *)str{
+    [MBProgressHUD showWithText:str];
+}
+
+
+-(void)saveFileToLibrary:(NSString *)fileUrl{
+    NSURL *fileURL = [NSURL fileURLWithPath:fileUrl];
+
+    UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
+    [documentController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
+}
+
+
+
+
 #pragma mark UITextViewDelegate
 - (void)textViewDidChange:(UITextView *)textView {
     NSLog(@"textViewDidChange---");
@@ -985,6 +1087,8 @@ static const CGFloat kQuoteViewHeight = 46.0f;
     _keybarShow=false;
 }
 
+
+
 -(void)dismissKeyboard{
     [self.view endEditing:YES];
 }
@@ -1483,7 +1587,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
     
     if (urls.count > 9) {
         //选择文件最多 9 个
-        [MBProgressHUD showWithText:@"一次最多上传 9 个文件"];
+        [MBProgressHUD showWithText:@"一次最多上傳 9 個檔案"];
         
     }
     
@@ -1499,27 +1603,10 @@ static const CGFloat kQuoteViewHeight = 46.0f;
         model.filePath = [url path];
         [fileArray addObject:model];
     }
-    
-    //无异常,走上传流程
-    for (ChatFileModel * model in fileArray) {
-        NSString *strtime = [self getLocalTime];
-        [self uploadFile:[NSString stringWithFormat:@"%@",model.fileURL] fpath:model.filePath state:1 act:1 localtime:strtime];
-        
-        [FileNetApi uploadWithFilePath:model.fileURL thrid:strtime progress:^(NSString * _Nullable thrid, NSProgress * _Nullable uploadProgress) {
-            
-        } succ:^(int code, NSString * _Nullable thrid, NSDictionary * dis) {
-            NSString *reCode =dis[@"code"];
-            if(reCode.intValue==200){
-                NSLog(@"上传成功:%@",dis[@"url"]);
-                [self uploadFile:dis[@"url"] fpath:model.filePath state:1 act:2 localtime:thrid];
-            }
-            else{
-                NSLog(@"上传失败");
-            }
-        } fail:^(NSString * _Nullable thrid, NSError * _Nonnull error) {
-            NSLog(@"上传失败");
-        }];
-    }
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [self handleMediaData:fileArray];
+    });
+   
 }
 
 
@@ -1527,37 +1614,122 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 - (void)handleMediaData:(NSArray *)mediaArray{
     
 //    NSMutableArray * tempArray = [NSMutableArray array];
-    
-    
         NSArray *sorArray = [self fileArraysort:mediaArray];
         
         for (ChatFileModel * model in sorArray) {
             NSString *strtime = [self getLocalTime];
-//            NSLog(@"------fileSize:%@",model.fileSize);
             [self uploadFile:[NSString stringWithFormat:@"%@",model.fileURL] fpath:model.filePath state:1 act:1 localtime:strtime];
-            //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-                [FileNetApi uploadWithFilePath:model.fileURL thrid:strtime progress:^(NSString *_Nullable thrid,NSProgress * _Nullable uploadProgress) {
+            [self OSSuploadFile:model thrid:strtime];
+////            NSLog(@"------fileSize:%@",model.fileSize);
+//            [self uploadFile:[NSString stringWithFormat:@"%@",model.fileURL] fpath:model.filePath state:1 act:1 localtime:strtime];
+//            //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+////            [FileNetApi uploadWithFilePath:model.fileURL thrid:strtime progress:^(NSString *_Nullable thrid,NSProgress * _Nullable uploadProgress) {
+//                [FileNetApi OSSuploadWithFilePath:model.fileURL thrid:strtime progress:^(NSString *_Nullable thrid,NSProgress * _Nullable uploadProgress) {
 //                    NSLog(@"thrid:%@,%@",thrid,uploadProgress);
-                } succ:^(int code, NSString *_Nullable thrid,NSDictionary * _Nullable dis) {
-                    NSString *reCode =dis[@"code"];
-                    if(reCode.intValue==200){
-                        NSLog(@"上传成功:%@",dis[@"url"]);
-                        [self uploadFile:dis[@"url"] fpath:model.filePath state:1 act:2 localtime:thrid];
-                    }
-                    else{
-                        NSLog(@"上传失败");
-                    }
-                } fail:^(NSString *_Nullable thrid,NSError * _Nonnull error) {
-                    NSLog(@"上传失败");
-                    [self uploadFilefail:thrid];
-                }];
-            //});
+//                    [self updatajidu:thrid uploadProgress:uploadProgress];
+//                } succ:^(int code, NSString *_Nullable thrid,NSDictionary * _Nullable dis) {
+//                    NSString *reCode =dis[@"code"];
+//                    if(reCode.intValue==200){
+//                        NSLog(@"上传成功:%@",dis[@"url"]);
+//                        [self uploadFile:dis[@"url"] fpath:model.filePath state:1 act:2 localtime:thrid];
+//                    }
+//                    else{
+//                        NSLog(@"上传失败");
+//                        [self uploadFilefail:thrid];
+//                    }
+//                } fail:^(NSString *_Nullable thrid,NSError * _Nonnull error) {
+//                    NSLog(@"上传失败");
+//                    [self uploadFilefail:thrid];
+//                }];
+//            //});
         }
 }
 
+
+
+
+-(void)OSSuploadFile:(ChatFileModel *)model thrid:(NSString *)strtime{
+//    普通上传
+//    [OSSManager.sharedManager asyncPutFile:model.fileURL.lastPathComponent localFilePath:model.filePath thrid:strtime progress:^(NSInteger pcent, NSString * loacaltime) {
+//        [self Ossupdatajidu:loacaltime uploadProgress:pcent];
+//    } success:^(id res, NSString * loacaltime) {
+//        [self uploadFile:model.fileURL.lastPathComponent fpath:model.filePath state:1 act:2 localtime:loacaltime];
+//    } failure:^(NSError * error, NSString * loacaltime) {
+//        [self uploadFilefail:loacaltime];
+//    }];
+   
+//    断点续传
+    [OSSManager.sharedManager asyncResumableUploadFile:model.fileURL.lastPathComponent localFilePath:model.filePath thrid:strtime progress:^(NSInteger pcent, NSString * loacaltime) {
+        [self Ossupdatajidu:loacaltime uploadProgress:pcent];
+    } success:^(id res, NSString * loacaltime) {
+        [self uploadFile:model.fileURL.lastPathComponent fpath:model.filePath state:1 act:2 localtime:loacaltime];
+    } failure:^(NSError * error, NSString * loacaltime) {
+        [self uploadFilefail:loacaltime];
+    }];
+    
+}
+
+-(void)resendFile:(ChatMessageModel *)msg{
+    
+    NSString *strtime = [NSString stringWithFormat:@"%ld",(long)msg.localtime];
+    NSString *loaclFile = [NSString stringWithFormat:@"file://%@",msg.localurl];
+    NSURL *fileURL = [NSURL URLWithString:loaclFile];
+    
+    [FileNetApi OSSuploadWithFilePath:fileURL thrid:strtime progress:^(NSString *_Nullable thrid,NSProgress * _Nullable uploadProgress) {
+        NSLog(@"thrid:%@,%@",thrid,uploadProgress);
+        [self updatajidu:thrid uploadProgress:uploadProgress];
+    } succ:^(int code, NSString *_Nullable thrid,NSDictionary * _Nullable dis) {
+        NSString *reCode =dis[@"code"];
+        if(reCode.intValue==200){
+            NSLog(@"上传成功:%@",dis[@"url"]);
+            [self uploadFile:dis[@"url"] fpath:msg.localurl state:1 act:2 localtime:thrid];
+        }
+        else{
+            NSLog(@"上传失败");
+            [self uploadFilefail:thrid];
+        }
+    } fail:^(NSString *_Nullable thrid,NSError * _Nonnull error) {
+        NSLog(@"上传失败");
+        [self uploadFilefail:thrid];
+    }];
+    
+    [GDBManager.shareInstance selectLocalmsgWithLocaltime:strtime succ:^(NSArray * _Nullable array) {
+        NSLog(@"selectLocalmsgWithLocaltime:%@",array);
+        
+        if(array){
+            if(array.count>0){
+                NSDictionary *msg =array[0];
+                NSString *msgtype = msg[@"messageType"];
+                
+                if (([msgtype isEqualToString:MessageType_Del]||[msgtype isEqualToString:MessageType_CallBack2])) {
+                    return;
+                }
+                NSString *strtime = [self getLocalTime];
+                NSDictionary *extend=msg[@"extend"];
+                NSMutableDictionary *mextend = [extend mutableCopy];
+                [mextend setObject:[NSNumber numberWithInt:0] forKey:@"fileError"];
+                NSMutableDictionary *mmsg = [msg mutableCopy];
+                [mmsg setObject:mextend forKey:@"extend"];
+                [ChatsStore.shareInstance reciveMsg:mmsg];
+            }
+        }
+    } fail:^(NSString * _Nullable error) {
+        ;
+    }];
+}
+
+
 -(void)uploadFile:(NSString *)url fpath:(NSString *)path state:(NSInteger)state act:(NSInteger)act localtime:(NSString *)localtime{
     
-    NSURL *filePath =[NSURL URLWithString:url]; //
+    NSURL *filePath;
+    if([url containsString:@"http"]){
+        filePath=[NSURL URLWithString:url]; //
+    }
+    else{
+        NSString *filestr = [NSString stringWithFormat:@"http://oss.abtim-my.com/%@",url];
+        filePath=[NSURL URLWithString:filestr]; //
+    }
+    
     NSString *content=@"【文件】";
     NSString *messageType=MessageType_file;
     NSDictionary *extend;
@@ -1632,18 +1804,27 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 //            NSLog(@"%@", jsonString);
             NSLog(@"----发送文件消息----%@",localtime);
             //self.ismyTurn = YES;
-            [GWebSocket.shareInstance sendMsg:jsonString];
+            //[GWebSocket.shareInstance sendMsg:jsonString];
         }
         [self movetoBotton];
     }
     if(act==2){
-        [self uploadFileSucc:url localtime:localtime];
+        if(url){
+            [self uploadFileSucc:url localtime:localtime];
+        }
+        else{
+            
+        }
     }
 }
 
 
 -(void)uploadFileSucc:(NSString *)url localtime:(NSString *)localtime{
-    NSURL *filePath =[NSURL URLWithString:url]; //
+    
+    if(![url containsString:@"http"]){
+        url = [NSString stringWithFormat:@"http://oss.abtim-my.com/%@",url];
+    }
+    NSURL *filePath = [NSURL URLWithString:url];
     
     [GDBManager.shareInstance selectLocalmsgWithLocaltime:localtime succ:^(NSArray * _Nullable array) {
 //        NSLog(@"selectLocalmsgWithLocaltime:%@",array);
@@ -1656,6 +1837,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
                 [mextend setObject:filePath.lastPathComponent forKey:@"fileName"];
                 NSMutableDictionary *mmsg = [msg mutableCopy];
                 [mmsg setObject:mextend forKey:@"extend"];
+                [mmsg setObject:@"" forKey:@"id"];
                 NSDictionary *sendInfo = @{
                     @"code":@"2",
                     @"message":mmsg,
@@ -1680,9 +1862,9 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 }
 
 -(void)uploadFilefail:(NSString *)localtime{
-   
+    NSLog(@"uploadFilefail----:%@",localtime);
     [GDBManager.shareInstance selectLocalmsgWithLocaltime:localtime succ:^(NSArray * _Nullable array) {
-//        NSLog(@"selectLocalmsgWithLocaltime:%@",array);
+        NSLog(@"selectLocalmsgWithLocaltime:%@",array);
         
         if(array){
             if(array.count>0){
@@ -1692,7 +1874,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
                 if (([msgtype isEqualToString:MessageType_Del]||[msgtype isEqualToString:MessageType_CallBack2])) {
                     return;
                 }
-                
+                NSString *strtime = [self getLocalTime];
                 NSDictionary *extend=msg[@"extend"];
                 NSMutableDictionary *mextend = [extend mutableCopy];
                 [mextend setObject:@"" forKey:@"url"];
@@ -1700,7 +1882,8 @@ static const CGFloat kQuoteViewHeight = 46.0f;
                 [mextend setObject:[NSNumber numberWithInt:1] forKey:@"fileError"];
                 NSMutableDictionary *mmsg = [msg mutableCopy];
                 [mmsg setObject:mextend forKey:@"extend"];
-                
+                [mmsg setObject:strtime forKey:@"timestamp"];
+                [ChatsStore.shareInstance reciveMsg:mmsg];
                 NSDictionary *sendInfo = @{
                     @"code":@"2",
                     @"message":mmsg,
@@ -1714,7 +1897,7 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 //                    NSLog(@"%@", jsonString);
                     NSLog(@"----发送文件失败消息2----%@",localtime);
 //                    self.ismyTurn = YES;
-                    [GWebSocket.shareInstance sendMsg:jsonString];
+                    //[GWebSocket.shareInstance sendMsg:jsonString];
                 }
             }
         }
@@ -1724,6 +1907,27 @@ static const CGFloat kQuoteViewHeight = 46.0f;
     
 }
 
+-(void)updatajidu:(NSString *)localtime uploadProgress:(NSProgress *)Progress{
+    CGFloat progres = Progress.completedUnitCount/(double)Progress.totalUnitCount;
+    CGFloat Pcode =progres*100;
+    NSLog(@"Pcode:%f",Pcode);
+    for (ChatMessageModel *message in self.messageArray) {
+        
+        if(message.localtime==localtime.integerValue){
+            NSLog(@"%ld|%ld",(long)message.localtime,(long)localtime.integerValue);
+            [message setuploadPersent:Pcode localtime:localtime.integerValue];
+        }
+    }
+}
+
+-(void)Ossupdatajidu:(NSString *)localtime uploadProgress:(NSInteger )Progress{
+    for (ChatMessageModel *message in self.messageArray) {
+        if(message.localtime==localtime.integerValue){
+            [message setuploadPersent:Progress localtime:localtime.integerValue];
+        }
+    }
+}
+
 #pragma mark 录音发送
 
 -(void)longTarget{
@@ -1785,70 +1989,79 @@ static const CGFloat kQuoteViewHeight = 46.0f;
         [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
         [self.heatBeat invalidate];
         self.heatBeat = nil;
+        [MBProgressHUD showWithText:@"語音太短"];
         return;
     }
-    NSString *content=@"【语音】";
-    NSString *messageType=[NSString stringWithFormat:@"%@",MessageType_voice];
-    content= [CryptoAES.shareInstance encryptStringL:content];
-    NSString *strtime = [self getLocalTime];
-    NSString *type = [NSString stringWithFormat:@"%ld",(long)self.type];
     
-    NSData *data = [NSData dataWithContentsOfURL:fileURL]; // 读取文件数据
-    [FileNetApi upLoadDataWToken:data fileName:_AudiofileName succ:^(int code, NSDictionary * res) {
-        NSLog(@"res:%@",res);
-        NSLog(@"上传成功:%@",res[@"url"]);
-        NSString *upurl =res[@"url"];
-        if(![upurl isKindOfClass:[NSString class]]){
-            [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
-            
-            return;//上传失败没有正确返回
-        }
-        NSDictionary *dic =@{
-            @"id":@"",
-            @"messageType":messageType,
-            @"chatId":self.chatId,
-            @"fromId":self.userId,
-            @"fromName":self.username,
-            @"fromAvatar":self.useravatar,
-            @"reSend":[NSNumber numberWithBool:false],
-            @"content":content,
-            @"type":type,
-            @"localtime":strtime,
-            @"timestamp":strtime,
-            @"mine":[NSNumber numberWithBool:YES],
-            @"extend":@{
-                @"url":res[@"url"],
-                @"time":[NSString stringWithFormat:@"%ld",self->_rcdL],
-                @"localurl":@""
-            }
-        };
-        NSDictionary *sendInfo = @{
-            @"code":@"2",
-            @"message":dic,
-        };
-        NSError *error;
-        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sendInfo options:0 error:&error];
-        if (!jsonData) {
-            NSLog(@"Got an error: %@", error);
-        } else {
-            NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
-            NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
-            NSLog(@"----发送语音----");
-            [GWebSocket.shareInstance sendMsg:jsonString];
-            [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
-            
-        }
-        
-    } fail:^(NSError * _Nonnull error) {
+    ChatFileModel * model = [[ChatFileModel alloc] initWithURL:fileURL];
+    model.fileURL = fileURL;
+    model.filePath = _AudiofilePath;
+    NSString *strtime = [self getLocalTime];
+    //普通上传
+    [OSSManager.sharedManager asyncPutFile:model.fileURL.lastPathComponent localFilePath:model.filePath thrid:strtime progress:^(NSInteger pcent, NSString * loacaltime) {
+//        [self Ossupdatajidu:loacaltime uploadProgress:pcent];
+    } success:^(id res, NSString * loacaltime) {
+        [self sendYuyinMsg:model.fileURL.lastPathComponent localtime:loacaltime];
         [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
+    } failure:^(NSError * error, NSString * loacaltime) {
         
+        [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
     }];
+   
     
     [self.heatBeat invalidate];
     self.heatBeat = nil;
 
 }
 
+-(void)sendYuyinMsg:(NSString *)url localtime:(NSString *)loacaltime{
+    NSString *filePath;
+    if([url containsString:@"http"]){
+        filePath=url;
+    }
+    else{
+        filePath = [NSString stringWithFormat:@"http://oss.abtim-my.com/%@",url];
+    }
+    NSString *content=@"【语音】";
+    NSString *messageType=[NSString stringWithFormat:@"%@",MessageType_voice];
+    content= [CryptoAES.shareInstance encryptStringL:content];
+    NSString *type = [NSString stringWithFormat:@"%ld",(long)self.type];
+    
+    NSDictionary *dic =@{
+        @"id":@"",
+        @"messageType":messageType,
+        @"chatId":self.chatId,
+        @"fromId":self.userId,
+        @"fromName":self.username,
+        @"fromAvatar":self.useravatar,
+        @"reSend":[NSNumber numberWithBool:false],
+        @"content":content,
+        @"type":type,
+        @"localtime":loacaltime,
+        @"timestamp":loacaltime,
+        @"mine":[NSNumber numberWithBool:YES],
+        @"extend":@{
+            @"url":filePath,
+            @"time":[NSString stringWithFormat:@"%ld",self->_rcdL],
+            @"localurl":@""
+        }
+    };
+    NSDictionary *sendInfo = @{
+        @"code":@"2",
+        @"message":dic,
+    };
+    NSError *error;
+    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sendInfo options:0 error:&error];
+    if (!jsonData) {
+        NSLog(@"Got an error: %@", error);
+    } else {
+        NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+        NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
+        NSLog(@"----发送语音----");
+        [GWebSocket.shareInstance sendMsg:jsonString];
+    }
+}
+
 
 -(void)showWebRtcVidio:(NSInteger)state{
     if(self.type==1){
@@ -1961,9 +2174,6 @@ static const CGFloat kQuoteViewHeight = 46.0f;
 }
 
 - (void)deleteMyMsg:(NSDictionary *)dict{
-//    //删除未完善
-//    [MBProgressHUD showWithText:@"功能待完善"];
-//    return;
     NSMutableDictionary * msgDict = [NSMutableDictionary dictionaryWithDictionary:dict];
     [msgDict setValue:@"12" forKey:@"messageType"];
     [msgDict setValue:@"删除了一条消息" forKey:@"content"];
@@ -2253,7 +2463,6 @@ static const CGFloat kQuoteViewHeight = 46.0f;
                     return;
                 }
             }
-            
 //            NSLog(@"othersChatMessageAlert---3:%@",message);
             weakSelf(self);
             [TopPopupView showWithNickname:message.nickName message:message.content chatId:message.type == 0 ? message.avatar : message.chatId type:message.type clickBlock:^{

+ 3 - 2
AIIM/AIIM/Controller/chat/ChatHistoryController.m

@@ -347,7 +347,7 @@
 
 -(CGFloat)getcellHeight:(NSString *)text{
     
-    NSString *dcontent = [CryptoAES.shareInstance decryptDataL:text];
+    NSString *dcontent = text;//[CryptoAES.shareInstance decryptDataL:text];
     
     
     _textV.font = [UIFont systemFontOfSize:17];
@@ -452,12 +452,13 @@
         NSDictionary *extend = msg[@"extend"];
         NSString *localurl=extend[@"localurl"];
         NSString *imgUrl = extend[@"url"];
+        NSString *msgId = msg[@"id"];
         if([self fileExist:localurl]){//文件已经下载,打开文件位置
             
         }
         else{//下载文件并保存
             NSLog(@"imgUrl:%@",imgUrl);
-            [FileNetApi downLoadWToken:[NSURL URLWithString:imgUrl] succ:^(int code, NSDictionary * res) {
+            [FileNetApi downLoadWToken:[NSURL URLWithString:imgUrl] thrid:msgId succ:^(int code, NSDictionary * res) {
                 NSLog(@"code:%d",code);
             } fail:^(NSError * _Nonnull error) {
                 NSLog(@"error:%@",error);

+ 3 - 0
AIIM/AIIM/Controller/chat/ChatIndexController.h

@@ -15,4 +15,7 @@
 
 @property(nonatomic, strong) NSMutableArray *chatlist;
 
+
+-(void)reloadList;
+
 @end

+ 17 - 3
AIIM/AIIM/Controller/chat/ChatIndexController.m

@@ -11,6 +11,7 @@
 #import "ChatListStore.h"
 #import "ChatController.h"
 #import "ChatNetApi.h"
+#import <Bugly/Bugly.h>
 
 
 @interface ChatIndexController()<UITableViewDelegate,UITableViewDataSource,ChatListStoreDelegate>
@@ -31,17 +32,29 @@
     [self._tableView registerNib:nib forCellReuseIdentifier:@"chat"];
     
     //[self._tableView registerClass:[ChatListCell class] forCellReuseIdentifier:@"chat"]; // 使用 Storyboard 时不需要这行代码,除非你混合使用 Storyboard 和代码配置 Cell。
-    ChatListStore.shareInstance.delegate = self;
+//    ChatListStore.shareInstance.delegate = self;
     //[ChatListStore.shareInstance reloadData:YES];
 }
 
 -(void)viewWillAppear:(BOOL)animated{
     [super viewWillAppear:animated];
     NSLog(@"ChatIndexController viewWillAppear");
+    [self reloadList];
+}
+
+-(void)viewDidAppear:(BOOL)animated{
+    [super viewDidAppear:animated];
+    NSLog(@"ChatIndexController viewDidAppear");
+//    NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
+//    [Bugly reportException:[NSException exceptionWithName:@"ChatIndexController viewDidAppear" reason:[NSString stringWithFormat:@"数量:%@",userinfo[@"name"]] userInfo:nil]];
+    
+}
+
+-(void)reloadList{
     ChatListStore.shareInstance.delegate = self;
     ChatListStore.shareInstance.chatId =@"";
     [ChatListStore.shareInstance reloadData:true];
-    
+    NSLog(@"ChatIndexController reloadList");
 }
 
 -(void)viewDidDisappear:(BOOL)animated{
@@ -54,7 +67,8 @@
 -(void)ChatListChange:(NSArray *)array{
     
     self.chatlist = [NSMutableArray arrayWithArray:array];
-//    NSLog(@"self.chatlist:%@",self.chatlist);
+    NSLog(@"self.chatlist:%@",self.chatlist);
+    
     [self._tableView reloadData];
 }
 

+ 29 - 15
AIIM/AIIM/Controller/chat/ChatListCell.m

@@ -40,7 +40,7 @@
     }
     [self.avatar sd_setImageWithURL:[NSURL URLWithString:avatar] placeholderImage:[UIImage imageNamed:@"Avatar"]];
      self.name.text = data[@"name"];
-    NSString *dcontent = [CryptoAES.shareInstance decryptDataL:data[@"lastMessage"]];
+    NSString *dcontent = data[@"lastMessage"];//[CryptoAES.shareInstance decryptDataL:data[@"lastMessage"]];
     self.lastMsg.text = dcontent;
     _countText.layer.cornerRadius = 10.0f; // 设置圆角
     _countText.layer.masksToBounds = YES; // 防止子视图超出边界
@@ -90,25 +90,39 @@
     if(time<=0){
         return @"";
     }
+    // 创建日期格式器
+    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+    [formatter setDateFormat:@"dd"]; // 设置你想要的日期格式
+    
+    
+    long long timestamp =(long)time/1000; // 例如:2021-10-01 00:00:00 UTC
+    // 转换为NSDate
+    NSDate *date = [NSDate dateWithTimeIntervalSince1970:timestamp];
+    NSString *dateString = [formatter stringFromDate:date];
+    
+    
     NSDate *now = [NSDate date];
     NSTimeInterval trt = [now timeIntervalSince1970];
-    NSInteger shijiancha = trt-(long)time/1000;
+    date = [NSDate dateWithTimeIntervalSince1970:trt];
+    NSString *tdateString = [formatter stringFromDate:date];
+    
+    
+    NSInteger shijiancha = trt-timestamp;
+    
     if(shijiancha<60){
         return NSLocalizedString(@"time-oneminint", @"");
     }
-    if(shijiancha>24*3600){
-        shijiancha=shijiancha/(24*3600);
-        if(shijiancha>0){
-            NSDate *date = [NSDate dateWithTimeIntervalSince1970:(long)time/1000];
-            // 初始化NSDateFormatter
-            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
-            // 设置日期格式,例如:"yyyy-MM-dd HH:mm:ss"
-            [formatter setDateFormat:@"yyyy-MM-dd"];
-            // 将日期格式化为字符串
-            NSString *dateString = [formatter stringFromDate:date];
-            return dateString;
-        }
-        return [NSString stringWithFormat:@"%ld%@",(long)shijiancha,NSLocalizedString(@"time-outday", @"")];
+    if(shijiancha>24*3600||dateString.intValue!=tdateString.intValue){
+        // 假设这是你的时间戳(以秒为单位)
+        long long timestamp =(long)time/1000; // 例如:2021-10-01 00:00:00 UTC
+        // 转换为NSDate
+        NSDate *date = [NSDate dateWithTimeIntervalSince1970:timestamp];
+        // 创建日期格式器
+        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+        [formatter setDateFormat:@"yyyy-MM-dd"]; // 设置你想要的日期格式
+        // 转换为字符串
+        NSString *dateString = [formatter stringFromDate:date];
+        return dateString;
     }
     else{
         NSInteger xiaoshi = shijiancha/3600;

+ 5 - 5
AIIM/AIIM/Controller/chat/ChatListCell.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
     <device id="retina6_12" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -22,7 +22,7 @@
                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                     </imageView>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9gh-hv-yML">
-                        <rect key="frame" x="84" y="18" width="220" height="30"/>
+                        <rect key="frame" x="84" y="18" width="194" height="30"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
                         <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
                         <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -44,7 +44,7 @@
                         <nil key="highlightedColor"/>
                     </label>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pbk-Na-0Ue">
-                        <rect key="frame" x="284" y="18" width="88" height="30"/>
+                        <rect key="frame" x="286" y="18" width="86" height="30"/>
                         <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
                         <fontDescription key="fontDescription" type="system" pointSize="14"/>
                         <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -64,7 +64,7 @@
     </objects>
     <resources>
         <systemColor name="systemPinkColor">
-            <color red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <color red="1" green="0.17647058823529413" blue="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
     </resources>
 </document>

+ 2 - 1
AIIM/AIIM/Controller/chat/chetCell/ChatLongPressMenuView.m

@@ -50,7 +50,8 @@
                                              NSLocalizedString(@"cellact-duoxuan", @""),
                                              NSLocalizedString(@"cellact-yinyong", @"")]];
         }else{
-            [tempArray addObjectsFromArray:@[NSLocalizedString(@"cellact-copy", @""),
+            [tempArray addObjectsFromArray:@[NSLocalizedString(@"cellact-save", @""),
+                                             NSLocalizedString(@"cellact-deleat", @""),
                                              NSLocalizedString(@"cellact-zhuanfa", @""),
                                              NSLocalizedString(@"cellact-shouchang", @""),
                                              NSLocalizedString(@"cellact-duoxuan", @""),

+ 12 - 1
AIIM/AIIM/Controller/chat/chetCell/ChatMessageModel.h

@@ -84,8 +84,19 @@ typedef NS_ENUM(NSUInteger, ChatMessageType) {
 - (void)setupWithDictionary:(NSDictionary *)dict;
 // 从模型设置属性方法
 - (void)exchangeModelWithModel:(ChatMessageModel *)model;
-// 生成缩略图的方法
+// 生成缩略图的方法,同时判断是否开始下载视频
 - (void)generateThumbnailWithCompletion:(void(^)(UIImage *thumbnail))completion;
+//下载文件保存本地
+-(void)xiazaiwenjian:(void(^)(NSInteger persent))loading;
+-(void)xiazaishipin:(void(^)(NSInteger persent))loading;
+
+
+//上传文件
+@property (nonatomic,copy) void(^uploadPersentChange)(NSInteger index,NSInteger localtime);
+
+
+-(void)setuploadPersent:(NSInteger)persent localtime:(NSInteger)localtime;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 128 - 18
AIIM/AIIM/Controller/chat/chetCell/ChatMessageModel.m

@@ -9,6 +9,7 @@
 #import "CryptoAES.h"
 #import "ChatsStore.h"
 #import "AVFoundation/AVFoundation.h"
+#import "FileNetApi.h"
 
 @implementation ChatMessageModel
 
@@ -38,7 +39,10 @@
     self.avatar = mutableDict[@"fromAvatar"]?:@"";
     
     // 通用内容
-    self.content = [CryptoAES.shareInstance decryptDataL:mutableDict[@"content"] ?: @""];
+//    self.content = mutableDict[@"content"] ?: @"";//本地明文存储
+    self.content =[CryptoAES.shareInstance decryptDataL:mutableDict[@"content"] ?: @""];//本地加密存储
+    
+    
     self.msgId = mutableDict[@"id"];
     self.fromId = mutableDict[@"fromId"];
     // 发送方标识
@@ -155,17 +159,30 @@
 }
 
 -(NSString *)timeF:(NSInteger)time{
+    //NSLog(@"time:%ld",(long)time);
+    // 创建日期格式器
+    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+    [formatter setDateFormat:@"dd"]; // 设置你想要的日期格式
+    
+    
+    long long timestamp =(long)time/1000; // 例如:2021-10-01 00:00:00 UTC
+    // 转换为NSDate
+    NSDate *date = [NSDate dateWithTimeIntervalSince1970:timestamp];
+    NSString *dateString = [formatter stringFromDate:date];
+    
+    
     NSDate *now = [NSDate date];
     NSTimeInterval trt = [now timeIntervalSince1970];
+    date = [NSDate dateWithTimeIntervalSince1970:trt];
+    NSString *tdateString = [formatter stringFromDate:date];
     
-    NSInteger shijiancha = trt-(long)time/1000;
     
-//    NSLog(@"trt:%f",trt);
-//    NSLog(@"time:%ld",(long)time);
+    NSInteger shijiancha = trt-timestamp;
+    
     if(shijiancha<60){
         return NSLocalizedString(@"time-oneminint", @"");
     }
-    if(shijiancha>24*3600){
+    if(shijiancha>24*3600||dateString.intValue!=tdateString.intValue){
         // 假设这是你的时间戳(以秒为单位)
         long long timestamp =(long)time/1000; // 例如:2021-10-01 00:00:00 UTC
         // 转换为NSDate
@@ -241,7 +258,7 @@
                 self.readstate = 2;
             }
             if(self.fileError==1){
-                readStatus = @"发送失败";
+                readStatus = @"發送失敗,點擊重發";
                 self.readstate = 4;
             }
         }
@@ -260,32 +277,34 @@
     
     NSURL *videoURL = nil;
     if (self.localurl.length != 0 && [[NSFileManager defaultManager] fileExistsAtPath:self.localurl]) {
-        NSLog(@"generateThumbnailWithCompletion localurl");
+//        NSLog(@"generateThumbnailWithCompletion localurl:%@",self.localurl);
         videoURL = [NSURL fileURLWithPath:self.localurl];
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-            AVURLAsset *asset = [AVURLAsset assetWithURL:videoURL];
-            AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
-            generator.appliesPreferredTrackTransform = YES;
-            generator.requestedTimeToleranceBefore = kCMTimeZero;
-            generator.requestedTimeToleranceAfter = kCMTimeZero;
+            AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
             
+            AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
+            generator.appliesPreferredTrackTransform = YES;
+
+            CMTime acttime;
             NSError *error = nil;
-            CGImageRef imageRef = [generator copyCGImageAtTime:CMTimeMake(0, 1) actualTime:NULL error:&error];
-            
+            CGImageRef imageRef = [generator copyCGImageAtTime:CMTimeMake(0, 600) actualTime:&acttime error:&error];
+            NSLog(@"error:%@",error);
             if (!error && imageRef) {
-                UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
+                UIImage *thumbnail = [[UIImage alloc] initWithCGImage:imageRef];
                 CGImageRelease(imageRef);
-                
                 // 缓存到内存
                 self.videoThumbnailImage = thumbnail;
                 
-                if (completion) completion(thumbnail);
+                if (completion){
+                    completion(thumbnail);
+                }
             } else {
+                
                 if (completion) completion(nil);
             }
         });
     }else{
-//        NSLog(@"generateThumbnailWithCompletion url");
+        NSLog(@"generateThumbnailWithCompletion url");
         if (self.url.length == 0){
             completion(nil);
             return;
@@ -320,6 +339,97 @@
     
 }
 
+//下载视频文件
+-(void)xiazaishipin:(void(^)(NSInteger persent))loading{
+   
+    if(!self.isSender){
+        if (self.localurl.length != 0 && [[NSFileManager defaultManager] fileExistsAtPath:self.localurl]){
+            NSLog(@"文件已经存在本地");
+            if (loading) {
+                loading(100);
+            }
+        }
+        else{
+            if(self.url&&self.url.length != 0){
+                [FileNetApi downLoadWToken:getURL(self.url) thrid:self.msgId succ:^(int code, NSDictionary * res) {
+    //                NSLog(@"11---downLoadWToken:%d",code);
+                    if(res!=nil){
+                        NSMutableDictionary *mutableDict = [self.formerMessage mutableCopy];
+                        NSMutableDictionary *extend = [self.formerMessage[@"extend"] mutableCopy];
+                        [extend setObject:res[@"filePath"] forKey:@"localurl"];
+                        [mutableDict setObject:extend forKey:@"extend"];
+                        self.localurl = res[@"filePath"];
+                        NSDictionary *NewMsg = [mutableDict copy];
+                        [ChatsStore.shareInstance reciveMsg:NewMsg];
+                        if (loading) {
+                            loading(100);
+                        }
+                    }
+                    else{
+                        if (code>=0&&code<200) {
+                            if (loading) {
+                                loading(code);
+                            }
+                        }
+                    }
+                } fail:^(NSError * _Nonnull error) {
+                    NSLog(@"error:%@",error);
+                }];
+            }
+            else{
+                if (loading) {
+                    loading(0);
+                }
+            }
+        }
+    }
+    else{
+        NSLog(@"downLoadWToken xiazaishipin-----");
+    }
+}
+
+-(void)xiazaiwenjian:(void(^)(NSInteger persent))loading{
+    NSLog(@"xiazaiwenjian---");
+    if (self.isSender) {
+        return;
+    }
+    else{
+        [FileNetApi downLoadWToken:getURL(self.url) thrid:self.msgId succ:^(int code, NSDictionary * res) {
+            if(res!=nil){
+                NSMutableDictionary *mutableDict = [self.formerMessage mutableCopy];
+                NSMutableDictionary *extend = [self.formerMessage[@"extend"] mutableCopy];
+                [extend setObject:res[@"filePath"] forKey:@"localurl"];
+                [mutableDict setObject:extend forKey:@"extend"];
+                self.localurl = res[@"filePath"];
+                NSDictionary *NewMsg = [mutableDict copy];
+                [ChatsStore.shareInstance reciveMsg:NewMsg];
+                if (loading) {
+                    loading(100);
+                }
+            }
+            else{
+                if (code>=0&&code<200) {
+                    if (loading) {
+                        loading(code);
+                    }
+                }
+            }
+        } fail:^(NSError * _Nonnull error) {
+            NSLog(@"error:%@",error);
+            NSLog(@"%@",self.url);
+        }];
+    }
+}
+
+
+-(void)setuploadPersent:(NSInteger)persent localtime:(NSInteger)localtime{
+    if(self.uploadPersentChange && localtime==self.localtime){
+        self.uploadPersentChange(persent,localtime);
+    }
+}
+
+
+
 // 根据语音时长计算气泡宽度
 - (CGFloat)voiceBubbleWidth {
     // 基础宽度

+ 299 - 45
AIIM/AIIM/Controller/chat/chetCell/chatCellView.m

@@ -18,7 +18,7 @@
 #import "FilePreviewer.h"
 #import "ChatRecordController.h"
 #import "QuoteDetailController.h"
-
+#import "UILabel+YBAttributeTextTapAction.h"
 
 // 定义一些常量
 static const CGFloat kTextVerticalMargin = 10.0f;        //  内容垂直边距
@@ -49,6 +49,8 @@ static const CGFloat kMediaCornerRadius = 4.0f;
 @property (nonatomic, strong) UIImageView *imageContentView;
 @property (nonatomic, strong) UIView *videoContentView;
 @property (nonatomic, strong) UIImageView *thumbnailView;
+@property (nonatomic, strong) UIImageView *loadingImg;
+
 @property (nonatomic, strong) UIView *fileContentView;
 @property (nonatomic, strong) UIView *voiceContentView;
 @property (nonatomic, strong) UIView *callContentView;
@@ -58,12 +60,16 @@ static const CGFloat kMediaCornerRadius = 4.0f;
 @property (nonatomic, strong) UILabel * deleateLbl;
 @property (nonatomic, strong) UILabel * quoteLbl;
 
+@property (nonatomic, strong) UILabel * jinduLbl;
+
 @property (strong, nonatomic) AVPlayer *player;
 @property (strong, nonatomic) AVPlayerViewController *playerViewController;
 
 // 当前显示的内容视图
 @property (nonatomic, weak) UIView *currentContentView;
 
+@property (nonatomic,strong) NSArray *matchesArray;
+
 @end
 
 
@@ -146,7 +152,13 @@ static const CGFloat kMediaCornerRadius = 4.0f;
     _textLbl = [UILabel new];
     _textLbl.numberOfLines = 0;
     _textLbl.textColor = UIColor.blackColor;
+    _textLbl.userInteractionEnabled = YES; // 允许用户交互
     [self.contentView addSubview:_textLbl];
+
+    
+//    UITapGestureRecognizer *taptext = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTapped:)];
+//    [_textLbl addGestureRecognizer:taptext];
+    
     
     _quoteLbl = [UILabel new];
     _quoteLbl.numberOfLines = 1;
@@ -182,15 +194,16 @@ static const CGFloat kMediaCornerRadius = 4.0f;
     _videoContentView = [UIView new];
     _videoContentView.layer.cornerRadius = kMediaCornerRadius;
     _videoContentView.layer.masksToBounds = YES;
-    _videoContentView.backgroundColor = [UIColor blackColor];
+    _videoContentView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
     _videoContentView.userInteractionEnabled = YES;
     
+    
+    
+    
+    
     _thumbnailView = [[UIImageView alloc] init];
-    NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"load" ofType:@"gif"];
-    NSData *gifData = [NSData dataWithContentsOfFile:gifPath];
-    UIImage *placeholder = [UIImage sd_imageWithGIFData:gifData];
+    
     _thumbnailView.contentMode = UIViewContentModeScaleAspectFill;
-    _thumbnailView.image = placeholder;
     _thumbnailView.clipsToBounds = YES;
     _thumbnailView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
     [_videoContentView addSubview:_thumbnailView];
@@ -198,6 +211,18 @@ static const CGFloat kMediaCornerRadius = 4.0f;
         make.edges.equalTo(_videoContentView);
     }];
     
+    NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"load" ofType:@"gif"];
+    NSData *gifData = [NSData dataWithContentsOfFile:gifPath];
+    UIImage *placeholder = [UIImage sd_imageWithGIFData:gifData];
+    
+    _loadingImg = [[UIImageView alloc] initWithImage:placeholder];
+    [_videoContentView addSubview:_loadingImg];
+    [_loadingImg mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.center.equalTo(_videoContentView);
+        make.width.height.mas_equalTo(100);
+    }];
+    _loadingImg.alpha = 0;
+    
     UIImageView *playIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"play_btn"]];
     [_videoContentView addSubview:playIcon];
     [playIcon mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -205,6 +230,25 @@ static const CGFloat kMediaCornerRadius = 4.0f;
         make.width.height.mas_equalTo(40);
     }];
     
+    
+    _jinduLbl = [UILabel new];
+    [_videoContentView addSubview:_jinduLbl];
+    _jinduLbl.alpha = 0;
+    _jinduLbl.numberOfLines = 1;
+    _jinduLbl.font = SYSFONT(16);
+    _jinduLbl.textColor = UIColor.whiteColor;
+    _jinduLbl.layer.cornerRadius = 20.f;
+    _jinduLbl.layer.masksToBounds = YES;
+    _jinduLbl.textAlignment = NSTextAlignmentCenter;
+    _jinduLbl.backgroundColor =[UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
+    _jinduLbl.text = @"99";
+    [_jinduLbl mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.equalTo(_videoContentView).offset(8);
+        make.top.equalTo(_videoContentView).offset(8);
+        make.width.height.mas_equalTo(40);
+    }];
+    
+    
     [self.contentView addSubview:_videoContentView];
     
     // 添加点击手势
@@ -507,6 +551,7 @@ static const CGFloat kMediaCornerRadius = 4.0f;
         _readStateLbl.textColor = [UIColor whiteColor];
     }
     
+    
     if (_messageModel.type==1) {
         if (_messageModel.nickName && ![_messageModel.nickName isKindOfClass:NSNull.class]) {
             _nameLabel.text = _messageModel.isSender ? @"": _messageModel.nickName;
@@ -626,31 +671,129 @@ static const CGFloat kMediaCornerRadius = 4.0f;
     }else{
         _quoteLbl.hidden = YES;
     }
-//    if (_messageModel.textLayoutSize.height>18) {
-//        CGRect frame =  _textLbl.frame;
-//        frame.size.height = _messageModel.textLayoutSize.height;
-//        _textLbl.frame = frame;
-//        _currentContentView = _textLbl;
-//        //[self highlightSpecialElementsInText:_textLbl.attributedText];
-//        return;
-//    }
-    
+//    NSLog(@"_messageModel.content:%@",_messageModel.content);
     // 创建富文本
     NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:_messageModel.content ?: @""];
-
-    
     // 处理特殊内容(链接、@用户等)
-    //[self highlightSpecialElementsInText:text];
+    [self highlightSpecialElementsInText:text];
     
     // 同步设置文本,避免闪烁
 //    [UIView performWithoutAnimation:^{
 //        _textLbl.attributedText = text;
 //    }];
+
+    if(_matchesArray.count>0){
+        NSMutableArray *array = [NSMutableArray new];
+        for (NSTextCheckingResult *match in _matchesArray) {
+            if (match.resultType == NSTextCheckingTypeLink) {
+                NSString *url =[NSString stringWithFormat:@"%@",match.URL];
+                url=[url stringByReplacingOccurrencesOfString:@"http://" withString:@""];
+                url=[url stringByReplacingOccurrencesOfString:@"https://" withString:@""];
+                [array addObject:url];
+            }
+        }
+        _textLbl.attributedText = [self getAttributeWith:array string:_messageModel.content orginFont:18 orginColor:[UIColor darkGrayColor] attributeFont:18 attributeColor:[UIColor blueColor]];
+//        _textLbl.attributedText = text;
+        [_textLbl yb_addAttributeTapActionWithStrings:array tapClicked:^(UILabel *label, NSString *string, NSRange range, NSInteger index) {
+            NSLog(@"%ld:%@",(long)index,self->_matchesArray[index]);
+            NSTextCheckingResult *match=self->_matchesArray[index];
+            [[UIApplication sharedApplication] openURL:match.URL options:@{} completionHandler:nil];
+        }];
+    }
+    else{
+        _textLbl.attributedText = text;
+    }
+    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressEvent:)];
+    longPress.minimumPressDuration = 0.3; // 设置长按的最小时间为0.3秒
+    [_textLbl addGestureRecognizer:longPress]; // 将手势识别器添加到视图上
     
-    _textLbl.attributedText = text;
     _currentContentView = _textLbl;
 }
 
+
+
+- (NSAttributedString *)getAttributeWith:(id)sender
+                                  string:(NSString *)string
+                               orginFont:(CGFloat)orginFont
+                              orginColor:(UIColor *)orginColor
+                           attributeFont:(CGFloat)attributeFont
+                          attributeColor:(UIColor *)attributeColor
+{
+    __block  NSMutableAttributedString *totalStr = [[NSMutableAttributedString alloc] initWithString:string];
+    [totalStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:orginFont] range:NSMakeRange(0, string.length)];
+    [totalStr addAttribute:NSForegroundColorAttributeName value:orginColor range:NSMakeRange(0, string.length)];
+    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
+    [paragraphStyle setLineSpacing:0.0f]; //设置行间距
+    [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
+    [paragraphStyle setAlignment:NSTextAlignmentLeft];
+    [paragraphStyle setLineBreakMode:NSLineBreakByCharWrapping];
+    [totalStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [totalStr length])];
+    
+    if ([sender isKindOfClass:[NSArray class]]) {
+        
+        __block NSString *oringinStr = string;
+        __weak typeof(self) weakSelf = self;
+        
+        [sender enumerateObjectsUsingBlock:^(NSString *  _Nonnull str, NSUInteger idx, BOOL * _Nonnull stop) {
+            
+            NSRange range = [oringinStr rangeOfString:str];
+            if(range.length>0){
+                [totalStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:attributeFont] range:range];
+                [totalStr addAttribute:NSForegroundColorAttributeName value:attributeColor range:range];
+//                oringinStr = [oringinStr stringByReplacingCharactersInRange:range withString:[weakSelf getStringWithRange:range]];
+            }
+            
+        }];
+        
+    }else if ([sender isKindOfClass:[NSString class]]) {
+        
+        NSRange range = [string rangeOfString:sender];
+        
+        [totalStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:attributeFont] range:range];
+        [totalStr addAttribute:NSForegroundColorAttributeName value:attributeColor range:range];
+    }
+    return totalStr;
+}
+
+- (NSString *)getStringWithRange:(NSRange)range
+{
+    NSMutableString *string = [NSMutableString string];
+    for (int i = 0; i < range.length ; i++) {
+        [string appendString:@" "];
+    }
+    return string;
+}
+
+
+
+
+
+
+#pragma mark - 辅助方法
+- (void)highlightSpecialElementsInText:(NSMutableAttributedString *)text {
+    // 高亮链接
+    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
+    NSArray *matches = [detector matchesInString:text.string options:0 range:NSMakeRange(0, text.length)];
+    NSLog(@"matches:%@",matches);
+    _matchesArray =matches;
+
+    // 高亮@用户(暂不开放)
+//    NSRegularExpression *atRegex = [NSRegularExpression regularExpressionWithPattern:@"@[\\u4e00-\\u9fa5a-zA-Z0-9_-]+" options:0 error:nil];
+//    NSArray *atMatches = [atRegex matchesInString:text.string options:0 range:text.yy_rangeOfAll];
+//
+//    for (NSTextCheckingResult *match in atMatches) {
+//        [text yy_setColor:[UIColor orangeColor] range:match.range];
+//        [text yy_setTextHighlightRange:match.range
+//                                color:[UIColor orangeColor]
+//                      backgroundColor:[UIColor colorWithWhite:0.9 alpha:0.5]
+//                            tapAction:^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
+//            NSString *atUser = [text.string substringWithRange:range];
+//            // 处理@用户点击
+//            NSLog(@"点击了: %@", atUser);
+//        }];
+//    }
+}
+
 - (void)setupImageContent {
     _imageContentView.hidden = NO;
     
@@ -690,6 +833,7 @@ static const CGFloat kMediaCornerRadius = 4.0f;
     NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"load" ofType:@"gif"];
     NSData *gifData = [NSData dataWithContentsOfFile:gifPath];
     UIImage *placeholder = [UIImage sd_imageWithGIFData:gifData];
+    
     weakSelf(self);
     [_imageContentView sd_setImageWithURL:[NSURL URLWithString:_messageModel.url]
                         placeholderImage:placeholder
@@ -725,48 +869,148 @@ static const CGFloat kMediaCornerRadius = 4.0f;
 //    }
     // 清除旧视图
     _thumbnailView.image  = nil;
+    _loadingImg.image = nil;
     
-    if(_messageModel.fileError==1){
-        
-        self.thumbnailView.image = [UIImage imageNamed:@"pictrue_load_fail"];
-        _currentContentView = _videoContentView;
-        return;
-    }
+//    if(_messageModel.fileError==1){
+//        
+//        self.thumbnailView.image = [UIImage imageNamed:@"pictrue_load_fail"];
+//        _currentContentView = _videoContentView;
+//        return;
+//    }
     
     weakSelf(self);
     if (_messageModel.videoThumbnailImage) {
-//        NSLog(@"videoThumbnailImage----");
-        self.thumbnailView.image = _messageModel.videoThumbnailImage;
+//        NSLog(@"videoThumbnailImage----:%@",_messageModel.videoThumbnailImage);
+        _thumbnailView.image = _messageModel.videoThumbnailImage;
+        [_thumbnailView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.edges.equalTo(_videoContentView);
+        }];
     }else{
 //        NSLog(@"videoThumbnailImage----load");
-        NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"load" ofType:@"gif"];
-        NSData *gifData = [NSData dataWithContentsOfFile:gifPath];
-        UIImage *placeholder = [UIImage sd_imageWithGIFData:gifData];
-        weakself.thumbnailView.image = placeholder;
         [_messageModel generateThumbnailWithCompletion:^(UIImage * _Nonnull thumbnail) {
+//            NSLog(@"111111---------------");
             if (thumbnail) {
+//                NSLog(@"2222---------------");
                 dispatch_async(dispatch_get_main_queue(), ^{
+                    [weakself.thumbnailView mas_makeConstraints:^(MASConstraintMaker *make) {
+                        make.edges.equalTo(self->_videoContentView);
+                    }];
                     weakself.thumbnailView.image = thumbnail;
                 });
             }
         }];
     }
+
+    [_messageModel xiazaishipin:^(NSInteger persent) {
+        if(persent>=100){
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if(weakself.jinduLbl){
+                    weakself.jinduLbl.alpha = 0;
+                    weakself.loadingImg.alpha = 0;
+                }
+            });
+            
+//            NSLog(@"下载完成:%@",self->_messageModel.localurl);
+        }
+        else{
+//            NSLog(@"下载中:%ld",(long)persent);
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if(weakself.jinduLbl){
+                    if(weakself.loadingImg.alpha!=1||!weakself.loadingImg.image){
+                        NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"load" ofType:@"gif"];
+                        NSData *gifData = [NSData dataWithContentsOfFile:gifPath];
+                        UIImage *placeholder = [UIImage sd_imageWithGIFData:gifData];
+                        weakself.loadingImg.image = placeholder;
+                        weakself.loadingImg.alpha = 1;
+                    }
+                    weakself.jinduLbl.alpha = 1;
+                    weakself.jinduLbl.text = [NSString stringWithFormat:@"%ld",(long)persent];
+                }
+            });
+            
+        }
+    }];
+    
+
+    _messageModel.uploadPersentChange = ^(NSInteger index,NSInteger localtime) {
+        
+        if(localtime==weakself.messageModel.localtime){
+            if(index>=100){
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    if(weakself.jinduLbl){
+                        weakself.jinduLbl.alpha = 0;
+                        weakself.loadingImg.alpha = 0;
+                    }
+                });
+            }
+            else{
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    if(weakself.jinduLbl){
+                        if(weakself.loadingImg.alpha!=1||!weakself.loadingImg.image){
+                            NSString *gifPath = [[NSBundle mainBundle] pathForResource:@"load" ofType:@"gif"];
+                            NSData *gifData = [NSData dataWithContentsOfFile:gifPath];
+                            UIImage *placeholder = [UIImage sd_imageWithGIFData:gifData];
+                            weakself.loadingImg.image = placeholder;
+                            weakself.loadingImg.alpha = 1;
+                        }
+                        weakself.jinduLbl.alpha = 1;
+                        weakself.jinduLbl.text = [NSString stringWithFormat:@"%ld",(long)index];
+                    }
+                });
+            }
+        }
+        else{
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if(weakself.jinduLbl){
+                    weakself.jinduLbl.alpha = 0;
+                    weakself.loadingImg.alpha = 0;
+                }
+            });
+        }
+    };
+    
     
     _currentContentView = _videoContentView;
 }
 
+
+
+
 - (void)setupFileContent {
     _fileContentView.hidden = NO;
     
     // 获取子视图
     UIImageView *iconView = _fileContentView.subviews[0];
     UILabel *nameLabel = _fileContentView.subviews[1];
-//    UILabel *sizeLabel = _fileContentView.subviews[2];
+    UILabel *sizeLabel = _fileContentView.subviews[2];
     
     // 设置文件内容
     iconView.image = [UIImage imageNamed: @"file_icon_black"];
     nameLabel.text = _messageModel.fileName ?: @"未知文件";
-//    sizeLabel.text = _messageModel.fileSize ?: @"0KB";
+    
+    sizeLabel.alpha = 0;
+
+    
+    [_messageModel xiazaiwenjian:^(NSInteger persent) {
+        NSLog(@"setupFileContent----------");
+        if(persent>=100){
+            NSLog(@"setupFileContent:下载完成:%@",self->_messageModel.localurl);
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if(sizeLabel){
+                    sizeLabel.alpha = 0;
+                }
+            });
+        }
+        else{
+            NSLog(@"setupFileContent 下载中:%ld",(long)persent);
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if(sizeLabel){
+                    sizeLabel.alpha = 1;
+                    sizeLabel.text = [NSString stringWithFormat:@"%ld",(long)persent];
+                }
+            });
+        }
+    }];
     
     _currentContentView = _fileContentView;
 }
@@ -852,7 +1096,7 @@ static const CGFloat kMediaCornerRadius = 4.0f;
         NSString * recordString = @"";
         switch ([messageType integerValue]) {
             case 0:
-                recordString = [NSString stringWithFormat:@"%@:%@\n",nickName,[CryptoAES.shareInstance decryptDataL:dict[@"content"]]];
+                recordString = [NSString stringWithFormat:@"%@:%@\n",nickName,dict[@"content"]?:@""];//[NSString stringWithFormat:@"%@:%@\n",nickName,[CryptoAES.shareInstance decryptDataL:dict[@"content"]]];
                 break;
             case 1:
                 recordString = [NSString stringWithFormat:@"%@:【图片】\n",nickName];;
@@ -962,7 +1206,7 @@ static const CGFloat kMediaCornerRadius = 4.0f;
             [_readStateLbl mas_remakeConstraints:^(MASConstraintMaker *make) {
                 make.right.mas_equalTo(self.contentView).offset(-30);
                 make.height.mas_equalTo(14);
-                make.top.mas_equalTo(self.currentContentView.mas_bottom);
+                make.top.mas_equalTo(self.currentContentView.mas_bottom).offset(2);
             }];
         }else{
             if (!_quoteLbl.hidden) {
@@ -1263,7 +1507,7 @@ static const CGFloat kMediaCornerRadius = 4.0f;
     NSString *text = _messageModel.content ?: @"";
     
     UILabel *label = [[UILabel alloc] init];
-    label.font = [UIFont systemFontOfSize:17.0]; // 设置字体大小
+    label.font = [UIFont systemFontOfSize:18.0]; // 设置字体大小
     label.numberOfLines = 0; // 设置为0表示不限制行数
     label.text = text; // 设置文本内容
     label.preferredMaxLayoutWidth = kContentMaxWidth; // 设置固定宽度
@@ -1275,15 +1519,16 @@ static const CGFloat kMediaCornerRadius = 4.0f;
 }
 
 - (NSString *)formatTimeWithMilliseconds:(NSInteger)milliseconds{
-    CGFloat seconds = milliseconds / 1000.0;
+    NSInteger seconds = milliseconds / 1000.0;
         
     if (seconds >= 60) {
         // 大于等于60秒时显示为分钟,保留一位小数
-        CGFloat minutes = seconds / 60.0;
-        return [NSString stringWithFormat:@"%.1f分钟", minutes];
+        NSInteger minutes = seconds / 60.0;
+        NSInteger sc = seconds%60;
+        return [NSString stringWithFormat:@"%ld分%ld秒", (long)minutes,(long)sc];
     } else {
         // 小于60秒时显示为秒,保留整数
-        return [NSString stringWithFormat:@"%.0f秒", seconds];
+        return [NSString stringWithFormat:@"%ld秒", seconds];
     }
 }
 
@@ -1294,7 +1539,10 @@ static const CGFloat kMediaCornerRadius = 4.0f;
         // 处理图片点击
         NSLog(@"点击了图片: %@", _messageModel.url);
         if(_messageModel.fileError==1){
-            [MBProgressHUD showWithText:@"图片传输错误或取消传输"];
+            weakSelf(self);
+            if(weakself.bubbleCellLongPressMenuBlock){
+                weakself.bubbleCellLongPressMenuBlock(8);
+            }
             return;
         }
         if (_messageModel.url.length == 0 && !_messageModel.isSender) {
@@ -1311,7 +1559,10 @@ static const CGFloat kMediaCornerRadius = 4.0f;
         // 处理视频点击
         NSLog(@"点击了视频: %@", _messageModel.url);
         if(_messageModel.fileError==1){
-            [MBProgressHUD showWithText:@"视频传输错误或取消传输"];
+            weakSelf(self);
+            if(weakself.bubbleCellLongPressMenuBlock){
+                weakself.bubbleCellLongPressMenuBlock(8);
+            }
             return;
         }
         if (_messageModel.url.length == 0 && !_messageModel.isSender) {
@@ -1327,7 +1578,10 @@ static const CGFloat kMediaCornerRadius = 4.0f;
         // 处理视频点击
         NSLog(@"点击了文件: %@", _messageModel.url);
         if(_messageModel.fileError==1){
-            [MBProgressHUD showWithText:@"文件传输错误或取消传输"];
+            weakSelf(self);
+            if(weakself.bubbleCellLongPressMenuBlock){
+                weakself.bubbleCellLongPressMenuBlock(8);
+            }
             return;
         }
         if (_messageModel.url.length == 0 && !_messageModel.isSender) {
@@ -1409,8 +1663,8 @@ static const CGFloat kMediaCornerRadius = 4.0f;
     [self.parentViewController presentViewController:navi animated:YES completion:nil];
 }
 
-- (void)handleQuoteTap {
-//    NSLog(@"handleQuoteTap----:%@",[_messageModel.quoteMessage class]);
+- (void)handleQuoteTap{
+    NSLog(@"handleQuoteTap----:%@",[_messageModel.quoteMessage class]);
     if(![_messageModel.quoteMessage isKindOfClass:[ChatMessageModel class]]){
         return;
     }

+ 6 - 0
AIIM/AIIM/Controller/friend/FriendListController.m

@@ -92,6 +92,12 @@
 
 -(void)getFriendlist{
     [FriendNetApi getfriends:nil succ:^(int code, NSDictionary * res) {
+        NSLog(@"self.friendlist:%@",res);
+        NSNumber *codeD = res[@"code"];
+        if([codeD intValue]==401){
+            [[NSNotificationCenter defaultCenter] postNotificationName: nkonLogoutSucc object:nil];
+            return;
+        }
         self.friendlist = res[@"data"];
         NSLog(@"self.friendlist:%@",self.friendlist);
         if(self.friendlist){

+ 6 - 1
AIIM/AIIM/Controller/group/GroupListController.m

@@ -45,7 +45,12 @@
 
 -(void)getGrouplistData{
     [GroupNetApi getGroupList:^(int code, NSDictionary * res) {
-        NSLog(@"res:%@",res);
+        NSLog(@"getGrouplistData res:%@",res);
+        NSNumber *codeD = res[@"code"];
+        if([codeD intValue]==401){
+            [[NSNotificationCenter defaultCenter] postNotificationName: nkonLogoutSucc object:nil];
+            return;
+        }
         self.grouplist = res[@"data"];
         [self.tableView reloadData];
     } fail:^(NSError * _Nonnull error) {

+ 10 - 1
AIIM/AIIM/Controller/login/GSignController.m

@@ -209,7 +209,16 @@
     if([_inputYX.text isEqualToString:_youxiang]){
         if([_inputMMA.text isEqualToString:_inputMMB.text]){
             if(_inputZH.text.length>3&&_inputMMA.text.length>3&&_inputYZM.text.length>3){
-                [self updateSign];
+                
+                NSString *emailRegex =  @"^[a-zA-Z0-9]+$";
+                NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
+                BOOL isValid = [emailTest evaluateWithObject:_inputZH.text];
+                if(isValid){
+                    [self updateSign];
+                }
+                else{
+                    [MBProgressHUD showWithText:@"帳號只能包含數位字母"];
+                }
             }
             else{//所有项目为必填,且不小于4个字符
                 

+ 3 - 0
AIIM/AIIM/Controller/mine/UserConterController.m

@@ -323,6 +323,9 @@
                 [UDManager.shareInstance setDDManager:ps key:dkuserinfo];
                 [self showUserData];
             }
+            else{
+                [self logoutAccaut];
+            }
             
         } fail:^(NSError * _Nonnull error) {
             NSLog(@"%@", error);

+ 67 - 23
AIIM/AIIM/Controller/webRTC/JSGController.m

@@ -15,6 +15,7 @@
 #import "AFNetworking/AFNetworkReachabilityManager.h"
 #import <SystemConfiguration/SystemConfiguration.h>
 #import "CustomJitsiLogger.h"
+#import <Bugly/Bugly.h>
 
 @interface JSGController()<WebRTCStoreDelegate,AVAudioPlayerDelegate>
 @property (nonatomic,strong) JitsiMeetView *jitsiView;
@@ -34,6 +35,9 @@
 
 @property (nonatomic) BOOL isSpeacker;
 @property (nonatomic) BOOL isjoin;
+
+@property (nonatomic) BOOL hadCall;
+
 @property (nonatomic) BOOL floadViewState;
 
 @property (nonatomic) BOOL startLison;
@@ -50,20 +54,22 @@
     _isClose=YES;
     _floadViewState=NO;
     _startLison=NO;
+    _hadCall = NO;
     
     WebRTCStore.shareInstance.isBusy=true;
     WebRTCStore.shareInstance.PeerId =self.chatId;
     WebRTCStore.shareInstance.delegate = self;
     _jitsiView = (JitsiMeetView*)self.view;
     _jitsiView.delegate = self;
+   
 
-//    CustomJitsiLogger *handler = [CustomJitsiLogger sharedHandler];
-//    handler.errorCount = 0;
-//    [handler.criticalErrors removeAllObjects];
-//    weakSelf(self);
-//    handler.WebsocketErrorBlock = ^{
-//        [weakself reconnectConference];
-//    };
+    CustomJitsiLogger *handler = [CustomJitsiLogger sharedHandler];
+    handler.errorCount = 0;
+    [handler.criticalErrors removeAllObjects];
+    weakSelf(self);
+    handler.WebsocketErrorBlock = ^{
+        [weakself reconnectConference];
+    };
     
     
     //挂断按钮
@@ -105,6 +111,7 @@
     }
 }
 
+
 #pragma mark 应用被唤醒时判断解锁状态
 - (void)GapplicationDidBecomeActive:(NSNotification *)notification {
     // 应用进入前台
@@ -159,6 +166,8 @@
     NSLog(@"startJitsiMeetCall--------1--------");
     _isClose=NO;
     _isjoin=false;
+    _isSpeacker = NO;
+    _hadCall = NO;
     [self.view bringSubviewToFront:_hangupButton];
     [_hangupButton mas_makeConstraints:^(MASConstraintMaker *make) {
         make.size.mas_equalTo(CGSizeMake(50, 50));
@@ -229,9 +238,20 @@
     [self initjsView];//初始化 房间页面
     
     _isjoin =true;
-    [_jitsiView join:self.currentOptions];//进入房间
+    if(self.currentOptions){
+        [_jitsiView join:self.currentOptions];//进入房间
+    }
+    else{
+        //初始化失败
+        NSString *bgMark = @"initjsView 初始化失败";
+        [Bugly reportException:[NSException exceptionWithName:[NSString stringWithFormat:@"voip:%@",bgMark] reason:@"" userInfo:nil]];
+        [self endJitsiMeetCall];
+        return;
+    }
+    
     [self.audioPlayer play];
     _FloadNote.alpha = 1;
+    [_jitsiView changeAudioSession:NO];
     
 }
 
@@ -251,6 +271,7 @@
 
 #pragma mark 重连操作,待完善
 - (void)reconnectConference {
+    NSLog(@"reconnectConference---------1");
     if (_isReconnecting) return;
     _isReconnecting = YES;
     _reconnectAttempt++;
@@ -258,17 +279,21 @@
         _isReconnecting = NO;
         return;
     }
+    NSLog(@"reconnectConference---------2");
     // 1. 先离开当前会议
     [self.jitsiView leave];
     // 2. 等待清理完成
+    NSLog(@"reconnectConference---------3");
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
         // 3. 重新加入会议
-        [self initjsView];
-        if(self.startTime==0){
-            NSDate *now = [NSDate date];
-            NSTimeInterval trt = [now timeIntervalSince1970];
-            self.startTime = trt*1000;
-        }
+//        [self initjsView];
+        [self.jitsiView join:self.currentOptions];//进入房间
+        NSLog(@"reconnectConference---------4");
+//        if(self.startTime==0){
+//            NSDate *now = [NSDate date];
+//            NSTimeInterval trt = [now timeIntervalSince1970];
+//            self.startTime = trt*1000;
+//        }
         
         // 4. 重置重连状态
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
@@ -395,8 +420,13 @@
             duration=[NSString stringWithFormat:@"%ld",(long)_startTime];
         }
         BOOL conetType=true;
+        NSString *content;
         if (self.audioOnly) {
             conetType=false;
+            content = @"【语音通话】";
+        }
+        else{
+            content = @"【视频通话】";
         }
         NSDictionary *callMsg = @{
             @"code":@"2",
@@ -413,7 +443,8 @@
                 @"result":result,
                 @"timestamp":strtime,
                 @"video":[NSNumber numberWithBool:conetType],
-                @"duration":duration
+                @"duration":duration,
+                @"content":content,
             }
         };
         NSError *error;
@@ -505,14 +536,21 @@
 
     JitsiMeetConferenceOptions *options=nil;
     if(self.isCaller){
+        NSLog(@"initjsView---00000---");
         // create the room.JitsiMeetConferenceOptions
         options = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
             builder.serverURL = [NSURL URLWithString:JitsiMeetSV];
             builder.room = self.room;
             builder.audioOnly = self.audioOnly;
+            [builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
+            
+            //界面优化 - 隐藏不必要的会议功能
             [builder setFeatureFlag:@"welcomepage.enabled" withBoolean:NO];
             [builder setFeatureFlag:@"pip.enabled" withBoolean:NO];
-            [builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
+            [builder setFeatureFlag:@"live-streaming.enabled" withBoolean:NO];
+            [builder setFeatureFlag:@"recording.enabled" withBoolean:NO];
+            [builder setFeatureFlag:@"kick-out.enabled" withBoolean:NO];
+            [builder setFeatureFlag:@"security-options.enabled" withBoolean:NO];
             [builder setFeatureFlag:@"chat.enabled" withBoolean:NO];
             [builder setFeatureFlag:@"invite.enabled" withBoolean:NO];
             [builder setFeatureFlag:@"add-people.enabled" withBoolean:NO];
@@ -520,16 +558,13 @@
             [builder setFeatureFlag:@"call-integration.enabled" withBoolean:NO];
             [builder setFeatureFlag:@"startWithAudioMuted" withBoolean:NO];
             [builder setFeatureFlag:@"prejoinpage.enabled" withBoolean:NO];
+            
             [builder setFeatureFlag:@"reconnect.enabled" withBoolean:YES];
             [builder setConfigOverride:@"iceTransportPolicy" withValue:@"relay"];
             [builder setConfigOverride:@"enableNetworkMonitor" withBoolean:YES];
             [builder setConfigOverride:@"toolbarButtons" withArray:@[@"microphone",@"camera"]];
             
-//            //界面优化 - 隐藏不必要的会议功能
-            [builder setFeatureFlag:@"live-streaming.enabled" withBoolean:NO];
-            [builder setFeatureFlag:@"recording.enabled" withBoolean:NO];
-            [builder setFeatureFlag:@"kick-out.enabled" withBoolean:NO];
-            [builder setFeatureFlag:@"security-options.enabled" withBoolean:NO];
+
 //            
 //            // 界面简化 - 更适合一对一场景
 //            [builder setFeatureFlag:@"toolbox.alwaysVisible" withBoolean:NO];
@@ -560,6 +595,8 @@
                 [builder setFeatureFlag:@"call-integration.enabled" withBoolean:NO];
                 [builder setFeatureFlag:@"startWithAudioMuted" withBoolean:NO];
                 [builder setFeatureFlag:@"prejoinpage.enabled" withBoolean:NO];
+                
+                
                 [builder setFeatureFlag:@"reconnect.enabled" withBoolean:YES];
                 [builder setConfigOverride:@"iceTransportPolicy" withValue:@"relay"];
                 [builder setConfigOverride:@"enableNetworkMonitor" withBoolean:YES];
@@ -567,6 +604,8 @@
             }];
     }
     NSLog(@"initjsView---2---:%@",options);
+
+
     self.currentOptions = options;
     
     
@@ -576,11 +615,16 @@
     NSLog(@"About to join conference---- %@", self.room);
     self.isInConference = NO;
     if (self.isCaller) {//拨打方进入房间成功,开始通知对方
+        if(_hadCall){
+            return;
+        }
+        _hadCall = YES;
         [self sendCall];
     }
     else{//接听方进入房间,播放等待接通铃声
         NSLog(@"self.audioPlayer-----------");
 //        [self.audioPlayer play];
+//        [self reconnectConference];
     }
     
 
@@ -622,7 +666,7 @@
 }
 
 - (void)conferenceTerminated:(NSDictionary *)data {//连接错误,重连处理待验证
-    NSLog(@"conferenceTerminated----------------------");
+    NSLog(@"conferenceTerminated----------------------:%@",data);
     _isInConference = NO;
     
     NSString *error = data[@"error"];
@@ -641,7 +685,6 @@
     if (_isReconnecting) {
         return;
     }
-//    [self endJitsiMeetCall];
 
 }
 
@@ -690,6 +733,7 @@
     else{
         [_speackerBt setImage:[UIImage imageNamed:@"speaker_on_icon"] forState:UIControlStateNormal];
     }
+    
 }
 
 

+ 44 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/Info.plist

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>AvailableLibraries</key>
+	<array>
+		<dict>
+			<key>BinaryPath</key>
+			<string>AliyunOSSiOS.framework/AliyunOSSiOS</string>
+			<key>LibraryIdentifier</key>
+			<string>ios-arm64</string>
+			<key>LibraryPath</key>
+			<string>AliyunOSSiOS.framework</string>
+			<key>SupportedArchitectures</key>
+			<array>
+				<string>arm64</string>
+			</array>
+			<key>SupportedPlatform</key>
+			<string>ios</string>
+		</dict>
+		<dict>
+			<key>BinaryPath</key>
+			<string>AliyunOSSiOS.framework/AliyunOSSiOS</string>
+			<key>LibraryIdentifier</key>
+			<string>ios-arm64_x86_64-simulator</string>
+			<key>LibraryPath</key>
+			<string>AliyunOSSiOS.framework</string>
+			<key>SupportedArchitectures</key>
+			<array>
+				<string>arm64</string>
+				<string>x86_64</string>
+			</array>
+			<key>SupportedPlatform</key>
+			<string>ios</string>
+			<key>SupportedPlatformVariant</key>
+			<string>simulator</string>
+		</dict>
+	</array>
+	<key>CFBundlePackageType</key>
+	<string>XFWK</string>
+	<key>XCFrameworkFormatVersion</key>
+	<string>1.0</string>
+</dict>
+</plist>

binární
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/AliyunOSSiOS


+ 22 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/AliyunOSSiOS.h

@@ -0,0 +1,22 @@
+//
+//  AliyunOSSiOS.h
+//  AliyunOSSiOS
+//
+//  Created by xuyecan on 28/11/2016.
+//  Copyright © 2016 xuyecan. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+//! Project version number for AliyunOSSiOS.
+FOUNDATION_EXPORT double AliyunOSSiOSVersionNumber;
+
+//! Project version string for AliyunOSSiOS.
+FOUNDATION_EXPORT const unsigned char AliyunOSSiOSVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <AliyunOSSiOS/PublicHeader.h>
+
+#import "OSSService.h"
+#import "OSSCompat.h"
+#import "OSSXMLDictionary.h"
+#import "OSSIPv6Adapter.h"

+ 19 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/NSDate+OSS.h

@@ -0,0 +1,19 @@
+//
+//  NSDate+OSS.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/7/31.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+/**
+ Categories NSDate
+ */
+@interface NSDate (OSS)
++ (void)oss_setClockSkew:(NSTimeInterval)clockSkew;
++ (NSDate *)oss_dateFromString:(NSString *)string;
++ (NSDate *)oss_clockSkewFixedDate;
+- (NSString *)oss_asStringValue;
+@end

+ 15 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/NSMutableData+OSS_CRC.h

@@ -0,0 +1,15 @@
+//
+//  NSMutableData+OSS_CRC.h
+//  AliyunOSSSDK
+//
+//  Created by 怀叙 on 2017/11/29.
+//  Copyright © 2017年 阿里云. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSMutableData (OSS_CRC)
+
+- (uint64_t)oss_crc64;
+
+@end

+ 15 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/NSMutableDictionary+OSS.h

@@ -0,0 +1,15 @@
+//
+//  NSMutableDictionary+OSS.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/8/1.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSMutableDictionary (OSS)
+
+- (void)oss_setObject:(id)anObject forKey:(id <NSCopying>)aKey;
+
+@end

+ 33 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSAllRequestNeededMessage.h

@@ -0,0 +1,33 @@
+//
+//  OSSAllRequestNeededMessage.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/22.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSConstants.h"
+#import "OSSTask.h"
+
+/**
+ All necessary information in one OSS request.
+ */
+@interface OSSAllRequestNeededMessage : NSObject
+@property (nonatomic, strong) NSString *endpoint;
+@property (nonatomic, strong) NSString *httpMethod;
+@property (nonatomic, strong) NSString *bucketName;
+@property (nonatomic, strong) NSString *objectKey;
+@property (nonatomic, strong) NSString *contentType;
+@property (nonatomic, strong) NSString *contentMd5;
+@property (nonatomic, strong) NSString *range;
+@property (nonatomic, strong) NSString *date;
+@property (nonatomic, strong) NSMutableDictionary *headerParams;
+@property (nonatomic, copy) NSDictionary *params;
+@property (nonatomic, copy) NSString *contentSHA1;
+@property (nonatomic, assign) BOOL isHostInCnameExcludeList;
+
+
+- (OSSTask *)validateRequestParamsInOperationType:(OSSOperationType)operType;
+
+@end

+ 26 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSBolts.h

@@ -0,0 +1,26 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import "OSSCancellationToken.h"
+#import "OSSCancellationTokenRegistration.h"
+#import "OSSCancellationTokenSource.h"
+#import "OSSExecutor.h"
+#import "OSSTask.h"
+#import "OSSTaskCompletionSource.h"
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ A string containing the version of the Bolts Framework used by the current application.
+ */
+extern NSString *const OSSBoltsFrameworkVersionString;
+
+NS_ASSUME_NONNULL_END

+ 42 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCancellationToken.h

@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "OSSCancellationTokenRegistration.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*!
+ A block that will be called when a token is cancelled.
+ */
+typedef void(^OSSCancellationBlock)(void);
+
+/*!
+ The consumer view of a CancellationToken.
+ Propagates notification that operations should be canceled.
+ A OSSCancellationToken has methods to inspect whether the token has been cancelled.
+ */
+@interface OSSCancellationToken : NSObject
+
+/*!
+ Whether cancellation has been requested for this token source.
+ */
+@property (nonatomic, assign, readonly, getter=isCancellationRequested) BOOL cancellationRequested;
+
+/*!
+ Register a block to be notified when the token is cancelled.
+ If the token is already cancelled the delegate will be notified immediately.
+ */
+- (OSSCancellationTokenRegistration *)registerCancellationObserverWithBlock:(OSSCancellationBlock)block;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 29 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCancellationTokenRegistration.h

@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*!
+ Represents the registration of a cancellation observer with a cancellation token.
+ Can be used to unregister the observer at a later time.
+ */
+@interface OSSCancellationTokenRegistration : NSObject
+
+/*!
+ Removes the cancellation observer registered with the token
+ and releases all resources associated with this registration.
+ */
+- (void)dispose;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 60 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCancellationTokenSource.h

@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class OSSCancellationToken;
+
+/*!
+ OSSCancellationTokenSource represents the producer side of a CancellationToken.
+ Signals to a CancellationToken that it should be canceled.
+ It is a cancellation token that also has methods
+ for changing the state of a token by cancelling it.
+ */
+@interface OSSCancellationTokenSource : NSObject
+
+/*!
+ Creates a new cancellation token source.
+ */
++ (instancetype)cancellationTokenSource;
+
+/*!
+ The cancellation token associated with this CancellationTokenSource.
+ */
+@property (nonatomic, strong, readonly) OSSCancellationToken *token;
+
+/*!
+ Whether cancellation has been requested for this token source.
+ */
+@property (nonatomic, assign, readonly, getter=isCancellationRequested) BOOL cancellationRequested;
+
+/*!
+ Cancels the token if it has not already been cancelled.
+ */
+- (void)cancel;
+
+/*!
+ Schedules a cancel operation on this CancellationTokenSource after the specified number of milliseconds.
+ @param millis The number of milliseconds to wait before completing the returned task.
+ If delay is `0` the cancel is executed immediately. If delay is `-1` any scheduled cancellation is stopped.
+ */
+- (void)cancelAfterDelay:(int)millis;
+
+/*!
+ Releases all resources associated with this token source,
+ including disposing of all registrations.
+ */
+- (void)dispose;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 527 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSClient.h

@@ -0,0 +1,527 @@
+//
+//  OSSClient.h
+//  oss_ios_sdk
+//
+//  Created by zhouzhuo on 8/16/15.
+//  Copyright (c) 2015 aliyun.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+@class OSSGetServiceRequest;
+@class OSSCreateBucketRequest;
+@class OSSDeleteBucketRequest;
+@class OSSHeadObjectRequest;
+@class OSSGetBucketRequest;
+@class OSSGetBucketACLRequest;
+@class OSSGetObjectRequest;
+@class OSSGetObjectACLRequest;
+@class OSSPutObjectRequest;
+@class OSSPutObjectACLRequest;
+@class OSSDeleteObjectRequest;
+@class OSSDeleteMultipleObjectsRequest;
+@class OSSCopyObjectRequest;
+@class OSSInitMultipartUploadRequest;
+@class OSSUploadPartRequest;
+@class OSSCompleteMultipartUploadRequest;
+@class OSSListPartsRequest;
+@class OSSListMultipartUploadsRequest;
+@class OSSAbortMultipartUploadRequest;
+@class OSSAppendObjectRequest;
+@class OSSResumableUploadRequest;
+@class OSSMultipartUploadRequest;
+@class OSSCallBackRequest;
+@class OSSImagePersistRequest;
+@class OSSGetBucketInfoRequest;
+@class OSSPutSymlinkRequest;
+@class OSSGetSymlinkRequest;
+@class OSSRestoreObjectRequest;
+@class OSSGetObjectTaggingRequest;
+@class OSSDeleteObjectTaggingRequest;
+@class OSSPutObjectTaggingRequest;
+
+@class OSSTask;
+@class OSSExecutor;
+@class OSSNetworking;
+@class OSSClientConfiguration;
+@protocol OSSCredentialProvider;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ OSSClient is the entry class to access OSS in an iOS client. It provides all the methods to communicate with OSS.
+ Generally speaking, only one instance of OSSClient is needed in the whole app.
+ */
+@interface OSSClient : NSObject
+
+/**
+ OSS endpoint. It varies in different regions. Please check out OSS official website for the exact endpoints for your data.
+ */
+@property (nonatomic, strong) NSString * endpoint;
+
+/**
+ The networking instance for sending and receiving data
+ */
+@property (nonatomic, strong) OSSNetworking * networking;
+
+/**
+ The credential provider instance
+ */
+@property (nonatomic, strong) id<OSSCredentialProvider> credentialProvider;
+
+/**
+ Client configuration instance
+ */
+@property (nonatomic, strong) OSSClientConfiguration * clientConfiguration;
+
+/**
+ oss operation task queue
+ */
+@property (nonatomic, strong, readonly) OSSExecutor * ossOperationExecutor;
+
+/**
+ Initializes an OSSClient instance with the default client configuration.
+ @endpoint it specifies domain of the bucket's region. Starting 2017, the domain must be prefixed with "https://" to follow Apple's ATS policy.
+             For example: "https://oss-cn-hangzhou.aliyuncs.com"
+ @credentialProvider The credential provider
+ */
+- (instancetype)initWithEndpoint:(NSString *)endpoint
+              credentialProvider:(id<OSSCredentialProvider>) credentialProvider;
+
+/**
+ Initializes an OSSClient with the custom client configuration.
+ @endpoint it specifies domain of the bucket's region. Starting 2017, the domain must be prefixed with "https://" to follow Apple's ATS policy.
+             For example: "https://oss-cn-hangzhou.aliyuncs.com"
+ @credentialProvider The credential provider
+ @conf The custom client configuration such as retry time, timeout values, etc.
+ */
+- (instancetype)initWithEndpoint:(NSString *)endpoint
+              credentialProvider:(id<OSSCredentialProvider>)credentialProvider
+             clientConfiguration:(OSSClientConfiguration *)conf;
+
+#pragma mark restful-api
+
+/**
+ The corresponding RESTFul API: GetService
+ Gets all the buckets of the current user
+ Notes:
+ 1. STS is not supported yet in this call.
+ 2. When all buckets are returned, the xml in response body does not have nodes of Prefix, Marker, MaxKeys, IsTruncated and NextMarker.
+    If there're remaining buckets to return, the xml will have these nodes. The nextMarker is the value of marker in the next call.
+ */
+- (OSSTask *)getService:(OSSGetServiceRequest *)request;
+
+@end
+
+
+@interface OSSClient (Bucket)
+
+/**
+ The corresponding RESTFul API: PutBucket
+ Creates a bucket--it does not support anonymous access. By default, the datacenter used is oss-cn-hangzhou.
+ Callers could explicitly specify the datacenter for the bucket to optimize the performance and cost or meet the regulation requirement.
+ Notes:
+ 1. STS is not supported yet.
+ */
+- (OSSTask *)createBucket:(OSSCreateBucketRequest *)request;
+
+/**
+ The corresponding RESTFul API: DeleteBucket
+ Deletes a bucket.
+ */
+- (OSSTask *)deleteBucket:(OSSDeleteBucketRequest *)request;
+
+/**
+ The corresponding RESTFul API: GetBucket
+ Lists all objects in a bucket. It could be specified with filters such as prefix, marker, delimeter and max-keys.
+ */
+- (OSSTask *)getBucket:(OSSGetBucketRequest *)request;
+
+/**
+ The corresponding RESTFul API: GetBucketInfo
+ Gets the {@link Bucket}'s basic information as well as its ACL.
+ */
+- (OSSTask *)getBucketInfo:(OSSGetBucketInfoRequest *)request;
+
+/**
+ The corresponding RESTFul API: GetBucketACL
+ Gets the bucket ACL.
+ */
+- (OSSTask *)getBucketACL:(OSSGetBucketACLRequest *)request;
+
+@end
+
+
+@interface OSSClient (Object)
+
+/**
+ The corresponding RESTFul API: HeadObject
+ Gets the object's metadata information. The object's content is not returned.
+ */
+- (OSSTask *)headObject:(OSSHeadObjectRequest *)request;
+
+/**
+ The corresponding RESTFul API: GetObject
+ Gets the whole object (includes content). It requires caller have read permission on the object.
+ */
+- (OSSTask *)getObject:(OSSGetObjectRequest *)request;
+
+/**
+ The corresponding RESTFul API: GetObjectACL
+ get the acl of an object.
+ */
+- (OSSTask *)getObjectACL:(OSSGetObjectACLRequest *)request;
+
+/**
+ The corresponding RESTFul API: PutObject
+ Uploads a file.
+ */
+- (OSSTask *)putObject:(OSSPutObjectRequest *)request;
+
+/**
+ Sets the object's ACL. Right now an object has three access permissions: private, public-ready, public-read-write.
+ The operation specifies the x-oss-object-acl header in the put request. The caller must be the owner of the object.
+ If succeeds, it returns HTTP status 200; otherwise it returns related error code and error messages.
+ */
+- (OSSTask *)putObjectACL:(OSSPutObjectACLRequest *)request;
+
+/**
+ The corresponding RESTFul API: AppendObject
+ Appends data to an existing or non-existing object. The object created by this operation is appendable.
+ As a comparison, the object created by Put Object is normal (non-appendable).
+ */
+- (OSSTask *)appendObject:(OSSAppendObjectRequest *)request;
+
+/**
+ *  @brief      Appends data to an existing or non-existing object on the OSS server.
+ *              The object created by this operation is appendable.
+ *  @request    request
+ *  @crc64ecma  crc64ecma
+ *             if object has been stored on OSS server, you need to invoke headObject
+ *             api get object's crc64ecma,then use this api to append data to the
+ *             object.
+ */
+- (OSSTask *)appendObject:(OSSAppendObjectRequest *)request withCrc64ecma:(nullable NSString *)crc64ecma;
+
+/**
+ The corresponding RESTFul API: copyObject
+ Copies an existing object to another one.The operation sends a PUT request with x-oss-copy-source header to specify the source object.
+ OSS server side will detect and copy the object. If it succeeds, the new object's metadata information will be returned.
+ The operation applies for files less than 1GB. For big files, use UploadPartCopy RESTFul API.
+ */
+- (OSSTask *)copyObject:(OSSCopyObjectRequest *)request;
+
+/**
+ * Batch deletes the specified files under a specific bucket. If the files
+ * are non-exist, the operation will still return successful.
+ *
+ * @param request
+ *            A OSSDeleteMultipleObjectsRequest instance which specifies the
+ *            bucket and file keys to delete.
+ * @return A OSSTask with result of OSSDeleteMultipleObjectsResult instance which specifies each
+ *         file's result in normal mode or only failed deletions in quite
+ *         mode. By default it's quite mode.
+ */
+- (OSSTask *)deleteMultipleObjects:(OSSDeleteMultipleObjectsRequest *)request;
+
+/**
+ The corresponding RESTFul API: DeleteObject
+ Deletes an object
+ */
+- (OSSTask *)deleteObject:(OSSDeleteObjectRequest *)request;
+
+/**
+ * Creates a symbol link to a target file under the bucket---this is not
+ * supported for archive class bucket.
+ *
+ * @param request
+ *            A OSSPutSymlinkRequest instance that specifies the
+ *            bucket name, symlink name.
+ * @return An instance of OSSTask. On successful execution, `task.result` will
+ *         contain an instance of `OSSPutSymlinkResult`,otherwise will contain
+ *         an instance of NSError.
+ *
+ * for more information,please refer to https://help.aliyun.com/document_detail/45126.html
+ */
+- (OSSTask *)putSymlink:(OSSPutSymlinkRequest *)request;
+
+/**
+ * Gets the symlink information for the given symlink name.
+ *
+ * @param request
+ *            A OSSGetSymlinkRequest instance which specifies the bucket
+ *            name and symlink name.
+ * @return An instance of OSSTask. On successful execution, `task.result` will
+ *         contain an instance of `OSSGetSymlinkResult`,otherwise will contain
+ *         an instance of NSError.
+ *
+ * for more information,please refer to https://help.aliyun.com/document_detail/45146.html
+ */
+- (OSSTask *)getSymlink:(OSSGetSymlinkRequest *)request;
+
+/**
+ * Restores the object of archive storage. The function is not applicable to
+ * Normal or IA storage. The restoreObject() needs to be called prior to
+ * calling getObject() on an archive object.
+ *
+ * @param request
+ *          A container for the necessary parameters to execute the RestoreObject
+ *          service method.
+ *
+ * @return An instance of OSSTask. On successful execution, `task.result` will
+ *         contain an instance of `OSSRestoreObjectResult`,otherwise will contain
+ *         an instance of NSError.
+ *
+ * for more information,please refer to https://help.aliyun.com/document_detail/52930.html
+ */
+- (OSSTask *)restoreObject:(OSSRestoreObjectRequest *)request;
+
+/**
+ * You can call this operation to query the tags of an object.
+ *
+ * @param request
+ *          A OSSGetObjectTaggingRequest instance which specifies the bucket
+ *            name and object key.
+ *
+ * @return An instance of OSSTask. On successful execution, `task.result` will
+ *         contain an instance of `OSSGetObjectTaggingResult`,otherwise will contain
+ *         an instance of NSError.
+ *
+ * for more information,please refer to https://help.aliyun.com/document_detail/114878.html
+ */
+- (OSSTask *)getObjectTagging:(OSSGetObjectTaggingRequest *)request;
+
+/**
+ * You can call this operation to add tags to an object or update the tags added to
+ *  the bucket. The object tagging feature uses a key-value pair to tag an object.
+ *
+ * @param request
+ *          A OSSPutObjectTaggingRequest instance which specifies the bucket
+ *            name、object key and tags.
+ *
+ * @return An instance of OSSTask. On successful execution, `task.result` will
+ *         contain an instance of `OSSPutObjectTaggingResult`,otherwise will contain
+ *         an instance of NSError.
+ *
+ * for more information,please refer to https://help.aliyun.com/document_detail/114855.html
+ */
+- (OSSTask *)putObjectTagging:(OSSPutObjectTaggingRequest *)request;
+
+/**
+ * You can call this operation to delete the tags of a specified object.
+ *
+ * @param request
+ *          A OSSDeleteObjectTaggingRequest instance which specifies the bucket
+ *            name and object key.
+ *
+ * @return An instance of OSSTask. On successful execution, `task.result` will
+ *         contain an instance of `OSSDeleteObjectTaggingResult`,otherwise will contain
+ *         an instance of NSError.
+ *
+ * for more information,please refer to https://help.aliyun.com/document_detail/114879.html
+ */
+- (OSSTask *)deleteObjectTagging:(OSSDeleteObjectTaggingRequest *)request;
+
+
+
+@end
+
+@interface OSSClient (MultipartUpload)
+
+/**
+ The corresponding RESTFul API: InitiateMultipartUpload
+ Initiates a multipart upload to get a upload Id. It's needed before starting uploading parts data.
+ The upload Id is used for subsequential operations such as aborting the upload, querying the uploaded parts, etc.
+ */
+- (OSSTask *)multipartUploadInit:(OSSInitMultipartUploadRequest *)request;
+
+/**
+ The corresponding RESTFul API: UploadPart
+ After the multipart upload is initiated, this API could be called to upload the data to the target file with the upload Id.
+ Every uploaded part has a unique id called part number, which ranges from 1 to 10,000.
+ For a given upload Id, the part number identifies the specific range of the data in the whole file.
+ If the same part number is used for another upload, the existing data will be overwritten by the new upload.
+ Except the last part, all other part's minimal size is 100KB.
+ But no minimal size requirement on the last part.
+ */
+- (OSSTask *)uploadPart:(OSSUploadPartRequest *)request;
+
+/**
+ The corresponding RESTFul API: CompleteMultipartUpload
+ This API is to complete the multipart upload after all parts data have been uploaded.
+ It must be provided with a valid part list (each part has the part number and ETag).
+ OSS will validate every part and then complete the multipart upload.
+ If any part is invalid (e.g. the part is updated by another part upload), this API will fail.
+ */
+- (OSSTask *)completeMultipartUpload:(OSSCompleteMultipartUploadRequest *)request;
+
+/**
+ The corresponding RESTFul API: ListParts
+ Lists all uploaded parts of the specified upload id.
+ */
+- (OSSTask *)listParts:(OSSListPartsRequest *)request;
+
+/**
+ The corresponding RESTFul API: ListMultipartUploads
+ Lists all multipart uploads with the specified bucket.
+ */
+- (OSSTask *)listMultipartUploads:(OSSListMultipartUploadsRequest *)request;
+
+/**
+ The corresponding RESTFul API: AbortMultipartUpload
+ Aborts the multipart upload by the specified upload Id.
+ Once the multipart upload is aborted by this API, all parts data will be deleted and the upload Id is invalid anymore.
+ */
+- (OSSTask *)abortMultipartUpload:(OSSAbortMultipartUploadRequest *)request;
+
+- (OSSTask *)abortResumableMultipartUpload:(OSSResumableUploadRequest *)request;
+
+/**
+ Multipart upload API
+ */
+- (OSSTask *)multipartUpload:(OSSMultipartUploadRequest *)request;
+/**
+ TODOTODO
+ Resumable upload API
+ This API wraps the multipart upload and also enables resuming upload by reading/writing  the checkpoint data.
+ For a new file, multipartUploadInit() needs to be called first to get the upload Id. Then use this upload id to call this API to upload the data.
+ If the upload fails, checks the error messages:
+ If it's a recoverable error, then call this API again with the same upload Id to retry. The uploaded data will not be uploaded again.
+ Otherwise then you may need to recreates a new upload Id and call this method again.
+ Check out demo for the detail.
+ */
+- (OSSTask *)resumableUpload:(OSSResumableUploadRequest *)request;
+
+/**
+ * multipart upload sequentially in order,support resume upload
+ */
+- (OSSTask *)sequentialMultipartUpload:(OSSResumableUploadRequest *)request;
+
+@end
+
+
+@interface OSSClient (PresignURL)
+
+/**
+ Generates a signed URL for the object and anyone has this URL will get the GET permission on the object.
+ @bucketName object's bucket name
+ @objectKey Object name
+ @interval Expiration time in seconds. The URL could be specified with the expiration time to limit the access window on the object.
+ */
+- (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
+                                 withObjectKey:(NSString *)objectKey
+                        withExpirationInterval:(NSTimeInterval)interval;
+
+/**
+ Generates a signed URL for the object and anyone has this URL will get the specified permission on the object.
+ @bucketName object's bucket name
+ @objectKey Object name
+ @interval Expiration time in seconds. The URL could be specified with the expiration time to limit the access window on the object.
+ @parameter it could specify allowed HTTP methods
+ */
+- (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
+                                 withObjectKey:(NSString *)objectKey
+                        withExpirationInterval:(NSTimeInterval)interval
+                                withParameters:(NSDictionary *)parameters;
+
+/**
+ Generates a signed URL for the object and anyone has this URL will get the specified permission on the object. currently only support get and head method.
+ @bucketName object's bucket name
+ @objectKey Object name
+ @httpMethod http method.currently only support get and head.
+ @interval Expiration time in seconds. The URL could be specified with the expiration time to limit the access window on the object.
+ @parameter it could specify allowed HTTP methods
+ */
+- (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
+                                 withObjectKey:(NSString *)objectKey
+                                    httpMethod:(NSString *)method
+                        withExpirationInterval:(NSTimeInterval)interval
+                                withParameters:(NSDictionary *)parameters;
+
+
+/// Generates a signed URL for the object and anyone has this URL will get the specified permission on the object.
+/// @param bucketName object's bucket name
+/// @param objectKey Object name
+/// @param method http method.currently only support get and head.
+/// @param interval Expiration time in seconds. The URL could be specified with the expiration time to limit the access window on the object.
+/// @param parameters it could specify allowed HTTP methods
+/// @param contentType Content-Type to url sign
+/// @param contentMd5 Content-MD5 to url sign
+- (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
+                                 withObjectKey:(NSString *)objectKey
+                                    httpMethod:(NSString *)method
+                        withExpirationInterval:(NSTimeInterval)interval
+                                withParameters:(NSDictionary *)parameters
+                                   contentType:(nullable NSString *)contentType
+                                    contentMd5:(nullable NSString *)contentMd5;
+
+/// Generates a signed URL for the object and anyone has this URL will get the specified permission on the object.
+/// @param bucketName object's bucket name
+/// @param objectKey Object name
+/// @param method http method.currently only support get and head.
+/// @param interval Expiration time in seconds. The URL could be specified with the expiration time to limit the access window on the object.
+/// @param parameters it could specify allowed HTTP methods
+/// @param headers Content Type, Content-MD5, and all HTTP headers prefixed with 'x-oss-*'
+- (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
+                                 withObjectKey:(NSString *)objectKey
+                                    httpMethod:(NSString *)method
+                        withExpirationInterval:(NSTimeInterval)interval
+                                withParameters:(NSDictionary *)parameters
+                                   withHeaders:(nullable NSDictionary *)headers;
+
+/**
+ If the object's ACL is public read or public read-write, use this API to generate a signed url for sharing.
+ @bucketName Object's bucket name
+ @objectKey Object name
+ */
+- (OSSTask *)presignPublicURLWithBucketName:(NSString *)bucketName
+                              withObjectKey:(NSString *)objectKey;
+
+/** TODOTODO
+ If the object's ACL is public read or public read-write, use this API to generate a signed url for sharing.
+ @bucketName Object's bucket name
+ @objectKey Object name
+ @parameter the request parameters.
+ */
+- (OSSTask *)presignPublicURLWithBucketName:(NSString *)bucketName
+                              withObjectKey:(NSString *)objectKey
+                             withParameters:(NSDictionary *)parameters;
+
+@end
+
+
+@interface OSSClient (ImageService)
+
+/*
+ * image persist action
+ * https://help.aliyun.com/document_detail/55811.html
+ */
+- (OSSTask *)imageActionPersist:(OSSImagePersistRequest *)request;
+
+@end
+
+
+@interface OSSClient (Utilities)
+
+/**
+ Checks if the object exists
+ @bucketName Object's bucket name
+ @objectKey Object name
+ 
+ return YES                     Object exists
+ return NO && *error = nil      Object does not exist
+ return NO && *error != nil     Error occured.
+ */
+- (BOOL)doesObjectExistInBucket:(NSString *)bucketName
+                      objectKey:(NSString *)objectKey
+                          error:(const NSError **)error;
+
+@end
+
+
+@interface OSSClient (Callback)
+
+- (OSSTask *)triggerCallBack:(OSSCallBackRequest *)request;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 75 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCocoaLumberjack.h

@@ -0,0 +1,75 @@
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2010-2016, Deusty, LLC
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+//
+// * Neither the name of Deusty nor the names of its contributors may be used
+//   to endorse or promote products derived from this software without specific
+//   prior written permission of Deusty, LLC.
+
+/**
+ * Welcome to CocoaLumberjack!
+ *
+ * The project page has a wealth of documentation if you have any questions.
+ *
+ * If you're new to the project you may wish to read "Getting Started" at:
+ * Documentation/GettingStarted.md
+ *
+ * Otherwise, here is a quick refresher.
+ * There are three steps to using the macros:
+ *
+ * Step 1:
+ * Import the header in your implementation or prefix file:
+ *
+ * #import <CocoaLumberjack/CocoaLumberjack.h>
+ *
+ * Step 2:
+ * Define your logging level in your implementation file:
+ *
+ * // Log levels: off, error, warn, info, verbose
+ * static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
+ *
+ * Step 2 [3rd party frameworks]:
+ *
+ * Define your LOG_LEVEL_DEF to a different variable/function than ddLogLevel:
+ *
+ * // #undef LOG_LEVEL_DEF // Undefine first only if needed
+ * #define LOG_LEVEL_DEF myLibLogLevel
+ *
+ * Define your logging level in your implementation file:
+ *
+ * // Log levels: off, error, warn, info, verbose
+ * static const DDLogLevel myLibLogLevel = DDLogLevelVerbose;
+ *
+ * Step 3:
+ * Replace your NSLog statements with DDLog statements according to the severity of the message.
+ *
+ * NSLog(@"Fatal error, no dohickey found!"); -> OSSLogError(@"Fatal error, no dohickey found!");
+ *
+ * DDLog works exactly the same as NSLog.
+ * This means you can pass it multiple variables just like NSLog.
+ **/
+
+#import <Foundation/Foundation.h>
+
+// Disable legacy macros
+#ifndef OSSDD_LEGACY_MACROS
+    #define OSSDD_LEGACY_MACROS 0
+#endif
+
+// Core
+#import "OSSDDLog.h"
+
+// Main macros
+#import "OSSLogMacros.h"
+
+// Loggers
+#import "OSSFileLogger.h"
+#import "OSSNSLogger.h"
+

+ 85 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSCompat.h

@@ -0,0 +1,85 @@
+//
+//  OSSCompat.h
+//  oss_ios_sdk_new
+//
+//  Created by zhouzhuo on 9/10/15.
+//  Copyright (c) 2015 aliyun.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSService.h"
+
+@class OSSCancellationTokenSource;
+
+typedef OSSCancellationTokenSource OSSTaskHandler;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSClient (Compat)
+
+/**
+ The old version's upload API.
+ Please use putObject instead.
+ */
+- (OSSTaskHandler *)uploadData:(NSData *)data
+               withContentType:(NSString *)contentType
+                withObjectMeta:(NSDictionary *)meta
+                  toBucketName:(NSString *)bucketName
+                   toObjectKey:(NSString *)objectKey
+                   onCompleted:(void(^)(BOOL, NSError *))onCompleted
+                    onProgress:(void(^)(float progress))onProgress;
+
+/**
+ The old version's download API.
+ Please use getObject instead.
+ */
+- (OSSTaskHandler *)downloadToDataFromBucket:(NSString *)bucketName
+                   objectKey:(NSString *)objectKey
+                 onCompleted:(void(^)(NSData *, NSError *))onCompleted
+                  onProgress:(void(^)(float progress))onProgress;
+
+/**
+ The old version's upload API.
+ Please use putObject instead.
+ */
+- (OSSTaskHandler *)uploadFile:(NSString *)filePath
+                withContentType:(NSString *)contentType
+                 withObjectMeta:(NSDictionary *)meta
+                   toBucketName:(NSString *)bucketName
+                    toObjectKey:(NSString *)objectKey
+                    onCompleted:(void(^)(BOOL, NSError *))onCompleted
+                     onProgress:(void(^)(float progress))onProgress;
+
+/**
+ The old version's download API.
+ Please use getObject instead.
+ */
+- (OSSTaskHandler *)downloadToFileFromBucket:(NSString *)bucketName
+                  objectKey:(NSString *)objectKey
+                     toFile:(NSString *)filePath
+                onCompleted:(void(^)(BOOL, NSError *))onCompleted
+                 onProgress:(void(^)(float progress))onProgress;
+
+
+/**
+ The old version's upload API with resumable upload support.
+ Please use resumableUpload instead.
+ */
+- (OSSTaskHandler *)resumableUploadFile:(NSString *)filePath
+          withContentType:(NSString *)contentType
+           withObjectMeta:(NSDictionary *)meta
+             toBucketName:(NSString *)bucketName
+              toObjectKey:(NSString *)objectKey
+              onCompleted:(void(^)(BOOL, NSError *))onCompleted
+               onProgress:(void(^)(float progress))onProgress;
+
+/**
+ The old version's delete API.
+ Please use deleteObject instead.
+ */
+- (void)deleteObjectInBucket:(NSString *)bucketName
+                   objectKey:(NSString *)objectKey
+                 onCompleted:(void(^)(BOOL, NSError *))onCompleted;
+@end
+
+NS_ASSUME_NONNULL_END

+ 133 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSConstants.h

@@ -0,0 +1,133 @@
+//
+//  OSSConstants.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/22.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NSString* _Nullable (^OSSCustomSignContentBlock) (NSString * contentToSign, NSError **error);
+typedef NSData * _Nullable (^OSSResponseDecoderBlock) (NSData * data);
+
+typedef void (^OSSNetworkingUploadProgressBlock) (int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
+typedef void (^OSSNetworkingDownloadProgressBlock) (int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);
+typedef void (^OSSNetworkingRetryBlock) (void);
+typedef void (^OSSNetworkingCompletionHandlerBlock) (id _Nullable responseObject, NSError * _Nullable error);
+typedef void (^OSSNetworkingOnRecieveDataBlock) (NSData * data);
+
+/**
+ The flag of verification about crc64
+ */
+typedef NS_ENUM(NSUInteger, OSSRequestCRCFlag) {
+    OSSRequestCRCUninitialized,
+    OSSRequestCRCOpen,
+    OSSRequestCRCClosed
+};
+
+/**
+ Retry type definition
+ */
+typedef NS_ENUM(NSInteger, OSSNetworkingRetryType) {
+    OSSNetworkingRetryTypeUnknown,
+    OSSNetworkingRetryTypeShouldRetry,
+    OSSNetworkingRetryTypeShouldNotRetry,
+    OSSNetworkingRetryTypeShouldRefreshCredentialsAndRetry,
+    OSSNetworkingRetryTypeShouldCorrectClockSkewAndRetry
+};
+
+/**
+ * @brief: The following constants are provided by OSSNetworking as possible operation types.
+ */
+typedef NS_ENUM(NSInteger, OSSOperationType) {
+    OSSOperationTypeGetService,
+    OSSOperationTypeCreateBucket,
+    OSSOperationTypeDeleteBucket,
+    OSSOperationTypeGetBucket,
+    OSSOperationTypeGetBucketInfo,
+    OSSOperationTypeGetBucketACL,
+    OSSOperationTypeHeadObject,
+    OSSOperationTypeGetObject,
+    OSSOperationTypeGetObjectACL,
+    OSSOperationTypePutObject,
+    OSSOperationTypePutObjectACL,
+    OSSOperationTypeAppendObject,
+    OSSOperationTypeDeleteObject,
+    OSSOperationTypeDeleteMultipleObjects,
+    OSSOperationTypeCopyObject,
+    OSSOperationTypeInitMultipartUpload,
+    OSSOperationTypeUploadPart,
+    OSSOperationTypeCompleteMultipartUpload,
+    OSSOperationTypeAbortMultipartUpload,
+    OSSOperationTypeListMultipart,
+    OSSOperationTypeListMultipartUploads,
+    OSSOperationTypeTriggerCallBack,
+    OSSOperationTypeImagePersist,
+    OSSOperationTypeRestoreObject,
+    OSSOperationTypePutSymlink,
+    OSSOperationTypeGetSymlink,
+    OSSOperationTypeGetObjectTagging,
+    OSSOperationTypePutObjectTagging,
+    OSSOperationTypeDeleteObjectTagging,
+};
+
+/**
+ * @brief: The following constants are provided by OSSClient as possible error codes.
+ */
+typedef NS_ENUM(NSInteger, OSSClientErrorCODE) {
+    OSSClientErrorCodeNetworkingFailWithResponseCode0,
+    OSSClientErrorCodeSignFailed,
+    OSSClientErrorCodeFileCantWrite,
+    OSSClientErrorCodeInvalidArgument,
+    OSSClientErrorCodeNilUploadid,
+    OSSClientErrorCodeTaskCancelled,
+    OSSClientErrorCodeNetworkError,
+    OSSClientErrorCodeInvalidCRC,
+    OSSClientErrorCodeCannotResumeUpload,
+    OSSClientErrorCodeExcpetionCatched,
+    OSSClientErrorCodeNotKnown,
+    OSSClientErrorCodeFileCantRead
+};
+
+typedef NS_ENUM(NSInteger, OSSXMLDictionaryAttributesMode)
+{
+    OSSXMLDictionaryAttributesModePrefixed = 0, //default
+    OSSXMLDictionaryAttributesModeDictionary,
+    OSSXMLDictionaryAttributesModeUnprefixed,
+    OSSXMLDictionaryAttributesModeDiscard
+};
+
+
+typedef NS_ENUM(NSInteger, OSSXMLDictionaryNodeNameMode)
+{
+    OSSXMLDictionaryNodeNameModeRootOnly = 0, //default
+    OSSXMLDictionaryNodeNameModeAlways,
+    OSSXMLDictionaryNodeNameModeNever
+};
+
+typedef NS_ENUM(NSInteger, OSSBucketStorageClass)
+{
+    OSSBucketStorageClassStandard,
+    OSSBucketStorageClassIA,
+    OSSBucketStorageClassArchive
+};
+
+typedef NSString * OSSXMLDictionaryAttributeName NS_EXTENSIBLE_STRING_ENUM;
+
+OBJC_EXTERN OSSXMLDictionaryAttributeName const OSSXMLDictionaryAttributesKey;
+OBJC_EXTERN OSSXMLDictionaryAttributeName const OSSXMLDictionaryCommentsKey;
+OBJC_EXTERN OSSXMLDictionaryAttributeName const OSSXMLDictionaryTextKey;
+OBJC_EXTERN OSSXMLDictionaryAttributeName const OSSXMLDictionaryNodeNameKey;
+OBJC_EXTERN OSSXMLDictionaryAttributeName const OSSXMLDictionaryAttributePrefix;
+
+OBJC_EXTERN NSString * const OSSHTTPMethodHEAD;
+OBJC_EXTERN NSString * const OSSHTTPMethodGET;
+OBJC_EXTERN NSString * const OSSHTTPMethodPUT;
+OBJC_EXTERN NSString * const OSSHTTPMethodPOST;
+OBJC_EXTERN NSString * const OSSHTTPMethodDELETE;
+
+
+NS_ASSUME_NONNULL_END

+ 860 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDDLog.h

@@ -0,0 +1,860 @@
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2010-2016, Deusty, LLC
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+//
+// * Neither the name of Deusty nor the names of its contributors may be used
+//   to endorse or promote products derived from this software without specific
+//   prior written permission of Deusty, LLC.
+
+#import <Foundation/Foundation.h>
+
+// Enable 1.9.x legacy macros if imported directly
+#ifndef OSSDD_LEGACY_MACROS
+    #define OSSDD_LEGACY_MACROS 1
+#endif
+
+#if OS_OBJECT_USE_OBJC
+    #define DISPATCH_QUEUE_REFERENCE_TYPE strong
+#else
+    #define DISPATCH_QUEUE_REFERENCE_TYPE assign
+#endif
+
+@class OSSDDLogMessage;
+@class OSSDDLoggerInformation;
+@protocol OSSDDLogger;
+@protocol OSSDDLogFormatter;
+
+/**
+ * Define the standard options.
+ *
+ * We default to only 4 levels because it makes it easier for beginners
+ * to make the transition to a logging framework.
+ *
+ * More advanced users may choose to completely customize the levels (and level names) to suite their needs.
+ * For more information on this see the "Custom Log Levels" page:
+ * Documentation/CustomLogLevels.md
+ *
+ * Advanced users may also notice that we're using a bitmask.
+ * This is to allow for custom fine grained logging:
+ * Documentation/FineGrainedLogging.md
+ *
+ * -- Flags --
+ *
+ * Typically you will use the LOG_LEVELS (see below), but the flags may be used directly in certain situations.
+ * For example, say you have a lot of warning log messages, and you wanted to disable them.
+ * However, you still needed to see your error and info log messages.
+ * You could accomplish that with the following:
+ *
+ * static const DDLogLevel ddLogLevel = DDLogFlagError | DDLogFlagInfo;
+ *
+ * When LOG_LEVEL_DEF is defined as ddLogLevel.
+ *
+ * Flags may also be consulted when writing custom log formatters,
+ * as the DDLogMessage class captures the individual flag that caused the log message to fire.
+ *
+ * -- Levels --
+ *
+ * Log levels are simply the proper bitmask of the flags.
+ *
+ * -- Booleans --
+ *
+ * The booleans may be used when your logging code involves more than one line.
+ * For example:
+ *
+ * if (LOG_VERBOSE) {
+ *     for (id sprocket in sprockets)
+ *         DDLogVerbose(@"sprocket: %@", [sprocket description])
+ * }
+ *
+ * -- Async --
+ *
+ * Defines the default asynchronous options.
+ * The default philosophy for asynchronous logging is very simple:
+ *
+ * Log messages with errors should be executed synchronously.
+ *     After all, an error just occurred. The application could be unstable.
+ *
+ * All other log messages, such as debug output, are executed asynchronously.
+ *     After all, if it wasn't an error, then it was just informational output,
+ *     or something the application was easily able to recover from.
+ *
+ * -- Changes --
+ *
+ * You are strongly discouraged from modifying this file.
+ * If you do, you make it more difficult on yourself to merge future bug fixes and improvements from the project.
+ * Instead, create your own MyLogging.h or ApplicationNameLogging.h or CompanyLogging.h
+ *
+ * For an example of customizing your logging experience, see the "Custom Log Levels" page:
+ * Documentation/CustomLogLevels.md
+ **/
+
+/**
+ *  Flags accompany each log. They are used together with levels to filter out logs.
+ */
+typedef NS_OPTIONS(NSUInteger, OSSDDLogFlag){
+    /**
+     *  0...00001 DDLogFlagError
+     */
+    OSSDDLogFlagError      = (1 << 0),
+    
+    /**
+     *  0...00010 DDLogFlagWarning
+     */
+    OSSDDLogFlagWarning    = (1 << 1),
+    
+    /**
+     *  0...00100 DDLogFlagInfo
+     */
+    OSSDDLogFlagInfo       = (1 << 2),
+    
+    /**
+     *  0...01000 DDLogFlagDebug
+     */
+    OSSDDLogFlagDebug      = (1 << 3),
+    
+    /**
+     *  0...10000 DDLogFlagVerbose
+     */
+    OSSDDLogFlagVerbose    = (1 << 4)
+};
+
+/**
+ *  Log levels are used to filter out logs. Used together with flags.
+ */
+typedef NS_ENUM(NSUInteger, OSSDDLogLevel){
+    /**
+     *  No logs
+     */
+    OSSDDLogLevelOff       = 0,
+    
+    /**
+     *  Error logs only
+     */
+    OSSDDLogLevelError     = (OSSDDLogFlagError),
+    
+    /**
+     *  Error and warning logs
+     */
+    OSSDDLogLevelWarning   = (OSSDDLogLevelError   | OSSDDLogFlagWarning),
+    
+    /**
+     *  Error, warning and info logs
+     */
+    OSSDDLogLevelInfo      = (OSSDDLogLevelWarning | OSSDDLogFlagInfo),
+    
+    /**
+     *  Error, warning, info and debug logs
+     */
+    OSSDDLogLevelDebug     = (OSSDDLogLevelInfo    | OSSDDLogFlagDebug),
+    
+    /**
+     *  Error, warning, info, debug and verbose logs
+     */
+    OSSDDLogLevelVerbose   = (OSSDDLogLevelDebug   | OSSDDLogFlagVerbose),
+    
+    /**
+     *  All logs (1...11111)
+     */
+    OSSDDLogLevelAll       = NSUIntegerMax
+};
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ *  Extracts just the file name, no path or extension
+ *
+ *  @param filePath input file path
+ *  @param copy     YES if we want the result to be copied
+ *
+ *  @return the file name
+ */
+NSString * __nullable OSSDDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
+
+/**
+ * The THIS_FILE macro gives you an NSString of the file name.
+ * For simplicity and clarity, the file name does not include the full path or file extension.
+ *
+ * For example: DDLogWarn(@"%@: Unable to find thingy", THIS_FILE) -> @"MyViewController: Unable to find thingy"
+ **/
+#define THIS_FILE         (DDExtractFileNameWithoutExtension(__FILE__, NO))
+
+/**
+ * The THIS_METHOD macro gives you the name of the current objective-c method.
+ *
+ * For example: DDLogWarn(@"%@ - Requires non-nil strings", THIS_METHOD) -> @"setMake:model: requires non-nil strings"
+ *
+ * Note: This does NOT work in straight C functions (non objective-c).
+ * Instead you should use the predefined __FUNCTION__ macro.
+ **/
+#define THIS_METHOD       NSStringFromSelector(_cmd)
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  The main class, exposes all logging mechanisms, loggers, ...
+ *  For most of the users, this class is hidden behind the logging functions like `DDLogInfo`
+ */
+@interface OSSDDLog : NSObject
+
+/**
+ *  Returns the singleton `DDLog`.
+ *  The instance is used by `DDLog` class methods.
+ */
+@property (class, nonatomic, strong, readonly) OSSDDLog *sharedInstance;
+
+/**
+ * Provides access to the underlying logging queue.
+ * This may be helpful to Logger classes for things like thread synchronization.
+ **/
+@property (class, nonatomic, DISPATCH_QUEUE_REFERENCE_TYPE, readonly) dispatch_queue_t loggingQueue;
+
+/**
+ * Logging Primitive.
+ *
+ * This method is used by the macros or logging functions.
+ * It is suggested you stick with the macros as they're easier to use.
+ *
+ *  @param asynchronous YES if the logging is done async, NO if you want to force sync
+ *  @param level        the log level
+ *  @param flag         the log flag
+ *  @param context      the context (if any is defined)
+ *  @param file         the current file
+ *  @param function     the current function
+ *  @param line         the current code line
+ *  @param tag          potential tag
+ *  @param format       the log format
+ */
++ (void)log:(BOOL)asynchronous
+      level:(OSSDDLogLevel)level
+       flag:(OSSDDLogFlag)flag
+    context:(NSInteger)context
+       file:(const char *)file
+   function:(const char *)function
+       line:(NSUInteger)line
+        tag:(id __nullable)tag
+     format:(NSString *)format, ... NS_FORMAT_FUNCTION(9,10);
+
+/**
+ * Logging Primitive.
+ *
+ * This method is used by the macros or logging functions.
+ * It is suggested you stick with the macros as they're easier to use.
+ *
+ *  @param asynchronous YES if the logging is done async, NO if you want to force sync
+ *  @param level        the log level
+ *  @param flag         the log flag
+ *  @param context      the context (if any is defined)
+ *  @param file         the current file
+ *  @param function     the current function
+ *  @param line         the current code line
+ *  @param tag          potential tag
+ *  @param format       the log format
+ */
+- (void)log:(BOOL)asynchronous
+      level:(OSSDDLogLevel)level
+       flag:(OSSDDLogFlag)flag
+    context:(NSInteger)context
+       file:(const char *)file
+   function:(const char *)function
+       line:(NSUInteger)line
+        tag:(id __nullable)tag
+     format:(NSString *)format, ... NS_FORMAT_FUNCTION(9,10);
+
+/**
+ * Logging Primitive.
+ *
+ * This method can be used if you have a prepared va_list.
+ * Similar to `log:level:flag:context:file:function:line:tag:format:...`
+ *
+ *  @param asynchronous YES if the logging is done async, NO if you want to force sync
+ *  @param level        the log level
+ *  @param flag         the log flag
+ *  @param context      the context (if any is defined)
+ *  @param file         the current file
+ *  @param function     the current function
+ *  @param line         the current code line
+ *  @param tag          potential tag
+ *  @param format       the log format
+ *  @param argList      the arguments list as a va_list
+ */
++ (void)log:(BOOL)asynchronous
+      level:(OSSDDLogLevel)level
+       flag:(OSSDDLogFlag)flag
+    context:(NSInteger)context
+       file:(const char *)file
+   function:(const char *)function
+       line:(NSUInteger)line
+        tag:(id __nullable)tag
+     format:(NSString *)format
+       args:(va_list)argList NS_SWIFT_NAME(log(asynchronous:level:flag:context:file:function:line:tag:format:arguments:));
+
+/**
+ * Logging Primitive.
+ *
+ * This method can be used if you have a prepared va_list.
+ * Similar to `log:level:flag:context:file:function:line:tag:format:...`
+ *
+ *  @param asynchronous YES if the logging is done async, NO if you want to force sync
+ *  @param level        the log level
+ *  @param flag         the log flag
+ *  @param context      the context (if any is defined)
+ *  @param file         the current file
+ *  @param function     the current function
+ *  @param line         the current code line
+ *  @param tag          potential tag
+ *  @param format       the log format
+ *  @param argList      the arguments list as a va_list
+ */
+- (void)log:(BOOL)asynchronous
+      level:(OSSDDLogLevel)level
+       flag:(OSSDDLogFlag)flag
+    context:(NSInteger)context
+       file:(const char *)file
+   function:(const char *)function
+       line:(NSUInteger)line
+        tag:(id __nullable)tag
+     format:(NSString *)format
+       args:(va_list)argList NS_SWIFT_NAME(log(asynchronous:level:flag:context:file:function:line:tag:format:arguments:));
+
+/**
+ * Logging Primitive.
+ *
+ * This method can be used if you manualy prepared DDLogMessage.
+ *
+ *  @param asynchronous YES if the logging is done async, NO if you want to force sync
+ *  @param logMessage   the log message stored in a `DDLogMessage` model object
+ */
++ (void)log:(BOOL)asynchronous
+    message:(OSSDDLogMessage *)logMessage NS_SWIFT_NAME(log(asynchronous:message:));
+
+/**
+ * Logging Primitive.
+ *
+ * This method can be used if you manualy prepared DDLogMessage.
+ *
+ *  @param asynchronous YES if the logging is done async, NO if you want to force sync
+ *  @param logMessage   the log message stored in a `DDLogMessage` model object
+ */
+- (void)log:(BOOL)asynchronous
+    message:(OSSDDLogMessage *)logMessage NS_SWIFT_NAME(log(asynchronous:message:));
+
+/**
+ * Since logging can be asynchronous, there may be times when you want to flush the logs.
+ * The framework invokes this automatically when the application quits.
+ **/
++ (void)flushLog;
+
+/**
+ * Since logging can be asynchronous, there may be times when you want to flush the logs.
+ * The framework invokes this automatically when the application quits.
+ **/
+- (void)flushLog;
+
+/**
+ * Loggers
+ *
+ * In order for your log statements to go somewhere, you should create and add a logger.
+ *
+ * You can add multiple loggers in order to direct your log statements to multiple places.
+ * And each logger can be configured separately.
+ * So you could have, for example, verbose logging to the console, but a concise log file with only warnings & errors.
+ **/
+
+/**
+ * Adds the logger to the system.
+ *
+ * This is equivalent to invoking `[DDLog addLogger:logger withLogLevel:DDLogLevelAll]`.
+ **/
++ (void)addLogger:(id <OSSDDLogger>)logger;
+
+/**
+ * Adds the logger to the system.
+ *
+ * This is equivalent to invoking `[DDLog addLogger:logger withLogLevel:DDLogLevelAll]`.
+ **/
+- (void)addLogger:(id <OSSDDLogger>)logger;
+
+/**
+ * Adds the logger to the system.
+ *
+ * The level that you provide here is a preemptive filter (for performance).
+ * That is, the level specified here will be used to filter out logMessages so that
+ * the logger is never even invoked for the messages.
+ *
+ * More information:
+ * When you issue a log statement, the logging framework iterates over each logger,
+ * and checks to see if it should forward the logMessage to the logger.
+ * This check is done using the level parameter passed to this method.
+ *
+ * For example:
+ *
+ * `[DDLog addLogger:consoleLogger withLogLevel:DDLogLevelVerbose];`
+ * `[DDLog addLogger:fileLogger    withLogLevel:DDLogLevelWarning];`
+ *
+ * `DDLogError(@"oh no");` => gets forwarded to consoleLogger & fileLogger
+ * `DDLogInfo(@"hi");`     => gets forwarded to consoleLogger only
+ *
+ * It is important to remember that Lumberjack uses a BITMASK.
+ * Many developers & third party frameworks may define extra log levels & flags.
+ * For example:
+ *
+ * `#define SOME_FRAMEWORK_LOG_FLAG_TRACE (1 << 6) // 0...1000000`
+ *
+ * So if you specify `DDLogLevelVerbose` to this method, you won't see the framework's trace messages.
+ *
+ * `(SOME_FRAMEWORK_LOG_FLAG_TRACE & DDLogLevelVerbose) => (01000000 & 00011111) => NO`
+ *
+ * Consider passing `DDLogLevelAll` to this method, which has all bits set.
+ * You can also use the exclusive-or bitwise operator to get a bitmask that has all flags set,
+ * except the ones you explicitly don't want. For example, if you wanted everything except verbose & debug:
+ *
+ * `((DDLogLevelAll ^ DDLogLevelVerbose) | DDLogLevelInfo)`
+ **/
++ (void)addLogger:(id <OSSDDLogger>)logger withLevel:(OSSDDLogLevel)level;
+
+/**
+ * Adds the logger to the system.
+ *
+ * The level that you provide here is a preemptive filter (for performance).
+ * That is, the level specified here will be used to filter out logMessages so that
+ * the logger is never even invoked for the messages.
+ *
+ * More information:
+ * When you issue a log statement, the logging framework iterates over each logger,
+ * and checks to see if it should forward the logMessage to the logger.
+ * This check is done using the level parameter passed to this method.
+ *
+ * For example:
+ *
+ * `[DDLog addLogger:consoleLogger withLogLevel:DDLogLevelVerbose];`
+ * `[DDLog addLogger:fileLogger    withLogLevel:DDLogLevelWarning];`
+ *
+ * `DDLogError(@"oh no");` => gets forwarded to consoleLogger & fileLogger
+ * `DDLogInfo(@"hi");`     => gets forwarded to consoleLogger only
+ *
+ * It is important to remember that Lumberjack uses a BITMASK.
+ * Many developers & third party frameworks may define extra log levels & flags.
+ * For example:
+ *
+ * `#define SOME_FRAMEWORK_LOG_FLAG_TRACE (1 << 6) // 0...1000000`
+ *
+ * So if you specify `DDLogLevelVerbose` to this method, you won't see the framework's trace messages.
+ *
+ * `(SOME_FRAMEWORK_LOG_FLAG_TRACE & DDLogLevelVerbose) => (01000000 & 00011111) => NO`
+ *
+ * Consider passing `DDLogLevelAll` to this method, which has all bits set.
+ * You can also use the exclusive-or bitwise operator to get a bitmask that has all flags set,
+ * except the ones you explicitly don't want. For example, if you wanted everything except verbose & debug:
+ *
+ * `((DDLogLevelAll ^ DDLogLevelVerbose) | DDLogLevelInfo)`
+ **/
+- (void)addLogger:(id <OSSDDLogger>)logger withLevel:(OSSDDLogLevel)level;
+
+/**
+ *  Remove the logger from the system
+ */
++ (void)removeLogger:(id <OSSDDLogger>)logger;
+
+/**
+ *  Remove the logger from the system
+ */
+- (void)removeLogger:(id <OSSDDLogger>)logger;
+
+/**
+ *  Remove all the current loggers
+ */
++ (void)removeAllLoggers;
+
+/**
+ *  Remove all the current loggers
+ */
+- (void)removeAllLoggers;
+
+/**
+ *  Return all the current loggers
+ */
+@property (class, nonatomic, copy, readonly) NSArray<id<OSSDDLogger>> *allLoggers;
+
+/**
+ *  Return all the current loggers
+ */
+@property (nonatomic, copy, readonly) NSArray<id<OSSDDLogger>> *allLoggers;
+
+/**
+ *  Return all the current loggers with their level (aka DDLoggerInformation).
+ */
+@property (class, nonatomic, copy, readonly) NSArray<OSSDDLoggerInformation *> *allLoggersWithLevel;
+
+/**
+ *  Return all the current loggers with their level (aka DDLoggerInformation).
+ */
+@property (nonatomic, copy, readonly) NSArray<OSSDDLoggerInformation *> *allLoggersWithLevel;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  This protocol describes a basic logger behavior. 
+ *  Basically, it can log messages, store a logFormatter plus a bunch of optional behaviors.
+ *  (i.e. flush, get its loggerQueue, get its name, ...
+ */
+@protocol OSSDDLogger <NSObject>
+
+/**
+ *  The log message method
+ *
+ *  @param logMessage the message (model)
+ */
+- (void)logMessage:(OSSDDLogMessage *)logMessage NS_SWIFT_NAME(log(message:));
+
+/**
+ * Formatters may optionally be added to any logger.
+ *
+ * If no formatter is set, the logger simply logs the message as it is given in logMessage,
+ * or it may use its own built in formatting style.
+ **/
+@property (nonatomic, strong) id <OSSDDLogFormatter> logFormatter;
+
+@optional
+
+/**
+ * Since logging is asynchronous, adding and removing loggers is also asynchronous.
+ * In other words, the loggers are added and removed at appropriate times with regards to log messages.
+ *
+ * - Loggers will not receive log messages that were executed prior to when they were added.
+ * - Loggers will not receive log messages that were executed after they were removed.
+ *
+ * These methods are executed in the logging thread/queue.
+ * This is the same thread/queue that will execute every logMessage: invocation.
+ * Loggers may use these methods for thread synchronization or other setup/teardown tasks.
+ **/
+- (void)didAddLogger;
+
+/**
+ * Since logging is asynchronous, adding and removing loggers is also asynchronous.
+ * In other words, the loggers are added and removed at appropriate times with regards to log messages.
+ *
+ * - Loggers will not receive log messages that were executed prior to when they were added.
+ * - Loggers will not receive log messages that were executed after they were removed.
+ *
+ * These methods are executed in the logging thread/queue given in parameter.
+ * This is the same thread/queue that will execute every logMessage: invocation.
+ * Loggers may use the queue parameter to set specific values on the queue with dispatch_set_specific() function.
+ **/
+- (void)didAddLoggerInQueue:(dispatch_queue_t)queue;
+
+/**
+ *  See the above description for `didAddLoger`
+ */
+- (void)willRemoveLogger;
+
+/**
+ * Some loggers may buffer IO for optimization purposes.
+ * For example, a database logger may only save occasionaly as the disk IO is slow.
+ * In such loggers, this method should be implemented to flush any pending IO.
+ *
+ * This allows invocations of DDLog's flushLog method to be propogated to loggers that need it.
+ *
+ * Note that DDLog's flushLog method is invoked automatically when the application quits,
+ * and it may be also invoked manually by the developer prior to application crashes, or other such reasons.
+ **/
+- (void)flush;
+
+/**
+ * Each logger is executed concurrently with respect to the other loggers.
+ * Thus, a dedicated dispatch queue is used for each logger.
+ * Logger implementations may optionally choose to provide their own dispatch queue.
+ **/
+@property (nonatomic, DISPATCH_QUEUE_REFERENCE_TYPE, readonly) dispatch_queue_t loggerQueue;
+
+/**
+ * If the logger implementation does not choose to provide its own queue,
+ * one will automatically be created for it.
+ * The created queue will receive its name from this method.
+ * This may be helpful for debugging or profiling reasons.
+ **/
+@property (nonatomic, readonly) NSString *loggerName;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  This protocol describes the behavior of a log formatter
+ */
+@protocol OSSDDLogFormatter <NSObject>
+@required
+
+/**
+ * Formatters may optionally be added to any logger.
+ * This allows for increased flexibility in the logging environment.
+ * For example, log messages for log files may be formatted differently than log messages for the console.
+ *
+ * For more information about formatters, see the "Custom Formatters" page:
+ * Documentation/CustomFormatters.md
+ *
+ * The formatter may also optionally filter the log message by returning nil,
+ * in which case the logger will not log the message.
+ **/
+- (NSString * __nullable)formatLogMessage:(OSSDDLogMessage *)logMessage NS_SWIFT_NAME(format(message:));
+
+@optional
+
+/**
+ * A single formatter instance can be added to multiple loggers.
+ * These methods provides hooks to notify the formatter of when it's added/removed.
+ *
+ * This is primarily for thread-safety.
+ * If a formatter is explicitly not thread-safe, it may wish to throw an exception if added to multiple loggers.
+ * Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter),
+ * it could possibly use these hooks to switch to thread-safe versions of the code.
+ **/
+- (void)didAddToLogger:(id <OSSDDLogger>)logger;
+
+/**
+ * A single formatter instance can be added to multiple loggers.
+ * These methods provides hooks to notify the formatter of when it's added/removed.
+ *
+ * This is primarily for thread-safety.
+ * If a formatter is explicitly not thread-safe, it may wish to throw an exception if added to multiple loggers.
+ * Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter),
+ * it could possibly use these hooks to switch to thread-safe versions of the code or use dispatch_set_specific()
+.* to add its own specific values.
+ **/
+- (void)didAddToLogger:(id <OSSDDLogger>)logger inQueue:(dispatch_queue_t)queue;
+
+/**
+ *  See the above description for `didAddToLogger:`
+ */
+- (void)willRemoveFromLogger:(id <OSSDDLogger>)logger;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  This protocol describes a dynamic logging component
+ */
+@protocol OSSDDRegisteredDynamicLogging
+
+/**
+ * Implement these methods to allow a file's log level to be managed from a central location.
+ *
+ * This is useful if you'd like to be able to change log levels for various parts
+ * of your code from within the running application.
+ *
+ * Imagine pulling up the settings for your application,
+ * and being able to configure the logging level on a per file basis.
+ *
+ * The implementation can be very straight-forward:
+ *
+ * ```
+ * + (int)ddLogLevel
+ * {
+ *     return ddLogLevel;
+ * }
+ *
+ * + (void)ddSetLogLevel:(DDLogLevel)level
+ * {
+ *     ddLogLevel = level;
+ * }
+ * ```
+ **/
+@property (class, nonatomic, readwrite, setter=ddSetLogLevel:) OSSDDLogLevel ossLogLevel;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef NS_DESIGNATED_INITIALIZER
+    #define NS_DESIGNATED_INITIALIZER
+#endif
+
+/**
+ *  Log message options, allow copying certain log elements
+ */
+typedef NS_OPTIONS(NSInteger, OSSDDLogMessageOptions){
+    /**
+     *  Use this to use a copy of the file path
+     */
+    OSSDDLogMessageCopyFile        = 1 << 0,
+    /**
+     *  Use this to use a copy of the function name
+     */
+    OSSDDLogMessageCopyFunction    = 1 << 1,
+    /**
+     *  Use this to use avoid a copy of the message
+     */
+    OSSDDLogMessageDontCopyMessage = 1 << 2
+};
+
+/**
+ * The `DDLogMessage` class encapsulates information about the log message.
+ * If you write custom loggers or formatters, you will be dealing with objects of this class.
+ **/
+@interface OSSDDLogMessage : NSObject <NSCopying>
+{
+    // Direct accessors to be used only for performance
+    @public
+    NSString *_message;
+    OSSDDLogLevel _level;
+    OSSDDLogFlag _flag;
+    NSInteger _context;
+    NSString *_file;
+    NSString *_fileName;
+    NSString *_function;
+    NSUInteger _line;
+    id _tag;
+    OSSDDLogMessageOptions _options;
+    NSDate *_timestamp;
+    NSString *_threadID;
+    NSString *_threadName;
+    NSString *_queueLabel;
+}
+
+/**
+ *  Default `init` for empty messages.
+ */
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Standard init method for a log message object.
+ * Used by the logging primitives. (And the macros use the logging primitives.)
+ *
+ * If you find need to manually create logMessage objects, there is one thing you should be aware of:
+ *
+ * If no flags are passed, the method expects the file and function parameters to be string literals.
+ * That is, it expects the given strings to exist for the duration of the object's lifetime,
+ * and it expects the given strings to be immutable.
+ * In other words, it does not copy these strings, it simply points to them.
+ * This is due to the fact that __FILE__ and __FUNCTION__ are usually used to specify these parameters,
+ * so it makes sense to optimize and skip the unnecessary allocations.
+ * However, if you need them to be copied you may use the options parameter to specify this.
+ *
+ *  @param message   the message
+ *  @param level     the log level
+ *  @param flag      the log flag
+ *  @param context   the context (if any is defined)
+ *  @param file      the current file
+ *  @param function  the current function
+ *  @param line      the current code line
+ *  @param tag       potential tag
+ *  @param options   a bitmask which supports DDLogMessageCopyFile and DDLogMessageCopyFunction.
+ *  @param timestamp the log timestamp
+ *
+ *  @return a new instance of a log message model object
+ */
+- (instancetype)initWithMessage:(NSString *)message
+                          level:(OSSDDLogLevel)level
+                           flag:(OSSDDLogFlag)flag
+                        context:(NSInteger)context
+                           file:(NSString *)file
+                       function:(NSString * __nullable)function
+                           line:(NSUInteger)line
+                            tag:(id __nullable)tag
+                        options:(OSSDDLogMessageOptions)options
+                      timestamp:(NSDate * __nullable)timestamp NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Read-only properties
+ **/
+
+/**
+ *  The log message
+ */
+@property (readonly, nonatomic) NSString *message;
+@property (readonly, nonatomic) OSSDDLogLevel level;
+@property (readonly, nonatomic) OSSDDLogFlag flag;
+@property (readonly, nonatomic) NSInteger context;
+@property (readonly, nonatomic) NSString *file;
+@property (readonly, nonatomic) NSString *fileName;
+@property (readonly, nonatomic) NSString * __nullable function;
+@property (readonly, nonatomic) NSUInteger line;
+@property (readonly, nonatomic) id __nullable tag;
+@property (readonly, nonatomic) OSSDDLogMessageOptions options;
+@property (readonly, nonatomic) NSDate *timestamp;
+@property (readonly, nonatomic) NSString *threadID; // ID as it appears in NSLog calculated from the machThreadID
+@property (readonly, nonatomic) NSString *threadName;
+@property (readonly, nonatomic) NSString *queueLabel;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * The `DDLogger` protocol specifies that an optional formatter can be added to a logger.
+ * Most (but not all) loggers will want to support formatters.
+ *
+ * However, writting getters and setters in a thread safe manner,
+ * while still maintaining maximum speed for the logging process, is a difficult task.
+ *
+ * To do it right, the implementation of the getter/setter has strict requiremenets:
+ * - Must NOT require the `logMessage:` method to acquire a lock.
+ * - Must NOT require the `logMessage:` method to access an atomic property (also a lock of sorts).
+ *
+ * To simplify things, an abstract logger is provided that implements the getter and setter.
+ *
+ * Logger implementations may simply extend this class,
+ * and they can ACCESS THE FORMATTER VARIABLE DIRECTLY from within their `logMessage:` method!
+ **/
+@interface OSSDDAbstractLogger : NSObject <OSSDDLogger>
+{
+    // Direct accessors to be used only for performance
+    @public
+    id <OSSDDLogFormatter> _logFormatter;
+    dispatch_queue_t _loggerQueue;
+}
+
+@property (nonatomic, strong, nullable) id <OSSDDLogFormatter> logFormatter;
+@property (nonatomic, DISPATCH_QUEUE_REFERENCE_TYPE) dispatch_queue_t loggerQueue;
+
+// For thread-safety assertions
+
+/**
+ *  Return YES if the current logger uses a global queue for logging
+ */
+@property (nonatomic, readonly, getter=isOnGlobalLoggingQueue)  BOOL onGlobalLoggingQueue;
+
+/**
+ *  Return YES if the current logger uses the internal designated queue for logging
+ */
+@property (nonatomic, readonly, getter=isOnInternalLoggerQueue) BOOL onInternalLoggerQueue;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@interface OSSDDLoggerInformation : NSObject
+
+@property (nonatomic, readonly) id <OSSDDLogger> logger;
+@property (nonatomic, readonly) OSSDDLogLevel level;
+
++ (OSSDDLoggerInformation *)informationWithLogger:(id <OSSDDLogger>)logger
+                           andLevel:(OSSDDLogLevel)level;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 85 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDefine.h

@@ -0,0 +1,85 @@
+//
+//  OSSDefine.h
+//  AliyunOSSiOS
+//
+//  Created by zhouzhuo on 5/1/16.
+//  Copyright © 2016 zhouzhuo. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#ifndef OSSDefine_h
+#define OSSDefine_h
+
+#if TARGET_OS_IOS
+#define OSSUAPrefix                             @"aliyun-sdk-ios"
+#elif TARGET_OS_OSX
+#define OSSUAPrefix                             @"aliyun-sdk-mac"
+#endif
+#define OSSSDKVersion                           @"2.10.20"
+
+#define OSSListBucketResultXMLTOKEN             @"ListBucketResult"
+#define OSSNameXMLTOKEN                         @"Name"
+#define OSSDelimiterXMLTOKEN                    @"Delimiter"
+#define OSSMarkerXMLTOKEN                       @"Marker"
+#define OSSKeyMarkerXMLTOKEN                    @"KeyMarker"
+#define OSSNextMarkerXMLTOKEN                   @"NextMarker"
+#define OSSNextKeyMarkerXMLTOKEN                @"NextKeyMarker"
+#define OSSUploadIdMarkerXMLTOKEN               @"UploadIdMarker"
+#define OSSNextUploadIdMarkerXMLTOKEN           @"NextUploadIdMarker"
+#define OSSMaxKeysXMLTOKEN                      @"MaxKeys"
+#define OSSMaxUploadsXMLTOKEN                   @"MaxUploads"
+#define OSSIsTruncatedXMLTOKEN                  @"IsTruncated"
+#define OSSContentsXMLTOKEN                     @"Contents"
+#define OSSUploadXMLTOKEN                       @"Upload"
+#define OSSKeyXMLTOKEN                          @"Key"
+#define OSSLastModifiedXMLTOKEN                 @"LastModified"
+#define OSSETagXMLTOKEN                         @"ETag"
+#define OSSTypeXMLTOKEN                         @"Type"
+#define OSSSizeXMLTOKEN                         @"Size"
+#define OSSStorageClassXMLTOKEN                 @"StorageClass"
+#define OSSCommonPrefixesXMLTOKEN               @"CommonPrefixes"
+#define OSSOwnerXMLTOKEN                        @"Owner"
+#define OSSAccessControlListXMLTOKEN            @"AccessControlList"
+#define OSSGrantXMLTOKEN                        @"Grant"
+#define OSSIDXMLTOKEN                           @"ID"
+#define OSSDisplayNameXMLTOKEN                  @"DisplayName"
+#define OSSBucketsXMLTOKEN                      @"Buckets"
+#define OSSBucketXMLTOKEN                       @"Bucket"
+#define OSSCreationDate                         @"CreationDate"
+#define OSSPrefixXMLTOKEN                       @"Prefix"
+#define OSSUploadIdXMLTOKEN                     @"UploadId"
+#define OSSLocationXMLTOKEN                     @"Location"
+#define OSSNextPartNumberMarkerXMLTOKEN         @"NextPartNumberMarker"
+#define OSSMaxPartsXMLTOKEN                     @"MaxParts"
+#define OSSPartXMLTOKEN                         @"Part"
+#define OSSPartNumberXMLTOKEN                   @"PartNumber"
+
+#define OSSClientErrorDomain                    @"com.aliyun.oss.clientError"
+#define OSSServerErrorDomain                    @"com.aliyun.oss.serverError"
+
+#define OSSErrorMessageTOKEN                    @"ErrorMessage"
+
+#define OSSHttpHeaderContentDisposition         @"Content-Disposition"
+#define OSSHttpHeaderXOSSCallback               @"x-oss-callback"
+#define OSSHttpHeaderXOSSCallbackVar            @"x-oss-callback-var"
+#define OSSHttpHeaderContentEncoding            @"Content-Encoding"
+#define OSSHttpHeaderContentType                @"Content-Type"
+#define OSSHttpHeaderContentMD5                 @"Content-MD5"
+#define OSSHttpHeaderCacheControl               @"Cache-Control"
+#define OSSHttpHeaderExpires                    @"Expires"
+#define OSSHttpHeaderHashSHA1                   @"x-oss-hash-sha1"
+#define OSSHttpHeaderBucketACL                  @"x-oss-acl"
+#define OSSHttpHeaderObjectACL                  @"x-oss-object-acl"
+#define OSSHttpHeaderCopySource                 @"x-oss-copy-source"
+#define OSSHttpHeaderSymlinkTarget              @"x-oss-symlink-target"
+
+#define OSSHttpQueryProcess                     @"x-oss-process"
+
+#define OSSDefaultRetryCount                    3
+#define OSSDefaultMaxConcurrentNum              5
+#define OSSDefaultTimeoutForRequestInSecond     15
+#define OSSDefaultTimeoutForResourceInSecond    7 * 24 * 60 * 60
+#define OSSDefaultThreadNum                     5
+
+#endif /* OSSDefine_h */

+ 31 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteMultipleObjectsRequest.h

@@ -0,0 +1,31 @@
+//
+//  OSSDeleteMultipleObjectsRequest.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/26.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+#import <Foundation/Foundation.h>
+#import "OSSRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSDeleteMultipleObjectsRequest : OSSRequest
+
+@property (nonatomic, copy) NSString *bucketName;
+
+@property (nonatomic, copy) NSArray<NSString *> *keys;
+
+/**
+ invalid value is @"url"
+ */
+@property (nonatomic, copy, nullable) NSString *encodingType;
+
+/**
+ whether to show verbose result,the default value is YES.
+ */
+@property (nonatomic, assign) BOOL quiet;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 17 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteMultipleObjectsResult.h

@@ -0,0 +1,17 @@
+//
+//  OSSDeleteMultipleObjectsResult.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/26.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+@interface OSSDeleteMultipleObjectsResult : OSSResult
+
+@property (nonatomic, copy) NSArray<NSString *> *deletedObjects;
+
+@property (nonatomic, copy) NSString *encodingType;
+
+@end

+ 23 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteObjectTaggingRequest.h

@@ -0,0 +1,23 @@
+//
+//  OSSDeleteObjectTaggingRequest.h
+//  AliyunOSSSDK
+//
+//  Created by ws on 2021/5/25.
+//  Copyright © 2021 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSDeleteObjectTaggingRequest : OSSRequest
+
+/* bucket name */
+@property (nonatomic, copy) NSString *bucketName;
+
+/* object name */
+@property (nonatomic, copy) NSString *objectKey;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 17 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSDeleteObjectTaggingResult.h

@@ -0,0 +1,17 @@
+//
+//  OSSDeleteObjectTaggingResult.h
+//  AliyunOSSSDK
+//
+//  Created by ws on 2021/5/25.
+//  Copyright © 2021 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSDeleteObjectTaggingResult : OSSResult
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 62 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSExecutor.h

@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*!
+ An object that can run a given block.
+ */
+@interface OSSExecutor : NSObject
+
+/*!
+ Returns a default executor, which runs continuations immediately until the call stack gets too
+ deep, then dispatches to a new GCD queue.
+ */
++ (instancetype)defaultExecutor;
+
+/*!
+ Returns an executor that runs continuations on the thread where the previous task was completed.
+ */
++ (instancetype)immediateExecutor;
+
+/*!
+ Returns an executor that runs continuations on the main thread.
+ */
++ (instancetype)mainThreadExecutor;
+
+/*!
+ Returns a new executor that uses the given block to execute continuations.
+ @param block The block to use.
+ */
++ (instancetype)executorWithBlock:(void(^)(void(^block)(void)))block;
+
+/*!
+ Returns a new executor that runs continuations on the given queue.
+ @param queue The instance of `dispatch_queue_t` to dispatch all continuations onto.
+ */
++ (instancetype)executorWithDispatchQueue:(dispatch_queue_t)queue;
+
+/*!
+ Returns a new executor that runs continuations on the given queue.
+ @param queue The instance of `NSOperationQueue` to run all continuations on.
+ */
++ (instancetype)executorWithOperationQueue:(NSOperationQueue *)queue;
+
+/*!
+ Runs the given block using this executor's particular strategy.
+ @param block The block to execute.
+ */
+- (void)execute:(void(^)(void))block;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 509 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSFileLogger.h

@@ -0,0 +1,509 @@
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2010-2016, Deusty, LLC
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+//
+// * Neither the name of Deusty nor the names of its contributors may be used
+//   to endorse or promote products derived from this software without specific
+//   prior written permission of Deusty, LLC.
+
+// Disable legacy macros
+#ifndef DD_LEGACY_MACROS
+    #define DD_LEGACY_MACROS 0
+#endif
+
+#import "OSSDDLog.h"
+
+@class OSSDDLogFileInfo;
+
+/**
+ * This class provides a logger to write log statements to a file.
+ **/
+
+
+// Default configuration and safety/sanity values.
+//
+// maximumFileSize         -> kDDDefaultLogMaxFileSize
+// rollingFrequency        -> kDDDefaultLogRollingFrequency
+// maximumNumberOfLogFiles -> kDDDefaultLogMaxNumLogFiles
+// logFilesDiskQuota       -> kDDDefaultLogFilesDiskQuota
+//
+// You should carefully consider the proper configuration values for your application.
+
+extern unsigned long long const osskDDDefaultLogMaxFileSize;
+extern NSTimeInterval     const osskDDDefaultLogRollingFrequency;
+extern NSUInteger         const osskDDDefaultLogMaxNumLogFiles;
+extern unsigned long long const osskDDDefaultLogFilesDiskQuota;
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  The LogFileManager protocol is designed to allow you to control all aspects of your log files.
+ *
+ *  The primary purpose of this is to allow you to do something with the log files after they have been rolled.
+ *  Perhaps you want to compress them to save disk space.
+ *  Perhaps you want to upload them to an FTP server.
+ *  Perhaps you want to run some analytics on the file.
+ *
+ *  A default LogFileManager is, of course, provided.
+ *  The default LogFileManager simply deletes old log files according to the maximumNumberOfLogFiles property.
+ *
+ *  This protocol provides various methods to fetch the list of log files.
+ *
+ *  There are two variants: sorted and unsorted.
+ *  If sorting is not necessary, the unsorted variant is obviously faster.
+ *  The sorted variant will return an array sorted by when the log files were created,
+ *  with the most recently created log file at index 0, and the oldest log file at the end of the array.
+ *
+ *  You can fetch only the log file paths (full path including name), log file names (name only),
+ *  or an array of `DDLogFileInfo` objects.
+ *  The `DDLogFileInfo` class is documented below, and provides a handy wrapper that
+ *  gives you easy access to various file attributes such as the creation date or the file size.
+ */
+@protocol OSSDDLogFileManager <NSObject>
+@required
+
+// Public properties
+
+/**
+ * The maximum number of archived log files to keep on disk.
+ * For example, if this property is set to 3,
+ * then the LogFileManager will only keep 3 archived log files (plus the current active log file) on disk.
+ * Once the active log file is rolled/archived, then the oldest of the existing 3 rolled/archived log files is deleted.
+ *
+ * You may optionally disable this option by setting it to zero.
+ **/
+@property (readwrite, assign, atomic) NSUInteger maximumNumberOfLogFiles;
+
+/**
+ * The maximum space that logs can take. On rolling logfile all old logfiles that exceed logFilesDiskQuota will
+ * be deleted.
+ *
+ * You may optionally disable this option by setting it to zero.
+ **/
+@property (readwrite, assign, atomic) unsigned long long logFilesDiskQuota;
+
+// Public methods
+
+/**
+ *  Returns the logs directory (path)
+ */
+@property (nonatomic, readonly, copy) NSString *logsDirectory;
+
+/**
+ * Returns an array of `NSString` objects,
+ * each of which is the filePath to an existing log file on disk.
+ **/
+@property (nonatomic, readonly, strong) NSArray<NSString *> *unsortedLogFilePaths;
+
+/**
+ * Returns an array of `NSString` objects,
+ * each of which is the fileName of an existing log file on disk.
+ **/
+@property (nonatomic, readonly, strong) NSArray<NSString *> *unsortedLogFileNames;
+
+/**
+ * Returns an array of `DDLogFileInfo` objects,
+ * each representing an existing log file on disk,
+ * and containing important information about the log file such as it's modification date and size.
+ **/
+@property (nonatomic, readonly, strong) NSArray<OSSDDLogFileInfo *> *unsortedLogFileInfos;
+
+/**
+ * Just like the `unsortedLogFilePaths` method, but sorts the array.
+ * The items in the array are sorted by creation date.
+ * The first item in the array will be the most recently created log file.
+ **/
+@property (nonatomic, readonly, strong) NSArray<NSString *> *sortedLogFilePaths;
+
+/**
+ * Just like the `unsortedLogFileNames` method, but sorts the array.
+ * The items in the array are sorted by creation date.
+ * The first item in the array will be the most recently created log file.
+ **/
+@property (nonatomic, readonly, strong) NSArray<NSString *> *sortedLogFileNames;
+
+/**
+ * Just like the `unsortedLogFileInfos` method, but sorts the array.
+ * The items in the array are sorted by creation date.
+ * The first item in the array will be the most recently created log file.
+ **/
+@property (nonatomic, readonly, strong) NSArray<OSSDDLogFileInfo *> *sortedLogFileInfos;
+
+// Private methods (only to be used by DDFileLogger)
+
+/**
+ * Generates a new unique log file path, and creates the corresponding log file.
+ **/
+- (NSString *)createNewLogFile;
+
+@optional
+
+// Notifications from DDFileLogger
+
+/**
+ *  Called when a log file was archieved
+ */
+- (void)didArchiveLogFile:(NSString *)logFilePath NS_SWIFT_NAME(didArchiveLogFile(atPath:));
+
+/**
+ *  Called when the roll action was executed and the log was archieved
+ */
+- (void)didRollAndArchiveLogFile:(NSString *)logFilePath NS_SWIFT_NAME(didRollAndArchiveLogFile(atPath:));
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Default log file manager.
+ *
+ * All log files are placed inside the logsDirectory.
+ * If a specific logsDirectory isn't specified, the default directory is used.
+ * On Mac, this is in `~/Library/Logs/<Application Name>`.
+ * On iPhone, this is in `~/Library/Caches/Logs`.
+ *
+ * Log files are named `"<bundle identifier> <date> <time>.log"`
+ * Example: `com.organization.myapp 2013-12-03 17-14.log`
+ *
+ * Archived log files are automatically deleted according to the `maximumNumberOfLogFiles` property.
+ **/
+@interface OSSDDLogFileManagerDefault : NSObject <OSSDDLogFileManager>
+
+/**
+ *  Default initializer
+ */
+- (instancetype)init;
+
+/**
+ *  Designated initialized, requires the logs directory
+ */
+- (instancetype)initWithLogsDirectory:(NSString *)logsDirectory NS_DESIGNATED_INITIALIZER;
+
+#if TARGET_OS_IPHONE
+/*
+ * Calling this constructor you can override the default "automagically" chosen NSFileProtection level.
+ * Useful if you are writing a command line utility / CydiaSubstrate addon for iOS that has no NSBundle
+ * or like SpringBoard no BackgroundModes key in the NSBundle:
+ *    iPhone:~ root# cycript -p SpringBoard
+ *    cy# [NSBundle mainBundle]
+ *    #"NSBundle </System/Library/CoreServices/SpringBoard.app> (loaded)"
+ *    cy# [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIBackgroundModes"];
+ *    null
+ *    cy#
+ **/
+- (instancetype)initWithLogsDirectory:(NSString *)logsDirectory defaultFileProtectionLevel:(NSFileProtectionType)fileProtectionLevel;
+#endif
+
+/*
+ * Methods to override.
+ *
+ * Log files are named `"<bundle identifier> <date> <time>.log"`
+ * Example: `com.organization.myapp 2013-12-03 17-14.log`
+ *
+ * If you wish to change default filename, you can override following two methods.
+ * - `newLogFileName` method would be called on new logfile creation.
+ * - `isLogFile:` method would be called to filter logfiles from all other files in logsDirectory.
+ *   You have to parse given filename and return YES if it is logFile.
+ *
+ * **NOTE**
+ * `newLogFileName` returns filename. If appropriate file already exists, number would be added
+ * to filename before extension. You have to handle this case in isLogFile: method.
+ *
+ * Example:
+ * - newLogFileName returns `"com.organization.myapp 2013-12-03.log"`,
+ *   file `"com.organization.myapp 2013-12-03.log"` would be created.
+ * - after some time `"com.organization.myapp 2013-12-03.log"` is archived
+ * - newLogFileName again returns `"com.organization.myapp 2013-12-03.log"`,
+ *   file `"com.organization.myapp 2013-12-03 2.log"` would be created.
+ * - after some time `"com.organization.myapp 2013-12-03 1.log"` is archived
+ * - newLogFileName again returns `"com.organization.myapp 2013-12-03.log"`,
+ *   file `"com.organization.myapp 2013-12-03 3.log"` would be created.
+ **/
+
+/**
+ * Generates log file name with default format `"<bundle identifier> <date> <time>.log"`
+ * Example: `MobileSafari 2013-12-03 17-14.log`
+ *
+ * You can change it by overriding `newLogFileName` and `isLogFile:` methods.
+ **/
+@property (readonly, copy) NSString *newLogFileName;
+
+/**
+ * Default log file name is `"<bundle identifier> <date> <time>.log"`.
+ * Example: `MobileSafari 2013-12-03 17-14.log`
+ *
+ * You can change it by overriding `newLogFileName` and `isLogFile:` methods.
+ **/
+- (BOOL)isLogFile:(NSString *)fileName NS_SWIFT_NAME(isLogFile(withName:));
+
+/* Inherited from DDLogFileManager protocol:
+
+   @property (readwrite, assign, atomic) NSUInteger maximumNumberOfLogFiles;
+   @property (readwrite, assign, atomic) NSUInteger logFilesDiskQuota;
+
+   - (NSString *)logsDirectory;
+
+   - (NSArray *)unsortedLogFilePaths;
+   - (NSArray *)unsortedLogFileNames;
+   - (NSArray *)unsortedLogFileInfos;
+
+   - (NSArray *)sortedLogFilePaths;
+   - (NSArray *)sortedLogFileNames;
+   - (NSArray *)sortedLogFileInfos;
+
+ */
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Most users will want file log messages to be prepended with the date and time.
+ * Rather than forcing the majority of users to write their own formatter,
+ * we will supply a logical default formatter.
+ * Users can easily replace this formatter with their own by invoking the `setLogFormatter:` method.
+ * It can also be removed by calling `setLogFormatter:`, and passing a nil parameter.
+ *
+ * In addition to the convenience of having a logical default formatter,
+ * it will also provide a template that makes it easy for developers to copy and change.
+ **/
+@interface OSSDDLogFileFormatterDefault : NSObject <OSSDDLogFormatter>
+
+/**
+ *  Default initializer
+ */
+- (instancetype)init;
+
+/**
+ *  Designated initializer, requires a date formatter
+ */
+- (instancetype)initWithDateFormatter:(NSDateFormatter *)dateFormatter NS_DESIGNATED_INITIALIZER;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  The standard implementation for a file logger
+ */
+@interface OSSDDFileLogger : OSSDDAbstractLogger <OSSDDLogger> {
+	OSSDDLogFileInfo *_currentLogFileInfo;
+}
+
+/**
+ *  Default initializer
+ */
+- (instancetype)init;
+
+/**
+ *  Designated initializer, requires a `DDLogFileManager` instance
+ */
+- (instancetype)initWithLogFileManager:(id <OSSDDLogFileManager>)logFileManager NS_DESIGNATED_INITIALIZER;
+
+/**
+ *  Called when the logger is about to write message. Call super before your implementation.
+ */
+- (void)willLogMessage NS_REQUIRES_SUPER;
+
+/**
+ *  Called when the logger wrote message. Call super after your implementation.
+ */
+- (void)didLogMessage NS_REQUIRES_SUPER;
+
+/**
+ *  Called when the logger checks archive or not current log file. 
+ *  Override this method to exdend standart behavior. By default returns NO.
+ */
+- (BOOL)shouldArchiveRecentLogFileInfo:(OSSDDLogFileInfo *)recentLogFileInfo;
+
+/**
+ * Log File Rolling:
+ *
+ * `maximumFileSize`:
+ *   The approximate maximum size (in bytes) to allow log files to grow.
+ *   If a log file is larger than this value after a log statement is appended,
+ *   then the log file is rolled.
+ *
+ * `rollingFrequency`
+ *   How often to roll the log file.
+ *   The frequency is given as an `NSTimeInterval`, which is a double that specifies the interval in seconds.
+ *   Once the log file gets to be this old, it is rolled.
+ *
+ * `doNotReuseLogFiles`
+ *   When set, will always create a new log file at application launch.
+ *
+ * Both the `maximumFileSize` and the `rollingFrequency` are used to manage rolling.
+ * Whichever occurs first will cause the log file to be rolled.
+ *
+ * For example:
+ * The `rollingFrequency` is 24 hours,
+ * but the log file surpasses the `maximumFileSize` after only 20 hours.
+ * The log file will be rolled at that 20 hour mark.
+ * A new log file will be created, and the 24 hour timer will be restarted.
+ *
+ * You may optionally disable rolling due to filesize by setting `maximumFileSize` to zero.
+ * If you do so, rolling is based solely on `rollingFrequency`.
+ *
+ * You may optionally disable rolling due to time by setting `rollingFrequency` to zero (or any non-positive number).
+ * If you do so, rolling is based solely on `maximumFileSize`.
+ *
+ * If you disable both `maximumFileSize` and `rollingFrequency`, then the log file won't ever be rolled.
+ * This is strongly discouraged.
+ **/
+@property (readwrite, assign) unsigned long long maximumFileSize;
+
+/**
+ *  See description for `maximumFileSize`
+ */
+@property (readwrite, assign) NSTimeInterval rollingFrequency;
+
+/**
+ *  See description for `maximumFileSize`
+ */
+@property (readwrite, assign, atomic) BOOL doNotReuseLogFiles;
+
+/**
+ * The DDLogFileManager instance can be used to retrieve the list of log files,
+ * and configure the maximum number of archived log files to keep.
+ *
+ * @see DDLogFileManager.maximumNumberOfLogFiles
+ **/
+@property (strong, nonatomic, readonly) id <OSSDDLogFileManager> logFileManager;
+
+/**
+ * When using a custom formatter you can set the `logMessage` method not to append
+ * `\n` character after each output. This allows for some greater flexibility with
+ * custom formatters. Default value is YES.
+ **/
+@property (nonatomic, readwrite, assign) BOOL automaticallyAppendNewlineForCustomFormatters;
+
+/**
+ *  You can optionally force the current log file to be rolled with this method.
+ *  CompletionBlock will be called on main queue.
+ */
+- (void)rollLogFileWithCompletionBlock:(void (^)(void))completionBlock NS_SWIFT_NAME(rollLogFile(withCompletion:));
+
+/**
+ *  Method is deprecated.
+ *  @deprecated Use `rollLogFileWithCompletionBlock:` method instead.
+ */
+- (void)rollLogFile __attribute((deprecated));
+
+// Inherited from DDAbstractLogger
+
+// - (id <DDLogFormatter>)logFormatter;
+// - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
+
+/**
+ * Returns the log file that should be used.
+ * If there is an existing log file that is suitable,
+ * within the constraints of `maximumFileSize` and `rollingFrequency`, then it is returned.
+ *
+ * Otherwise a new file is created and returned.
+ **/
+@property (nonatomic, readonly, strong) OSSDDLogFileInfo *currentLogFileInfo;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * `DDLogFileInfo` is a simple class that provides access to various file attributes.
+ * It provides good performance as it only fetches the information if requested,
+ * and it caches the information to prevent duplicate fetches.
+ *
+ * It was designed to provide quick snapshots of the current state of log files,
+ * and to help sort log files in an array.
+ *
+ * This class does not monitor the files, or update it's cached attribute values if the file changes on disk.
+ * This is not what the class was designed for.
+ *
+ * If you absolutely must get updated values,
+ * you can invoke the reset method which will clear the cache.
+ **/
+@interface OSSDDLogFileInfo : NSObject
+
+@property (strong, nonatomic, readonly) NSString *filePath;
+@property (strong, nonatomic, readonly) NSString *fileName;
+
+#if FOUNDATION_SWIFT_SDK_EPOCH_AT_LEAST(8)
+@property (strong, nonatomic, readonly) NSDictionary<NSFileAttributeKey, id> *fileAttributes;
+#else
+@property (strong, nonatomic, readonly) NSDictionary<NSString *, id> *fileAttributes;
+#endif
+
+@property (strong, nonatomic, readonly) NSDate *creationDate;
+@property (strong, nonatomic, readonly) NSDate *modificationDate;
+
+@property (nonatomic, readonly) unsigned long long fileSize;
+
+@property (nonatomic, readonly) NSTimeInterval age;
+
+@property (nonatomic, readwrite) BOOL isArchived;
+
++ (instancetype)logFileWithPath:(NSString *)filePath NS_SWIFT_UNAVAILABLE("Use init(filePath:)");
+
+- (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithFilePath:(NSString *)filePath NS_DESIGNATED_INITIALIZER;
+
+- (void)reset;
+- (void)renameFile:(NSString *)newFileName NS_SWIFT_NAME(renameFile(to:));
+
+#if TARGET_IPHONE_SIMULATOR
+
+// So here's the situation.
+// Extended attributes are perfect for what we're trying to do here (marking files as archived).
+// This is exactly what extended attributes were designed for.
+//
+// But Apple screws us over on the simulator.
+// Everytime you build-and-go, they copy the application into a new folder on the hard drive,
+// and as part of the process they strip extended attributes from our log files.
+// Normally, a copy of a file preserves extended attributes.
+// So obviously Apple has gone to great lengths to piss us off.
+//
+// Thus we use a slightly different tactic for marking log files as archived in the simulator.
+// That way it "just works" and there's no confusion when testing.
+//
+// The difference in method names is indicative of the difference in functionality.
+// On the simulator we add an attribute by appending a filename extension.
+//
+// For example:
+// "mylog.txt" -> "mylog.archived.txt"
+// "mylog"     -> "mylog.archived"
+
+- (BOOL)hasExtensionAttributeWithName:(NSString *)attrName;
+
+- (void)addExtensionAttributeWithName:(NSString *)attrName;
+- (void)removeExtensionAttributeWithName:(NSString *)attrName;
+
+#else /* if TARGET_IPHONE_SIMULATOR */
+
+// Normal use of extended attributes used everywhere else,
+// such as on Macs and on iPhone devices.
+
+- (BOOL)hasExtendedAttributeWithName:(NSString *)attrName;
+
+- (void)addExtendedAttributeWithName:(NSString *)attrName;
+- (void)removeExtendedAttributeWithName:(NSString *)attrName;
+
+#endif /* if TARGET_IPHONE_SIMULATOR */
+
+@end

+ 15 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetBucketInfoRequest.h

@@ -0,0 +1,15 @@
+//
+//  OSSGetBucketInfoRequest.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/7/10.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+@interface OSSGetBucketInfoRequest : OSSRequest
+
+@property (nonatomic, copy) NSString *bucketName;
+
+@end

+ 57 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetBucketInfoResult.h

@@ -0,0 +1,57 @@
+//
+//  OSSGetBucketInfoResult.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/7/10.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+@interface OSSBucketOwner : NSObject
+
+@property (nonatomic, copy) NSString *userName;
+
+@property (nonatomic, copy) NSString *userId;
+
+@end
+
+@interface OSSAccessControlList : NSObject
+
+@property (nonatomic, copy) NSString *grant;
+
+@end
+
+
+
+@interface OSSGetBucketInfoResult : OSSResult
+
+/// Created date.
+@property (nonatomic, copy) NSString *creationDate;
+
+/// Bucket name.
+@property (nonatomic, copy) NSString *bucketName;
+
+/// Bucket location.
+@property (nonatomic, copy) NSString *location;
+
+/// Storage class (Standard, IA, Archive)
+@property (nonatomic, copy) NSString *storageClass;
+
+/**
+ Internal endpoint. It could be accessed within AliCloud under the same
+ location.
+ */
+@property (nonatomic, copy) NSString *intranetEndpoint;
+
+/**
+ External endpoint.It could be accessed from anywhere.
+ */
+@property (nonatomic, copy) NSString *extranetEndpoint;
+
+/// Bucket owner.
+@property (nonatomic, strong) OSSBucketOwner *owner;
+
+@property (nonatomic, strong) OSSAccessControlList *acl;
+
+@end

+ 26 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectACLRequest.h

@@ -0,0 +1,26 @@
+//
+//  OSSGetObjectACLRequest.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/26.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+@interface OSSGetObjectACLRequest : OSSRequest
+
+/**
+ the bucket's name which object stored
+ */
+@property (nonatomic, copy) NSString *bucketName;
+
+/**
+ the name of object
+ */
+@property (nonatomic, copy) NSString *objectName;
+
+
+@end
+NS_ASSUME_NONNULL_END

+ 19 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectACLResult.h

@@ -0,0 +1,19 @@
+//
+//  OSSGetObjectACLResult.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/26.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+@interface OSSGetObjectACLResult : OSSResult
+
+/**
+ the ACL of object,valid values: @"private",@"public-read",@"public-read-write".
+ if object's ACL inherit from bucket,it will return @"default".
+ */
+@property (nonatomic, copy) NSString *grant;
+
+@end

+ 23 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectTaggingRequest.h

@@ -0,0 +1,23 @@
+//
+//  GetObjectTaggingRequest.h
+//  AliyunOSSSDK
+//
+//  Created by ws on 2021/5/25.
+//  Copyright © 2021 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSGetObjectTaggingRequest : OSSRequest
+
+/* bucket name */
+@property (nonatomic, copy) NSString *bucketName;
+
+/* object name */
+@property (nonatomic, copy) NSString *objectKey;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 19 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetObjectTaggingResult.h

@@ -0,0 +1,19 @@
+//
+//  GetObjectTaggingResult.h
+//  AliyunOSSSDK
+//
+//  Created by ws on 2021/5/25.
+//  Copyright © 2021 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSGetObjectTaggingResult : OSSResult
+
+@property (nonatomic, strong) NSDictionary *tags;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 17 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetSymlinkRequest.h

@@ -0,0 +1,17 @@
+//
+//  OSSGetSymlinkRequest.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/8/1.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+@interface OSSGetSymlinkRequest : OSSRequest
+
+@property (nonatomic, copy) NSString *bucketName;
+
+@property (nonatomic, copy) NSString *objectKey;
+
+@end

+ 13 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSGetSymlinkResult.h

@@ -0,0 +1,13 @@
+//
+//  OSSGetSymlinkResult.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/8/1.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+@interface OSSGetSymlinkResult : OSSResult
+
+@end

+ 39 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSHttpResponseParser.h

@@ -0,0 +1,39 @@
+//
+//  OSSHttpResponseParser.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/22.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSConstants.h"
+#import "OSSTask.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ HTTP response parser
+ */
+@interface OSSHttpResponseParser : NSObject
+
+@property (nonatomic, copy) OSSNetworkingOnRecieveDataBlock onRecieveBlock;
+
+@property (nonatomic, strong) NSURL *downloadingFileURL;
+
+/**
+ *  A Boolean value that determines whether verfifying crc64.
+ When set to YES, it will verify crc64 when transmission is completed normally.
+ The default value of this property is NO.
+ */
+@property (nonatomic, assign) BOOL crc64Verifiable;
+
+- (instancetype)initForOperationType:(OSSOperationType)operationType;
+- (void)consumeHttpResponse:(NSHTTPURLResponse *)response;
+- (OSSTask *)consumeHttpResponseBody:(NSData *)data;
+- (nullable id)constructResultObject;
+- (void)reset;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 16 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSHttpdns.h

@@ -0,0 +1,16 @@
+//
+//  OSSHttpdns.h
+//  AliyunOSSiOS
+//
+//  Created by zhouzhuo on 5/1/16.
+//  Copyright © 2016 zhouzhuo. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface OSSHttpdns : NSObject
+
++ (instancetype)sharedInstance;
+
+- (NSString *)asynGetIpByHost:(NSString *)host;
+@end

+ 114 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSIPv6Adapter.h

@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2000-2015 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * https://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)route.h	8.3 (Berkeley) 4/19/94
+ * $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
+ */
+
+
+#ifndef AlicloudIPv6Adapter_h
+#define AlicloudIPv6Adapter_h
+#import <Foundation/Foundation.h>
+
+@interface OSSIPv6Adapter : NSObject
+
++ (instancetype)getInstance;
+
+/**
+ *	@brief	Checks if it's a IPv6-only network. If it's true, it's IPv6-only.
+ *
+ *	@return return YES for IPv6-only network,otherWise return NO
+ */
+- (BOOL)isIPv6OnlyNetwork;
+
+/**
+ *	@brief	Refresh the IPV6-only check
+ *
+ *	@return return YES for IPv6-only network,otherWise return NO
+ */
+- (BOOL)reResolveIPv6OnlyStatus;
+
+/**
+ *	@brief	Adapts the IPv4 address into IPv6 format under IPv6-only network.
+ *          For example:
+                42.156.220.114 -> 64:ff9b::2a9c:dc72
+ *	@param 	addr
+ *          ip address
+ *
+ *	@return return an IPv6 address
+ */
+- (NSString *)handleIpv4Address:(NSString *)addr;
+
+/**
+ *	@brief	Checks if it's an IPv4 address.
+ *
+ *	@return return YES while addr is an IPv4 address,otherwise return NO
+ */
+- (BOOL)isIPv4Address:(NSString *)addr;
+
+/**
+ *	@brief	Checks if it's an IPv6 address
+ *
+ *	@return return YES while addr is an IPv6 address,otherwise return NO
+ */
+- (BOOL)isIPv6Address:(NSString *)addr;
+
+@end
+
+#endif /* OSSIPv6Adapter_h */

+ 23 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSIPv6PrefixResolver.h

@@ -0,0 +1,23 @@
+//
+//  OSSIPv6PrefixResolver.h
+//
+//  Created by lingkun on 16/5/16.
+//  Edit by zhouzhuo on 16/5/22
+//  Copyright © 2016 Ali. All rights reserved.
+//
+
+#ifndef AlicloudIPv6PrefixResolver_h
+#define AlicloudIPv6PrefixResolver_h
+#import <Foundation/Foundation.h>
+
+@interface OSSIPv6PrefixResolver : NSObject
+
++ (instancetype)getInstance;
+
+- (void)updateIPv6Prefix;
+
+- (NSString *)convertIPv4toIPv6:(NSString *)ipv4;
+
+@end
+
+#endif /* OSSIPv6PrefixResolver_h */

+ 54 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSLog.h

@@ -0,0 +1,54 @@
+//
+//  OSSLog.h
+//  oss_ios_sdk
+//
+//  Created by zhouzhuo on 8/16/15.
+//  Copyright (c) 2015 aliyun.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSCocoaLumberjack.h"
+static const OSSDDLogLevel ossLogLevel = OSSDDLogLevelAll;
+
+// colorful log configuration
+// see https://github.com/robbiehanson/XcodeColors
+
+#define XCODE_COLORS_ESCAPE @"\033["
+
+#define XCODE_COLORS_RESET_FG  XCODE_COLORS_ESCAPE @"fg;" // Clear any foreground color
+#define XCODE_COLORS_RESET_BG  XCODE_COLORS_ESCAPE @"bg;" // Clear any background color
+#define XCODE_COLORS_RESET     XCODE_COLORS_ESCAPE @";"   // Clear any foreground or background color
+
+#define OSSLogVerbose(frmt, ...)\
+if ([OSSLog isLogEnable]) {\
+OSSDDLogVerbose(@"[Verbose]: %@", [NSString stringWithFormat:(frmt), ##__VA_ARGS__]);\
+}
+
+#define OSSLogDebug(frmt, ...)\
+if ([OSSLog isLogEnable]) {\
+OSSDDLogDebug(@"[Debug]: %@", [NSString stringWithFormat:(frmt), ##__VA_ARGS__]);\
+}
+
+#define OSSLogDebugNoFile(frmt, ...)\
+if ([OSSLog isLogEnable]) {\
+NSLog(@"[Debug]: %@", [NSString stringWithFormat:(frmt), ##__VA_ARGS__]);\
+}
+
+#define OSSLogError(frmt, ...)\
+if ([OSSLog isLogEnable]) {\
+OSSDDLogError(@"[Error]: %@", [NSString stringWithFormat:(frmt), ##__VA_ARGS__]);\
+}
+
+#define OSSLogWarn(frmt, ...)\
+if ([OSSLog isLogEnable]) {\
+OSSDDLogWarn(@"[Warning]: %@", [NSString stringWithFormat:(frmt), ##__VA_ARGS__]);\
+}
+
+static BOOL isEnable;
+
+@interface OSSLog : NSObject
+
++ (void)enableLog;
++ (void)disableLog;
++ (BOOL)isLogEnable;
+@end

+ 82 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSLogMacros.h

@@ -0,0 +1,82 @@
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2010-2016, Deusty, LLC
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+//
+// * Neither the name of Deusty nor the names of its contributors may be used
+//   to endorse or promote products derived from this software without specific
+//   prior written permission of Deusty, LLC.
+
+// Disable legacy macros
+#ifndef OSSDD_LEGACY_MACROS
+    #define OSSDD_LEGACY_MACROS 0
+#endif
+
+#import "OSSDDLog.h"
+
+/**
+ * The constant/variable/method responsible for controlling the current log level.
+ **/
+#ifndef OSSLOG_LEVEL_DEF
+    #define OSSLOG_LEVEL_DEF ossLogLevel
+#endif
+
+/**
+ * Whether async should be used by log messages, excluding error messages that are always sent sync.
+ **/
+#ifndef OSSLOG_ASYNC_ENABLED
+    #define OSSLOG_ASYNC_ENABLED YES
+#endif
+
+/**
+ * These are the two macros that all other macros below compile into.
+ * These big multiline macros makes all the other macros easier to read.
+ **/
+#define OSSLOG_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \
+        [OSSDDLog log : isAsynchronous                                     \
+             level : lvl                                                \
+              flag : flg                                                \
+           context : ctx                                                \
+              file : __FILE__                                           \
+          function : fnct                                               \
+              line : __LINE__                                           \
+               tag : atag                                               \
+            format : (frmt), ## __VA_ARGS__]
+
+/**
+ * Define version of the macro that only execute if the log level is above the threshold.
+ * The compiled versions essentially look like this:
+ *
+ * if (logFlagForThisLogMsg & ddLogLevel) { execute log message }
+ *
+ * When LOG_LEVEL_DEF is defined as ddLogLevel.
+ *
+ * As shown further below, Lumberjack actually uses a bitmask as opposed to primitive log levels.
+ * This allows for a great amount of flexibility and some pretty advanced fine grained logging techniques.
+ *
+ * Note that when compiler optimizations are enabled (as they are for your release builds),
+ * the log messages above your logging threshold will automatically be compiled out.
+ *
+ * (If the compiler sees LOG_LEVEL_DEF/ddLogLevel declared as a constant, the compiler simply checks to see
+ *  if the 'if' statement would execute, and if not it strips it from the binary.)
+ *
+ * We also define shorthand versions for asynchronous and synchronous logging.
+ **/
+#define OSSLOG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, ...) \
+        do { if(lvl & flg) OSSLOG_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, ##__VA_ARGS__); } while(0)
+
+/**
+ * Ready to use log macros with no context or tag.
+ **/
+#define OSSDDLogError(frmt, ...)   OSSLOG_MAYBE(NO,                OSSLOG_LEVEL_DEF, OSSDDLogFlagError,   0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
+#define OSSDDLogWarn(frmt, ...)    OSSLOG_MAYBE(OSSLOG_ASYNC_ENABLED, OSSLOG_LEVEL_DEF, OSSDDLogFlagWarning, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
+#define OSSDDLogInfo(frmt, ...)    OSSLOG_MAYBE(OSSLOG_ASYNC_ENABLED, OSSLOG_LEVEL_DEF, OSSDDLogFlagInfo,    0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
+#define OSSDDLogDebug(frmt, ...)   OSSLOG_MAYBE(OSSLOG_ASYNC_ENABLED, OSSLOG_LEVEL_DEF, OSSDDLogFlagDebug,   0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
+#define OSSDDLogVerbose(frmt, ...) OSSLOG_MAYBE(OSSLOG_ASYNC_ENABLED, OSSLOG_LEVEL_DEF, OSSDDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
+

+ 1520 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSModel.h

@@ -0,0 +1,1520 @@
+//
+//  OSSModel.h
+//  oss_ios_sdk
+//
+//  Created by zhouzhuo on 8/16/15.
+//  Copyright (c) 2015 aliyun.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSRequest.h"
+#import "OSSResult.h"
+
+@class OSSAllRequestNeededMessage;
+@class OSSFederationToken;
+@class OSSTask;
+@class OSSClientConfiguration;
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef OSSFederationToken * _Nullable (^OSSGetFederationTokenBlock) (void);
+
+/**
+ Categories NSDictionary
+ */
+@interface NSDictionary (OSS)
+- (NSString *)base64JsonString;
+@end
+
+/**
+ A thread-safe dictionary
+ */
+@interface OSSSyncMutableDictionary : NSObject
+@property (nonatomic, strong) NSMutableDictionary *dictionary;
+@property (nonatomic, strong) dispatch_queue_t dispatchQueue;
+
+- (id)objectForKey:(id)aKey;
+- (NSArray *)allKeys;
+- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
+- (void)removeObjectForKey:(id)aKey;
+@end
+
+/**
+ FederationToken class
+ */
+@interface OSSFederationToken : NSObject
+@property (nonatomic, copy) NSString * tAccessKey;
+@property (nonatomic, copy) NSString * tSecretKey;
+@property (nonatomic, copy) NSString * tToken;
+
+/**
+ Token's expiration time in milliseconds of the unix time.
+ */
+@property (atomic, assign) int64_t expirationTimeInMilliSecond;
+
+/**
+ Token's expiration time in GMT format string.
+ */
+@property (atomic, strong, nullable) NSString *expirationTimeInGMTFormat;
+@end
+
+/**
+ CredentialProvider protocol, needs to implement sign API.
+ */
+@protocol OSSCredentialProvider <NSObject>
+@optional
+- (nullable NSString *)sign:(NSString *)content error:(NSError **)error;
+@end
+
+/**
+ The plaint text AK/SK credential provider for test purposely.
+ */
+
+__attribute__((deprecated("PLEASE DO NOT USE THIS CLASS AGAIN")))
+@interface OSSPlainTextAKSKPairCredentialProvider : NSObject <OSSCredentialProvider>
+@property (nonatomic, copy) NSString * accessKey;
+@property (nonatomic, copy) NSString * secretKey;
+
+- (instancetype)initWithPlainTextAccessKey:(NSString *)accessKey
+                                 secretKey:(NSString *)secretKey __attribute__((deprecated("We recommend the STS authentication mode on mobile")));
+@end
+
+/**
+TODOTODO
+ The custom signed credential provider
+ */
+@interface OSSCustomSignerCredentialProvider : NSObject <OSSCredentialProvider>
+@property (nonatomic, copy, readonly,) NSString * _Nonnull (^ _Nonnull signContent)( NSString * _Nonnull , NSError * _Nullable *_Nullable);
+
++ (instancetype _Nullable)new NS_UNAVAILABLE;
+- (instancetype _Nullable)init NS_UNAVAILABLE;
+
+/**
+ * During the task execution, this API is called for signing
+ * It's executed at the background thread instead of UI thread.
+ */
+- (instancetype _Nullable)initWithImplementedSigner:(OSSCustomSignContentBlock)signContent NS_DESIGNATED_INITIALIZER;
+@end
+
+/**
+TODOTODO
+ User's custom federation credential provider.
+ */
+@interface OSSFederationCredentialProvider : NSObject <OSSCredentialProvider>
+@property (nonatomic, strong) OSSFederationToken * cachedToken;
+@property (nonatomic, copy) OSSFederationToken * (^federationTokenGetter)(void);
+
+/**
+ During the task execution, this method is called to get the new STS token.
+ It runs in the background thread, not the UI thread.
+ */
+- (instancetype)initWithFederationTokenGetter:(OSSGetFederationTokenBlock)federationTokenGetter;
+- (nullable OSSFederationToken *)getToken:(NSError **)error;
+@end
+
+/**
+ The STS token's credential provider.
+ */
+@interface OSSStsTokenCredentialProvider : NSObject <OSSCredentialProvider>
+@property (nonatomic, copy) NSString * accessKeyId;
+@property (nonatomic, copy) NSString * secretKeyId;
+@property (nonatomic, copy) NSString * securityToken;
+
+- (OSSFederationToken *)getToken;
+- (instancetype)initWithAccessKeyId:(NSString *)accessKeyId
+                        secretKeyId:(NSString *)secretKeyId
+                      securityToken:(NSString *)securityToken;
+@end
+
+/**
+ Auth credential provider require a STS INFO Server URL,also you can customize a decoder block which returns json data.
+ 
+ 
+ OSSAuthCredentialProvider *acp = [[OSSAuthCredentialProvider alloc] initWithAuthServerUrl:@"sts_server_url" responseDecoder:^NSData * (NSData * data) {
+        // 1.hanle response from server.
+ 
+ // 2.initialize json object from step 1. json object require message like {AccessKeyId:@"xxx",AccessKeySecret:@"xxx",SecurityToken:@"xxx",Expiration:@"xxx"}
+ 
+        // 3.generate jsonData from step 2 and return it.
+ }];
+ 
+ */
+
+@interface OSSAuthCredentialProvider : OSSFederationCredentialProvider
+@property (nonatomic, copy) NSString * authServerUrl;
+@property (nonatomic, copy) NSData * (^responseDecoder)(NSData *);
+- (instancetype)initWithAuthServerUrl:(NSString *)authServerUrl;
+- (instancetype)initWithAuthServerUrl:(NSString *)authServerUrl responseDecoder:(nullable OSSResponseDecoderBlock)decoder;
+@end
+
+/**
+ OSSClient side configuration.
+ */
+@interface OSSClientConfiguration : NSObject
+
+/**
+ Max retry count
+ */
+@property (nonatomic, assign) uint32_t maxRetryCount;
+
+/**
+ Max concurrent requests
+ */
+@property (nonatomic, assign) uint32_t maxConcurrentRequestCount;
+
+/**
+ Flag of enabling background file transmit service.
+ Note: it's only applicable for file upload.
+ */
+@property (nonatomic, assign) BOOL enableBackgroundTransmitService;
+
+/**
+ Flag of using Http request for DNS resolution.
+ */
+@property (nonatomic, assign) BOOL isHttpdnsEnable;
+
+/**
+Sets the session Id for background file transmission
+ */
+@property (nonatomic, copy) NSString * backgroundSesseionIdentifier;
+
+/**
+ Sets request timeout
+ */
+@property (nonatomic, assign) NSTimeInterval timeoutIntervalForRequest;
+
+/**
+ Sets single object download's max time
+ */
+@property (nonatomic, assign) NSTimeInterval timeoutIntervalForResource;
+
+/**
+ Sets proxy host and port.
+ */
+@property (nonatomic, copy) NSString * proxyHost;
+@property (nonatomic, strong) NSNumber * proxyPort;
+
+/**
+ Sets UA
+ */
+@property (nonatomic, copy) NSString * userAgentMark;
+
+/**
+ Sets the flag of using Second Level Domain style to access the endpoint. By default it's false.
+ */
+@property (nonatomic, assign) BOOL isPathStyleAccessEnable;
+
+/**
+ Sets  the flag of using custom path prefix to access the endpoint. By default it's false.
+ */
+@property (nonatomic, assign) BOOL isCustomPathPrefixEnable;
+
+/**
+ Sets CName excluded list.
+ */
+@property (nonatomic, strong, setter=setCnameExcludeList:) NSArray * cnameExcludeList;
+
+/**
+ 是否开启crc校验(当同时设置了此选项和请求中的checkCRC开关时,以请求中的checkCRC开关为准)
+ */
+@property (nonatomic, assign) BOOL crc64Verifiable;
+
+/// Set whether to allow UA to carry system information
+@property (nonatomic, assign) BOOL isAllowUACarrySystemInfo;
+
+/// Set whether to allow the redirection with a modified request
+@property (nonatomic, assign) BOOL isFollowRedirectsEnable;
+
+/// The maximum number of simultaneous persistent connections per host.
+/// The default value is NSURLSessionConfiguration's default value
+/// https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1407597-httpmaximumconnectionsperhost
+@property (nonatomic, assign) uint32_t HTTPMaximumConnectionsPerHost;
+
+@end
+
+@protocol OSSRequestInterceptor <NSObject>
+- (OSSTask *)interceptRequestMessage:(OSSAllRequestNeededMessage *)request;
+@end
+
+/**
+ Signs the request when it's being created.
+ */
+@interface OSSSignerInterceptor : NSObject <OSSRequestInterceptor>
+@property (nonatomic, strong) id<OSSCredentialProvider> credentialProvider;
+
+- (instancetype)initWithCredentialProvider:(id<OSSCredentialProvider>)credentialProvider;
+@end
+
+/**
+ Updates the UA when creating the request.
+ */
+@interface OSSUASettingInterceptor : NSObject <OSSRequestInterceptor>
+@property (nonatomic, weak) OSSClientConfiguration *clientConfiguration;
+- (instancetype)initWithClientConfiguration:(OSSClientConfiguration *) clientConfiguration;
+@end
+
+/**
+ Fixes the time skew issue when creating the request.
+ */
+@interface OSSTimeSkewedFixingInterceptor : NSObject <OSSRequestInterceptor>
+@end
+
+/**
+ The download range of OSS object
+ */
+@interface OSSRange : NSObject
+@property (nonatomic, assign) int64_t startPosition;
+@property (nonatomic, assign) int64_t endPosition;
+
+- (instancetype)initWithStart:(int64_t)start
+                      withEnd:(int64_t)end;
+
+/**
+ * Converts the header to string: 'bytes=${start}-${end}'
+ */
+- (NSString *)toHeaderString;
+@end
+
+#pragma mark RequestAndResultClass
+
+/**
+ The request to list all buckets of current user.
+ */
+@interface OSSGetServiceRequest : OSSRequest
+
+/**
+ The prefix filter for listing buckets---optional.
+ */
+@property (nonatomic, copy) NSString * prefix;
+
+/**
+ The marker filter for listing buckets----optional.
+ The marker filter is to ensure any returned bucket name must be greater than the marker in the lexicographic order.
+ */
+@property (nonatomic, copy) NSString * marker;
+
+/**
+ The max entries to return. By default it's 100 and max value of this property is 1000.
+ */
+@property (nonatomic, assign) int32_t maxKeys;
+
+
+@end
+
+/**
+ The result class of listing all buckets
+ */
+@interface OSSGetServiceResult : OSSResult
+
+/**
+ The owner Id
+ */
+@property (nonatomic, copy) NSString * ownerId;
+
+/**
+ Bucket owner name---currently it's same as owner Id.
+ */
+@property (nonatomic, copy) NSString * ownerDispName;
+
+/**
+ The prefix of this query. It's only set when there's remaining buckets to return.
+ */
+@property (nonatomic, copy) NSString * prefix;
+
+/**
+ The marker of this query. It's only set when there's remaining buckets to return.
+ */
+@property (nonatomic, copy) NSString * marker;
+
+/**
+ The max buckets to return. It's only set when there's remaining buckets to return.
+ */
+@property (nonatomic, assign) int32_t maxKeys;
+
+/**
+ Flag of the result is truncated. If it's truncated, it means there's remaining buckets to return.
+ */
+@property (nonatomic, assign) BOOL isTruncated;
+
+/**
+ The marker for the next ListBucket call. It's only set when there's remaining buckets to return.
+ */
+@property (nonatomic, copy) NSString * nextMarker;
+
+/**
+ The container of the buckets. It's a dictionary array, in which every element has keys "Name", "CreationDate" and "Location".
+ */
+@property (nonatomic, strong, nullable) NSArray * buckets;
+@end
+
+/**
+ The request to create bucket
+ */
+@interface OSSCreateBucketRequest : OSSRequest
+
+/**
+ *  存储空间,命名规范如下:(1)只能包括小写字母、数字和短横线(-);(2)必须以小写字母或者数字开头和结尾;(3)长度必须在3-63字节之间.
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ The bucket location
+ For more information about OSS datacenter and endpoint, please check out <a>https://docs.aliyun.com/#/pub/oss/product-documentation/domain-region</a>
+ */
+@property (nonatomic, copy) NSString * location __attribute__ ((deprecated));
+
+/**
+ Sets Bucket access permission. For now there're three permissions:public-read-write,public-read and private. if this key is not set, the default value is private
+ */
+@property (nonatomic, copy) NSString * xOssACL;
+
+@property (nonatomic, assign) OSSBucketStorageClass storageClass;
+
+
+- (NSString *)storageClassAsString;
+
+@end
+
+/**
+ Result class of bucket creation
+ */
+@interface OSSCreateBucketResult : OSSResult
+
+/**
+ Bucket datacenter
+ */
+@property (nonatomic, copy) NSString * location;
+@end
+
+/**
+ The request class of deleting bucket
+ */
+@interface OSSDeleteBucketRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+@end
+
+/**
+ Result class of deleting bucket
+ */
+@interface OSSDeleteBucketResult : OSSResult
+@end
+
+/**
+ The request class of listing objects under a bucket
+ */
+@interface OSSGetBucketRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ The delimiter is very important and it determines the behavior of common prefix.
+ For most cases, use the default '/' as the delimiter. 
+ For example, if a bucket has folder 'prefix/' and a file 'abc'. And inside the folder it has file '123.txt'
+ If the delimiter is '/', then the ListObject will return a common prefix 'prefix/' and a file 'abc'.
+ If the delimiter is something else, then ListObject will return three files: prefix/, abc and prefix/123.txt. No common prefix!.
+ */
+@property (nonatomic, copy) NSString * delimiter;
+
+/**
+ The marker filter for listing objects----optional.
+ The marker filter is to ensure any returned object name must be greater than the marker in the lexicographic order.
+ */
+@property (nonatomic, copy) NSString * marker;
+
+/**
+ The max entries count to return. By default it's 100 and it could be up to 1000.
+ */
+@property (nonatomic, assign) int32_t maxKeys;
+
+/**
+ The filter prefix of the objects to return----the returned objects' name must have the prefix.
+ */
+@property (nonatomic, copy) NSString * prefix;
+
+
+@end
+
+/**
+ The result class of listing objects.
+ */
+@interface OSSGetBucketResult : OSSResult
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ The prefix of the objects returned----the returned objects must have this prefix.
+ */
+@property (nonatomic, copy) NSString * prefix;
+
+/**
+ The marker filter of the objects returned---all objects returned are greater than this marker in lexicographic order.
+ */
+@property (nonatomic, copy) NSString * marker;
+
+/**
+ The max entries to return. By default it's 100 and it could be up to 1000.
+ */
+@property (nonatomic, assign) int32_t maxKeys;
+
+/**
+ The delimiter to differentiate the folder object and file object.
+ For object whose name ends with the delimiter, then it's treated as folder or common prefixes.
+ */
+@property (nonatomic, copy) NSString * delimiter;
+
+/**
+ The maker for the next call. If no more entries to return, it's null.
+ */
+@property (nonatomic, copy) NSString * nextMarker;
+
+/**
+ Flag of truncated result. If it's truncated, it means there's more entries to return.
+ */
+@property (nonatomic, assign) BOOL isTruncated;
+
+/**
+ The dictionary arrary, in which each dictionary has keys of "Key", "LastModified", "ETag", "Type", "Size", "StorageClass" and "Owner".
+ */
+@property (nonatomic, strong, nullable) NSArray * contents;
+
+/**
+ The arrary of common prefixes. Each element is one common prefix.
+ */
+@property (nonatomic, strong) NSArray * commentPrefixes;
+@end
+
+/**
+ The request class to get the bucket ACL.
+ */
+@interface OSSGetBucketACLRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+@end
+
+/**
+ The result class to get the bucket ACL.
+ */
+@interface OSSGetBucketACLResult : OSSResult
+
+/**
+ The bucket ACL. It could be one of the three values: private/public-read/public-read-write.
+ */
+@property (nonatomic, copy) NSString * aclGranted;
+@end
+
+/**
+ The request class to get object metadata
+ */
+@interface OSSHeadObjectRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+@end
+
+/**
+ The result class of getting object metadata.
+ */
+@interface OSSHeadObjectResult : OSSResult
+
+/**
+ Object metadata
+ */
+@property (nonatomic, copy) NSDictionary * objectMeta;
+@end
+
+/**
+ The request class to get object
+ */
+@interface OSSGetObjectRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ OSS Download Range: For example, bytes=0-9 means uploading the first to the tenth's character.
+ */
+@property (nonatomic, strong) OSSRange * range;
+
+/**
+ The local file path to download to.
+ */
+@property (nonatomic, strong) NSURL * downloadToFileURL;
+
+/**
+ Image processing configuration.
+ */
+@property (nonatomic, copy) NSString * xOssProcess;
+
+/**
+ Download progress callback.
+ It runs at background thread.
+ */
+@property (nonatomic, copy) OSSNetworkingDownloadProgressBlock downloadProgress;
+
+/**
+ During the object download, the callback is called upon response is received.
+ It runs under background thread (not UI thread)
+ */
+@property (nonatomic, copy) OSSNetworkingOnRecieveDataBlock onRecieveData;
+
+/**
+ * set request headers
+ */
+@property (nonatomic, copy) NSDictionary *headerFields;
+
+@end
+
+/**
+ Result class of downloading an object.
+ */
+@interface OSSGetObjectResult : OSSResult
+
+/**
+ The in-memory content of the downloaded object, if the local file path is not specified.
+ */
+@property (nonatomic, strong) NSData * downloadedData;
+
+/**
+ The object metadata dictionary
+ */
+@property (nonatomic, copy) NSDictionary * objectMeta;
+@end
+
+
+/**
+ The response class to update the object ACL.
+ */
+@interface OSSPutObjectACLResult : OSSResult
+@end
+
+/**
+ The request class to upload an object.
+ */
+@interface OSSPutObjectRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ The in-memory data to upload.
+ */
+@property (nonatomic, strong) NSData * uploadingData;
+
+/**
+ The local file path to upload.
+ */
+@property (nonatomic, strong) NSURL * uploadingFileURL;
+
+/**
+ The callback parameters.
+ */
+@property (nonatomic, copy) NSDictionary * callbackParam;
+
+/**
+ The callback variables.
+ */
+@property (nonatomic, copy) NSDictionary * callbackVar;
+
+/**
+ The content type.
+ */
+@property (nonatomic, copy) NSString * contentType;
+
+/**
+ The content's MD5 digest. 
+ It's calculated on the request body (not headers) according to RFC 1864 to get the 128 bit digest data.
+ Then use base64 encoding on the 128bit result to get this MD5 value.
+ This header is for integrity check on the data. And it's recommended to turn on for every body.
+ */
+@property (nonatomic, copy) NSString * contentMd5;
+
+/**
+ Specifies the download name of the object. Checks out RFC2616 for more details.
+ */
+@property (nonatomic, copy) NSString * contentDisposition;
+
+/**
+ Specifies the content encoding during the download. Checks out RFC2616 for more details.
+ */
+@property (nonatomic, copy) NSString * contentEncoding;
+
+/**
+ Specifies the cache behavior during the download. Checks out RFC2616 for more details.
+ */
+@property (nonatomic, copy) NSString * cacheControl;
+
+/**
+ Expiration time in milliseconds. Checks out RFC2616 for more details.
+ */
+@property (nonatomic, copy) NSString * expires;
+
+/**
+ The object's metadata.
+ When the object is being uploaded, it could be specified with http headers prefixed with x-oss-meta for user metadata.
+ The total size of all user metadata cannot be more than 8K. 
+ It also could include standard HTTP headers in this object.
+ */
+@property (nonatomic, copy) NSDictionary * objectMeta;
+
+/**
+ The upload progress callback.
+ It runs in background thread (not UI thread).
+ */
+@property (nonatomic, copy) OSSNetworkingUploadProgressBlock uploadProgress;
+
+/**
+ The upload retry callback.
+ It runs in background thread (not UI thread).
+ */
+@property (nonatomic, copy) OSSNetworkingRetryBlock uploadRetryCallback;
+
+/**
+ * the sha1 of content
+ */
+@property (nonatomic, copy) NSString *contentSHA1;
+ 
+@end
+
+/**
+ The request class to update the object ACL.
+ */
+@interface OSSPutObjectACLRequest : OSSPutObjectRequest
+
+/**
+ *@brief:指定oss创建object时的访问权限,合法值:public-read、private、public-read-write
+ */
+@property (nonatomic, copy, nullable) NSString *acl;
+
+@end
+
+/**
+ The result class to put an object
+ */
+@interface OSSPutObjectResult : OSSResult
+
+/**
+ETag (entity tag) is the tag during the object creation in OSS server side.
+It's the MD5 value for put object request. If the object is created by other APIs, the ETag is the UUID of the content.
+ ETag could be used to check if the object has been updated.
+ */
+@property (nonatomic, copy) NSString * eTag;
+
+/**
+ If the callback is specified, this is the callback response result.
+ */
+@property (nonatomic, copy) NSString * serverReturnJsonString;
+@end
+
+/**
+ * append object request
+ */
+@interface OSSAppendObjectRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ Specifies which position to append. For a new file, the first append should start from 0. And the subsequential calls will start from the current length of the object.
+ For example, if the first append's size is 65536, then the appendPosition value in the next call will be 65536.
+ In its response, the header x-oss-next-append-position is included for next call.
+ */
+@property (nonatomic, assign) int64_t appendPosition;
+
+/**
+ The in-memory data to upload from.
+ */
+@property (nonatomic, strong) NSData * uploadingData;
+
+/**
+ The local file path to upload from.
+ */
+@property (nonatomic, strong) NSURL * uploadingFileURL;
+
+/**
+ Sets the content type
+ */
+@property (nonatomic, copy) NSString * contentType;
+
+/**
+ The content's MD5 digest value.
+ It's calculated from the MD5 value of the request body according to RFC 1864 and then encoded by base64.
+ */
+@property (nonatomic, copy) NSString *contentMd5;
+
+/**
+ The object's name during the download according to RFC 2616.
+ */
+@property (nonatomic, copy) NSString * contentDisposition;
+
+/**
+ The content encoding during the object upload. Checks out RFC2616 for more detail.
+ */
+@property (nonatomic, copy) NSString * contentEncoding;
+
+/**
+ Specifies the cache control behavior when it's being downloaded.Checks out RFC 2616 for more details.
+ */
+@property (nonatomic, copy) NSString * cacheControl;
+
+/**
+ Expiration time. Checks out RFC2616 for more information.
+ */
+@property (nonatomic, copy) NSString * expires;
+
+/**
+ The object's metadata, which start with x-oss-meta-, such as x-oss-meta-location.
+ Each request can have multiple metadata as long as the total size of all metadata is no bigger than 8KB.
+ It could include standard headers as well.
+ */
+@property (nonatomic, copy) NSDictionary * objectMeta;
+
+/**
+ Upload progress callback.
+ It's called on the background thread.
+ */
+@property (nonatomic, copy) OSSNetworkingUploadProgressBlock uploadProgress;
+
+/**
+ * the sha1 of content
+ */
+@property (nonatomic, copy) NSString *contentSHA1;
+
+
+@end
+
+/**
+ * append object result
+ */
+@interface OSSAppendObjectResult : OSSResult
+
+/**
+ TODOTODO
+ ETag (entity tag). It's created for every object when it's created.
+ For Objects created by PUT, ETag is the MD5 value of the content data. For others, ETag is the UUID of the content.
+ ETag is used for checking data integrity.
+ */
+@property (nonatomic, copy) NSString * eTag;
+
+/**
+ Specifies the next starting position. It's essentially the current object size.
+ This header is included in the successful response or the error response when the start position does not match the object size.
+ */
+@property (nonatomic, assign, readwrite) int64_t xOssNextAppendPosition;
+@end
+
+/**
+ The request of deleting an object.
+ */
+@interface OSSDeleteObjectRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object object
+ */
+@property (nonatomic, copy) NSString * objectKey;
+@end
+
+/**
+ Result class of deleting an object
+ */
+@interface OSSDeleteObjectResult : OSSResult
+@end
+
+/**
+ Request class of copying an object in OSS.
+ */
+@interface OSSCopyObjectRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ * Source object's address (the caller needs the read permission on this object)
+ */
+@property (nonatomic, copy) NSString * sourceCopyFrom DEPRECATED_MSG_ATTRIBUTE("please use sourceBucketName & sourceObjectKey instead!it will be removed in next version.");
+
+@property (nonatomic, copy) NSString * sourceBucketName;
+
+@property (nonatomic, copy) NSString * sourceObjectKey;
+
+/**
+ The content type
+ */
+@property (nonatomic, copy) NSString * contentType;
+
+/**
+ The content's MD5 digest.
+ It's calculated according to RFC 1864 and encoded in base64.
+ Though it's optional, it's recommended to turn it on for integrity check.
+ */
+@property (nonatomic, copy) NSString * contentMd5;
+
+/**
+ The user metadata dictionary, which starts with x-oss-meta-. 
+ The total size of user metadata can be no more than 8KB.
+ It could include standard http headers as well.
+ */
+@property (nonatomic, copy) NSDictionary * objectMeta;
+
+/**
+ * the sha1 of content
+ */
+@property (nonatomic, copy) NSString *contentSHA1;
+
+
+@end
+
+/**
+ The result class of copying an object
+ */
+@interface OSSCopyObjectResult : OSSResult
+
+/**
+ The last modified time
+ */
+@property (nonatomic, copy) NSString * lastModifed;
+
+/**
+ The ETag of the new object.
+ */
+@property (nonatomic, copy) NSString * eTag;
+@end
+
+/**
+ Request class of initiating a multipart upload.
+ */
+@interface OSSInitMultipartUploadRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ Content type
+ */
+@property (nonatomic, copy) NSString * contentType;
+
+/**
+ The object's download name. Checks out RFC 2616 for more details.
+ */
+@property (nonatomic, copy) NSString * contentDisposition;
+
+/**
+ The content encoding. Checks out RFC 2616.
+ */
+@property (nonatomic, copy) NSString * contentEncoding;
+
+/**
+ Specifies the cache control behavior when it's downloaded. Checks out RFC 2616 for more details.
+ */
+@property (nonatomic, copy) NSString * cacheControl;
+
+/**
+ Expiration time in milliseconds. Checks out RFC 2616 for more details.
+ */
+@property (nonatomic, copy) NSString * expires;
+
+/**
+ The dictionary of object's custom metadata, which starts with x-oss-meta-. 
+ The total size of user metadata is no more than 8KB.
+ It could include other standard http headers.
+ */
+@property (nonatomic, copy) NSDictionary * objectMeta;
+
+/**
+ * When Setting this value to YES , parts will be uploaded in order. Default value is NO.
+ */
+@property (nonatomic, assign) BOOL sequential;
+
+@end
+
+/**
+ The resutl class of initiating a multipart upload.
+ */
+@interface OSSInitMultipartUploadResult : OSSResult
+
+/**
+ The upload Id of the multipart upload
+ */
+@property (nonatomic, copy) NSString * uploadId;
+@end
+
+/**
+ The request class of uploading one part.
+ */
+@interface OSSUploadPartRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectkey;
+
+/**
+ Multipart Upload id.
+ */
+@property (nonatomic, copy) NSString * uploadId;
+
+/**
+ The part number of this part.
+ */
+@property (nonatomic, assign) int partNumber;
+
+/**
+ The content MD5 value.
+ It's calculated according to RFC 1864 and encoded in base64.
+ Though it's optional, it's recommended to turn it on for integrity check.
+ */
+@property (nonatomic, copy) NSString * contentMd5;
+
+/**
+ The in-memory data to upload from.
+ */
+@property (nonatomic, strong) NSData * uploadPartData;
+
+/**
+ The local file path to upload from
+ */
+@property (nonatomic, strong) NSURL * uploadPartFileURL;
+
+/**
+ The upload progress callback.
+ It runs in background thread (not UI thread);
+ */
+@property (nonatomic, copy) OSSNetworkingUploadProgressBlock uploadPartProgress;
+
+/**
+ * the sha1 of content
+ */
+@property (nonatomic, copy) NSString *contentSHA1;
+
+@end
+
+/**
+ The result class of uploading one part.
+ */
+@interface OSSUploadPartResult : OSSResult
+@property (nonatomic, copy) NSString * eTag;
+@end
+
+/**
+ The Part information. It's called by CompleteMultipartUpload().
+ */
+@interface OSSPartInfo : NSObject<NSCopying>
+
+/**
+ The part number in this part upload.
+ */
+@property (nonatomic, assign) int32_t partNum;
+
+/**
+ ETag value of this part returned by OSS.
+ */
+@property (nonatomic, copy) NSString * eTag;
+
+/**
+ The part size.
+ */
+@property (nonatomic, assign) int64_t size;
+
+@property (nonatomic, assign) uint64_t crc64;
+
++ (instancetype)partInfoWithPartNum:(int32_t)partNum eTag:(NSString *)eTag size:(int64_t)size __attribute__((deprecated("Use partInfoWithPartNum:eTag:size:crc64: to instead!")));
++ (instancetype)partInfoWithPartNum:(int32_t)partNum eTag:(NSString *)eTag size:(int64_t)size crc64:(uint64_t)crc64;
+
+- (NSDictionary *)entityToDictionary;
+
+@end
+
+/**
+ The request class of completing a multipart upload.
+ */
+@interface OSSCompleteMultipartUploadRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ Multipart upload Id
+ */
+@property (nonatomic, copy) NSString * uploadId;
+
+/**
+ The content MD5 value.
+ It's calculated according to RFC 1864 and encoded in base64.
+ Though it's optional, it's recommended to turn it on for integrity check. 
+ */
+@property (nonatomic, copy) NSString * contentMd5;
+
+/**
+ All parts' information.
+ */
+@property (nonatomic, strong) NSArray * partInfos;
+
+/**
+ Server side callback parameter
+ */
+@property (nonatomic, copy) NSDictionary * callbackParam;
+
+/**
+ Callback variables 
+ */
+@property (nonatomic, copy) NSDictionary * callbackVar;
+
+/**
+ The metadata header
+ */
+@property (nonatomic, copy) NSDictionary * completeMetaHeader;
+
+/**
+ * the sha1 of content
+ */
+@property (nonatomic, copy) NSString *contentSHA1;
+
+@end
+
+/**
+ The resutl class of completing a multipart upload.
+ */
+@interface OSSCompleteMultipartUploadResult : OSSResult
+
+/**
+ The object's URL
+ */
+@property (nonatomic, copy) NSString * location;
+
+/**
+ ETag (entity tag).
+ It's generated when the object is created. 
+ */
+@property (nonatomic, copy) NSString * eTag;
+
+/**
+ The callback response if the callback is specified.
+ The resutl class of initiating a multipart upload.
+ */
+@property (nonatomic, copy) NSString * serverReturnJsonString;
+@end
+
+/**
+ The request class of listing all parts that have been uploaded.
+ */
+@interface OSSListPartsRequest : OSSRequest
+
+/**
+ Bucket name
+ The request class of uploading one part.*/
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ The multipart upload Id.
+ */
+@property (nonatomic, copy) NSString * uploadId;
+
+/**
+ The max part count to return
+ */
+@property (nonatomic, assign) int maxParts;
+
+/**
+ The part number marker filter---only parts whose part number is greater than this value will be returned.
+ */
+@property (nonatomic, assign) int partNumberMarker;
+@end
+
+/**
+The result class of listing uploaded parts.
+*/
+@interface OSSListPartsResult : OSSResult
+
+/**
+ The next part number marker. If the response does not include all data, this header specifies what's the start point for the next list call.
+ */
+@property (nonatomic, assign) int nextPartNumberMarker;
+
+/**
+ The max parts count to return.
+ */
+@property (nonatomic, assign) int maxParts;
+
+/**
+ Flag of truncated data in the response. If it's true, it means there're more data to come.
+ If it's false, it means all data have been returned.
+ */
+@property (nonatomic, assign) BOOL isTruncated;
+
+/**
+ The array of the part information.
+ */
+@property (nonatomic, strong, nullable) NSArray * parts;
+@end
+
+/**
+ The request class of listing all multipart uploads.
+ */
+@interface OSSListMultipartUploadsRequest : OSSRequest
+/**
+ Bucket name.
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ The delimiter.
+ */
+@property (nonatomic, copy) NSString * delimiter;
+
+/**
+ The prefix.
+ */
+@property (nonatomic, copy) NSString * prefix;
+
+/**
+ The max number of uploads.
+ */
+@property (nonatomic, assign) int32_t maxUploads;
+
+/**
+ The key marker filter.
+ */
+@property (nonatomic, copy) NSString * keyMarker;
+
+/**
+ The upload Id marker.
+ */
+@property (nonatomic, copy) NSString * uploadIdMarker;
+
+/**
+ The encoding type of the object in the response body.
+ */
+@property (nonatomic, copy) NSString * encodingType;
+
+@end
+
+/**
+ The result class of listing multipart uploads.
+ */
+@interface OSSListMultipartUploadsResult : OSSResult
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ The marker filter of the objects returned---all objects returned are greater than this marker in lexicographic order.
+ */
+@property (nonatomic, copy) NSString * keyMarker;
+
+/**
+ The delimiter to differentiate the folder object and file object.
+ For object whose name ends with the delimiter, then it's treated as folder or common prefixes.
+ */
+@property (nonatomic, copy) NSString * delimiter;
+
+/**
+ The prefix of the objects returned----the returned objects must have this prefix.
+ */
+@property (nonatomic, copy) NSString * prefix;
+
+/**
+ The upload Id marker.
+ */
+@property (nonatomic, copy) NSString * uploadIdMarker;
+
+/**
+ The max entries to return. By default it's 100 and it could be up to 1000.
+ */
+@property (nonatomic, assign) int32_t maxUploads;
+
+/**
+ If not all results are returned this time, the response request includes the NextKeyMarker element to indicate the value of KeyMarker in the next request.
+ */
+@property (nonatomic, copy) NSString * nextKeyMarker;
+
+/**
+ If not all results are returned this time, the response request includes the NextUploadMarker element to indicate the value of UploadMarker in the next request.
+ */
+@property (nonatomic, copy) NSString * nextUploadIdMarker;
+
+/**
+ Flag of truncated result. If it's truncated, it means there's more entries to return.
+ */
+@property (nonatomic, assign) BOOL isTruncated;
+
+@property (nonatomic, strong, nullable) NSArray * uploads;
+
+/**
+ The arrary of common prefixes. Each element is one common prefix.
+ */
+@property (nonatomic, strong) NSArray * commonPrefixes;
+@end
+
+/**
+ Request to abort a multipart upload
+ */
+@interface OSSAbortMultipartUploadRequest : OSSRequest
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object name
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ The multipart upload Id.
+ */
+@property (nonatomic, copy) NSString * uploadId;
+@end
+
+/**
+ The result class of aborting a multipart upload
+ */
+@interface OSSAbortMultipartUploadResult : OSSResult
+@end
+
+/**
+ The request class of multipart upload.
+ */
+@interface OSSMultipartUploadRequest : OSSRequest
+
+/**
+ The upload Id
+ */
+@property (nonatomic, copy) NSString * uploadId;
+
+/**
+ Bucket name
+ */
+@property (nonatomic, copy) NSString * bucketName;
+
+/**
+ Object object
+ */
+@property (nonatomic, copy) NSString * objectKey;
+
+/**
+ The local file path to upload from.
+ */
+@property (nonatomic, strong) NSURL * uploadingFileURL;
+
+/**
+ The part size, minimal value is 100KB.
+ */
+@property (nonatomic, assign) NSUInteger partSize;
+
+/**
+ Upload progress callback.
+ It runs at the background thread (not UI thread).
+ */
+@property (nonatomic, copy) OSSNetworkingUploadProgressBlock uploadProgress;
+
+/**
+ The callback parmeters
+ */
+@property (nonatomic, copy) NSDictionary * callbackParam;
+
+/**
+ The callback variables
+ */
+@property (nonatomic, copy) NSDictionary * callbackVar;
+
+/**
+ Content type
+ */
+@property (nonatomic, copy) NSString * contentType;
+
+/**
+ The metadata header
+ */
+@property (nonatomic, copy) NSDictionary * completeMetaHeader;
+
+/**
+ * the sha1 of content
+ */
+@property (nonatomic, copy) NSString *contentSHA1;
+
+/**
+ * the md5 of content
+ */
+@property (nonatomic, copy) NSString *md5String;
+
+/// The concurrent number of shard uploads
+@property (nonatomic, assign) uint32_t threadNum;
+
+- (void)cancel;
+@end
+
+/**
+ The request class of resumable upload.
+ */
+@interface OSSResumableUploadRequest : OSSMultipartUploadRequest
+
+
+/**
+ directory path about create record uploadId file 
+ */
+@property (nonatomic, copy) NSString * recordDirectoryPath;
+
+
+/**
+ need or not delete uploadId with cancel
+ */
+@property (nonatomic, assign) BOOL deleteUploadIdOnCancelling;
+
+/**
+ All running children requests
+ */
+@property (atomic, weak) OSSRequest * runningChildrenRequest;
+
+@end
+
+
+/**
+ The result class of resumable uploading
+ */
+@interface OSSResumableUploadResult : OSSResult
+
+/**
+ The callback response, if the callback is specified.
+ */
+@property (nonatomic, copy) NSString * serverReturnJsonString;
+
+@end
+
+
+/**
+ for more information,Please refer to the link https://help.aliyun.com/document_detail/31989.html
+ */
+@interface OSSCallBackRequest : OSSRequest
+
+@property (nonatomic, copy) NSString *bucketName;
+
+@property (nonatomic, copy) NSString *objectName;
+/**
+ The callback parameters.when you set this value,there are required params as below:
+ {
+    "callbackUrl": xxx
+    "callbackBody": xxx
+ }
+ */
+@property (nonatomic, copy) NSDictionary *callbackParam;
+/**
+ The callback variables.
+ */
+@property (nonatomic, copy) NSDictionary *callbackVar;
+
+@end
+
+
+
+@interface OSSCallBackResult : OSSResult
+
+@property (nonatomic, copy) NSDictionary *serverReturnXML;
+
+/**
+ If the callback is specified, this is the callback response result.
+ */
+@property (nonatomic, copy) NSString *serverReturnJsonString;
+
+@end
+
+
+/**
+ for more information,Please refer to the link https://help.aliyun.com/document_detail/55811.html
+ */
+@interface OSSImagePersistRequest : OSSRequest
+
+@property (nonatomic, copy) NSString *fromBucket;
+
+@property (nonatomic, copy) NSString *fromObject;
+
+@property (nonatomic, copy) NSString *toBucket;
+
+@property (nonatomic, copy) NSString *toObject;
+
+@property (nonatomic, copy) NSString *action;
+
+@end
+
+@interface OSSImagePersistResult : OSSResult
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 14 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSNSLogger.h

@@ -0,0 +1,14 @@
+//
+//  OSSNSLogger.h
+//  AliyunOSSiOS
+//
+//  Created by jingdan on 2017/10/24.
+//  Copyright © 2017年 zhouzhuo. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSDDLog.h"
+
+@interface OSSNSLogger : OSSDDAbstractLogger <OSSDDLogger>
+@property (class, readonly, strong) OSSNSLogger *sharedInstance;
+@end

+ 47 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSNetworking.h

@@ -0,0 +1,47 @@
+//
+//  OSSNetworking.h
+//  oss_ios_sdk
+//
+//  Created by zhouzhuo on 8/16/15.
+//  Copyright (c) 2015 aliyun.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSModel.h"
+
+@class OSSSyncMutableDictionary;
+@class OSSNetworkingRequestDelegate;
+@class OSSExecutor;
+
+
+
+/**
+ Network parameters
+ */
+@interface OSSNetworkingConfiguration : NSObject
+@property (nonatomic, assign) uint32_t maxRetryCount;
+@property (nonatomic, assign) uint32_t maxConcurrentRequestCount;
+@property (nonatomic, assign) BOOL enableBackgroundTransmitService;
+@property (nonatomic, strong) NSString * backgroundSessionIdentifier;
+@property (nonatomic, assign) NSTimeInterval timeoutIntervalForRequest;
+@property (nonatomic, assign) NSTimeInterval timeoutIntervalForResource;
+@property (nonatomic, strong) NSString * proxyHost;
+@property (nonatomic, strong) NSNumber * proxyPort;
+@property (nonatomic, assign) BOOL enableFollowRedirects;
+@property (nonatomic, assign) uint32_t HTTPMaximumConnectionsPerHost;
+@end
+
+
+/**
+ The network interface which OSSClient uses for network read and write operations.
+ */
+@interface OSSNetworking : NSObject <NSURLSessionDelegate, NSURLSessionDataDelegate>
+@property (nonatomic, strong) NSURLSession * session;
+@property (nonatomic, assign) BOOL isUsingBackgroundSession;
+@property (nonatomic, strong) OSSSyncMutableDictionary * sessionDelagateManager;
+@property (nonatomic, strong) OSSNetworkingConfiguration * configuration;
+@property (nonatomic, strong) OSSExecutor * taskExecutor;
+
+- (instancetype)initWithConfiguration:(OSSNetworkingConfiguration *)configuration;
+- (OSSTask *)sendRequest:(OSSNetworkingRequestDelegate *)request;
+@end

+ 79 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSNetworkingRequestDelegate.h

@@ -0,0 +1,79 @@
+//
+//  OSSNetworkingRequestDelegate.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/22.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSConstants.h"
+#import "OSSTask.h"
+
+@class OSSAllRequestNeededMessage;
+@class OSSURLRequestRetryHandler;
+@class OSSHttpResponseParser;
+
+/**
+ The proxy object class for each OSS request.
+ */
+@interface OSSNetworkingRequestDelegate : NSObject
+
+@property (nonatomic, strong) NSMutableArray * interceptors;
+
+@property (nonatomic, strong) NSMutableURLRequest *internalRequest;
+@property (nonatomic, assign) OSSOperationType operType;
+@property (nonatomic, assign) BOOL isAccessViaProxy;
+
+@property (nonatomic, assign) BOOL isRequestCancelled;
+
+@property (nonatomic, strong) OSSAllRequestNeededMessage *allNeededMessage;
+@property (nonatomic, strong) OSSURLRequestRetryHandler *retryHandler;
+@property (nonatomic, strong) OSSHttpResponseParser *responseParser;
+
+@property (nonatomic, strong) NSData * uploadingData;
+@property (nonatomic, strong) NSURL * uploadingFileURL;
+
+@property (nonatomic, assign) int64_t payloadTotalBytesWritten;
+
+@property (nonatomic, assign) BOOL isBackgroundUploadFileTask;
+@property (nonatomic, assign) BOOL isHttpdnsEnable;
+
+@property (nonatomic, assign) BOOL isPathStyleAccessEnable;
+@property (nonatomic, assign) BOOL isCustomPathPrefixEnable;
+@property (nonatomic, copy) NSArray * cnameExcludeList;
+
+@property (nonatomic, assign) uint32_t currentRetryCount;
+@property (nonatomic, strong) NSError * error;
+@property (nonatomic, assign) BOOL isHttpRequestNotSuccessResponse;
+@property (nonatomic, strong) NSMutableData *httpRequestNotSuccessResponseBody;
+
+@property (atomic, strong) NSURLSessionDataTask *currentSessionTask;
+
+@property (nonatomic, copy) OSSNetworkingUploadProgressBlock uploadProgress;
+@property (nonatomic, copy) OSSNetworkingDownloadProgressBlock downloadProgress;
+@property (nonatomic, copy) OSSNetworkingRetryBlock retryCallback;
+@property (nonatomic, copy) OSSNetworkingCompletionHandlerBlock completionHandler;
+@property (nonatomic, copy) OSSNetworkingOnRecieveDataBlock onRecieveData;
+
+/**
+ * when put object to server,client caculate crc64 code and assigns it to
+ * this property.
+ */
+@property (nonatomic, copy) NSString *contentCRC;
+
+/** last crc64 code */
+@property (nonatomic, copy) NSString *lastCRC;
+
+/**
+ * determine whether to verify crc64 code
+ */
+@property (nonatomic, assign) BOOL crc64Verifiable;
+
+
+
+- (OSSTask *)buildInternalHttpRequest;
+- (void)reset;
+- (void)cancel;
+
+@end

+ 27 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutObjectTaggingRequest.h

@@ -0,0 +1,27 @@
+//
+//  OSSPutObjectTaggingRequest.h
+//  AliyunOSSSDK
+//
+//  Created by ws on 2021/5/25.
+//  Copyright © 2021 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSPutObjectTaggingRequest : OSSRequest
+
+/* bucket name */
+@property (nonatomic, copy) NSString *bucketName;
+
+/* object name */
+@property (nonatomic, copy) NSString *objectKey;
+
+@property (nonatomic, copy) NSDictionary *tags;
+
+- (NSDictionary *)entityToDictionary;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 17 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutObjectTaggingResult.h

@@ -0,0 +1,17 @@
+//
+//  OSSPutObjectTaggingResult.h
+//  AliyunOSSSDK
+//
+//  Created by ws on 2021/5/25.
+//  Copyright © 2021 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OSSPutObjectTaggingResult : OSSResult
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 25 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutSymlinkRequest.h

@@ -0,0 +1,25 @@
+//
+//  OSSPutSymlinkRequest.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/8/1.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+@interface OSSPutSymlinkRequest : OSSRequest
+
+/* bucket name */
+@property (nonatomic, copy) NSString *bucketName;
+
+/* object name */
+@property (nonatomic, copy) NSString *objectKey;
+
+/* target object name */
+@property (nonatomic, copy) NSString *targetObjectName;
+
+/* meta info in request header fields */
+@property (nonatomic, copy) NSDictionary *objectMeta;
+
+@end

+ 13 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSPutSymlinkResult.h

@@ -0,0 +1,13 @@
+//
+//  OSSPutSymlinkResult.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/8/1.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+@interface OSSPutSymlinkResult : OSSResult
+
+@end

+ 64 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSReachability.h

@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ See LICENSE.txt for this sample’s licensing information
+ 
+ Abstract:
+ Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
+ */
+
+#import <Foundation/Foundation.h>
+#import <SystemConfiguration/SystemConfiguration.h>
+#import <netinet/in.h>
+
+
+typedef enum : NSInteger {
+	OSSNotReachable = 0,
+	OSSReachableViaWiFi,
+	OSSReachableViaWWAN
+} OSSNetworkStatus;
+
+#pragma mark IPv6 Support
+//Reachability fully support IPv6.  For full details, see ReadMe.md.
+
+
+extern NSString *ossReachabilityChangedNotification;
+
+
+@interface OSSReachability : NSObject
+
+/*!
+ * Use to check the reachability of a given host name.
+ */
++ (instancetype)reachabilityWithHostName:(NSString *)hostName;
+
+/*!
+ * Use to check the reachability of a given IP address.
+ */
++ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress;
+
+/*!
+ * Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
+ */
++ (instancetype)reachabilityForInternetConnection;
+
+
+#pragma mark reachabilityForLocalWiFi
+//reachabilityForLocalWiFi has been removed from the sample.  See ReadMe.md for more information.
+//+ (instancetype)reachabilityForLocalWiFi;
+
+/*!
+ * Start listening for reachability notifications on the current run loop.
+ */
+- (BOOL)startNotifier;
+- (void)stopNotifier;
+
+- (OSSNetworkStatus)currentReachabilityStatus;
+
+/*!
+ * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
+ */
+- (BOOL)connectionRequired;
+
+@end
+
+

+ 41 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSRequest.h

@@ -0,0 +1,41 @@
+//
+//  OSSRequest.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/22.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSConstants.h"
+
+/**
+ The base class of request to OSS.
+ */
+@interface OSSRequest : NSObject
+/**
+ Flag of requiring authentication. It's per each request.
+ */
+@property (nonatomic, assign) BOOL isAuthenticationRequired;
+
+/**
+ the flag of request canceled.
+ */
+@property (atomic, assign) BOOL isCancelled;
+
+/**
+ the flag of verification about crc64
+ */
+@property (nonatomic, assign) OSSRequestCRCFlag crcFlag;
+
+/**
+ Cancels the request
+ */
+- (void)cancel;
+
+/**
+ Gets the query parameters' dictionary according to the properties.
+ */
+- (NSDictionary *)requestParams;
+
+@end

+ 17 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSRestoreObjectRequest.h

@@ -0,0 +1,17 @@
+//
+//  OSSRestoreObjectRequest.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/8/1.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSRequest.h"
+
+@interface OSSRestoreObjectRequest : OSSRequest
+
+@property (nonatomic, copy) NSString *bucketName;
+
+@property (nonatomic, copy) NSString *objectKey;
+
+@end

+ 13 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSRestoreObjectResult.h

@@ -0,0 +1,13 @@
+//
+//  OSSRestoreObjectResult.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/8/1.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import "OSSResult.h"
+
+@interface OSSRestoreObjectResult : OSSResult
+
+@end

+ 42 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSResult.h

@@ -0,0 +1,42 @@
+//
+//  OSSResult.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/26.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+/**
+ The base class of result from OSS.
+ */
+@interface OSSResult : NSObject
+
+/**
+ The http response code.
+ */
+@property (nonatomic, assign) NSInteger httpResponseCode;
+
+/**
+ The http headers, in the form of key value dictionary.
+ */
+@property (nonatomic, strong) NSDictionary * httpResponseHeaderFields;
+
+/**
+ The request Id. It's the value of header x-oss-request-id, which is created from OSS server.
+ It's a unique Id represents this request. This is used for troubleshooting when you contact OSS support.
+ */
+@property (nonatomic, strong) NSString * requestId;
+
+/**
+ It's the value of header x-oss-hash-crc64ecma, which is created from OSS server.
+ */
+@property (nonatomic, copy) NSString *remoteCRC64ecma;
+
+/**
+ It's the value of local Data.
+ */
+@property (nonatomic, copy) NSString *localCRC64ecma;
+
+@end

+ 46 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSService.h

@@ -0,0 +1,46 @@
+//
+//  OSSService.h
+//  oss_ios_sdk
+//
+//  Created by zhouzhuo on 8/20/15.
+//  Copyright (c) 2015 aliyun.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#define OSS_IOS_SDK_VERSION OSSSDKVersion
+
+#import "OSSDefine.h"
+#import "OSSConstants.h"
+
+#import "OSSNetworking.h"
+#import "OSSNetworkingRequestDelegate.h"
+#import "OSSAllRequestNeededMessage.h"
+#import "OSSURLRequestRetryHandler.h"
+#import "OSSHttpResponseParser.h"
+#import "OSSRequest.h"
+#import "OSSGetObjectACLRequest.h"
+#import "OSSGetObjectACLResult.h"
+#import "OSSDeleteMultipleObjectsRequest.h"
+#import "OSSDeleteMultipleObjectsResult.h"
+#import "OSSGetBucketInfoRequest.h"
+#import "OSSGetBucketInfoResult.h"
+#import "OSSPutSymlinkRequest.h"
+#import "OSSPutSymlinkResult.h"
+#import "OSSGetSymlinkRequest.h"
+#import "OSSGetSymlinkResult.h"
+#import "OSSRestoreObjectRequest.h"
+#import "OSSRestoreObjectResult.h"
+#import "OSSGetObjectTaggingRequest.h"
+#import "OSSGetObjectTaggingResult.h"
+#import "OSSPutObjectTaggingRequest.h"
+#import "OSSPutObjectTaggingResult.h"
+#import "OSSDeleteObjectTaggingRequest.h"
+#import "OSSDeleteObjectTaggingResult.h"
+
+#import "OSSClient.h"
+#import "OSSModel.h"
+#import "OSSUtil.h"
+#import "OSSLog.h"
+
+#import "OSSBolts.h"

+ 295 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSTask.h

@@ -0,0 +1,295 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "OSSCancellationToken.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*!
+ Error domain used if there was multiple errors on <OSSTask taskForCompletionOfAllTasks:>.
+ */
+extern NSString *const OSSTaskErrorDomain;
+
+/*!
+ An error code used for <OSSTask taskForCompletionOfAllTasks:>, if there were multiple errors.
+ */
+extern NSInteger const kOSSMultipleErrorsError;
+
+/*!
+ An exception that is thrown if there was multiple exceptions on <OSSTask taskForCompletionOfAllTasks:>.
+ */
+extern NSString *const OSSTaskMultipleExceptionsException;
+
+/*!
+ An error userInfo key used if there were multiple errors on <OSSTask taskForCompletionOfAllTasks:>.
+ Value type is `NSArray<NSError *> *`.
+ */
+extern NSString *const OSSTaskMultipleErrorsUserInfoKey;
+
+/*!
+ An error userInfo key used if there were multiple exceptions on <OSSTask taskForCompletionOfAllTasks:>.
+ Value type is `NSArray<NSException *> *`.
+ */
+extern NSString *const OSSTaskMultipleExceptionsUserInfoKey;
+
+@class OSSExecutor;
+@class OSSTask;
+
+/*!
+ The consumer view of a Task. A OSSTask has methods to
+ inspect the state of the task, and to add continuations to
+ be run once the task is complete.
+ */
+@interface OSSTask<__covariant ResultType> : NSObject
+
+/*!
+ A block that can act as a continuation for a task.
+ */
+typedef __nullable id(^OSSContinuationBlock)(OSSTask<ResultType> *task);
+
+/*!
+ Creates a task that is already completed with the given result.
+ @param result The result for the task.
+ */
++ (instancetype)taskWithResult:(_Nullable ResultType)result;
+
+/*!
+ Creates a task that is already completed with the given error.
+ @param error The error for the task.
+ */
++ (instancetype)taskWithError:(NSError *)error;
+
+/*!
+ Creates a task that is already completed with the given exception.
+ @param exception The exception for the task.
+ */
++ (instancetype)taskWithException:(NSException *)exception;
+
+/*!
+ Creates a task that is already cancelled.
+ */
++ (instancetype)cancelledTask;
+
+/*!
+ Returns a task that will be completed (with result == nil) once
+ all of the input tasks have completed.
+ @param tasks An `NSArray` of the tasks to use as an input.
+ */
++ (instancetype)taskForCompletionOfAllTasks:(nullable NSArray<OSSTask *> *)tasks;
+
+/*!
+ Returns a task that will be completed once all of the input tasks have completed.
+ If all tasks complete successfully without being faulted or cancelled the result will be
+ an `NSArray` of all task results in the order they were provided.
+ @param tasks An `NSArray` of the tasks to use as an input.
+ */
++ (instancetype)taskForCompletionOfAllTasksWithResults:(nullable NSArray<OSSTask *> *)tasks;
+
+/*!
+ Returns a task that will be completed once there is at least one successful task.
+ The first task to successuly complete will set the result, all other tasks results are 
+ ignored.
+ @param tasks An `NSArray` of the tasks to use as an input.
+ */
++ (instancetype)taskForCompletionOfAnyTask:(nullable NSArray<OSSTask *> *)tasks;
+
+/*!
+ Returns a task that will be completed a certain amount of time in the future.
+ @param millis The approximate number of milliseconds to wait before the
+ task will be finished (with result == nil).
+ */
++ (instancetype)taskWithDelay:(int)millis;
+
+/*!
+ Returns a task that will be completed a certain amount of time in the future.
+ @param millis The approximate number of milliseconds to wait before the
+ task will be finished (with result == nil).
+ @param token The cancellation token (optional).
+ */
++ (instancetype)taskWithDelay:(int)millis cancellationToken:(nullable OSSCancellationToken *)token;
+
+/*!
+ Returns a task that will be completed after the given block completes with
+ the specified executor.
+ @param executor A OSSExecutor responsible for determining how the
+ continuation block will be run.
+ @param block The block to immediately schedule to run with the given executor.
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
++ (instancetype)taskFromExecutor:(OSSExecutor *)executor withBlock:(nullable id (^)(void))block;
+
+// Properties that will be set on the task once it is completed.
+
+/*!
+ The result of a successful task.
+ */
+@property (nullable, nonatomic, strong, readonly) ResultType result;
+
+/*!
+ The error of a failed task.
+ */
+@property (nullable, nonatomic, strong, readonly) NSError *error;
+
+/*!
+ The exception of a failed task.
+ */
+@property (nullable, nonatomic, strong, readonly) NSException *exception;
+
+/*!
+ Whether this task has been cancelled.
+ */
+@property (nonatomic, assign, readonly, getter=isCancelled) BOOL cancelled;
+
+/*!
+ Whether this task has completed due to an error or exception.
+ */
+@property (nonatomic, assign, readonly, getter=isFaulted) BOOL faulted;
+
+/*!
+ Whether this task has completed.
+ */
+@property (nonatomic, assign, readonly, getter=isCompleted) BOOL completed;
+
+/*!
+ Enqueues the given block to be run once this task is complete.
+ This method uses a default execution strategy. The block will be
+ run on the thread where the previous task completes, unless the
+ the stack depth is too deep, in which case it will be run on a
+ dispatch queue with default priority.
+ @param block The block to be run once this task is complete.
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithBlock:(OSSContinuationBlock)block;
+
+/*!
+ Enqueues the given block to be run once this task is complete.
+ This method uses a default execution strategy. The block will be
+ run on the thread where the previous task completes, unless the
+ the stack depth is too deep, in which case it will be run on a
+ dispatch queue with default priority.
+ @param block The block to be run once this task is complete.
+ @param cancellationToken The cancellation token (optional).
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithBlock:(OSSContinuationBlock)block cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
+
+/*!
+ Enqueues the given block to be run once this task is complete.
+ @param executor A OSSExecutor responsible for determining how the
+ continuation block will be run.
+ @param block The block to be run once this task is complete.
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor withBlock:(OSSContinuationBlock)block;
+/*!
+ Enqueues the given block to be run once this task is complete.
+ @param executor A OSSExecutor responsible for determining how the
+ continuation block will be run.
+ @param block The block to be run once this task is complete.
+ @param cancellationToken The cancellation token (optional).
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ his method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor
+                           block:(OSSContinuationBlock)block
+               cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
+
+/*!
+ Identical to continueWithBlock:, except that the block is only run
+ if this task did not produce a cancellation, error, or exception.
+ If it did, then the failure will be propagated to the returned
+ task.
+ @param block The block to be run once this task is complete.
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithSuccessBlock:(OSSContinuationBlock)block;
+
+/*!
+ Identical to continueWithBlock:, except that the block is only run
+ if this task did not produce a cancellation, error, or exception.
+ If it did, then the failure will be propagated to the returned
+ task.
+ @param block The block to be run once this task is complete.
+ @param cancellationToken The cancellation token (optional).
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithSuccessBlock:(OSSContinuationBlock)block cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
+
+/*!
+ Identical to continueWithExecutor:withBlock:, except that the block
+ is only run if this task did not produce a cancellation, error, or
+ exception. If it did, then the failure will be propagated to the
+ returned task.
+ @param executor A OSSExecutor responsible for determining how the
+ continuation block will be run.
+ @param block The block to be run once this task is complete.
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor withSuccessBlock:(OSSContinuationBlock)block;
+
+/*!
+ Identical to continueWithExecutor:withBlock:, except that the block
+ is only run if this task did not produce a cancellation, error, or
+ exception. If it did, then the failure will be propagated to the
+ returned task.
+ @param executor A OSSExecutor responsible for determining how the
+ continuation block will be run.
+ @param block The block to be run once this task is complete.
+ @param cancellationToken The cancellation token (optional).
+ @returns A task that will be completed after block has run.
+ If block returns a OSSTask, then the task returned from
+ this method will not be completed until that task is completed.
+ */
+- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor
+                    successBlock:(OSSContinuationBlock)block
+               cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
+
+/*!
+ Waits until this operation is completed.
+ This method is inefficient and consumes a thread resource while
+ it's running. It should be avoided. This method logs a warning
+ message if it is used on the main thread.
+ */
+- (void)waitUntilFinished;
+
+@end
+
+@class OSSResult;
+
+@interface OSSTask(OSS)
+
+typedef void(^OSSCompleteBlock)(BOOL isSuccess, NSError * _Nullable error, OSSResult * _Nullable result);
+
+- (BOOL)isSuccessful;
+
+- (NSError *)toError;
+
+- (OSSTask *)completed:(OSSCompleteBlock)block;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 89 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSTaskCompletionSource.h

@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class OSSTask<ResultType>;
+
+/*!
+ A OSSTaskCompletionSource represents the producer side of tasks.
+ It is a task that also has methods for changing the state of the
+ task by settings its completion values.
+ */
+@interface OSSTaskCompletionSource<__covariant ResultType> : NSObject
+
+/*!
+ Creates a new unfinished task.
+ */
++ (instancetype)taskCompletionSource;
+
+/*!
+ The task associated with this TaskCompletionSource.
+ */
+@property (nonatomic, strong, readonly) OSSTask<ResultType> *task;
+
+/*!
+ Completes the task by setting the result.
+ Attempting to set this for a completed task will raise an exception.
+ @param result The result of the task.
+ */
+- (void)setResult:(nullable ResultType)result;
+
+/*!
+ Completes the task by setting the error.
+ Attempting to set this for a completed task will raise an exception.
+ @param error The error for the task.
+ */
+- (void)setError:(NSError *)error;
+
+/*!
+ Completes the task by setting an exception.
+ Attempting to set this for a completed task will raise an exception.
+ @param exception The exception for the task.
+ */
+- (void)setException:(NSException *)exception;
+
+/*!
+ Completes the task by marking it as cancelled.
+ Attempting to set this for a completed task will raise an exception.
+ */
+- (void)cancel;
+
+/*!
+ Sets the result of the task if it wasn't already completed.
+ @returns whether the new value was set.
+ */
+- (BOOL)trySetResult:(nullable ResultType)result;
+
+/*!
+ Sets the error of the task if it wasn't already completed.
+ @param error The error for the task.
+ @returns whether the new value was set.
+ */
+- (BOOL)trySetError:(NSError *)error;
+
+/*!
+ Sets the exception of the task if it wasn't already completed.
+ @param exception The exception for the task.
+ @returns whether the new value was set.
+ */
+- (BOOL)trySetException:(NSException *)exception;
+
+/*!
+ Sets the cancellation state of the task if it wasn't already completed.
+ @returns whether the new value was set.
+ */
+- (BOOL)trySetCancelled;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 36 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSURLRequestRetryHandler.h

@@ -0,0 +1,36 @@
+//
+//  OSSURLRequestRetryHandler.h
+//  AliyunOSSSDK
+//
+//  Created by huaixu on 2018/1/22.
+//  Copyright © 2018年 aliyun. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSConstants.h"
+
+@class OSSNetworkingRequestDelegate;
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ The retry handler interface
+ */
+@interface OSSURLRequestRetryHandler : NSObject
+
+@property (nonatomic, assign) uint32_t maxRetryCount;
+
+
++ (instancetype)defaultRetryHandler;
+
+- (OSSNetworkingRetryType)shouldRetry:(uint32_t)currentRetryCount
+                      requestDelegate:(OSSNetworkingRequestDelegate *)delegate
+                             response:(NSHTTPURLResponse *)response
+                                error:(NSError *)error;
+
+- (NSTimeInterval)timeIntervalForRetry:(uint32_t)currentRetryCount
+                             retryType:(OSSNetworkingRetryType)retryType;
+@end
+
+NS_ASSUME_NONNULL_END

+ 77 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSUtil.h

@@ -0,0 +1,77 @@
+//
+//  OSSUtil.h
+//  oss_ios_sdk
+//
+//  Created by zhouzhuo on 8/16/15.
+//  Copyright (c) 2015 aliyun.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSFileLogger.h"
+
+#import "NSMutableDictionary+OSS.h"
+#import "NSMutableData+OSS_CRC.h"
+#import "NSDate+OSS.h"
+
+@class OSSFederationToken;
+
+@interface OSSUtil : NSObject
+
++ (BOOL)isIncludeCnameExcludeList:(NSArray *)cnameExcludeList host:(NSString *)host;
++ (NSString *)calBase64Sha1WithData:(NSString *)data withSecret:(NSString *)key;
++ (NSString *)calBase64WithData:(uint8_t *)data;
++ (NSString *)encodeURL:(NSString *)url;
++ (NSData *)constructHttpBodyFromPartInfos:(NSArray *)partInfos;
++ (NSData *)constructHttpBodyForDeleteMultipleObjects:(NSArray<NSString *> *)keys quiet:(BOOL)quiet;
++ (NSData *)constructHttpBodyForCreateBucketWithLocation:(NSString *)location __attribute__((deprecated("deprecated!")));
++ (BOOL)validateBucketName:(NSString *)bucketName;
++ (BOOL)validateObjectKey:(NSString *)objectKey;
++ (BOOL)isOssOriginBucketHost:(NSString *)host;
++ (NSString *)getIpByHost:(NSString *)host;
++ (BOOL)isNetworkDelegateState;
+
++ (NSData *)fileMD5:(NSString *)path;
++ (NSString *)dataMD5String:(NSData *)data;
++ (NSString *)fileMD5String:(NSString *)path;
++ (NSString *)base64Md5ForData:(NSData *)data;
++ (NSString *)base64Md5ForFilePath:(NSString *)filePath;
++ (NSString *)base64Md5ForFileURL:(NSURL *)fileURL;
++ (NSString *)base64ForData:(uint8_t *)input length:(int32_t)length;
++ (NSString *)dataMD5String:(NSData *)data error:(NSError **)error;
++ (NSString *)fileMD5String:(NSString *)path error:(NSError **)error;
+
++ (NSString *)populateSubresourceStringFromParameter:(NSDictionary *)parameters;
++ (NSString *)populateQueryStringFromParameter:(NSDictionary *)parameters;
++ (BOOL)isSubresource:(NSString *)param;
++ (NSString *)sign:(NSString *)content withToken:(OSSFederationToken *)token;
++ (NSString *)getRelativePath:(NSString *)fullPath;
++ (NSString *)detemineMimeTypeForFilePath:(NSString *)filePath uploadName:(NSString *)uploadName;
++ (BOOL)hasPhoneFreeSpace;
+
++ (uint64_t)crc64ecma:(uint64_t)crc1 buffer:(void *)buffer length:(size_t)len;
+
+/**
+ * @brief: combine crc1 and crc2
+ */
+
++ (uint64_t)crc64ForCombineCRC1:(uint64_t)crc1 CRC2:(uint64_t)crc2 length:(size_t)len2;
+
++ (NSString *)sha1WithString:(NSString *)string;
++ (NSString *)sha1WithData:(NSData *)data;
++ (NSString *)sha1WithFilePath:(NSString *)filePath;
+
++ (NSData *)constructHttpBodyForTriggerCallback:(NSString *)callbackParams callbackVaribles:(NSString *)callbackVaribles;
+
++ (NSData *)constructHttpBodyForImagePersist:(NSString *)action toBucket:(NSString *)toBucket toObjectKey:(NSString *)toObjectKey;
+
+@end
+
+@interface NSString (OSS)
+
+- (NSString *)oss_trim;
+- (BOOL)oss_isNotEmpty;
+- (NSString *)oss_stringByAppendingPathComponentForURL:(NSString *)path;
++ (NSString *)oss_documentDirectory;
+- (NSString *)oss_urlEncodedString;
+
+@end

+ 88 - 0
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Headers/OSSXMLDictionary.h

@@ -0,0 +1,88 @@
+//
+//  XMLDictionary.h
+//
+//  Version 1.4
+//
+//  Created by Nick Lockwood on 15/11/2010.
+//  Copyright 2010 Charcoal Design. All rights reserved.
+//
+//  Get the latest version of XMLDictionary from here:
+//
+//  https://github.com/nicklockwood/XMLDictionary
+//
+//  This software is provided 'as-is', without any express or implied
+//  warranty.  In no event will the authors be held liable for any damages
+//  arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,
+//  including commercial applications, and to alter it and redistribute it
+//  freely, subject to the following restrictions:
+//
+//  1. The origin of this software must not be misrepresented; you must not
+//  claim that you wrote the original software. If you use this software
+//  in a product, an acknowledgment in the product documentation would be
+//  appreciated but is not required.
+//
+//  2. Altered source versions must be plainly marked as such, and must not be
+//  misrepresented as being the original software.
+//
+//  3. This notice may not be removed or altered from any source distribution.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSSConstants.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis"
+@interface OSSXMLDictionaryParser : NSObject <NSCopying>
+
++ (OSSXMLDictionaryParser *)sharedInstance;
+
+@property (nonatomic, assign) BOOL collapseTextNodes; // defaults to YES
+@property (nonatomic, assign) BOOL stripEmptyNodes;   // defaults to YES
+@property (nonatomic, assign) BOOL trimWhiteSpace;    // defaults to YES
+@property (nonatomic, assign) BOOL alwaysUseArrays;   // defaults to NO
+@property (nonatomic, assign) BOOL preserveComments;  // defaults to NO
+@property (nonatomic, assign) BOOL wrapRootNode;      // defaults to NO
+
+@property (nonatomic, assign) OSSXMLDictionaryAttributesMode attributesMode;
+@property (nonatomic, assign) OSSXMLDictionaryNodeNameMode nodeNameMode;
+
+- (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser;
+- (NSDictionary *)dictionaryWithData:(NSData *)data;
+- (NSDictionary *)dictionaryWithString:(NSString *)string;
+- (NSDictionary *)dictionaryWithFile:(NSString *)path;
+
+@end
+
+
+@interface NSDictionary (OSSXMLDictionary)
+
++ (NSDictionary *)oss_dictionaryWithXMLParser:(NSXMLParser *)parser;
++ (NSDictionary *)oss_dictionaryWithXMLData:(NSData *)data;
++ (NSDictionary *)oss_dictionaryWithXMLString:(NSString *)string;
++ (NSDictionary *)oss_dictionaryWithXMLFile:(NSString *)path;
+
+- (NSDictionary *)oss_attributes;
+- (NSDictionary *)oss_childNodes;
+- (NSArray *)oss_comments;
+- (NSString *)oss_nodeName;
+- (NSString *)oss_innerText;
+- (NSString *)oss_innerXML;
+- (NSString *)oss_XMLString;
+
+- (NSArray *)oss_arrayValueForKeyPath:(NSString *)keyPath;
+- (NSString *)oss_stringValueForKeyPath:(NSString *)keyPath;
+- (NSDictionary *)oss_dictionaryValueForKeyPath:(NSString *)keyPath;
+
+@end
+
+
+@interface NSString (OSSXMLDictionary)
+
+- (NSString *)oss_XMLEncodedString;
+
+@end
+
+
+#pragma GCC diagnostic pop

binární
AIIM/AIIM/frameworks/AliyunOSSiOS.xcframework/ios-arm64/AliyunOSSiOS.framework/Info.plist


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů