Kaynağa Gözat

修复任务列表图标随机变化的bug

fancy 5 yıl önce
ebeveyn
işleme
c224441e3d

+ 1 - 1
o2ios/O2Platform/App/BBS-论坛/BBSViewModel.swift

@@ -44,7 +44,7 @@ extension BBSViewModel {
                 switch result {
                 case .success(_):
                     //下载成功
-                    let fileURL = O2CloudFileManager.shared.cloudFileLocalFolder().appendingPathComponent(att.fileName!)
+                    let fileURL = O2.cloudFileLocalFolder().appendingPathComponent(att.fileName!)
                     fulfill(fileURL)
                 case .failure(let err):
                     reject(err)

+ 13 - 0
o2ios/O2Platform/App/Setting-设置/c/SCommonViewController.swift

@@ -91,6 +91,12 @@ class SCommonViewController: UITableViewController {
                 self.group.leave()
             })
         }))
+        self.group.enter()
+        DispatchQueue.main.async(group: self.group, execute: DispatchWorkItem(block: {
+            self.clearO2CacheFolder()
+            print("清除本地缓存目录")
+            self.group.leave()
+        }))
         
         self.group.notify(queue: DispatchQueue.main) {
             self.showSuccess(title: "清理完成")
@@ -98,6 +104,13 @@ class SCommonViewController: UITableViewController {
         }
     }
     
+    ///清楚本地的缓存文件
+    private func clearO2CacheFolder() {
+        O2.deleteFolder(folder: O2.cloudFileLocalFolder())
+        O2.deleteFolder(folder: O2.base64CacheLocalFolder())
+        O2.deleteFolder(folder: O2.inforCacheLocalFolder())
+    }
+    
     private func notify() {
     // 通知门户页面刷新 因为清除了浏览器缓存 没有cookie了 需要重新加载webview
         NotificationCenter.default.post(name: OONotification.reloadPortal.notificationName, object: nil)

+ 2 - 4
o2ios/O2Platform/App/Work-工作/c/TodoTaskViewController.swift

@@ -421,13 +421,11 @@ class TodoTaskViewController: UITableViewController {
         let cell = tableView.dequeueReusableCell(withIdentifier: "TodoTaskTableViewCell", for: indexPath) as! TodoTaskTableViewCell
         if   !self.searchController.isActive {
             let model = self.models[indexPath.row]
-            cell.cellModel = model
-
+            cell.setData(cellModel: model)
         }else{
             let model = self.filterModels[indexPath.row]
-            cell.cellModel = model
+            cell.setData(cellModel: model)
         }
-
         return cell
     }
     

+ 13 - 0
o2ios/O2Platform/App/Work-工作/m/O2Application.swift

@@ -4,6 +4,7 @@
 
 import Foundation 
 import ObjectMapper
+import HandyJSON
 
 
 class O2Application : NSObject, NSCoding, Mappable{
@@ -130,3 +131,15 @@ class O2Application : NSObject, NSCoding, Mappable{
 	}
 
 }
+
+
+class O2ApplicationIcon: NSObject, DataModel {
+    @objc var icon: String?
+    @objc var iconHue: String?
+    
+    required override init() {
+    }
+    
+    func mapping(mapper: HelpingMapper) {
+    }
+}

+ 21 - 31
o2ios/O2Platform/App/Work-工作/task.storyboard

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Yna-g7-LKp">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Yna-g7-LKp">
     <device id="retina5_5" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15509"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -435,51 +435,41 @@
                                     <autoresizingMask key="autoresizingMask"/>
                                     <subviews>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="我的报销单" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cNB-vb-QcB">
-                                            <rect key="frame" x="58" y="19" width="336" height="16"/>
+                                            <rect key="frame" x="60" y="8.0000000000000018" width="334" height="19.666666666666671"/>
                                             <fontDescription key="fontDescription" name="PingFangSC-Regular" family="PingFang SC" pointSize="14"/>
                                             <color key="textColor" red="0.070588235294117646" green="0.070588235294117646" blue="0.070588235294117646" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                             <nil key="highlightedColor"/>
                                         </label>
-                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="核稿" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dXO-41-4yT">
-                                            <rect key="frame" x="58" y="38" width="238" height="15"/>
-                                            <constraints>
-                                                <constraint firstAttribute="height" constant="15" id="MQy-8H-jwG"/>
-                                            </constraints>
-                                            <fontDescription key="fontDescription" name="PingFangSC-Thin" family="PingFang SC" pointSize="12"/>
-                                            <color key="textColor" red="0.60784313725490191" green="0.60784313725490191" blue="0.60784313725490191" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                            <nil key="highlightedColor"/>
-                                        </label>
                                         <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="El2-Gs-GuT">
-                                            <rect key="frame" x="14" y="28" width="20" height="14"/>
+                                            <rect key="frame" x="12" y="23" width="24" height="24"/>
                                             <constraints>
-                                                <constraint firstAttribute="height" constant="20" id="dCK-xO-15s"/>
-                                                <constraint firstAttribute="width" constant="20" id="e2w-ZX-1pG"/>
+                                                <constraint firstAttribute="height" constant="24" id="dCK-xO-15s"/>
+                                                <constraint firstAttribute="width" constant="24" id="e2w-ZX-1pG"/>
                                             </constraints>
                                         </imageView>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2015.10.10 10:27" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Sc-3D-x8m">
-                                            <rect key="frame" x="233" y="43" width="124" height="15"/>
-                                            <constraints>
-                                                <constraint firstAttribute="width" constant="124" id="Ng5-na-Rxu"/>
-                                            </constraints>
+                                            <rect key="frame" x="293.33333333333331" y="41" width="88.666666666666686" height="17"/>
                                             <fontDescription key="fontDescription" name="PingFangSC-Thin" family="PingFang SC" pointSize="12"/>
                                             <color key="textColor" red="0.73333333333333328" green="0.80784313725490198" blue="0.82745098039215681" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                             <nil key="highlightedColor"/>
                                         </label>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="核稿" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dXO-41-4yT">
+                                            <rect key="frame" x="60" y="41" width="24" height="17"/>
+                                            <fontDescription key="fontDescription" name="PingFangSC-Thin" family="PingFang SC" pointSize="12"/>
+                                            <color key="textColor" red="0.60784313725490191" green="0.60784313725490191" blue="0.60784313725490191" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
                                     </subviews>
                                     <constraints>
-                                        <constraint firstItem="4Sc-3D-x8m" firstAttribute="centerY" secondItem="3D0-U7-9Ot" secondAttribute="centerY" constant="15.5" id="9qR-aG-MKj"/>
-                                        <constraint firstItem="El2-Gs-GuT" firstAttribute="leading" secondItem="3D0-U7-9Ot" secondAttribute="leadingMargin" constant="-6" id="Okf-pj-YfM"/>
-                                        <constraint firstItem="4Sc-3D-x8m" firstAttribute="leading" secondItem="3D0-U7-9Ot" secondAttribute="leading" constant="233" id="Psq-a9-aWV"/>
-                                        <constraint firstItem="cNB-vb-QcB" firstAttribute="top" secondItem="3D0-U7-9Ot" secondAttribute="topMargin" constant="8" id="Ysx-ZF-Q8p"/>
-                                        <constraint firstItem="El2-Gs-GuT" firstAttribute="top" secondItem="3D0-U7-9Ot" secondAttribute="topMargin" constant="17" id="cNt-D5-mFU"/>
-                                        <constraint firstItem="4Sc-3D-x8m" firstAttribute="top" secondItem="3D0-U7-9Ot" secondAttribute="topMargin" constant="32" id="cxE-iv-lEB"/>
+                                        <constraint firstItem="El2-Gs-GuT" firstAttribute="leading" secondItem="3D0-U7-9Ot" secondAttribute="leading" constant="12" id="RkS-cN-bqt"/>
+                                        <constraint firstAttribute="trailingMargin" secondItem="4Sc-3D-x8m" secondAttribute="trailing" constant="12" id="Swx-yV-Uua"/>
+                                        <constraint firstItem="cNB-vb-QcB" firstAttribute="top" secondItem="3D0-U7-9Ot" secondAttribute="top" constant="8" id="XMp-E3-YOU"/>
+                                        <constraint firstAttribute="bottom" secondItem="4Sc-3D-x8m" secondAttribute="bottom" constant="12" id="eT6-gu-ONE"/>
                                         <constraint firstItem="El2-Gs-GuT" firstAttribute="centerY" secondItem="3D0-U7-9Ot" secondAttribute="centerY" id="jsT-PR-OTY"/>
                                         <constraint firstItem="cNB-vb-QcB" firstAttribute="leading" secondItem="dXO-41-4yT" secondAttribute="leading" id="kr1-dv-RFg"/>
-                                        <constraint firstItem="cNB-vb-QcB" firstAttribute="trailing" secondItem="dXO-41-4yT" secondAttribute="trailing" constant="98" id="lWn-8K-Thp"/>
+                                        <constraint firstAttribute="bottom" secondItem="dXO-41-4yT" secondAttribute="bottom" constant="12" id="n8y-9k-s8g"/>
                                         <constraint firstItem="cNB-vb-QcB" firstAttribute="trailing" secondItem="3D0-U7-9Ot" secondAttribute="trailingMargin" id="sld-rx-UmN"/>
                                         <constraint firstItem="cNB-vb-QcB" firstAttribute="leading" secondItem="El2-Gs-GuT" secondAttribute="trailing" constant="24" id="v8r-wZ-ciT"/>
-                                        <constraint firstAttribute="bottomMargin" secondItem="dXO-41-4yT" secondAttribute="bottom" constant="6" id="yka-dl-Gvh"/>
-                                        <constraint firstItem="dXO-41-4yT" firstAttribute="top" secondItem="cNB-vb-QcB" secondAttribute="bottom" constant="3" id="zJ9-oI-5xF"/>
                                     </constraints>
                                 </tableViewCellContentView>
                                 <inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
@@ -670,11 +660,11 @@
             <point key="canvasLocation" x="1741" y="-1051"/>
         </scene>
     </scenes>
+    <inferredMetricsTieBreakers>
+        <segue reference="QJV-sf-Oi5"/>
+    </inferredMetricsTieBreakers>
     <resources>
         <image name="icon_daiban" width="38" height="38"/>
         <image name="todoedStatusIcon" width="32" height="32"/>
     </resources>
-    <inferredMetricsTieBreakers>
-        <segue reference="QJV-sf-Oi5"/>
-    </inferredMetricsTieBreakers>
 </document>

+ 15 - 9
o2ios/O2Platform/App/Work-工作/v/TodoTaskTableViewCell.swift

@@ -19,15 +19,7 @@ class TodoTaskTableViewCell: UITableViewCell {
     
     @IBOutlet weak var timeLabel: UILabel!
     
-    var cellModel:TodoCellModel<TodoTask>?{
-        didSet {
-            let i = 1 + arc4random() % 10
-            self.imageView?.image = UIImage.scaleTo(image: UIImage(named: "todo_\(i)")!, w: 20.0, h: 20.0)
-            self.titleLabel.text = "[\((cellModel!.applicationName)!)] \((cellModel!.title)!)"
-            self.statusLabel.text = cellModel?.status
-            self.timeLabel.text = cellModel?.time
-        }
-    }
+
     
 
     override func awakeFromNib() {
@@ -40,5 +32,19 @@ class TodoTaskTableViewCell: UITableViewCell {
 
         // Configure the view for the selected state
     }
+    
+    func setData(cellModel:TodoCellModel<TodoTask>) {
+        if let applicationId = cellModel.sourceObj?.application {
+            ImageUtil.shared.getProcessApplicationIcon(id: applicationId)
+                .then { (image)  in
+                    self.todoIconImageView?.image = image
+            }.catch { (err) in
+                self.todoIconImageView?.image = UIImage(named: "todo_8")
+            }
+        }
+        self.titleLabel.text = "[\((cellModel.applicationName)!)] \((cellModel.title)!)"
+        self.statusLabel.text = cellModel.status
+        self.timeLabel.text = cellModel.time
+    }
 
 }

+ 9 - 0
o2ios/O2Platform/Extension/UIImage+Extension.swift

@@ -37,6 +37,15 @@ extension UIImage {
         
         return rect
     }
+    //base64 转UIImage
+    public static func base64ToImage(_ source:String,defaultImage:UIImage=UIImage(named: "personDefaultIcon")!) -> UIImage {
+        if source != ""{
+            let theImage = UIImage(data: Data(base64Encoded:source,options:NSData.Base64DecodingOptions.ignoreUnknownCharacters)!)
+            return theImage!
+        }else{
+            return defaultImage
+        }
+    }
 }
  
 

+ 1 - 1
o2ios/O2Platform/Framework/O2API/BBSAPI/O2BBSAPI.swift

@@ -137,7 +137,7 @@ extension O2BBSAPI:TargetType{
     
     func getDownDest(filename: String) -> DownloadDestination {
         let myDest:DownloadDestination = { temporaryURL, response in
-            let fileURL = O2CloudFileManager.shared.cloudFileLocalFolder().appendingPathComponent(filename)
+            let fileURL = O2.cloudFileLocalFolder().appendingPathComponent(filename)
             return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
             
         }

+ 2 - 7
o2ios/O2Platform/Framework/O2API/InformationAPI/O2InformationAPI.swift

@@ -93,8 +93,6 @@ extension O2InformationAPI:TargetType {
             return .requestPlain
         case .docAttachDownload(_):
             return .downloadDestination(self.getDownDest()!)
-        default:
-            return .requestPlain
         }
     }
     
@@ -106,8 +104,7 @@ extension O2InformationAPI:TargetType {
         switch self {
         case .docAttachDownload(let attachmentInfo):
             let fileName = attachmentInfo.name
-             let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
-            let fileURL = documentsURL.appendingPathComponent("O2").appendingPathComponent("infor").appendingPathComponent(fileName!)
+            let fileURL = O2.inforCacheLocalFolder().appendingPathComponent(fileName!)
             return NSURL(string: fileURL.absoluteString)
         default:
             return nil
@@ -118,11 +115,9 @@ extension O2InformationAPI:TargetType {
         switch self {
         case .docAttachDownload(let attachmentInfo):
             let myDest:DownloadDestination = { temporaryURL, response in
-                let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
                 let fileName = attachmentInfo.name
-                let fileURL = documentsURL.appendingPathComponent("O2").appendingPathComponent("infor").appendingPathComponent(fileName!)
+                let fileURL = O2.inforCacheLocalFolder().appendingPathComponent(fileName!)
                 return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
-                
             }
             return myDest
         default:

+ 3 - 0
o2ios/O2Platform/Framework/O2API/TaskAPI/OOApplicationAPI.swift

@@ -17,6 +17,7 @@ enum OOApplicationAPI {
     case applicationItem(String)
     case availableIdentityWithProcess(String)
     case startProcess(String, String, String) // processId identity title
+    case icon(String)
 }
 
 // MARK:- 上下文实现
@@ -53,6 +54,8 @@ extension OOApplicationAPI:TargetType {
             return "/jaxrs/process/list/available/identity/process/\(processId)"
         case .startProcess(let processId, _, _):
             return "/jaxrs/work/process/\(processId)"
+        case .icon(let applicationId):
+            return "/jaxrs/application/\(applicationId)/icon"
         }
     }
     

+ 117 - 21
o2ios/O2Platform/Framework/Utils/ImageUtil.swift

@@ -7,29 +7,125 @@
 //
 
 import Foundation
-extension UIImage{
-    public static func base64ToImage(_ source:String,defaultImage:UIImage=UIImage(named: "personDefaultIcon")!) -> UIImage {
-        if source != ""{
-            let theImage = UIImage(data: Data(base64Encoded:source,options:NSData.Base64DecodingOptions.ignoreUnknownCharacters)!)
-            return theImage!
-        }else{
-            return defaultImage
+import CocoaLumberjack
+import Promises
+
+extension UIImage {
+//    public static func base64ToImage(_ source:String,defaultImage:UIImage=UIImage(named: "personDefaultIcon")!) -> UIImage {
+//        if source != ""{
+//            let theImage = UIImage(data: Data(base64Encoded:source,options:NSData.Base64DecodingOptions.ignoreUnknownCharacters)!)
+//            return theImage!
+//        }else{
+//            return defaultImage
+//        }
+//    }
+//
+//    class func image(color: UIColor, size: CGSize) -> UIImage {
+//
+//        let rect = CGRect.init(x: 0, y: 0, width: size.width, height: size.height)
+//        UIGraphicsBeginImageContext(rect.size)
+//
+//        let context = UIGraphicsGetCurrentContext()
+//
+//        context?.setFillColor(color.cgColor)
+//        context?.fill(rect)
+//
+//        let img = UIGraphicsGetImageFromCurrentImageContext()
+//        UIGraphicsEndImageContext()
+//
+//        return img!
+//    }
+}
+
+
+class ImageUtil {
+    private init() { }
+
+    static let shared: ImageUtil = {
+        return ImageUtil()
+    }()
+
+    private let o2ProcessAPI = OOMoyaProvider<OOApplicationAPI>()
+
+    //获取流程应用的图标
+    func getProcessApplicationIcon(id: String) -> Promise<UIImage> {
+        return Promise { fulfill, reject in
+            self.loadApplicationBase64FromCache(id: id).then { (image) in
+                fulfill(image)
+            }.catch { (error) in
+                DDLogError("从缓存获取流程应用图标失败 \(error.localizedDescription)")
+                self.loadApplicationBase64FromNet(id: id).then { (img) in
+                    fulfill(img)
+                }.catch { (err) in
+                    DDLogError("从网络获取流程应用图标失败 \(err.localizedDescription)")
+                    fulfill(UIImage(named: "todo_8")!)
+                }
+            }
+        }
+    }
+
+
+    //从缓存文件读取base64 转换成image
+    private func loadApplicationBase64FromCache(id: String) -> Promise<UIImage> {
+        return Promise { fulfill, reject in
+            let icon = self.readBase64String(id: id)
+            if icon != nil && icon?.isEmpty != true {
+                fulfill(UIImage.base64ToImage(icon!, defaultImage: UIImage(named: "todo_8")!))
+            } else {
+                reject(OOAppError.apiEmptyResultError)
+            }
+        }
+    }
+
+    //下载base64 转换成image
+    private func loadApplicationBase64FromNet(id: String) -> Promise<UIImage> {
+        return Promise { fulfill, reject in
+            self.o2ProcessAPI.request(.icon(id), completion: { result in
+                    let myResult = OOResult<BaseModelClass<O2ApplicationIcon>>(result)
+                    if myResult.isResultSuccess() {
+                        if let item = myResult.model?.data, let icon = item.icon, !icon.isEmpty {
+                            DDLogDebug("网络获取icon成功...............")
+                            self.writeBase64StringFile(id: id, base64: icon)//写入缓存
+                            fulfill(UIImage.base64ToImage(icon, defaultImage: UIImage(named: "todo_8")!))
+                        } else {
+                            reject(OOAppError.apiEmptyResultError)
+                        }
+                    } else {
+                        reject(myResult.error!)
+                    }
+                })
         }
     }
+
     
-    class func image(color: UIColor, size: CGSize) -> UIImage {
-        
-        let rect = CGRect.init(x: 0, y: 0, width: size.width, height: size.height)
-        UIGraphicsBeginImageContext(rect.size)
-        
-        let context = UIGraphicsGetCurrentContext()
-        
-        context?.setFillColor(color.cgColor)
-        context?.fill(rect)
-        
-        let img = UIGraphicsGetImageFromCurrentImageContext()
-        UIGraphicsEndImageContext()
-        
-        return img!
+
+
+    //从缓存文件读取base64字符串
+    private func readBase64String(id: String) -> String? {
+        let path = O2.base64CacheLocalFolder().appendingPathComponent("\(id)")
+        do {
+            return try String(contentsOf: path, encoding: .utf8)
+        }
+        catch {
+            DDLogError(error.localizedDescription)
+        }
+        return nil
     }
+
+    //base64字符串写入本地缓存文件 用id作为文件名称
+    private func writeBase64StringFile(id: String, base64: String) {
+        let path = O2.base64CacheLocalFolder().appendingPathComponent("\(id)")
+        do {
+            try base64.write(to: path, atomically: false, encoding: .utf8)
+        } catch {
+            DDLogError(error.localizedDescription)
+        }
+//        if FileManager.default.fileExists(atPath: path.path) {
+//
+//        }else {
+//            let result = FileManager.default.createFile(atPath: path.path, contents: base64.data(using: .utf8), attributes: nil)
+//            DDLogDebug("创建文件完成, result:\(result)")
+//        }
+    }
+
 }

+ 5 - 11
o2ios/O2Platform/Manager/O2CloudFileManager.swift

@@ -27,22 +27,16 @@ class O2CloudFileManager {
     
     
     // MARK: - 工具服务 获取url 本地文件夹路径等等
-    //文件存储目录
-    func cloudFileLocalFolder() -> URL {
-        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
-        return documentsURL
-            .appendingPathComponent("O2")
-            .appendingPathComponent("cloud")
-    }
+    
     //本地文件存储路径
     func cloudFileLocalPath(file: OOAttachment) -> URL {
         let fileName = "\(file.name!).\(file.`extension`!)"
         if let id = file.id {
-            return self.cloudFileLocalFolder()
+            return O2.cloudFileLocalFolder()
                 .appendingPathComponent(id)
                 .appendingPathComponent(fileName)
         }
-        return self.cloudFileLocalFolder()
+        return O2.cloudFileLocalFolder()
             .appendingPathComponent(fileName)
         
     }
@@ -118,7 +112,7 @@ class O2CloudFileManager {
             }).then({ (dbFile)  in
                 if let filePath = dbFile.filePath, !filePath.isBlank {
                     DDLogDebug("查询到数据 文件路径:\(filePath)")
-                    let url = self.cloudFileLocalFolder().appendingPathComponent(filePath)
+                    let url = O2.cloudFileLocalFolder().appendingPathComponent(filePath)
                     fulfill(url)
                 }else {
                     reject(O2DBError.EmptyResultError)
@@ -136,7 +130,7 @@ class O2CloudFileManager {
             DBManager.shared.queryCloudFile(fileId: id).then({ (dbFile) in
                 if let filePath = dbFile.filePath, !filePath.isBlank {
                     DDLogDebug("查询到数据 文件路径:\(filePath)")
-                    let url = self.cloudFileLocalFolder().appendingPathComponent(filePath)
+                    let url = O2.cloudFileLocalFolder().appendingPathComponent(filePath)
                     fulfill(url)
                 }else {
                     reject(O2DBError.EmptyResultError)

+ 71 - 6
o2ios/O2Platform/config/O2.swift

@@ -7,6 +7,7 @@
 //
 
 import Foundation
+import CocoaLumberjack
 
 
 struct O2 {
@@ -19,25 +20,25 @@ struct O2 {
         } else if let bundleName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String {
             return bundleName
         }
-        
+
         return nil
     }
-    
+
     /// EZSE: Returns app's version number
     public static var appVersion: String? {
         return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
     }
-    
+
     /// EZSE: Return app's build number
     public static var appBuild: String? {
         return Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
     }
-    
+
     /// EZSE: Return app's bundle ID
     public static var appBundleID: String? {
         return Bundle.main.bundleIdentifier
     }
-    
+
     /// EZSE: Returns both app's version and build numbers "v0.3(7)"
     public static var appVersionAndBuild: String? {
         if appVersion != nil && appBuild != nil {
@@ -49,7 +50,7 @@ struct O2 {
         }
         return nil
     }
-    
+
     /// EZSE: Return device version ""
     public static var deviceVersion: String {
         var size: Int = 0
@@ -58,4 +59,68 @@ struct O2 {
         sysctlbyname("hw.machine", &machine, &size, nil, 0)
         return String(cString: machine)
     }
+
+    // MARK: - 本地缓存目录
+
+    ///云盘缓存目录
+    public static func cloudFileLocalFolder() -> URL {
+        let manager = FileManager.default
+        let documentsURL = manager.urls(for: .documentDirectory, in: .userDomainMask)[0]
+        let cloudFolder = documentsURL
+            .appendingPathComponent("O2")
+            .appendingPathComponent("cloud")
+        if !manager.fileExists(atPath: cloudFolder.path) {
+            do {
+                try manager.createDirectory(at: cloudFolder, withIntermediateDirectories: true, attributes: nil)
+            } catch {
+                DDLogError("创建文件夹错误,\(error.localizedDescription)")
+            }
+        }
+        return cloudFolder
+    }
+
+
+    ///base64缓存目录
+    public static func base64CacheLocalFolder() -> URL {
+        let manager = FileManager.default
+        let documentsURL = manager.urls(for: .documentDirectory, in: .userDomainMask)[0]
+        let base64Folder = documentsURL
+            .appendingPathComponent("O2")
+            .appendingPathComponent("base64")
+        if !manager.fileExists(atPath: base64Folder.path) {
+            do {
+                try manager.createDirectory(at: base64Folder, withIntermediateDirectories: true, attributes: nil)
+            } catch {
+                DDLogError("创建文件夹错误,\(error.localizedDescription)")
+            }
+        }
+        return base64Folder
+    }
+
+
+    ///info缓存目录
+    public static func inforCacheLocalFolder() -> URL {
+        let manager = FileManager.default
+        let documentsURL = manager.urls(for: .documentDirectory, in: .userDomainMask)[0]
+        let inforFolder = documentsURL
+            .appendingPathComponent("O2")
+            .appendingPathComponent("infor")
+        if !manager.fileExists(atPath: inforFolder.path) {
+            do {
+                try manager.createDirectory(at: inforFolder, withIntermediateDirectories: true, attributes: nil)
+            } catch {
+                DDLogError("创建文件夹错误,\(error.localizedDescription)")
+            }
+        }
+        return inforFolder
+    }
+    
+    ///删除文件夹
+    public static func deleteFolder(folder: URL) {
+        do{
+            try FileManager.default.removeItem(atPath: folder.path)
+        }catch{
+            DDLogError("删除目录失败,\(error.localizedDescription)")
+        }
+    }
 }