| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073 |
- //
- // RAOfflineHandler.m
- // Apex And Drivers
- //
- // Created by Jack on 2018/10/22.
- // Copyright © 2018年 USAI. All rights reserved.
- //
- #import "RAOfflineHandler.h"
- #import "NetworkUtils.h"
- #import "RADetailBaseModel.h"
- #import "RAHomeOrderModel.h"
- #import "RADetailActionModel.h"
- #import "AppDelegate.h"
- #import "RAEditImageBaseModel.h"
- #import "RAArchiver.h"
- #define Lock() dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER)
- #define Unlock() dispatch_semaphore_signal(_lock)
- static dispatch_semaphore_t _lock;
- @interface RAOfflineHandler () {
- NSString *_offlineDir;
- NSString *_offlineTmp;
- NSString *_offlineUploadDir;
- NSString *_zipPassword;
- }
- @property (nonatomic,strong) NSMutableDictionary *detailCache;///< 缓存查看过的Detai
- @property (nonatomic,strong,readonly) NSString *offlineDir; ///< 缓存文件夹
- @property (nonatomic,strong,readonly) NSString *offlineTmp; ///< 临时保存解压文件的文件夹
- @property (nonatomic,strong,readonly) NSString *offlineUploadDir; ///<上传文件目录
- @property (nonatomic,copy,readonly) NSString *zipPassword; ///<压缩/解压 密码
- @end
- @implementation RAOfflineHandler
- #pragma mark - Handler
- + (instancetype)defaultHandler {
- static RAOfflineHandler *handler;
- static dispatch_once_t token;
- dispatch_once(&token, ^{
- handler = [[RAOfflineHandler alloc] init];
- _lock = dispatch_semaphore_create(1);
- });
- return handler;
- }
- - (void)prepareParams:(NSMutableDictionary* )params {
-
- NSAssert(params != nil, @"params can't be nil");
-
- NSString *user = RASingleton.sharedInstance.encryptUser;
- NSString *password = RASingleton.sharedInstance.encryptPassword;
-
- if (user.length && password.length) {
- [params setObject:user forKey:@"name"];
- [params setObject:password forKey:@"password"];
- }
-
- [params setObject:@"iOS" forKey:@"platform"];
-
- NSDictionary* infoDict =[[NSBundle mainBundle] infoDictionary];
- NSString* short_version =[infoDict objectForKey:@"CFBundleShortVersionString"];
- [params setValue:short_version forKey:@"app_short_ver"];
-
- NSString *localeLanguageCode = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode];
- [params setValue:localeLanguageCode forKey:@"language"];
-
- NSString *time = [self currentDate];
- [params setObject:time forKey:@"date"];
- [params setObject:@(1) forKey:@"offline"];
-
- #if TARGET_IPHONE_SIMULATOR//模拟器
- [params setValue:@"simulator_uuid" forKey:@"deviceid"];
- #elif TARGET_OS_IPHONE//真机
- UIDevice * dev = [UIDevice currentDevice];
- NSUUID* uuid =dev.identifierForVendor;
- [params setValue:uuid.UUIDString forKey:@"deviceid"];
- #endif
- }
- - (NSString *)offlineDir {
- if (!_offlineDir) {
-
- NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
- _offlineDir = [cachePath stringByAppendingPathComponent:@"offline"];
-
- NSFileManager *fm = [NSFileManager defaultManager];
- BOOL isDir = YES;
- if ([fm fileExistsAtPath:_offlineDir isDirectory:&isDir] && isDir) {
-
- } else {
- [fm createDirectoryAtPath:_offlineDir withIntermediateDirectories:NO attributes:nil error:nil];
- }
-
- }
- return _offlineDir;
-
- }
- - (NSString *)offlineTmp {
- if (!_offlineTmp) {
-
- _offlineTmp = [self.offlineDir stringByAppendingPathComponent:@"tmp"];
-
- NSFileManager *fm = [NSFileManager defaultManager];
- BOOL isDir = YES;
- if ([fm fileExistsAtPath:_offlineTmp isDirectory:&isDir] && isDir) {
-
- } else {
- [fm createDirectoryAtPath:_offlineTmp withIntermediateDirectories:YES attributes:nil error:nil];
- }
- }
- return _offlineTmp;
- }
- - (NSString *)offlineUploadDir {
- if (!_offlineUploadDir) {
-
- NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
- _offlineUploadDir = [docDir stringByAppendingPathComponent:@"upload"];
-
- NSFileManager *fm = [NSFileManager defaultManager];
- BOOL isDir = YES;
- if ([fm fileExistsAtPath:_offlineUploadDir isDirectory:&isDir] && isDir) {
-
- } else {
- [fm createDirectoryAtPath:_offlineUploadDir withIntermediateDirectories:YES attributes:nil error:nil];
- }
-
- }
- return _offlineUploadDir;
- }
- - (NSString *)zipPassword {
- if (!_zipPassword) {
- _zipPassword = @"usai";
- }
- return _zipPassword;
- }
- #pragma mark - Download
- /**
- * @brief 向服务器请求离线数据
- */
- - (void)downloadOfflineData {
-
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
-
- NSMutableDictionary *params = [NSMutableDictionary dictionary];
- [self prepareParams:params];
- [NetworkUtils downloadFileOffset:0 Param:params from:@"http://192.168.0.130/fake_offline.zip" method:@"POST" toPath:self.offlineDir progressHandler:^(NSURLSessionTask *task, double progress) {
- } completionHandler:^(NSMutableDictionary *result) {
- int rs = [[result objectForKey:@"result"] intValue];
- NSString *path = [result objectForKey:@"path"];
- if (rs == RESULT_TRUE) {
- [self handleDownloadFile:path];
- }
- }];
-
- // NSString *path = [self.offlineDir stringByAppendingPathComponent:@"download.zip"];
- // [self handleDownloadFile:path];
- //
- });
- }
- /**
- * @brief 加载沙盒中的数据
- * @param path 沙盒数据路径
- */
- - (NSDictionary *)_loadCacheData:(NSString *)path {
- if (path == nil || path.length == 0) {
- return nil;
- }
-
- NSData *data = [NSData dataWithContentsOfFile:path];
- if (data) {
- NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
- return dic;
- }
- return nil;
- }
- - (void)_moveFile:(NSString *)filePath toFolder:(NSString *)folder {
-
- NSFileManager *fm = [NSFileManager defaultManager];
- BOOL isDir = NO;
- if ([fm fileExistsAtPath:filePath isDirectory:&isDir] && !isDir) {
-
- BOOL fIsDir = NO;
- if ([fm fileExistsAtPath:folder isDirectory:&fIsDir] && fIsDir) {
-
- } else {
- NSError *err = nil;
- [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:nil error:&err];
- if (err) {
- NSLog(@"create folder error: %@",err);
- return;
- }
- }
-
- NSString *to = [folder stringByAppendingPathComponent:filePath.lastPathComponent];
-
- NSError *err = nil;
- [fm moveItemAtPath:filePath toPath:to error:&err];
- if (err) {
- NSLog(@"move file error: %@",err);
- }
- }
- }
- - (void)_moveFolder:(NSString *)srcfolder toFolder:(NSString *)destFolder {
-
- NSFileManager *fm = [NSFileManager defaultManager];
- BOOL isDir = NO;
- if ([fm fileExistsAtPath:srcfolder isDirectory:&isDir] && isDir) {
-
- NSString *dest = [destFolder stringByAppendingPathComponent:srcfolder.lastPathComponent];
- isDir = NO;
- if ([fm fileExistsAtPath:dest isDirectory:&isDir] && isDir) {
-
- } else {
- NSError *err = nil;
- [fm createDirectoryAtPath:dest withIntermediateDirectories:YES attributes:nil error:&err];
- if (err) {
- NSLog(@"create folder error: %@",err);
- return;
- }
- }
-
- NSArray<NSString *> *contents = [fm contentsOfDirectoryAtPath:srcfolder error:nil];
- if (contents.count > 0) {
-
- [contents enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSString *path = [srcfolder stringByAppendingPathComponent:obj];
-
- BOOL fileIsDir = NO;
- if ([fm fileExistsAtPath:path isDirectory:&fileIsDir]) {
-
- if (fileIsDir) {
-
- [self _moveFolder:path toFolder:dest];
-
- } else {
- [self _moveFile:path toFolder:dest];
- }
-
- }
- }];
-
- }
- }
- }
- /**
- * @brief 处理下载的压缩文件
- * @param path 压缩文件路径
- */
- - (void)handleDownloadFile:(NSString *)path {
-
- Lock();
-
- // 解压
- BOOL zipRes = [self _unzipOfflineZip:path toDir:self.offlineTmp];
- if (zipRes) {
- NSFileManager *fm = [NSFileManager defaultManager];
-
- // 删除旧数据,除了tmp
- NSArray<NSString *> *items = [fm contentsOfDirectoryAtPath:self.offlineDir error:nil];
- [items enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSString *path = [self.offlineDir stringByAppendingPathComponent:obj];
- if (![path isEqualToString:self.offlineTmp] && ![path.lastPathComponent isEqualToString:@"finish"] && ![path isEqualToString:self.offlineUploadDir]) {
- [fm removeItemAtPath:path error:nil];
- }
- }];
-
- // 将tmp中解压数据移出来
- items = [fm contentsOfDirectoryAtPath:self.offlineTmp error:nil];
- [items enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSString *src = [self.offlineTmp stringByAppendingPathComponent:obj];
- BOOL isDir = NO;
- if ([fm fileExistsAtPath:src isDirectory:&isDir]) {
-
- if (isDir) {
- [self _moveFolder:src toFolder:self.offlineDir];
- } else {
- [self _moveFile:src toFolder:self.offlineDir];
- }
-
- }
- }];
-
- // 重置缓存的action
- [self _resetFinish];
- }
-
- Unlock();
- }
- /**
- * @brief 重置离线完成的Action,将finished order对应的action的剔除
- */
- - (void)_resetFinish {
-
- NSDictionary *homeJson = [self _requestOfflineHome];
- NSArray<NSDictionary *> *sections = [homeJson objectForKey:@"sections"];
-
- NSMutableDictionary *finishDic = [NSMutableDictionary dictionary];
- NSDictionary *finishDicTmp = [self _finishedActions];
- if (finishDicTmp.count > 0) {
- [sections enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSArray<NSDictionary *> *orders = [obj objectForKey:@"orders"];
- [orders enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull order, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSString *orderId = [order objectForKey:@"orderID"];
- NSNumber *finish = [finishDicTmp objectForKey:orderId];
- if (finish) {
- [finishDic setObject:finish forKey:orderId];
- }
- }];
- }];
- }
-
- NSString *finishPath = [self.offlineDir stringByAppendingPathComponent:@"finish"];
- [finishDic writeToFile:finishPath atomically:NO];
- }
- #pragma mark - Request Data
- /**
- * @brief 加载离线首页数据
- */
- - (NSDictionary *)_requestOfflineHome {
-
- NSString *homeJsonPath = [self.offlineDir stringByAppendingPathComponent:@"home.json"];
- NSDictionary *result = [self _loadCacheData:homeJsonPath];
- return result;
- }
- /**
- * @brief 加载离线首页数据
- */
- - (NSDictionary *)requestOfflineHome {
- Lock();
-
- NSDictionary *result = [self _requestOfflineHome];
-
- Unlock();
- return result;
- }
- /**
- * @brief 加载离线Detail
- * @param orderId 订单号
- * @param type 订单类型,包括 new order 和 processing order
- */
- - (NSDictionary *)requestOfflineDetailForOrder:(NSString *)orderId withOrderType:(NSInteger)type {
- Lock();
-
- NSString *detailJsonPath = [self.offlineDir stringByAppendingPathComponent:[NSString stringWithFormat:@"detail/%@_%ld",orderId,(long)type]];
- NSMutableDictionary *detailJson = [[self _loadCacheData:detailJsonPath] mutableCopy];
-
- NSNumber *finish = [self _lastActionIndexForOrder:orderId];
-
- detailJson = [self filtrateActionFromDetail:detailJson withFinishActions:finish];
-
- Unlock();
- return detailJson;
- }
- /**
- * @brief 记载离线Edit Order
- * @param orderId 订单号
- * @param actionIndex 操作标记
- */
- - (NSDictionary *)requestOfflineEditOrder:(NSString *)orderId withAction:(NSInteger)actionIndex {
- Lock();
-
- NSString *editJsonPath = [self.offlineDir stringByAppendingPathComponent:[NSString stringWithFormat:@"edit/%@_%ld",orderId,(long)actionIndex]];
- NSDictionary *editJson = [self _loadCacheData:editJsonPath];
-
- Unlock();
- return editJson;
- }
- #pragma mark - Utils
- /**
- * @brief 解压离线下载的压缩包
- * @return 解压是否成功
- */
- - (BOOL)_unzipOfflineZip:(NSString *)path toDir:(NSString *)to {
-
- return [RAArchiver ra_unzipOfflineZip:path toDir:to withPassword:self.zipPassword];
- }
- /**
- * @brief 压缩文件夹
- * @param dir 被压缩文件夹
- * @return 压缩文件路径
- */
- - (NSString *)_zipDir:(NSString *)dir {
-
- NSString *zipFile = [dir stringByAppendingPathExtension:@"zip"];
-
- if ([RAArchiver ra_zipFile:dir withPassword:self.zipPassword]) {
- return zipFile;
- }
- return nil;
- }
- /**
- * @brief 在detail中过滤订单已经做过的操作
- * @param detail order detail界面数据
- * @param finish order最后完成的一个action索引
- */
- - (NSMutableDictionary *)filtrateActionFromDetail:(NSMutableDictionary *)detail withFinishActions:(NSNumber *)finish {
-
- if (finish == nil) {
- return detail;
- }
-
- int result = [[detail objectForKey:@"result"] intValue];
- if (result != RESULT_TRUE) {
- return detail;
- }
-
- // 一层层解开,获取到目标值后作出修改,然后反向一层层的套回去
- NSMutableArray<NSDictionary *> *sections = [[detail objectForKey:@"sections"] mutableCopy];
-
- NSMutableIndexSet *rmSectionArr = [NSMutableIndexSet indexSet];
-
- [sections enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSMutableDictionary *section = [obj mutableCopy];
- NSMutableArray<NSDictionary *> *values = [[section objectForKey:@"values"] mutableCopy];
-
- NSMutableIndexSet *rmValueArr = [NSMutableIndexSet indexSet];
- [values enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- int type = [[obj objectForKey:@"type"] intValue];
- if (type == RAOrderDetailValueTypeAction) {
- NSMutableDictionary *mObj = [obj mutableCopy];
- NSMutableArray<NSDictionary *> *actions = [[mObj objectForKey:@"actions"] mutableCopy];
- NSMutableArray *rmArr = [NSMutableArray array];
- [actions enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSInteger index = [[obj objectForKey:@"index"] integerValue];
- if ([finish integerValue] >= index) {
- [rmArr addObject:obj];
- }
-
- }];
- [actions removeObjectsInArray:rmArr];
-
- if (actions.count == 0) {
- [rmValueArr addIndex:idx];
- }
-
- [mObj setObject:actions forKey:@"actions"];
- [values replaceObjectAtIndex:idx withObject:mObj];
- }
-
- }];
-
- if (rmValueArr.count > 0) {
- [values removeObjectsAtIndexes:rmValueArr];
- }
-
- if (values.count == 0) {
- [rmSectionArr addIndex:idx];
- }
-
- [section setObject:values forKey:@"values"];
- [sections replaceObjectAtIndex:idx withObject:section];
- }];
-
- if (rmSectionArr.count > 0) {
- [sections removeObjectsAtIndexes:rmSectionArr];
- }
-
- [detail setObject:sections forKey:@"sections"];
-
- return detail;
- }
- /**
- * @brief 判断Order Action是否是最后一步
- * @param orderId 订单号
- * @return YES/NO
- */
- - (BOOL)isLastActionForOrder:(NSString *)orderId index:(NSInteger)actionIndex {
- if (!orderId) {
- return NO;
- }
- NSDictionary *detail = [self requestOfflineDetailForOrder:orderId withOrderType:RAOrderStatusProcessing];
- int result = [[detail objectForKey:@"result"] intValue];
- if (result != RESULT_TRUE) {
- return NO;
- }
-
- __block BOOL isLast = NO;
- NSMutableArray<NSDictionary *> *sections = [[detail objectForKey:@"sections"] mutableCopy];
- [sections enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSMutableDictionary *section = [obj mutableCopy];
- NSMutableArray<NSDictionary *> *values = [[section objectForKey:@"values"] mutableCopy];
- __block BOOL findAction = NO;
- [values enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- int type = [[obj objectForKey:@"type"] intValue];
- if (type == RAOrderDetailValueTypeAction) {
- findAction = YES;
- NSMutableDictionary *mObj = [obj mutableCopy];
- NSMutableArray<NSDictionary *> *actions = [[mObj objectForKey:@"actions"] mutableCopy];
-
- __block int maxActionIndex = 0;
- [actions enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- int index = [[obj objectForKey:@"index"] intValue];
- maxActionIndex = MAX(maxActionIndex, index);
- }];
- if (actionIndex == maxActionIndex) {
- isLast = YES;
- }
- *stop = YES;
- }
- }];
-
- if (findAction) {
- *stop = YES;
- }
- }];
-
- return isLast;
- }
- /**
- * @brief 加载所有完成的订单Action
- */
- - (NSDictionary<NSString *, NSNumber *> *)_finishedActions {
-
- NSString *path = [self.offlineDir stringByAppendingPathComponent:@"finish"];
- NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:path];
-
- if (dic == nil) {
- dic = [NSDictionary dictionary];
- }
-
- return dic;
- }
- /**
- * @brief 最后一次修改Order的 Action 索引
- * @param orderId 订单号
- */
- - (NSNumber *)_lastActionIndexForOrder:(NSString *)orderId {
-
- NSDictionary *finishDic = [self _finishedActions];
- NSNumber *finish = [finishDic objectForKey:orderId];
-
- return finish;
- }
- /**
- * @brief 最后一次修改Order的 Action 索引
- * @param orderId 订单号
- */
- - (NSNumber *)lastActionIndexForOrder:(NSString *)orderId {
- Lock();
-
- NSDictionary *finishDic = [self _finishedActions];
- NSNumber *finish = [finishDic objectForKey:orderId];
-
- Unlock();
- return finish;
- }
- /**
- * @brief 删除文件
- * @param path 待删除文件路径
- */
- - (void)deleteFileAtPath:(NSString *)path {
- Lock();
-
- NSFileManager *fm = [NSFileManager defaultManager];
- if([fm fileExistsAtPath:path]) {
- [fm removeItemAtPath:path error:nil];
- }
-
- Unlock();
- }
- /**
- * @brief 将字典以Json格式写入文件
- * @param json 待写入字典数据
- * @param path 写入文件路径
- */
- - (void)_writeJson:(NSDictionary *)json toPath:(NSString *)path {
-
- NSData *data = [NSJSONSerialization dataWithJSONObject:json options:NSJSONWritingPrettyPrinted error:nil];
- [data writeToFile:path atomically:NO];
- }
- /**
- * @brief 将字典以Json格式写入文件
- * @param json 待写入字典数据
- * @param path 写入文件路径
- */
- - (void)writeJson:(NSDictionary *)json toPath:(NSString *)path {
-
- Lock();
-
- [self _writeJson:json toPath:path];
-
- Unlock();
- }
- /**
- * @brief 当前时间字符串,格式 MM/DD/YYYY HH:mm
- */
- - (NSString *)currentDate {
-
- NSDate *date = [NSDate date];
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- formatter.dateFormat = @"MM/dd/YYYY HH:mm";
-
- return [formatter stringFromDate:date];
- }
- - (NSString *)statusTitleForActionIndex:(NSInteger)actionIndex {
-
- Lock();
-
- NSString *path = [self.offlineDir stringByAppendingPathComponent:@"status_title.json"];
- NSDictionary *titleDic = [self _loadCacheData:path];
-
- Unlock();
-
- NSString *title = [titleDic objectForKey:[NSString stringWithFormat:@"%ld",(long)actionIndex]];
-
- if (!title) {
- title = @"";
- }
- return title;
- }
- - (NSString *)homeSectionTitleForStatus:(NSInteger)status {
-
- Lock();
-
- NSString *path = [self.offlineDir stringByAppendingPathComponent:@"home_section_title.json"];
- NSDictionary *titleDic = [self _loadCacheData:path];
-
- Unlock();
-
- NSString *title = [titleDic objectForKey:[NSString stringWithFormat:@"%ld",(long)status]];
-
- if (!title) {
- title = @"";
- }
- return title;
- }
- - (void)homeSection:(NSMutableDictionary *)section addOrder:(NSDictionary *)curOrder forActionIndex:(NSInteger)actionIdx {
-
- if (curOrder == nil) {
- return;
- }
-
- NSMutableArray<NSDictionary *> *orders = [[section objectForKey:@"orders"] mutableCopy];
-
- if (orders == nil) {
- orders = [NSMutableArray array];
- }
-
-
- // 修改order状态为Processing
- [curOrder setValue:@(RAOrderStatusProcessing) forKey:@"status"];
- [curOrder setValue:@(NO) forKey:@"backendFlag"];
- [curOrder setValue:[self statusTitleForActionIndex:actionIdx] forKey:@"title"];
-
- // 将当前order插入第一个位置
- [orders insertObject:curOrder atIndex:0];
-
- [section setObject:orders forKey:@"orders"];
-
- }
- #pragma mark - Update Data
- /**
- * @brief 更新离线缓存Home数据
- * @param homeJson 新的Home数据
- */
- - (void)updateHome:(NSDictionary *)homeJson {
-
- NSString *homeJsonPath = [self.offlineDir stringByAppendingPathComponent:@"home.json"];
- [self writeJson:homeJson toPath:homeJsonPath];
- }
- /**
- * @brief 更新order最后一次操作标记
- * @param actionIdx 操作索引
- * @param orderId 订单号
- */
- - (void)updateLastAction:(NSInteger)actionIdx forOrder:(NSString *)orderId {
- if (!orderId) {
- return;
- }
- Lock();
- NSMutableDictionary<NSString *, NSNumber *> *finishDic = [[self _finishedActions] mutableCopy];
- Unlock();
-
- [finishDic setObject:@(actionIdx) forKey:orderId];
-
- NSString *path = [self.offlineDir stringByAppendingPathComponent:@"finish"];
- [finishDic writeToFile:path atomically:NO];
- }
- /**
- * @brief 删除order操作对应的json文件
- * @param orderId 订单号
- * @param actionIdx 操作索引
- */
- - (void)deleteEditJsonFileForOrder:(NSString *)orderId withActionIndex:(NSInteger)actionIdx {
-
- NSString *editJsonPath = [self.offlineDir stringByAppendingPathComponent:[NSString stringWithFormat:@"edit/%@_%ld",orderId,(long)actionIdx]];
- [self deleteFileAtPath:editJsonPath];
- }
- /**
- * @brief 离线提交Detail Remote Action
- * @param orderId 订单号
- * @param type 订单类型 RAOrderStatus, New Order / Processing Order
- * @param action 操作类型 RADetailActionSubType, Reject / Accept
- * @param actionIdx 操作索引
- * @param actionName 操作名称
- * @param url 操作提交目标地址
- * @param params 操作提交的参数
- * @return 成功/失败
- */
- - (NSDictionary *)reportOrder:(NSString *)orderId type:(NSInteger)type actionType:(NSInteger)action actionIndex:(NSInteger)actionIdx actionName:(NSString *)actionName withURL:(NSString *)url params:(NSDictionary *)params {
-
- // 组织参数
- NSString *time = [self currentDate];
- NSMutableDictionary *mParams = [params mutableCopy];
- [self prepareParams:mParams];
-
- NSMutableDictionary *task = [@{
- @"order" : orderId,
- @"action" : actionName,
- @"name" : actionName,
- @"time" : time,
- @"url" : url,
- @"noFile" : @YES,
- @"params" : mParams
- } mutableCopy];
-
- dispatch_async(dispatch_get_main_queue(), ^{
-
- // @"file" : photoPath,
-
- // 提交参数给UploadManager
- AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
- [appDelegate.uploadManager addTask:task];
- });
-
- // New Order
- if (type == RAOrderStatusNew) {
-
- // 加载Home
- NSMutableDictionary *home = [[self requestOfflineHome] mutableCopy];
-
- if (home != nil) {
-
- // 遍历order,查找当前order,并修改状态/移除
- // Accept 移动order到processing
- // Reject 删除Order及对应的detail、edit
- NSMutableArray<NSDictionary *> *sections = [[home objectForKey:@"sections"] mutableCopy];
- __block NSDictionary *curOrder = nil; // 当前order
- __block NSDictionary *rmSection = nil; // 若section下没有order,则移除section
-
- if (sections) {
-
- // 查找New Order
- for (int i = 0; i < sections.count; i++) {
- NSDictionary *section = [sections objectAtIndex:i];
-
- RAOrderStatus type = [[section objectForKey:@"type"] intValue];
- if (type == RAOrderStatusNew) {
-
- // 查找当前order
- NSMutableArray<NSDictionary *> *orders = [[section objectForKey:@"orders"] mutableCopy];
- [orders enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSString *orderID = [obj objectForKey:@"orderID"];
- if ([orderId isEqualToString:orderID]) {
- curOrder = obj;
- *stop = YES;
- }
- }];
-
- // 找到order并移除
- if (curOrder) {
- [orders removeObject:curOrder];
-
- // 移除过后如果orders为空,则移除section
- if (orders.count == 0) {
- rmSection = section;
- }
- else {
- // orders不为空,重新修改
- rmSection = nil;
- NSMutableDictionary *mSec = [section mutableCopy];
- [mSec setObject:orders forKey:@"orders"];
- [sections replaceObjectAtIndex:i withObject:mSec];
- }
- }
-
- // 删除Order 操作对应Edit文件
- [self deleteEditJsonFileForOrder:orderId withActionIndex:actionIdx];
-
- break;
- }
- }
-
- if (rmSection) {
- [sections removeObject:rmSection];
- }
-
- // 如果是Accept则将order添加到Processing Order
- if (action == RADetailActionSubTypeAccept) {
-
- BOOL findSection = NO;
- for (int i = 0; i < sections.count; i++) {
- NSMutableDictionary *section = [[sections objectAtIndex:i] mutableCopy];
-
- RAOrderStatus type = [[section objectForKey:@"type"] intValue];
- if (type == RAOrderStatusProcessing) {
- [self homeSection:section addOrder:curOrder forActionIndex:actionIdx];
-
- // 重新生成section
- [sections replaceObjectAtIndex:i withObject:section];
-
- findSection = YES;
- break;
- }
- }
-
- if (!findSection) {
-
- NSMutableDictionary *section = [@{
- @"type" : @(RAOrderStatusProcessing),
- @"totalCount" : @0,
- @"backendFlagCount" : @0,
- @"title" : [self homeSectionTitleForStatus:RAOrderStatusProcessing]
- } mutableCopy];
-
- [self homeSection:section addOrder:curOrder forActionIndex:actionIdx];
-
- [sections addObject:section];
- }
- }
-
- // 重新生成sections
- [home setObject:sections forKey:@"sections"];
-
- }
-
- // 更新Home文件
- [self updateHome:home];
- }
- }
-
- // 更新Action
- [self updateLastAction:actionIdx forOrder:orderId];
-
- return @{
- @"result" : @(RESULT_TRUE)
- };
- }
- /**
- * @brief 离线提交订单
- * @param orderId 订单号
- * @param actionId 操作ID,RADetailActionSubType
- * @param title 操作名称
- * @param idx 操作索引
- * @param params 订单填写的信息
- * @param photos 待上传的图片模型数组
- * @param dir 待上传的图片存储目录
- */
- - (NSDictionary *)updateOrder:(NSString *)orderId action:(NSInteger)actionId title:(NSString *)title index:(NSInteger)idx withParams:(NSDictionary *)params photos:(NSArray<RAEditImageBaseModel *> *)photos cacheDir:(NSString *)dir {
-
- NSFileManager *fm = [NSFileManager defaultManager];
-
- // 修改Params
- NSString *time = [self currentDate];
- NSMutableDictionary *mParams = [params mutableCopy];
- [self prepareParams:mParams];
- // // 将params写入目录
- // NSString *paramPath = [upDir stringByAppendingPathComponent:@"params.json"];
- // [self _writeJson:mParams toPath:paramPath];
-
- NSString *zipF = nil;
- if (photos.count > 0) {
-
- Lock();
-
- // 生成上传目录
- NSString *upDir = [self.offlineUploadDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%ld",orderId,(long)idx]];
- [fm createDirectoryAtPath:upDir withIntermediateDirectories:NO attributes:nil error:nil];
-
- // 生成图片目录
- NSString *imageDir = [upDir stringByAppendingPathComponent:@"images"];
- [fm createDirectoryAtPath:imageDir withIntermediateDirectories:NO attributes:nil error:nil];
-
- // 将图片移动到图片目录
- for (RAEditImageBaseModel *model in photos) {
- NSString *path = [dir stringByAppendingPathComponent:model.imageName];
- NSString *toPath = [imageDir stringByAppendingString:model.imageName];
-
- if ([fm fileExistsAtPath:path]) {
-
- NSError *err;
- BOOL move = [fm moveItemAtPath:path toPath:toPath error:&err];
- if (!move) {
-
- NSString *msg = NSLocalizedString(@"sorry", nil);
- if (err) {
- msg = err.localizedDescription;
- }
-
- Unlock();
- return @{
- @"result" : @(RESULT_FALSE),
- @"err_msg" : msg
- };
- }
-
- }
- }
-
- // 压缩目录
- NSString *zip = [self _zipDir:upDir];
-
- // 删除目录
- [fm removeItemAtPath:upDir error:nil];
-
- NSRange start = [zip rangeOfString:@"upload"];
- zipF = [zip substringFromIndex:start.location];
-
- Unlock();
- }
-
- // 创建Task
- NSMutableDictionary *task = [@{
- @"order" : orderId,
- @"action" : title,
- @"name" : title,
- @"time" : time,
- @"url" : URL_UPLOAD,
- @"params" : mParams
- } mutableCopy];
- if (zipF) {
- [task setObject:zipF forKey:@"file"];
- } else {
- [task setObject:@(YES) forKey:@"noFile"];
- }
-
- dispatch_async(dispatch_get_main_queue(), ^{
-
- // 提交Task
- AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
- [appDelegate.uploadManager addTask:task];
- });
-
- // 删除Edit文件
- [self deleteEditJsonFileForOrder:orderId withActionIndex:idx];
-
- // 判断是否完成order 所有操作
- BOOL finish = [self isLastActionForOrder:orderId index:idx];
-
- // 将order从Processing中删除
- // 加载Home
- NSMutableDictionary *home = [[self requestOfflineHome] mutableCopy];
- if (home) {
- NSMutableArray<NSDictionary *> *sections = [[home objectForKey:@"sections"] mutableCopy];
- if (sections) {
-
- __block NSDictionary *rmSection = nil; // 若section下没有order,则移除section
- for (int i = 0; i < sections.count; i++) {
- NSMutableDictionary *section = [[sections objectAtIndex:i] mutableCopy];
-
- RAOrderStatus type = [[section objectForKey:@"type"] intValue];
- if (type == RAOrderStatusProcessing) {
- NSMutableArray<NSDictionary *> *orders = [[section objectForKey:@"orders"] mutableCopy];
-
- __block NSDictionary *curOrder = nil; // 当前order
- [orders enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-
- NSString *orderID = [obj objectForKey:@"orderID"];
- if ([orderId isEqualToString:orderID]) {
- curOrder = obj;
- *stop = YES;
- }
-
- }];
-
- if (finish) {
- [orders removeObject:curOrder];
-
- if (orders.count > 0) {
- [section setObject:orders forKey:@"orders"];
-
- // 重新生成section
- [sections replaceObjectAtIndex:i withObject:section];
- } else {
-
- rmSection = [sections objectAtIndex:i];
- }
- } else {
-
- [curOrder setValue:@(NO) forKey:@"backendFlag"];
- [curOrder setValue:[self statusTitleForActionIndex:idx] forKey:@"title"];
- }
-
- break;
- }
- }
-
- if (rmSection) {
- [sections removeObject:rmSection];
- }
-
- // 重新生成sections
- [home setObject:sections forKey:@"sections"];
-
- }
-
- // 更新Home文件
- [self updateHome:home];
- }
-
- // 更新Action
- [self updateLastAction:idx forOrder:orderId];
-
- return @{
- @"result" : @(RESULT_TRUE)
- };
- }
- @end
|