Procházet zdrojové kódy

1.修改iOS Apex Mobile Result Action。

Pen Li před 7 roky
rodič
revize
91bcdfe2a9
25 změnil soubory, kde provedl 1169 přidání a 22 odebrání
  1. 45 1
      Apex Mobile/Apex Mobile.xcodeproj/project.pbxproj
  2. 142 13
      Apex Mobile/Apex Mobile/RANetwork.m
  3. 4 1
      Apex Mobile/Apex Mobile/Result/ApexResultProtocol.h
  4. 117 2
      Apex Mobile/Apex Mobile/Result/ApexResultViewController.m
  5. 19 0
      Apex Mobile/Apex Mobile/Result/Cell/ApexResultAdditionView.h
  6. 60 0
      Apex Mobile/Apex Mobile/Result/Cell/ApexResultAdditionView.m
  7. 15 0
      Apex Mobile/Apex Mobile/Result/Cell/ApexResultDocumentCell.m
  8. 4 1
      Apex Mobile/Apex Mobile/Result/Cell/ApexResultDocumentCell.xib
  9. 2 0
      Apex Mobile/Apex Mobile/Result/Cell/ApexResultShipCell.h
  10. 64 0
      Apex Mobile/Apex Mobile/Result/Cell/ApexResultShipCell.m
  11. 1 0
      Apex Mobile/Apex Mobile/Result/Model/ApexResultBaseModel.h
  12. 9 0
      Apex Mobile/Apex Mobile/Result/Model/ApexResultShipModel.h
  13. 32 1
      Apex Mobile/Apex Mobile/Result/Model/ApexResultShipModel.m
  14. 15 2
      Apex Mobile/Apex Mobile/Result/Presenter/ApexResultPresenter.h
  15. 75 1
      Apex Mobile/Apex Mobile/Result/Presenter/ApexResultPresenter.m
  16. 17 0
      Apex Mobile/Apex Mobile/Result/QuickLook/ApexResultViewController+QuickLook.h
  17. 176 0
      Apex Mobile/Apex Mobile/Result/QuickLook/ApexResultViewController+QuickLook.m
  18. 3 0
      Apex Mobile/Apex Mobile/Result/TableDataSource/ApexResultViewController+TableDataSource.m
  19. 101 0
      Apex Mobile/Apex Mobile/Result/TableDelegate/ApexResultViewController+TableDelegate.m
  20. 17 0
      Apex Mobile/Apex Mobile/ResultFields/ApexFieldsViewController.h
  21. 123 0
      Apex Mobile/Apex Mobile/ResultFields/ApexFieldsViewController.m
  22. 16 0
      Apex Mobile/Apex Mobile/ResultFields/ApexResultFieldCell.h
  23. 34 0
      Apex Mobile/Apex Mobile/ResultFields/ApexResultFieldCell.m
  24. 74 0
      Apex Mobile/Apex Mobile/ResultFields/ApexResultFields.storyboard
  25. 4 0
      Apex Mobile/Apex Mobile/SearchViewController.m

+ 45 - 1
Apex Mobile/Apex Mobile.xcodeproj/project.pbxproj

@@ -66,6 +66,11 @@
 		42BCACCA209AE243009DDA43 /* AMAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BCACC9209AE243009DDA43 /* AMAnnotationView.m */; };
 		42BCACCD209AE342009DDA43 /* AMMapAnnotaion.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BCACCC209AE342009DDA43 /* AMMapAnnotaion.m */; };
 		42BFD2D2207B697800DA9038 /* KPICell.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BFD2D1207B697800DA9038 /* KPICell.m */; };
+		42C6754E21E2F1D4001E3FF4 /* ApexResultAdditionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 42C6754D21E2F1D4001E3FF4 /* ApexResultAdditionView.m */; };
+		42C6755221E32654001E3FF4 /* ApexResultViewController+QuickLook.m in Sources */ = {isa = PBXBuildFile; fileRef = 42C6755121E32654001E3FF4 /* ApexResultViewController+QuickLook.m */; };
+		42C6755621E34EAF001E3FF4 /* ApexFieldsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 42C6755521E34EAF001E3FF4 /* ApexFieldsViewController.m */; };
+		42C6755821E34FB0001E3FF4 /* ApexResultFields.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 42C6755721E34FB0001E3FF4 /* ApexResultFields.storyboard */; };
+		42C6755B21E35112001E3FF4 /* ApexResultFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 42C6755A21E35112001E3FF4 /* ApexResultFieldCell.m */; };
 		42DE626220A41907005FB582 /* AMTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 42DE626120A41907005FB582 /* AMTextField.m */; };
 		7101BEC82031389A00CC6E3A /* DetailCellKVNew.m in Sources */ = {isa = PBXBuildFile; fileRef = 7101BEC72031389A00CC6E3A /* DetailCellKVNew.m */; };
 		711BA6C1191E0525002EDE6F /* MessageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 711BA6C0191E0525002EDE6F /* MessageViewController.m */; };
@@ -310,6 +315,15 @@
 		42BCACCC209AE342009DDA43 /* AMMapAnnotaion.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AMMapAnnotaion.m; sourceTree = "<group>"; };
 		42BFD2D0207B697800DA9038 /* KPICell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KPICell.h; sourceTree = "<group>"; };
 		42BFD2D1207B697800DA9038 /* KPICell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KPICell.m; sourceTree = "<group>"; };
+		42C6754C21E2F1D4001E3FF4 /* ApexResultAdditionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApexResultAdditionView.h; sourceTree = "<group>"; };
+		42C6754D21E2F1D4001E3FF4 /* ApexResultAdditionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApexResultAdditionView.m; sourceTree = "<group>"; };
+		42C6755021E32654001E3FF4 /* ApexResultViewController+QuickLook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ApexResultViewController+QuickLook.h"; sourceTree = "<group>"; };
+		42C6755121E32654001E3FF4 /* ApexResultViewController+QuickLook.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "ApexResultViewController+QuickLook.m"; sourceTree = "<group>"; };
+		42C6755421E34EAF001E3FF4 /* ApexFieldsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApexFieldsViewController.h; sourceTree = "<group>"; };
+		42C6755521E34EAF001E3FF4 /* ApexFieldsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApexFieldsViewController.m; sourceTree = "<group>"; };
+		42C6755721E34FB0001E3FF4 /* ApexResultFields.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ApexResultFields.storyboard; sourceTree = "<group>"; };
+		42C6755921E35112001E3FF4 /* ApexResultFieldCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApexResultFieldCell.h; sourceTree = "<group>"; };
+		42C6755A21E35112001E3FF4 /* ApexResultFieldCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApexResultFieldCell.m; sourceTree = "<group>"; };
 		42DE626020A41907005FB582 /* AMTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AMTextField.h; sourceTree = "<group>"; };
 		42DE626120A41907005FB582 /* AMTextField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AMTextField.m; sourceTree = "<group>"; };
 		7101BEC62031389A00CC6E3A /* DetailCellKVNew.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DetailCellKVNew.h; sourceTree = "<group>"; };
@@ -615,6 +629,7 @@
 				4225E42321E08502009D2364 /* ApexResultViewController.m */,
 				4225E42521E08576009D2364 /* ApexResult.storyboard */,
 				4225E44521E099B7009D2364 /* Presenter */,
+				42C6754F21E3262D001E3FF4 /* QuickLook */,
 				4225E42A21E08858009D2364 /* TableDelegate */,
 				4225E42921E0884E009D2364 /* TableDataSource */,
 				4225E42821E085E3009D2364 /* Model */,
@@ -632,6 +647,8 @@
 				4225E43621E08A8C009D2364 /* ApexResultDocumentCell.h */,
 				4225E43721E08A8C009D2364 /* ApexResultDocumentCell.m */,
 				4225E43821E08A8C009D2364 /* ApexResultDocumentCell.xib */,
+				42C6754C21E2F1D4001E3FF4 /* ApexResultAdditionView.h */,
+				42C6754D21E2F1D4001E3FF4 /* ApexResultAdditionView.m */,
 			);
 			path = Cell;
 			sourceTree = "<group>";
@@ -689,8 +706,8 @@
 		4225E44C21E0A39A009D2364 /* LayoutConstraint */ = {
 			isa = PBXGroup;
 			children = (
-				4225E44D21E0A39A009D2364 /* UIView+RAConstraint.m */,
 				4225E44E21E0A39A009D2364 /* UIView+RAConstraint.h */,
+				4225E44D21E0A39A009D2364 /* UIView+RAConstraint.m */,
 			);
 			name = LayoutConstraint;
 			path = ../../common/LayoutConstraint;
@@ -822,6 +839,27 @@
 			path = ../../common/customUI/Alert;
 			sourceTree = "<group>";
 		};
+		42C6754F21E3262D001E3FF4 /* QuickLook */ = {
+			isa = PBXGroup;
+			children = (
+				42C6755021E32654001E3FF4 /* ApexResultViewController+QuickLook.h */,
+				42C6755121E32654001E3FF4 /* ApexResultViewController+QuickLook.m */,
+			);
+			path = QuickLook;
+			sourceTree = "<group>";
+		};
+		42C6755321E34E77001E3FF4 /* ResultFields */ = {
+			isa = PBXGroup;
+			children = (
+				42C6755421E34EAF001E3FF4 /* ApexFieldsViewController.h */,
+				42C6755521E34EAF001E3FF4 /* ApexFieldsViewController.m */,
+				42C6755721E34FB0001E3FF4 /* ApexResultFields.storyboard */,
+				42C6755921E35112001E3FF4 /* ApexResultFieldCell.h */,
+				42C6755A21E35112001E3FF4 /* ApexResultFieldCell.m */,
+			);
+			path = ResultFields;
+			sourceTree = "<group>";
+		};
 		713AA79E1917366A00B44092 /* documents */ = {
 			isa = PBXGroup;
 			children = (
@@ -1203,6 +1241,7 @@
 				4225E44921E0A39A009D2364 /* HUD */,
 				4225E44C21E0A39A009D2364 /* LayoutConstraint */,
 				4225E42121E084A4009D2364 /* Result */,
+				42C6755321E34E77001E3FF4 /* ResultFields */,
 				426E8AB4202163EB0073BA5D /* Alert */,
 				425CF089201EB2B500750E32 /* Refresh */,
 				715643B820198A6000B04267 /* new */,
@@ -1431,6 +1470,7 @@
 			files = (
 				42541ACF207C49610072BC5A /* fake_home.json in Resources */,
 				71625470201C5205009E3A41 /* fake_container_list.json in Resources */,
+				42C6755821E34FB0001E3FF4 /* ApexResultFields.storyboard in Resources */,
 				7162546B201C3AF1009E3A41 /* readme.txt in Resources */,
 				42604129201C57A7002374A8 /* ShipSearch.storyboard in Resources */,
 				715643DC201C117300B04267 /* search.json in Resources */,
@@ -1494,6 +1534,7 @@
 				71406DD118C36A6E000914C4 /* TableCellDate.m in Sources */,
 				717D772F18C84E3F0070302D /* PageData.m in Sources */,
 				425390202079B99B00ECF982 /* XYCommon.m in Sources */,
+				42C6755B21E35112001E3FF4 /* ApexResultFieldCell.m in Sources */,
 				715709BB20215E0000EFE5C5 /* NSData+Base64.m in Sources */,
 				71375C8F18D96EDE00EBA026 /* TabBarController.m in Sources */,
 				42BB7402208431DA00B9B6E4 /* KPILegendCell.m in Sources */,
@@ -1531,6 +1572,7 @@
 				715709BA20215E0000EFE5C5 /* NSString+Base64.m in Sources */,
 				71AE427318C47AF900B8EC3D /* SearchViewController.m in Sources */,
 				715643BE2019AA9B00B04267 /* LoginViewController.m in Sources */,
+				42C6755621E34EAF001E3FF4 /* ApexFieldsViewController.m in Sources */,
 				4225E43321E08A54009D2364 /* ApexResultShipCell.m in Sources */,
 				71308AF7191E7B0E0024B2B0 /* MessageDetailItem.m in Sources */,
 				71A565D918C20F5900CDAC07 /* SearchTableAdapter.m in Sources */,
@@ -1581,6 +1623,7 @@
 				71FCDE0720492B5E00B0746B /* MyQLPreviewController.m in Sources */,
 				71F67CF919065EA8004E8462 /* SimpleMenu.m in Sources */,
 				719A51BA18C5AB7B0080C075 /* SimpleGridComponent.m in Sources */,
+				42C6754E21E2F1D4001E3FF4 /* ApexResultAdditionView.m in Sources */,
 				71570996202157A600EFE5C5 /* RAUtils.m in Sources */,
 				715643BB20198A9900B04267 /* RootViewController.m in Sources */,
 				4225E42D21E08895009D2364 /* ApexResultViewController+TableDelegate.m in Sources */,
@@ -1600,6 +1643,7 @@
 				715709AB20215B6200EFE5C5 /* ZipArchive.mm in Sources */,
 				42BCACCA209AE243009DDA43 /* AMAnnotationView.m in Sources */,
 				425CF09A201EB2B500750E32 /* UIView+JLExtension.m in Sources */,
+				42C6755221E32654001E3FF4 /* ApexResultViewController+QuickLook.m in Sources */,
 				71A01D7918C9AE77003307A9 /* DetailCellKV.m in Sources */,
 				42604127201C578B002374A8 /* ShipSearchController.m in Sources */,
 				713AA7A41917373600B44092 /* LocalDocumentsViewController.m in Sources */,

+ 142 - 13
Apex Mobile/Apex Mobile/RANetwork.m

@@ -1405,26 +1405,155 @@
 
     sleep(2);
     
-    NSDictionary *item = @{
-                           @"type": @0,
-                           @"title": @"CN - TRANSNATIONAL FOODS LLC.",
-                           @"icon": @"status_ae",
-                           @"serial_no": @"b9a21e6d80e3b78761ecfd35d2a9d123",
-                           @"hbol": @"A1812530804",
-                           @"desc": @"A1812530804(1 containers)",
-                           @"detail": @"Loaded at Relay Port; VNCMT (CAI MEP, VN  2019-01-05)",
-                           @"date": @"12/23/2018 - 02/03/2019",
-                           @"port": @"VNHPH - USORF",
-                           @"transport_stage": @3
-                           };
+    // Booking : module_name = Ocean Booking
+    NSDictionary *item_booking = @{
+                                   @"type": @0,
+                                   @"icon": @"status_ae",
+                                   @"title":@"FU YAMA TRADing", // Consignee
+                                   @"date":@"03/28/2019 - 04/24/2019", // M.V ETD - M.V ETA
+                                   @"port":@"CNYTN - USLAX", // pol pod
+                                   @"desc":@"B61180700423", // Booking#
+                                   @"detail":@"HUNG TA GARDEN ENTERPRISE CO., LTD", // Shipper
+                                   @"transport_stage": @3,
+                                   @"addition":@[
+                                           @{
+                                               @"name":@"Carrier Booking#",
+                                               @"value":@"NAM1774822"
+                                               },
+                                           @{
+                                               @"name":@"Consignee",
+                                               @"value":@"FU YAMA TRADing"
+                                               },
+                                           @{
+                                               @"name":@"Place Of Delivery",
+                                               @"value":@"CAPE TOWN, SOUTH AFRICA"
+                                               },
+                                           ],
+                                   @"rowActionParameters":@[
+                                           @"27d620831e3f458643c8046305e2cd13"
+                                           ]
+                                   };
+    
+    // B/L Info : module_name = Ocean B/L info.
+    NSDictionary *item_BL = @{
+                               @"type": @0,
+                               @"icon": @"status_ae",
+                               @"title":@"FU YAMA TRADing", // Consignee
+                               @"date":@"03/28/2019 - 04/24/2019", // ETD - ETA Port
+                               @"port":@"CNYTN - USLAX", // pol pod
+                               @"desc":@"A1903300004", // hbol#
+                               @"detail":@"VIENXING GLOBAL PTE LTD", // Shipper
+                               @"transport_stage": @3,
+                               @"rowActionParameters":@[
+                                       @"27d620831e3f458643c8046305e2cd13"
+                                       ]
+                               };
+    
+    // Container : module_name = Container detail
+    NSDictionary *item_container = @{
+                                      @"type": @0,
+                                      @"icon": @"status_ae",
+                                      @"title": @"CN - YC STONE INC",
+                                      @"hbol": @"A1901280696",
+                                      @"desc": @"A1901280696(1 containers)",
+                                      @"detail": @"Gate in full for a booking; CNGOM (GAOMING, 44, CN  2019-01-04)",
+                                      @"date": @"01/16/2019 - 01/29/2019",
+                                      @"port": @"CNNSA - USLGB",
+                                      @"transport_stage": @3,
+                                      @"rowActionParameters":@[
+                                              @"27d620831e3f458643c8046305e2cd13"
+                                              ]
+                                      };
+    
+    // Document : module_name = Download Document
+    NSDictionary *item_doc = @{
+                                @"type": @1,
+                                @"fileName":@"A1811390637FR1-UTA.pdf",
+                                @"fileType":@"HBL",
+                                @"fileDesc":@"BOL:A1811390637, PO#:0001791,0001722,0001885",
+                                @"rowActionParameters":@[
+                                                         @"handset_search",
+                                                         @"download_doc",
+                                                         @"https://ra.apexshipping.com/main_new.php",
+                                                         @"QW10UUtFeDdRNlBFTzhLbFpYcCUyRmtUSFJnWHRwZ1RQSnBnZmpQblc0c1BHJTJCR1E5c2ZScWY3NXpIazJ0OXdicHEyUnolMkJxSkN1MDVV",
+                                                         @"Question : FileName: ONEYSRGU12759300FR3.PDF, BOL: ONEYSRGU12759300",
+                                                         @"FileName: ONEYSRGU12759300FR3.PDF, BOL: ONEYSRGU12759300",
+                                                         @""
+                                                         ]
+                                };
     
+    NSString *module_name = [params objectForKey:@"module_name"];
     NSMutableArray *arr = [NSMutableArray array];
     for (int i = 0; i < 20; i++) {
-        [arr addObject:item.copy];
+        if ([module_name isEqualToString:@"Ocean Booking"]) {
+            [arr addObject:item_booking.copy];
+        } else if ([module_name isEqualToString:@"Ocean B/L info."]) {
+            [arr addObject:item_BL.copy];
+        } else if ([module_name isEqualToString:@"Container detail"]) {
+            [arr addObject:item_container.copy];
+        } else if ([module_name isEqualToString:@"Download Document"]) {
+            [arr addObject:item_doc.copy];
+        }
     }
     
+    NSString *title = @"";
+    if ([module_name isEqualToString:@"Ocean Booking"]) {
+        
+        title = @"Ocean Booking";
+    } else if ([module_name isEqualToString:@"Ocean B/L info."]) {
+        
+        title = @"Ocean B/L info";
+    } else if ([module_name isEqualToString:@"Container detail"]) {
+        
+        title = @"Container detail";
+    } else if ([module_name isEqualToString:@"Download Document"]) {
+        
+        title = @"Download Document";
+    }
+    
+    NSArray *row_actions;
+    if ([module_name isEqualToString:@"Download Document"]) {
+        
+        row_actions = @[@{
+                            @"title": @"Download Document",
+                            @"module": @"quick_look",
+                            @"url": @"https://ra.apexshipping.com/main_new.php",
+                            @"params": @{
+                                    @"action": @0,
+                                    @"action_type": @1,
+                                    @"prefix": @2,
+                                    @"url": @3,
+                                    @"email_subject": @4,
+                                    @"email_content": @5,
+                                    @"email": @6
+                                    }
+                            }];
+    } else {
+        
+        row_actions = @[@{
+                            @"title": @"Ocean B/L info Detail",
+                            @"module": @"detail",
+                            @"url": @"https://ra.apexshipping.com/main_new.php?action=handset_search",
+                            @"params": @{
+                                    @"id": @0,
+                                    }
+                            }];
+    }
+    
+    // for detail
+    NSArray *actions = @[
+                         @"Detail",
+                         @"ISF LOG",
+                         @"AMS LOG",
+                         @"Tracing",
+                         @"Detail"
+                         ];
+    
     NSDictionary *resultDic = @{
                                 @"result" : @RESULT_TRUE,
+                                @"title" : title,
+                                @"row_actions" : row_actions,
+                                @"actions" : actions,
                                 @"items" : arr
                                 };
     

+ 4 - 1
Apex Mobile/Apex Mobile/Result/ApexResultProtocol.h

@@ -13,16 +13,19 @@
 
 @protocol ApexResultProtocol <NSObject>
 
+@required
 - (void)onStartLoading;
 
 - (void)onStopLoading;
 
 - (void)onNoMoreData;
 
-- (void)onSuccess;
+- (void)onSuccess:(NSString *)title;
 
 - (void)onFailed:(NSString *)errMsg;
 
+- (void)onDownloadFile:(NSString *)path;
+
 @end
 
 #endif /* ApexResultProtocol_h */

+ 117 - 2
Apex Mobile/Apex Mobile/Result/ApexResultViewController.m

@@ -6,7 +6,7 @@
 //  Copyright © 2019 United Software Applications, Inc. All rights reserved.
 //
 
-#import "ApexResultViewController.h"
+#import "ApexResultViewController+QuickLook.h"
 #import "ApexResultProtocol.h"
 #import "ApexResultPresenter.h"
 #import "ApexResultShipCell.h"
@@ -14,6 +14,8 @@
 #import "JLRefreshHeader.h"
 #import "JLRefreshFooter.h"
 #import "RAProgressHUD.h"
+#import "RAUtils.h"
+#import "MyQLPreviewController.h"
 
 @interface ApexResultViewController ()<ApexResultProtocol, JLRefreshDelegate>
 
@@ -22,6 +24,7 @@
 
 @property (nonatomic,strong) IBOutlet UITableView *resultTableView;
 @property (nonatomic,strong) ApexResultPresenter *presenter;
+@property (nonatomic,strong) MyQLPreviewController *quickLook;
 
 @end
 
@@ -39,6 +42,7 @@
     [super viewDidLoad];
     // Do any additional setup after loading the view.
     
+    [self setupNavigationBar];
     [self setupPresenter];
     [self setupTableView];
     
@@ -70,12 +74,43 @@
     self.tableView.jl_footer = footer;
 }
 
+- (void)setupNavigationBar {
+    
+    UIBarButtonItem *menuItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"ic_menu"] style:UIBarButtonItemStylePlain target:self action:@selector(menuItemClick:)];
+    self.navigationItem.rightBarButtonItem = menuItem;
+    
+    UIBarButtonItem *backItem = [[UIBarButtonItem alloc] init];
+    backItem.title = @"";
+    self.navigationItem.backBarButtonItem = backItem;
+}
+
+- (void)_setParameters:(NSDictionary *)params {
+    self.params = params;
+    [self.presenter modifyParameters:params];
+}
+
 #pragma mark - Getter
 
 - (UITableView *)tableView {
     return self.resultTableView;
 }
 
+- (MyQLPreviewController *)quickLook {
+    if (!_quickLook)
+    {
+        _quickLook = [[MyQLPreviewController alloc] init];
+        _quickLook.delegate = self;
+        _quickLook.dataSource = self;
+        UIBarButtonItem *previewMenuBtn = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"ic_menu"] style:UIBarButtonItemStylePlain target:self action:@selector(quickLookMenuClick:)];
+        _quickLook.navigationItem.rightBarButtonItem = previewMenuBtn;
+    }
+    else
+    {
+        [_quickLook reloadData];
+    }
+    return _quickLook;
+}
+
 #pragma mark - Presenter Delegate
 
 - (void)onStartLoading {
@@ -90,15 +125,23 @@
     [(JLRefreshFooter *)self.tableView.jl_footer noMoreData];
 }
 
-- (void)onSuccess {
+- (void)onSuccess:(NSString *)title {
     [self.curRefresh endRefresh];
     [self.tableView reloadData];
+    
+    self.title = title;
 }
 
 - (void)onFailed:(NSString *)errMsg {
     [self.curRefresh endRefresh];
 }
 
+- (void)onDownloadFile:(NSString *)path {
+    if (path) {
+        [self.navigationController pushViewController:self.quickLook animated:YES];
+    }
+}
+
 #pragma mark - Refresh Delegate
 
 - (void)jl_pullRefresh:(JLRefreshBasis *)refresh state:(JLRefreshState)state percentage:(float)percentage {
@@ -123,5 +166,77 @@
     
 }
 
+#pragma mark - Navigation Item Click
+
+- (void)menuItemClick:(id)sender {
+    
+    __weak typeof(self) weakSelf = self;
+    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
+    UIAlertAction *settingAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"fields setting", @"Setting") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        [weakSelf showFieldsSetting];
+    }];
+    
+    UIAlertAction *saveAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"save", @"Save") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        
+        [weakSelf saveSearchParameters];
+    }];
+    
+    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
+        
+    }];
+    
+    [alertVC addAction:settingAction];
+    [alertVC addAction:saveAction];
+    [alertVC addAction:cancelAction];
+    
+    [self presentViewController:alertVC animated:YES completion:nil];
+}
+
+#pragma mark - Action
+
+- (void)saveSearchParameters {
+    
+    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"alert_title_create_tag", nil) message:NSLocalizedString(@"alert_msg_savehint", nil) preferredStyle:UIAlertControllerStyleAlert];
+    __block UITextField *inputTextField;
+    [alertVC addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
+        inputTextField = textField;
+    }];
+    
+    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"cancel", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        
+    }];
+    
+    __weak typeof(self) weakSelf = self;
+    UIAlertAction *saveAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"save", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        
+        UITextField * txt= inputTextField;
+        NSString* name = txt.text;
+        if(name.length==0)
+        {
+            [RAUtils message_alert:@"Name can not be empty." title:@"Save Search" controller:self];
+            return;
+        }
+        
+        [weakSelf.presenter saveSearchParameters];
+        
+    }];
+    
+    [alertVC addAction:cancelAction];
+    [alertVC addAction:saveAction];
+    
+    [self presentViewController:alertVC animated:YES completion:nil];
+}
+
+- (void)showFieldsSetting {
+    
+//    // 返回show fields
+//    NSArray *showFields;
+//
+//    // 修改params
+//    NSString *columns = [showFields componentsJoinedByString:@","];
+//    NSMutableDictionary *mParams = [self.presenter.params mutableCopy];
+//    mParams[@"columns"] = columns;
+//    [self _setParameters:mParams.copy];
+}
 
 @end

+ 19 - 0
Apex Mobile/Apex Mobile/Result/Cell/ApexResultAdditionView.h

@@ -0,0 +1,19 @@
+//
+//  ApexResultAdditionView.h
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ApexResultAdditionView : UIView
+
+@property (nonatomic,readonly,strong) UILabel *titleLabel;
+@property (nonatomic,readonly,strong) UILabel *valueLabel;
+
++ (instancetype)additionView;
+
+@end
+

+ 60 - 0
Apex Mobile/Apex Mobile/Result/Cell/ApexResultAdditionView.m

@@ -0,0 +1,60 @@
+//
+//  ApexResultAdditionView.m
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import "ApexResultAdditionView.h"
+#import "UIView+RAConstraint.h"
+
+@interface ApexResultAdditionView ()
+
+@property (nonatomic,strong) UILabel *titleLabel;
+@property (nonatomic,strong) UILabel *valueLabel;
+
+@end
+
+@implementation ApexResultAdditionView
+
++ (instancetype)additionView {
+    ApexResultAdditionView *v = [ApexResultAdditionView new];
+    [v setup];
+    return v;
+}
+
+- (void)setup {
+    
+    self.titleLabel = [[UILabel alloc] init];
+    self.titleLabel.font = [UIFont systemFontOfSize:15.0f];
+    self.titleLabel.textColor = [UIColor blackColor];
+    [self addSubview:self.titleLabel];
+    
+    self.valueLabel = [[UILabel alloc] init];
+    self.valueLabel.font = [UIFont systemFontOfSize:15.0f];
+    self.valueLabel.textColor = [UIColor blackColor];
+    [self addSubview:self.valueLabel];
+    
+    __weak typeof(self) weakSelf = self;
+    [self.titleLabel ra_applyConstraints:^(RAConstraintMaker *maker) {
+       
+        maker.left.ra_equalTo(weakSelf.left);
+        maker.top.ra_equalTo(weakSelf.top);
+        maker.height.ra_offset(20.0f);
+    }];
+    
+    [self.valueLabel ra_applyConstraints:^(RAConstraintMaker *maker) {
+        
+        maker.left.ra_equalTo(weakSelf.titleLabel.right).ra_offset(5);
+        maker.top.ra_equalTo(weakSelf.titleLabel.top);
+        maker.height.ra_equalTo(weakSelf.titleLabel.height);
+        maker.right.ra_lessThanOrEqualTo(weakSelf.right);
+    }];
+    
+    [self ra_applyConstraints:^(RAConstraintMaker *maker) {
+        maker.height.ra_offset(25.0f);
+    }];
+}
+
+@end

+ 15 - 0
Apex Mobile/Apex Mobile/Result/Cell/ApexResultDocumentCell.m

@@ -16,6 +16,8 @@
 @property (nonatomic,strong) IBOutlet UILabel *fileTypeLabel;
 @property (nonatomic,strong) IBOutlet UILabel *fileDescLabel;
 
+@property (nonatomic,strong) UIView *selectView;
+
 @end
 
 @implementation ApexResultDocumentCell
@@ -29,6 +31,19 @@
     self.bgView.layer.cornerRadius = 5;
     self.bgView.layer.borderColor = [UIColor darkGrayColor].CGColor;
     self.bgView.layer.borderWidth = 0.3;
+    
+    self.selectView = [UIView new];
+    self.selectView.layer.cornerRadius = 5;
+    self.selectView.layer.borderColor = [UIColor darkGrayColor].CGColor;
+    self.selectView.layer.borderWidth = 0.3;
+    self.selectView.backgroundColor = [UIColor colorWithWhite:0.7 alpha:0.8];
+    self.selectedBackgroundView = self.selectView;
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    
+    self.selectView.frame = self.bgView.frame;
 }
 
 - (void)prepareForReuse {

+ 4 - 1
Apex Mobile/Apex Mobile/Result/Cell/ApexResultDocumentCell.xib

@@ -22,7 +22,7 @@
                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Svu-j8-b5X">
                         <rect key="frame" x="5" y="15" width="557" height="61.5"/>
                         <subviews>
-                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="HhT-58-RDI">
+                            <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mode_document" translatesAutoresizingMaskIntoConstraints="NO" id="HhT-58-RDI">
                                 <rect key="frame" x="10" y="10" width="48" height="48"/>
                                 <constraints>
                                     <constraint firstAttribute="width" constant="48" id="OT1-ho-dUl"/>
@@ -81,4 +81,7 @@
             <point key="canvasLocation" x="-178.40000000000001" y="56.221889055472268"/>
         </tableViewCell>
     </objects>
+    <resources>
+        <image name="mode_document" width="48" height="48"/>
+    </resources>
 </document>

+ 2 - 0
Apex Mobile/Apex Mobile/Result/Cell/ApexResultShipCell.h

@@ -21,5 +21,7 @@
 - (instancetype)setTransportStage:(NSInteger)stage;
 - (instancetype)setIconSelect:(BOOL)select;
 
+- (instancetype)addAdditionName:(NSString *)name value:(NSString *)value;
+
 @end
 

+ 64 - 0
Apex Mobile/Apex Mobile/Result/Cell/ApexResultShipCell.m

@@ -8,6 +8,8 @@
 
 #import "ApexResultShipCell.h"
 #import "const.h"
+#import "ApexResultAdditionView.h"
+#import "UIView+RAConstraint.h"
 
 @interface ApexResultShipCell ()
 
@@ -20,6 +22,10 @@
 @property (strong, nonatomic) IBOutlet UILabel *detailLabel;
 @property (strong, nonatomic) IBOutlet UIView *transportStageView;
 
+@property (nonatomic,strong) UIView *selectView;
+@property (nonatomic,assign) NSInteger additionCount;
+@property (nonatomic,strong) NSMutableArray<ApexResultAdditionView *> *additionArray;
+
 @end
 
 @implementation ApexResultShipCell
@@ -40,6 +46,21 @@
     self.portLabel.textColor = [UIColor colorWithRed:168 / 255.0 green:9 / 255.0 blue:26 / 255.0 alpha:1.0];
     self.timeLabel.textColor = [UIColor colorWithRed:168 / 255.0 green:9 / 255.0 blue:26 / 255.0 alpha:1.0];
     self.descLabel.textColor = [UIColor colorWithRed:53 / 255.0 green:53 / 255.0 blue:55 / 255.0 alpha:1.0];
+    
+    self.selectView = [UIView new];
+    self.selectView.layer.cornerRadius = 5;
+    self.selectView.layer.borderColor = [UIColor darkGrayColor].CGColor;
+    self.selectView.layer.borderWidth = 0.3;
+    self.selectView.backgroundColor = [UIColor colorWithWhite:0.7 alpha:0.8];
+    self.selectedBackgroundView = self.selectView;
+    
+    self.additionArray = [NSMutableArray array];
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    
+    self.selectView.frame = self.bgView.frame;
 }
 
 - (void)prepareForReuse {
@@ -149,4 +170,47 @@
     return self;
 }
 
+- (instancetype)addAdditionName:(NSString *)name value:(NSString *)value {
+    
+    ApexResultAdditionView *additionView;
+    if (self.additionCount >= self.additionArray.count) {
+        
+        additionView = [ApexResultAdditionView additionView];
+        additionView.backgroundColor = [UIColor redColor];
+        [self.bgView addSubview:additionView];
+        
+        __weak typeof(self) weakSelf = self;
+        [additionView ra_applyConstraints:^(RAConstraintMaker *maker) {
+           
+            maker.left.ra_equalTo(weakSelf.bgView.left).ra_offset(10);
+            maker.top.ra_equalTo(weakSelf.bgView.top).ra_offset(110.0f + 25.0f * weakSelf.additionCount);
+            maker.right.ra_equalTo(weakSelf.bgView.right).ra_offset(-10);
+        }];
+        
+        [self addAdditionView:additionView];
+        
+    } else {
+        
+        additionView = [self.additionArray objectAtIndex:self.additionCount];
+    }
+    additionView.titleLabel.text = name;
+    additionView.valueLabel.text = value;
+    
+    return self;
+}
+
+#pragma mark - Private
+
+- (void)clearAdditionView {
+    for (ApexResultAdditionView *additionView in self.additionArray) {
+        [additionView removeFromSuperview];
+    }
+    self.additionCount = 0;
+}
+
+- (void)addAdditionView:(ApexResultAdditionView *)additionView {
+    [self.additionArray addObject:additionView];
+    self.additionCount++;
+}
+
 @end

+ 1 - 0
Apex Mobile/Apex Mobile/Result/Model/ApexResultBaseModel.h

@@ -17,5 +17,6 @@ typedef NS_ENUM(NSUInteger, ApexResultType) {
 
 @property (nonatomic,assign) ApexResultType type;
 @property (nonatomic, readonly, assign) CGFloat height;
+@property (nonatomic,strong) NSArray *rowActionParameters;
 
 @end

+ 9 - 0
Apex Mobile/Apex Mobile/Result/Model/ApexResultShipModel.h

@@ -8,6 +8,13 @@
 
 #import "ApexResultBaseModel.h"
 
+@interface ApexResultAddition : NSObject
+
+@property (nonatomic,copy) NSString *name;
+@property (nonatomic,copy) NSString *value;
+
+@end
+
 @interface ApexResultShipModel : ApexResultBaseModel
 
 @property (nonatomic,copy) NSString *title;
@@ -18,4 +25,6 @@
 @property (nonatomic,copy) NSString *port;
 @property (nonatomic,strong) NSNumber *transport_stage;
 
+@property (nonatomic,strong) NSArray<ApexResultAddition *> *addition;
+
 @end

+ 32 - 1
Apex Mobile/Apex Mobile/Result/Model/ApexResultShipModel.m

@@ -8,10 +8,41 @@
 
 #import "ApexResultShipModel.h"
 
+@implementation ApexResultAddition
+
+- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
+    
+}
+
+- (void)setName:(NSString *)name {
+     name = [NSString stringWithFormat:@"%@: ", name];
+    _name = name;
+}
+
+@end
+
 @implementation ApexResultShipModel
 
 - (CGFloat)height {
-    return 125.0f;
+    return 125.0f + self.addition.count * 25.0f;
+}
+
+- (void)setAddition:(NSArray<ApexResultAddition *> *)addition {
+    if (addition && addition.count > 0) {
+        
+        NSMutableArray *additionArr = [NSMutableArray array];
+        for (id add_item in addition) {
+            if ([add_item isKindOfClass:[NSDictionary class]]) {
+                ApexResultAddition *subModel = [ApexResultAddition new];
+                [subModel setValuesForKeysWithDictionary:add_item];
+                [additionArr addObject:subModel];
+            }
+        }
+        _addition = additionArr.copy;
+        
+    } else {
+        _addition = nil;
+    }
 }
 
 @end

+ 15 - 2
Apex Mobile/Apex Mobile/Result/Presenter/ApexResultPresenter.h

@@ -14,15 +14,28 @@
 
 @property (nonatomic,weak) id<ApexResultProtocol> delegate;
 
+@property (nonatomic,readonly,strong) NSDictionary *params;
 @property (nonatomic,readonly,assign) NSUInteger dataCount;
+@property (nonatomic,readonly,copy) NSString *documentPath;
+@property (nonatomic,readonly,strong) NSArray *rowActions;
+@property (nonatomic,readonly,strong) NSArray *actions;///< Detail Parameter, from query table actions_info
+@property (nonatomic,strong) NSDictionary *actionParams;///< Click Cell Action Parameters
+
+- (instancetype)initWithParameters:(NSDictionary *)params;
+
+- (ApexResultBaseModel *)resultModelForIndex:(NSInteger)index;
+
+- (NSArray *)rowActionParametersForIndex:(NSInteger)index;
 
 - (void)loadData;
 - (void)refreshData;
 - (void)loadMoreData;
 
-- (instancetype)initWithParameters:(NSDictionary *)params;
+- (void)saveSearchParameters;
 
-- (ApexResultBaseModel *)resultModelForIndex:(NSInteger)index;
+- (void)modifyParameters:(NSDictionary *)params;
+
+- (void)downloadFile:(NSString *)url withParams:(NSDictionary *)params;
 
 @end
 

+ 75 - 1
Apex Mobile/Apex Mobile/Result/Presenter/ApexResultPresenter.m

@@ -24,7 +24,10 @@ static const NSInteger detal = 20;
 
 @property (nonatomic,strong) NSDictionary *params;
 @property (nonatomic,assign) NSInteger offset;
+@property (nonatomic,copy) NSString *documentPath;
 @property (nonatomic,strong) NSArray<ApexResultBaseModel *> *dataArray;
+@property (nonatomic,strong) NSArray *rowActions;
+@property (nonatomic,strong) NSArray *actions;
 
 @end
 
@@ -83,12 +86,16 @@ static const NSInteger detal = 20;
             } // for
             self.offset = modelsArr.count;
             
+            NSString *title = [json objectForKey:@"title"];
+            self.rowActions = [json objectForKey:@"row_actions"];
+            self.actions = [json objectForKey:@"actions"];
+            
             dispatch_async(dispatch_get_main_queue(), ^{
                 
                 self.dataArray = [modelsArr copy];
                 if (self.delegate) {
                     [self.delegate onStopLoading];
-                    [self.delegate onSuccess];
+                    [self.delegate onSuccess:title];
                     if (items.count < detal) {
                         [self.delegate onNoMoreData];
                     }
@@ -134,4 +141,71 @@ static const NSInteger detal = 20;
     return self.dataArray[index];
 }
 
+- (NSArray *)rowActionParametersForIndex:(NSInteger)index {
+    if (index < 0 || index >= self.dataCount) {
+        return nil;
+    }
+    return self.dataArray[index].rowActionParameters;
+}
+
+#pragma mark - Save Search
+
+- (void)saveSearchParameters {
+    
+}
+
+#pragma mark - Field Modify
+
+- (void)modifyParameters:(NSDictionary *)params {
+    self.params = params;
+    [self loadData];
+}
+
+#pragma mark - Download File
+
+- (void)downloadFile:(NSString *)url withParams:(NSDictionary *)params {
+    
+    if (self.delegate) {
+        [self.delegate onStartLoading];
+    }
+    
+    dispatch_async(dispatch_get_global_queue(0, 0), ^{
+        
+        NSString *cacheDir = NSTemporaryDirectory();
+        
+        if (![[NSFileManager defaultManager] fileExistsAtPath:cacheDir]) {
+            [[NSFileManager defaultManager] createDirectoryAtPath:cacheDir withIntermediateDirectories:NO attributes:nil error:nil];
+        }
+        
+        [RANetwork download_file:[params mutableCopy] url:url toCachePath:cacheDir progressHandler:^(NSURLSessionTask *task, double progress) {
+            
+            DebugLog(@"download progress %f",progress);
+        } completionHandler:^(NSMutableDictionary *result) {
+            
+            dispatch_async(dispatch_get_main_queue(), ^{
+                
+                if (self.delegate) {
+                    [self.delegate onStopLoading];
+
+                    self.documentPath = nil;
+                    if ([[result objectForKey:@"result"] intValue] == RESULT_TRUE) {
+                        
+                        NSString *cachePath = [result objectForKey:@"path"];
+                        self.documentPath = cachePath;
+                        [self.delegate onDownloadFile:cachePath];
+                        
+                    } else {
+                        
+                        NSString *msg = [result objectForKey:@"msg"];
+                        [self.delegate onFailed:msg];
+                    }
+                }
+                
+            }); // main queue
+            
+        }]; // network
+        
+    }); // global queue
+}
+
 @end

+ 17 - 0
Apex Mobile/Apex Mobile/Result/QuickLook/ApexResultViewController+QuickLook.h

@@ -0,0 +1,17 @@
+//
+//  ApexResultViewController+QuickLook.h
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import "ApexResultViewController.h"
+#import <QuickLook/QuickLook.h>
+
+@interface ApexResultViewController (QuickLook) <QLPreviewControllerDataSource,QLPreviewControllerDelegate>
+
+- (void)quickLookMenuClick:(id)sender;
+
+@end
+

+ 176 - 0
Apex Mobile/Apex Mobile/Result/QuickLook/ApexResultViewController+QuickLook.m

@@ -0,0 +1,176 @@
+//
+//  ApexResultViewController+QuickLook.m
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import "ApexResultViewController+QuickLook.h"
+#import "ApexResultPresenter.h"
+#import "LPShareActivity.h"
+#import "RAConvertor.h"
+
+@implementation ApexResultViewController (QuickLook)
+
+#pragma mark - QuickLook Data Source
+
+- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
+    return 1;
+}
+
+- (id <QLPreviewItem>) previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
+    
+    if(self.presenter.documentPath==nil)
+        return nil;
+    return [NSURL fileURLWithPath:self.presenter.documentPath];
+}
+
+#pragma mark - QuickLook Delegate
+
+- (void) previewControllerDidDismiss:(QLPreviewController *)controller {
+    self.presenter.actionParams = nil;
+}
+
+/**
+ * 文件内部链接点击不进行外部跳转
+ */
+- (BOOL) previewController:(QLPreviewController *)controller shouldOpenURL:(NSURL *)url forPreviewItem:(id<QLPreviewItem>)item {
+    return NO;
+}
+
+#pragma mark - Quick Look Menu Item Click
+
+- (void)quickLookMenuClick:(id)sender {
+    
+    UIAlertController *menuAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
+    NSDictionary *rowAction = self.presenter.actionParams;
+    self.presenter.actionParams = nil;
+    
+    __weak typeof(self) weakSelf = self;
+    UIAlertAction *saveAction = [UIAlertAction actionWithTitle:@"Save Document" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        [weakSelf saveDocument:rowAction];
+    }];
+    UIAlertAction *shareAction = [UIAlertAction actionWithTitle:@"Share With Someone" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        [weakSelf shareDocument:rowAction];
+    }];
+    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
+        
+    }];
+    
+    [menuAlert addAction:saveAction];
+    [menuAlert addAction:shareAction];
+    [menuAlert addAction:cancelAction];
+    
+    [self presentViewController:menuAlert animated:YES completion:nil];
+}
+
+- (void)saveDocument:(NSDictionary *)rowAction {
+
+    NSString *email = rowAction[@"email"];
+    NSString *email_subject = rowAction[@"email_subject"];
+    NSString *email_content = rowAction[@"email_content"];
+    
+    NSMutableDictionary *emailInfo = [NSMutableDictionary new];
+    if (email.length==0) {
+        email=@"";
+        
+    }
+    if (email_subject.length==0) {
+        email_subject=@"";
+        
+    }
+    if (email_content.length==0) {
+        email_content=@"";
+        
+    }
+    [emailInfo setValue:email forKey:@"reciptions"];
+    [emailInfo setValue:email_subject forKey:@"subject"];
+    [emailInfo setValue:email_content forKey:@"content"];
+    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+    NSString *path = [paths objectAtIndex:0];
+    NSString *filePath = [path stringByAppendingPathComponent:[self.presenter.documentPath lastPathComponent]];
+    NSString *emailPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@".%@",[[self.presenter.documentPath stringByDeletingPathExtension] lastPathComponent]]];
+    
+    NSError *err;
+    
+    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
+        [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
+    }
+    [[NSFileManager defaultManager] moveItemAtPath:self.presenter.documentPath toPath:filePath error:&err];
+    
+    NSData* saved_email_data = [RAConvertor dict2data:emailInfo];
+    
+    [saved_email_data writeToFile:emailPath atomically:NO];
+
+    UIAlertController *alertVC;
+    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        
+    }];
+    if (err) {
+        alertVC = [UIAlertController alertControllerWithTitle:@"Warning" message:[NSString stringWithFormat:@"save document failed:\n%@",err.localizedDescription] preferredStyle:UIAlertControllerStyleAlert];
+    } else {
+        alertVC = [UIAlertController alertControllerWithTitle:nil message:@"Document Saved" preferredStyle:UIAlertControllerStyleAlert];
+    }
+    [alertVC addAction:action];
+    
+    [self presentViewController:alertVC animated:YES completion:nil];
+}
+
+- (void)shareDocument:(NSDictionary *)rowAction {
+    
+    NSString *email = rowAction[@"email"];
+    NSString *email_subject = rowAction[@"email_subject"];
+    NSString *email_content = rowAction[@"email_content"];
+    
+    // 设置分享内容
+    //    NSString *text = @"分享内容";
+    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+    NSString *path = [paths objectAtIndex:0];
+    NSString *filePath = [path stringByAppendingPathComponent:[self.presenter.documentPath lastPathComponent]];
+    
+    // 没有保存的情况
+    if ([[NSFileManager defaultManager] fileExistsAtPath:self.presenter.documentPath]) {
+        filePath = self.presenter.documentPath;
+    }
+    
+    NSURL *url = [NSURL fileURLWithPath:filePath];
+    
+    NSArray *activityItems = @[url];
+    
+    LPShareActivity *share = [[LPShareActivity alloc] init];
+    share.to = [email componentsSeparatedByString:@","];//@[@"676767@qq.com"];
+    share.subject = email_subject;//@"test subject";
+    share.body = email_content;// @"body";
+    share.filePath = filePath;
+    share.handle = ^(UIViewController *vc) {
+        [self presentViewController:vc animated:YES completion:^{
+            //                [share activityDidFinish:YES];
+            // ...
+        }];
+    };
+    
+    // 服务类型控制器
+    UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:@[share]];
+//    _activityViewController = activityViewController;
+//    activityViewController.excludedActivityTypes = @[UIActivityTypeMail];
+    activityViewController.modalInPopover = true;
+    
+    // 选中分享类型
+    [activityViewController setCompletionWithItemsHandler:^(NSString * __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError){
+        
+        // 显示选中的分享类型
+        NSLog(@"act type %@",activityType);
+        
+        if (completed) {
+            NSLog(@"ok");
+        }else {
+            NSLog(@"not ok");
+        }
+        
+    }];
+    
+    [self presentViewController:activityViewController animated:YES completion:nil];
+}
+
+@end

+ 3 - 0
Apex Mobile/Apex Mobile/Result/TableDataSource/ApexResultViewController+TableDataSource.m

@@ -29,6 +29,9 @@
             ApexResultShipModel *shipModel = (ApexResultShipModel *)model;
             ApexResultShipCell *cell = [tableView dequeueReusableCellWithIdentifier:ApexResultShipCell.identifier forIndexPath:indexPath];
             [[[[[[cell setTitle:shipModel.title] setDetail:shipModel.detail] setIcon:shipModel.icon] setPort:shipModel.port] setTime:shipModel.date] setDescription:shipModel.desc];
+            for (ApexResultAddition *addition in shipModel.addition) {
+                [cell addAdditionName:addition.name value:addition.value];
+            }
             return cell;
             
         }

+ 101 - 0
Apex Mobile/Apex Mobile/Result/TableDelegate/ApexResultViewController+TableDelegate.m

@@ -9,12 +9,113 @@
 #import "ApexResultViewController+TableDelegate.h"
 #import "ApexResultBaseModel.h"
 #import "ApexResultPresenter.h"
+#import "DetailTabBarController.h"
 
 @implementation ApexResultViewController (TableDelegate)
 
+#pragma mark - Table Delegate
+
 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
     ApexResultBaseModel *model = [self.presenter resultModelForIndex:indexPath.row];
     return model.height;
 }
 
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    [self handleRowAction:indexPath];
+}
+
+#pragma mark - Row Action
+
+- (NSDictionary *)paramsForIndexPath:(NSIndexPath *)indexPath withAction:(NSDictionary *)action {
+    
+    NSArray *parameters = [self.presenter rowActionParametersForIndex:indexPath.row];
+    NSMutableDictionary *params = [NSMutableDictionary dictionary];
+    for(NSString* key in [action[@"params"] allKeys] )
+    {
+        int idx = [action[@"params"][key] intValue];
+        params[key] = parameters[idx];
+    }
+    return params;
+}
+
+- (void)handleRowAction:(NSIndexPath *)indexPath {
+    
+    NSArray *rowActions = self.presenter.rowActions;
+    if(rowActions != nil)
+    {
+        
+        if(rowActions.count==1)
+        {
+            NSDictionary* action = rowActions.firstObject;
+            NSDictionary *params = [self paramsForIndexPath:indexPath withAction:action];
+            
+            NSString * module =  action[@"module"];
+            if([module isEqualToString:@"quick_look"])
+            {
+                [self showQuickLookForAction:action withParams:params];
+            }
+            else if([module isEqualToString:@"detail"])
+            {
+                [self showDetailForAction:action withParams:params];
+            }
+        }
+        else
+        {
+            
+            UIAlertController *alertControl = [UIAlertController alertControllerWithTitle:@"" message:nil preferredStyle:UIAlertControllerStyleAlert];
+            
+            __weak typeof(self) weakSelf = self;
+            for(int i=0;i< rowActions.count;i++)
+            {
+                NSMutableDictionary* json = rowActions[i];
+                NSDictionary *params = [self paramsForIndexPath:indexPath withAction:json];
+                
+                NSString* title =json[@"title"];
+                NSString* module = json[@"module"];
+                UIAlertAction *actioni = [UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+                    
+                    if([module isEqualToString:@"quick_look"])
+                    {
+                        [weakSelf showQuickLookForAction:json withParams:params];
+                    }
+                    else if([module isEqualToString:@"order_detail"])
+                    {
+                        [weakSelf showDetailForAction:json withParams:params];
+                    }
+                    
+                }];
+                [alertControl addAction:actioni];
+            }
+            
+            UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
+                
+            }];
+            [alertControl addAction:actionCancel];
+            
+            [self presentViewController:alertControl animated:NO completion:nil];
+            
+        }
+        
+    }
+}
+
+- (void)showQuickLookForAction:(NSDictionary *)action withParams:(NSDictionary *)params {
+
+    self.presenter.actionParams = params;
+    NSString *url = action[@"url"];
+    [self.presenter downloadFile:url withParams:params];
+}
+
+- (void)showDetailForAction:(NSDictionary *)action withParams:(NSDictionary *)params {
+    
+    NSMutableDictionary *mParams = [[NSMutableDictionary alloc] initWithDictionary:self.presenter.params copyItems:true];
+    mParams[@"id"] = params[@"id"];
+    NSString *module_name = mParams[@"module_name"];
+    DetailTabBarController *detailViewController=[[DetailTabBarController alloc] init:module_name actions:self.presenter.actions params:mParams];
+    
+    if (detailViewController) {
+        [self.navigationController pushViewController:detailViewController animated:YES];
+    }
+}
+
 @end

+ 17 - 0
Apex Mobile/Apex Mobile/ResultFields/ApexFieldsViewController.h

@@ -0,0 +1,17 @@
+//
+//  ApexFieldsViewController.h
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ApexFieldsViewController : UIViewController
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 123 - 0
Apex Mobile/Apex Mobile/ResultFields/ApexFieldsViewController.m

@@ -0,0 +1,123 @@
+//
+//  ApexFieldsViewController.m
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import "ApexFieldsViewController.h"
+#import "ApexResultFieldCell.h"
+
+typedef NS_ENUM(NSInteger, ApexFieldSectionType) {
+    ApexFieldSectionTypeStable,
+    ApexFieldSectionTypeShow,
+    ApexFieldSectionTypeHide,
+};
+
+#pragma mark - Field
+
+@interface ApexFieldValue : NSObject
+
+@property (nonatomic,copy) NSString *value;
+
+@end
+
+@implementation ApexFieldValue
+
+- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
+    
+}
+
+@end
+
+#pragma Section
+
+@interface ApexFieldSection : NSObject
+
+@property (nonatomic,assign) ApexFieldSectionType type;
+@property (nonatomic,copy) NSString *title;
+@property (nonatomic,strong) NSArray<ApexFieldValue *> *fields;
+
+@end
+
+@implementation ApexFieldSection
+
+- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
+    
+}
+
+- (void)setFields:(NSArray<ApexFieldValue *> *)fields {
+    
+    NSMutableArray *arr = [NSMutableArray array];
+    for (id field in fields) {
+        if ([field isKindOfClass:[NSString class]]) {
+            NSString *value = (NSString *)field;
+            ApexFieldValue *fieldValue = [ApexFieldValue new];
+            fieldValue.value = value;
+            [arr addObject:fieldValue];
+        }
+    }
+    _fields = arr.copy;
+}
+
+@end
+
+#pragma VC
+
+@interface ApexFieldsViewController () <UITableViewDataSource, UITableViewDelegate>
+
+@property (nonatomic,strong) IBOutlet UITableView *tableView;
+@property (nonatomic,strong) NSArray<ApexFieldSection *> *sectionArray;
+
+@end
+
+@implementation ApexFieldsViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    
+    [self loadData];
+}
+
+- (void)loadData {
+    
+}
+
+#pragma mark - TableView
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+    return self.sectionArray.count;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return self.sectionArray[section].fields.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    
+    ApexResultFieldCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ApexResultFieldCell" forIndexPath:indexPath];
+    [cell setValue:self.sectionArray[indexPath.section].fields[indexPath.row].value];
+    
+    return cell;
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+    return 50.0f;
+}
+
+- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
+    
+    return nil;
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
+    return 25.0f;
+}
+
+#pragma mark - Edit
+
+
+
+@end

+ 16 - 0
Apex Mobile/Apex Mobile/ResultFields/ApexResultFieldCell.h

@@ -0,0 +1,16 @@
+//
+//  ApexResultFieldCell.h
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ApexResultFieldCell : UITableViewCell
+
+- (void)setValue:(NSString *)value;
+
+@end
+

+ 34 - 0
Apex Mobile/Apex Mobile/ResultFields/ApexResultFieldCell.m

@@ -0,0 +1,34 @@
+//
+//  ApexResultFieldCell.m
+//  Apex Mobile
+//
+//  Created by Jack on 2019/1/7.
+//  Copyright © 2019 United Software Applications, Inc. All rights reserved.
+//
+
+#import "ApexResultFieldCell.h"
+
+@interface ApexResultFieldCell ()
+
+@property (nonatomic,strong) IBOutlet UILabel *fieldLabel;
+
+@end
+
+@implementation ApexResultFieldCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+- (void)setValue:(NSString *)value {
+    self.fieldLabel.text = value;
+}
+
+@end

+ 74 - 0
Apex Mobile/Apex Mobile/ResultFields/ApexResultFields.storyboard

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Apex Fields View Controller-->
+        <scene sceneID="fZx-Hv-qZZ">
+            <objects>
+                <viewController storyboardIdentifier="ApexFieldsViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="6ez-on-RYb" customClass="ApexFieldsViewController" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="433-KF-MfW">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" contentViewInsetsToSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7zl-J6-SFG">
+                                <rect key="frame" x="0.0" y="20" width="375" height="647"/>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <prototypes>
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="ApexResultFieldCell" rowHeight="50" id="CdT-OW-I0f" customClass="ApexResultFieldCell">
+                                        <rect key="frame" x="0.0" y="28" width="375" height="50"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="CdT-OW-I0f" id="yux-Fg-TbI">
+                                            <rect key="frame" x="0.0" y="0.0" width="375" height="49.5"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <subviews>
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="egc-tt-tnc">
+                                                    <rect key="frame" x="10" y="14.5" width="355" height="21"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                                    <nil key="textColor"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                            <constraints>
+                                                <constraint firstAttribute="trailing" secondItem="egc-tt-tnc" secondAttribute="trailing" constant="10" id="2VG-Vf-23Z"/>
+                                                <constraint firstItem="egc-tt-tnc" firstAttribute="leading" secondItem="yux-Fg-TbI" secondAttribute="leading" constant="10" id="AkR-vP-vVN"/>
+                                                <constraint firstItem="egc-tt-tnc" firstAttribute="centerY" secondItem="yux-Fg-TbI" secondAttribute="centerY" id="SB6-sc-JGg"/>
+                                            </constraints>
+                                        </tableViewCellContentView>
+                                        <connections>
+                                            <outlet property="fieldLabel" destination="egc-tt-tnc" id="Ftb-ou-rGC"/>
+                                        </connections>
+                                    </tableViewCell>
+                                </prototypes>
+                                <connections>
+                                    <outlet property="dataSource" destination="6ez-on-RYb" id="Ypp-AC-eFS"/>
+                                    <outlet property="delegate" destination="6ez-on-RYb" id="FbW-GN-Ypp"/>
+                                </connections>
+                            </tableView>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="7zl-J6-SFG" firstAttribute="leading" secondItem="D15-EH-QV3" secondAttribute="leading" id="Mpk-3P-Apv"/>
+                            <constraint firstItem="D15-EH-QV3" firstAttribute="bottom" secondItem="7zl-J6-SFG" secondAttribute="bottom" id="gbV-x9-PXU"/>
+                            <constraint firstItem="D15-EH-QV3" firstAttribute="trailing" secondItem="7zl-J6-SFG" secondAttribute="trailing" id="uPh-XF-n3h"/>
+                            <constraint firstItem="7zl-J6-SFG" firstAttribute="top" secondItem="D15-EH-QV3" secondAttribute="top" id="wCl-eg-rG8"/>
+                        </constraints>
+                        <viewLayoutGuide key="safeArea" id="D15-EH-QV3"/>
+                    </view>
+                    <connections>
+                        <outlet property="tableView" destination="7zl-J6-SFG" id="JBD-5R-E5a"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="ryS-aj-Tmh" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-252" y="-94"/>
+        </scene>
+    </scenes>
+</document>

+ 4 - 0
Apex Mobile/Apex Mobile/SearchViewController.m

@@ -72,6 +72,10 @@
         self.searchToolbar.hidden = YES;
         self.showTable = YES;
     }
+    
+    UIBarButtonItem *backItem = [[UIBarButtonItem alloc] init];
+    backItem.title = @"";
+    self.navigationItem.backBarButtonItem = backItem;
 }
 
 - (void)viewWillDisappear:(BOOL)animated {