// // RAOrderEditViewController.m // Apex And Drivers // // Created by Jack on 2018/6/4. // Copyright © 2018年 USAI. All rights reserved. // #import "RAOrderEditViewController.h" #import "RAEditInputModel.h" #import "RAEditMultInputModel.h" #import "RAEditLabelModel.h" #import "RAEditImageBaseModel.h" #import "RAEditPhotoModel.h" #import "RAEditSignatureModel.h" #import "RAProgressHUD.h" #import "ZipArchive.h" #import "AppDelegate.h" #import @interface RAEditSectionModel : NSObject @property (nonatomic,strong) NSArray *items; @property (nonatomic,copy) NSString *title; @end @implementation RAEditSectionModel - (void)setValue:(id)value forUndefinedKey:(NSString *)key { } - (void)setItems:(NSArray *)items { NSArray *tmpItems = items; NSMutableArray *itemArr = [NSMutableArray arrayWithCapacity:items.count]; for (int i = 0; i < tmpItems.count; i++) { NSDictionary *item = [tmpItems objectAtIndex:i]; RAEditType type = [[item objectForKey:@"type"] intValue]; switch (type) { case RAEditTypeLabel: { RAEditLabelModel *model = [RAEditLabelModel new]; [model setValuesForKeysWithDictionary:item]; [itemArr addObject:model]; } break; case RAEditTypeInput: { RAEditInputModel *model = [RAEditInputModel new]; [model setValuesForKeysWithDictionary:item]; [itemArr addObject:model]; } break; case RAEditTypeMultInput: { RAEditMultInputModel *model = [RAEditMultInputModel new]; [model setValuesForKeysWithDictionary:item]; [itemArr addObject:model]; } break; case RAEditTypePhoto: { RAEditPhotoModel *model = [RAEditPhotoModel new]; [model setValuesForKeysWithDictionary:item]; [itemArr addObject:model]; } break; case RAEditTypeSignature: { RAEditSignatureModel *model = [RAEditSignatureModel new]; [model setValuesForKeysWithDictionary:item]; [itemArr addObject:model]; } break; default: break; } } _items = itemArr; } - (NSInteger)itemCount { return self.items.count; } - (RAEditBaseModel *)itemModelForIndex:(NSInteger)index { return [self.items objectAtIndex:index]; } @end #pragma mark - View Controller @interface RAOrderEditViewController () @property (nonatomic,strong) IBOutlet UITableView *orderEditTableView; @property (nonatomic,strong) NSMutableArray *sectionArray; @property (nonatomic,copy) NSString *photoDir; @property (nonatomic,strong) UIRefreshControl *refreshControl; @end @implementation RAOrderEditViewController + (instancetype)viewControllerFromStoryboard { RAOrderEditViewController *editVC = [[UIStoryboard storyboardWithName:@"Edit" bundle:nil] instantiateViewControllerWithIdentifier:[self storyboardID]]; return editVC; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self configureTable]; [self configureNavigationBar]; [self loadData]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self registKeyboardListener]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self unregistKeyboardListener]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Configure - (void)configureTable { if (@available(iOS 11.0, *)) { self.orderEditTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { self.automaticallyAdjustsScrollViewInsets = NO; } self.orderEditTableView.tableFooterView = [UIView new]; self.orderEditTableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0); UIRefreshControl *refresh = [[UIRefreshControl alloc] init]; [refresh addTarget:self action:@selector(refreshControlValueChanged:) forControlEvents:UIControlEventValueChanged]; [self.orderEditTableView addSubview:refresh]; self.refreshControl = refresh; } - (void)configureNavigationBar { UIBarButtonItem *updateItem = [[UIBarButtonItem alloc] initWithTitle:@"Update" style:UIBarButtonItemStylePlain target:self action:@selector(updateBtnClick:)]; self.navigationItem.rightBarButtonItem = updateItem; } - (void)registKeyboardListener { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; } - (void)unregistKeyboardListener { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - Action - (void)refreshControlValueChanged:(UIRefreshControl *)refresh { [self loadData]; } #pragma mark - Getter - (NSMutableArray *)sectionArray { if (!_sectionArray) { _sectionArray = [NSMutableArray array]; } return _sectionArray; } - (NSUInteger)editSectionCount { return self.sectionArray.count; } - (NSInteger)itemCountForSection:(NSInteger)section { return [[self.sectionArray objectAtIndex:section] itemCount]; } - (RAEditBaseModel *)modelForIndexPath:(NSIndexPath *)indexPath { return [[self.sectionArray objectAtIndex:indexPath.section] itemModelForIndex:indexPath.row]; } - (NSString *)titleForSection:(NSInteger)section { return [[self.sectionArray objectAtIndex:section] title]; } - (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell { return [self.orderEditTableView indexPathForCell:cell]; } #pragma mark - Data - (void)loadData { if (self.loading) { return; } self.loading = YES; // show progress RAProgressHUD *hud = [RAProgressHUD showHUDOnView:self.view]; NSString *orderID = self.orderID; NSInteger actionID = self.actionID; __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSDictionary *json = [RADataProvider requestUpdateOrder:orderID driverAction:actionID]; dispatch_async(dispatch_get_main_queue(), ^{ // dismiss progress [hud dismiss]; if (weakSelf.refreshControl.isRefreshing) { [weakSelf.refreshControl endRefreshing]; } if (weakSelf) { __strong typeof(weakSelf) strongSelf = weakSelf; int result = [[json objectForKey:@"result"] intValue]; if (result == RESULT_TRUE) { NSArray *sectionArray = [json objectForKey:@"sections"]; [strongSelf.sectionArray removeAllObjects]; for (int i = 0; i < sectionArray.count; i++) { NSDictionary *section = [sectionArray objectAtIndex:i]; RAEditSectionModel *model = [RAEditSectionModel new]; [model setValuesForKeysWithDictionary:section]; [strongSelf.sectionArray addObject:model]; } [strongSelf.orderEditTableView reloadData]; } else { [strongSelf.sectionArray removeAllObjects]; strongSelf.orderEditTableView.contentOffset = CGPointZero; [strongSelf.orderEditTableView reloadData]; // process error NSString *msg = [json objectForKey:@"err_msg"]; // [strongSelf showAlert:msg]; [strongSelf showAlertTilte:@"Warning" message:msg]; } } self.loading = NO; }); }); } #pragma mark - Tap Action - (IBAction)tapToResignFirstResponder:(UITapGestureRecognizer *)sender { [self.view endEditing:YES]; } - (void)updateBtnClick:(UIBarButtonItem *)sender { // show progress RAProgressHUD *hud = [RAProgressHUD showHUDOnView:self.view]; NSMutableDictionary *params = [NSMutableDictionary dictionary]; if (self.orderType2) { [params setObject:self.orderType2 forKey:@"orderType2"]; } if (RASingleton.sharedInstance.requiredLocation) { CLLocation *location = RASingleton.sharedInstance.currentLocation; NSString *latLon = [NSString stringWithFormat:@"%f,%f",location.coordinate.latitude,location.coordinate.longitude]; [params setObject:latLon forKey:@"location"]; } NSMutableArray *photoArr = [self prepareParams:params]; __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSDictionary *json = [RADataProvider submitEditOrder:params]; if (weakSelf) { __strong typeof(weakSelf) strongSelf = weakSelf; int result = [[json objectForKey:@"result"] intValue]; if (result == RESULT_TRUE) { BOOL requiredLocation = [[json objectForKey:@"requiredLocation"] boolValue]; [RASingleton sharedInstance].requiredLocation = requiredLocation; dispatch_async(dispatch_get_main_queue(), ^{ if (photoArr.count > 0) { [strongSelf syncUploadPhotos:photoArr Json:json HUD:hud]; } else { [self gobackHome]; } }); } else { // process error dispatch_async(dispatch_get_main_queue(), ^{ // dismiss progress [hud dismiss:^{ NSString *msg = [json objectForKey:@"err_msg"]; [strongSelf showAlertTilte:@"Warning" message:msg]; }]; }); } } }); } - (void)backgroundUploadPhoto:(NSArray *)photos Json:(NSDictionary *)json { AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; NSDate *date = [NSDate date]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"MM/dd/YYYY HH:mm"; NSString *time = [formatter stringFromDate:date]; for (RAEditImageBaseModel *model in photos) { NSString *serial = [json objectForKey:model.key]; if (serial.length) { NSMutableDictionary *params = [NSMutableDictionary dictionary]; [params setObject:serial forKey:@"serial"]; if (self.orderType2) { [params setObject:self.orderType2 forKey:@"orderType2"]; } [params setObject:[RASingleton.sharedInstance encryptUser] forKey:@"name"]; [params setObject:[RASingleton.sharedInstance encryptPassword] forKey:@"password"]; [params setObject:@"iOS" forKey:@"platform"]; NSString *photoPath = [self.photoDir.lastPathComponent stringByAppendingPathComponent:model.imageName]; NSMutableDictionary *task = [@{ @"order" : self.orderID, @"action" : self.actionTitle, @"name" : model.title, @"time" : time, @"url" : URL_UPLOAD, @"file" : photoPath, @"params" : params } mutableCopy]; [appDelegate.uploadManager addTask:task]; } } } - (void)syncUploadPhotos:(NSMutableArray *)photoArr Json:(NSDictionary *)json HUD:(RAProgressHUD *)hud { dispatch_async(dispatch_get_main_queue(), ^{ RAProgressHUD *innerHUD = hud; if (!innerHUD) { innerHUD = [RAProgressHUD showHUDOnView:self.view]; // main queue } dispatch_async(dispatch_get_global_queue(0, 0), ^{ // network int retryCount = 0; NSMutableArray *completArr = [NSMutableArray array]; // 同步上传照片 for (int i = 0; i < photoArr.count; i++) { RAEditImageBaseModel *model = [photoArr objectAtIndex:i]; NSString *serial = [json objectForKey:model.key]; if (serial.length) { NSMutableDictionary *fileParams = [NSMutableDictionary dictionary]; [fileParams setObject:serial forKey:@"serial"]; if (self.orderType2) { [fileParams setObject:self.orderType2 forKey:@"orderType2"]; } NSString *photoPath = [self.photoDir stringByAppendingPathComponent:model.imageName]; NSDictionary *uploadJson = [RADataProvider uploadFile:photoPath parameters:fileParams]; int uploadResult = [[uploadJson objectForKey:@"result"] intValue]; if (uploadResult != RESULT_TRUE) { // 失败重试 i--; retryCount++; if (retryCount >= 3) { break; } } else { [completArr addObject:model]; retryCount = 0; // 删除文件 if ([[NSFileManager defaultManager] fileExistsAtPath:photoPath]) { [[NSFileManager defaultManager] removeItemAtPath:photoPath error:nil]; } } } // serial } // for // 将完成的model移除 [photoArr removeObjectsInArray:completArr]; __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ [innerHUD dismiss:^{ if (photoArr.count > 0) { // 上传失败,询问是否丢到后台线程上传,否则重启上传 UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Warning" message:@"upload the photos failed,would you like to retry or do it background?" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *backgroundAction = [UIAlertAction actionWithTitle:@"Background" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 开启后台上传 [weakSelf backgroundUploadPhoto:photoArr Json:json]; // 返回首页 [weakSelf gobackHome]; }]; UIAlertAction *retryAction = [UIAlertAction actionWithTitle:@"Retry" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ [weakSelf syncUploadPhotos:photoArr Json:json HUD:nil]; }); }]; [alertVC addAction:backgroundAction]; [alertVC addAction:retryAction]; [weakSelf presentViewController:alertVC animated:YES completion:nil]; } else { // 上传完成,返回到首页 [weakSelf gobackHome]; } }]; }); }); }); } - (void)gobackHome { [[NSNotificationCenter defaultCenter] postNotificationName:RANotificationReloadHome object:nil]; [self.navigationController popToRootViewControllerAnimated:YES]; } #pragma mark - Keyboard Listener - (void)keyboardWillChangeFrame:(NSNotification *)notification { CGRect end = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGFloat screenHeight = CGRectGetHeight([UIScreen mainScreen].bounds); CGFloat keyboardHeight = screenHeight - CGRectGetMinY(end); UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, keyboardHeight, 0); self.orderEditTableView.contentInset = insets; if (self.editingIndexPath) { [self.orderEditTableView scrollToRowAtIndexPath:self.editingIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } } #pragma mark - Package Update Data - (NSString *)photoDir { if (!_photoDir) { NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *photoDir = [cacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%ld_%@",self.orderID,(long)self.actionID,[NSUUID UUID].UUIDString]]; NSError *error; // BOOL dirExist = YES; // for (int i = 0; i < INT_MAX; i++) { // if (i != 0) { // photoDir = [photoDir stringByAppendingString:[NSString stringWithFormat:@"(%d)",i]]; // } // if (![[NSFileManager defaultManager] fileExistsAtPath:photoDir]) { // dirExist = NO; // break; // } // } [[NSFileManager defaultManager] createDirectoryAtPath:photoDir withIntermediateDirectories:YES attributes:nil error:&error]; if (error) { NSLog(@"create dir %@ failed %@",photoDir,error.localizedDescription); return nil; } _photoDir = photoDir; } return _photoDir; } - (NSMutableArray *)prepareParams:(NSMutableDictionary *)params { if (params == nil) { return nil; } NSMutableArray *photoArr = [NSMutableArray array]; NSString *photoDir = [self photoDir]; [params setObject:self.orderID forKey:@"orderID"]; [params setObject:@(self.actionID) forKey:@"actionID"]; NSString* encryptu = [RASingleton sharedInstance].encryptUser; NSString* encryptp = [RASingleton sharedInstance].encryptPassword; [params setObject:encryptu forKey:@"name"]; [params setObject:encryptp forKey:@"password"]; [params setObject:@"iOS" forKey:@"platform"]; if ([RASingleton sharedInstance].currentLocation) { [params setObject:[NSString stringWithFormat:@"%f,%f",[RASingleton sharedInstance].currentLocation.coordinate.latitude,[RASingleton sharedInstance].currentLocation.coordinate.longitude] forKey:@"location"]; } for (RAEditSectionModel *section in self.sectionArray) { for (int i = 0; i < [section itemCount]; i++) { RAEditBaseModel *model = [section itemModelForIndex:i]; switch (model.type) { case RAEditTypeLabel: { } break; case RAEditTypeInput: { RAEditInputModel *inputModel = (RAEditInputModel *)model; if (inputModel.key && inputModel.value.length > 0) { [params setObject:inputModel.value forKey:inputModel.key]; } } break; case RAEditTypeMultInput: { RAEditMultInputModel *multInputModel = (RAEditMultInputModel *)model; if (multInputModel.key && multInputModel.value.length > 0) { [params setObject:multInputModel.value forKey:multInputModel.key]; } } break; case RAEditTypePhoto: case RAEditTypeSignature: { if (photoDir) { RAEditImageBaseModel *imageModel = (RAEditImageBaseModel *)model; if (imageModel.image) { NSString *photoPath = [photoDir stringByAppendingPathComponent:imageModel.imageName]; NSData *imgData = UIImageJPEGRepresentation(imageModel.image, 1.0f); if (imgData) { [imgData writeToFile:photoPath atomically:NO]; [params setObject:imageModel.imageName forKey:imageModel.key]; [photoArr addObject:imageModel]; } } } } break; default: break; } } } return photoArr; } - (NSMutableDictionary *)preparePackage { NSMutableDictionary *params = [NSMutableDictionary dictionary]; NSInteger photoCount = [self prepareParams:params].count; NSString *photoDir = [self photoDir]; NSMutableDictionary *task = [@{ @"order" : self.orderID, @"action" : self.actionTitle, @"url" : URL_HOST, @"noFile" : @(YES) } mutableCopy]; if (photoCount > 0) { // 压缩文件 NSString *zipPath = [photoDir stringByAppendingPathExtension:@".zip"]; ZipArchive *zip = [[ZipArchive alloc] init]; [zip CreateZipFile2:zipPath]; NSArray *subPaths = [[NSFileManager defaultManager] subpathsAtPath:photoDir]; for (NSString *subPath in subPaths) { NSString *fullPath = [photoDir stringByAppendingPathComponent:subPath]; BOOL isDir; if([[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDir]) { if (!isDir) { [zip addFileToZip:fullPath newname:subPath]; } } } [zip CloseZipFile2]; [[NSFileManager defaultManager] removeItemAtPath:photoDir error:nil]; NSString *md5 = [RAUtils md5WithFile:zipPath]; [params setObject:md5 forKey:@"md5"]; [task setObject:@"file" forKey:zipPath.lastPathComponent]; } [task setObject:params forKey:@"params"]; return task; } @end