Ver Fonte

1.拆上传库BFUploadKit 2.取消全局引用

wenweiwei há 3 anos atrás
pai
commit
d6850cf6ac
25 ficheiros alterados com 32 adições e 4134 exclusões
  1. 1 1
      BFStuckPointKit.podspec
  2. 0 552
      BFStuckPointKit/Classes/BFUtils/PQAliOssUtil.swift
  3. 0 484
      BFStuckPointKit/Classes/BFUtils/PQSingletoRealmUtil.swift
  4. 1 0
      BFStuckPointKit/Classes/BFUtils/PQSingletoVideoPlayer.swift
  5. 6 5
      BFStuckPointKit/Classes/Controller/PQStuckPointEditerController.swift
  6. 6 5
      BFStuckPointKit/Classes/Controller/PQStuckPointPublicController.swift
  7. 0 26
      BFStuckPointKit/Classes/Extensions/OperationQueue+Ext.swift
  8. 0 39
      BFStuckPointKit/Classes/Extensions/Task+Ext.swift
  9. 0 182
      BFStuckPointKit/Classes/Model/PQLoginUserInfo.swift
  10. 0 176
      BFStuckPointKit/Classes/Model/PQUserInfoModel.swift
  11. 0 380
      BFStuckPointKit/Classes/Model/PQVideoListModel.swift
  12. 0 259
      BFStuckPointKit/Classes/SelectImage/PQImageCropVC.swift
  13. 0 52
      BFStuckPointKit/Classes/SelectImage/PQImageSelectedController.swift
  14. 0 130
      BFStuckPointKit/Classes/SelectImage/PQSelecteVideoItemCell.swift
  15. 0 993
      BFStuckPointKit/Classes/SelectImage/PQUploadController.swift
  16. 0 107
      BFStuckPointKit/Classes/View/PQAssetCategoryCell.swift
  17. 0 84
      BFStuckPointKit/Classes/View/PQBaseVideoInfoView.swift
  18. 1 0
      BFStuckPointKit/Classes/ViewModel/PQBaseViewModel.swift
  19. 0 77
      BFStuckPointKit/Classes/ViewModel/PQDownloadFileManager.swift
  20. 0 228
      BFStuckPointKit/Classes/ViewModel/PQDownloadManager.swift
  21. 0 191
      BFStuckPointKit/Classes/ViewModel/PQSessionManager.swift
  22. 0 160
      BFStuckPointKit/Classes/ViewModel/PQUploadViewModel.swift
  23. 2 0
      Example/BFStuckPointKit.xcodeproj/project.pbxproj
  24. 2 0
      Example/Podfile
  25. 13 3
      Example/Podfile.lock

+ 1 - 1
BFStuckPointKit.podspec

@@ -35,7 +35,7 @@ TODO: Add long description of the pod here.
   s.dependency 'BFMaterialKit'
   s.dependency 'BFMediaKit'
   s.dependency 'BFAnalyzeKit'
-  s.dependency 'AliyunOSSiOS'             ,'2.10.10'  # 阿里云组件
+  s.dependency 'BFUploadKit'
   s.dependency 'WechatOpenSDK-Swift'      ,'1.8.7.1'  # 微信组件
   s.dependency 'MJRefresh'                ,'~> 3.0'    # 刷新组件
   s.dependency 'LMJHorizontalScrollText'  ,'2.0.2'

+ 0 - 552
BFStuckPointKit/Classes/BFUtils/PQAliOssUtil.swift

@@ -1,552 +0,0 @@
-//
-//  PQAliOssUtil.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/12/9.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-import BFNetRequestKit
-import BFAnalyzeKit
-
-// MARK: - 阿里OSS工具类
-
-/// 阿里OSS工具类
-public class PQAliOssUtil: NSObject {
-    static public let shared = PQAliOssUtil()
-    public var client: OSSClient?
-    // 文件类型:materialType (1:PICTURE, 2:VIDEO, 3:VOICE, 4:FILE, 5:GIF)
-    public  var aliOssHander: ((_ isMatarialUpload: Bool, _ materialType: StickerType, _ fileExtensions: String, _ code: Int, _ objectKey: String?, _ contentMD5: String, _ width: CGFloat, _ height: CGFloat, _ duration: CGFloat, _ frameNumber: Int, _ netResourceUrl: String?, _ fileURL: URL?, _ data: Data?, _ msg: String?) -> Void)?
-    public  var aliOssProgressHander: ((_ bytesSent: Int64, _ totalBytesSent: Int64, _ totalBytesExpectedToSend: Int64, _ resttime: Int64, _ uploadSpeed: String?) -> Void)?
-    public  var lastInterfaceBytes: Int64 = 0 // 上次网速
-    public var oldTime: Int = 0 // 上次进度时间S
-    public var oloaded: Int64 = 0
-    public var dics: [String: Any] = [:]
-
-    public  var allTasks: [String: OSSMultipartUploadRequest] = [:] // add by ak 保存当前所有任务 用于取消某个任务使用
-    public  func startClient(accessKeyId: String, secretKeyId: String, securityToken: String, endpoint: String) -> PQAliOssUtil {
-        if endpoint.count == 0 {
-            debugPrint("endpoint is nil xxxxxx \(endpoint)")
-        }
-
-        let credential = OSSStsTokenCredentialProvider(accessKeyId: accessKeyId, secretKeyId: secretKeyId, securityToken: securityToken)
-        let conf = OSSClientConfiguration()
-        conf.timeoutIntervalForRequest = 60 // 连接超时,默认15秒
-        conf.maxRetryCount = 3
-        conf.maxConcurrentRequestCount = 5 // 最大并发请求书,默认5个
-        client = OSSClient(endpoint: endpoint, credentialProvider: credential, clientConfiguration: conf)
-        return .shared
-    }
-
-    /// 图片上传
-    /// - Parameters:
-    ///   - bucketName: <#bucketName description#>
-    ///   - objectKey: <#objectKey description#>
-    ///   - data: <#data description#>
-    /// - Returns: <#description#>
-    public  func uploadObjectAsync(bucketName: String, objectKey: String, data: Data, materialType: StickerType = .IMAGE, fileExtensions: String, isMatarialUpload: Bool = false, contentMD5: String = "", width: CGFloat = 0, height: CGFloat = 0, imageUploadBlock: @escaping (_ osstask: OSSTask<AnyObject>?, _ code: Int, _ objectKey: String, _ fileExtensions: String) -> Void) -> PQAliOssUtil {
-        let putRequest: OSSPutObjectRequest = OSSPutObjectRequest()
-        putRequest.bucketName = bucketName
-        putRequest.objectKey = objectKey
-        putRequest.uploadingData = data
-        putRequest.uploadProgress = { [weak self] _, totalByteSent, totalBytesExpectedToSend in
-            debugPrint("文件上传进度:totalByteSent = \(totalByteSent),totalBytesExpectedToSend = \(totalBytesExpectedToSend)")
-            if totalBytesExpectedToSend > 0, totalByteSent == totalBytesExpectedToSend {
-                if isMatarialUpload, self?.aliOssHander != nil {
-                    self?.aliOssHander!(isMatarialUpload, materialType, fileExtensions, 1, objectKey, contentMD5, width, height, 0, 0, nil, nil, data, "上传成功")
-                }
-            }
-        }
-        putRequest.contentType = "application/octet-stream"
-        //        putRequest.contentMd5 = contentMD5
-        putRequest.contentEncoding = ""
-        putRequest.contentDisposition = ""
-        let putTask: OSSTask = (client?.putObject(putRequest))!
-        putTask.continue(successBlock: { [weak self] (osstask) -> Any? in
-            if osstask.error == nil {
-                let task = self?.client?.presignPublicURL(withBucketName: putRequest.bucketName, withObjectKey: putRequest.objectKey)
-                debugPrint("图片原方法上传完成=\(objectKey)")
-                debugPrint("url == \(task?.result ?? "" as AnyObject)")
-                imageUploadBlock(osstask, 1, objectKey, fileExtensions)
-            } else {
-                if self?.aliOssHander != nil {
-                    self?.aliOssHander!(isMatarialUpload, materialType, fileExtensions, 0, objectKey, contentMD5, width, height, 0, 0, nil, nil, data, "上传失败")
-                }
-                debugPrint("图片原方法上传失败=\(objectKey),osstask.error = \(osstask.error ?? PQError(msg: "失败"))")
-                imageUploadBlock(osstask, 0, objectKey, fileExtensions)
-            }
-
-            return nil
-
-        }).waitUntilFinished()
-
-        return .shared
-    }
-
-    /// 快速上传视频
-    /// - Parameters:
-    ///   - localPath: <#localPath description#>
-    ///   - response: <#response description#>
-    /// - Returns: <#description#>
-    class public  func multipartUpload(localPath: String, response: [String: Any]?,videoSource:String? = nil) {
-        let accessKeyId: String = "\(response?["AccessKeyId"] ?? "")"
-        let secretKeyId: String = "\(response?["AccessKeySecret"] ?? "")"
-        let securityToken: String = "\(response?["SecurityToken"] ?? "")"
-        let endpoint: String = "\(response?["Host"] ?? "")"
-        let bucketName: String = "\(response?["Bucket"] ?? "")"
-        let FileName: String = "\(response?["FileName"] ?? "")"
-        let uploadID: String = "\(response?["Upload"] ?? "")"
-        var endpoints: [String] = Array<String>.init()
-        if response?.keys.contains("Hosts") ?? false {
-            endpoints = response?["Hosts"] as! [String]
-            endpoints.append(endpoint)
-        }
-        PQAliOssUtil.shared.PQOSSMultipartUpload(accessKeyId: accessKeyId, secretKeyId: secretKeyId, securityToken: securityToken, bucketName: bucketName, endpoints: endpoints, FileName: FileName, fileURL: URL(fileURLWithPath: localPath.replacingOccurrences(of: "file:///", with: "")), ossUploadID: uploadID, videoSource: videoSource)
-    }
-
-    /// 重新上传
-    /// - Parameters:
-    ///   - response: <#response description#>
-    ///   - localPath: <#localPath description#>
-    /// - Returns: <#description#>
-    public  func reloadTask(response: [String: Any]?, localPath: String?,videoSource:String? = nil) {
-        if response == nil {
-            return
-        }
-        let accessKeyId: String = "\(response?["AccessKeyId"] ?? "")"
-        let secretKeyId: String = "\(response?["AccessKeySecret"] ?? "")"
-        let securityToken: String = "\(response?["SecurityToken"] ?? "")"
-        let endpoint: String = "\(response?["Host"] ?? "")"
-        let bucketName: String = "\(response?["Bucket"] ?? "")"
-        let FileName: String = "\(response?["FileName"] ?? "")"
-        let uploadID: String = "\(response?["Upload"] ?? "")"
-        var endpoints: [String] = Array<String>.init()
-        if response?.keys.contains("Hosts") ?? false {
-            endpoints = response?["Hosts"] as! [String]
-            endpoints.append(endpoint)
-        }
-        debugPrint("取我方服务器STS 返回数据 \(String(describing: response))")
-        PQAliOssUtil.shared.PQOSSMultipartUpload(accessKeyId: accessKeyId, secretKeyId: secretKeyId, securityToken: securityToken, bucketName: bucketName, endpoints: endpoints, FileName: FileName, fileURL: URL(fileURLWithPath: (localPath ?? "").replacingOccurrences(of: "file:///", with: "")), ossUploadID: uploadID,videoSource: videoSource)
-    }
-
-    /// 分片上传
-    /// - Parameters:
-    ///   - accessKeyId: <#accessKeyId description#>
-    ///   - secretKeyId: <#secretKeyId description#>
-    ///   - securityToken: <#securityToken description#>
-    ///   - bucketName: <#bucketName description#>
-    ///   - endpoints: oss host域名
-    ///   - FileName: oss 资源地址
-    ///   - fileURL: 文件本地地址
-    ///   - ossUploadID: oss 上传ID
-    ///   - contentType: 文件类型
-    ///   - materialType: 素材类型
-    ///   - isMatarialUpload: 是否是素材上传
-    ///   - contentMD5: 素材内容MD5值 isMatarialUpload = true时传
-    ///   - width: 视频宽 isMatarialUpload = true时传
-    ///   - height: 视频高 isMatarialUpload = true时传
-    /// - Returns: <#description#>
-    public  func PQOSSMultipartUpload(accessKeyId: String, secretKeyId: String, securityToken: String, bucketName: String, endpoints: [String], FileName: String, fileURL: URL, ossUploadID: String, materialType: StickerType = .VIDEO, isMatarialUpload: Bool = false, contentMD5: String = "", width: CGFloat = 0, height: CGFloat = 0,videoSource:String? = nil) -> PQAliOssUtil {
-        debugPrint("上传数据 参数\n accessKeyId:\(accessKeyId)\n secretKeyId:\(secretKeyId)\n  securityToken:\(securityToken) \n bucketName:\(bucketName)\n endpoint:\(endpoints)\n FileName:\(FileName)")
-        if endpoints.count <= 0 || (endpoints.first?.count ?? 0) <= 0 {
-            debugPrint("endpoints 为空")
-            return .shared
-        }
-        #if DEBUG
-            // 打开 oss 日志
-            OSSLog.enable()
-        #endif
-
-        // 1,设置鉴权
-        let url = PQENVUtil.shared.longvideoapi + (isMatarialUpload ? materialUploadStsTokenUrl : getStsTokenUrl)
-        
-        let authServerUrl = url + "?appType=\(commonParams()["appType"] as? String ?? "")" + "&machineCode=" + getMachineCode()
-            + "&token=" + (BFConfig.shared.token ?? "") + "&loginUid" + (BFConfig.shared.uid ?? "") + "&fileType=2" + "&uploadId=\(ossUploadID)"
-        debugPrint("authServerUrl is: \(authServerUrl)")
-        debugPrint("当前上传authServerUrl线程:\(Thread.isMainThread) ")
-
-        let provider = OSSAuthCredentialProvider(authServerUrl: authServerUrl) { (data) -> Data? in
-            debugPrint("当前上传provider线程:\(Thread.isMainThread) ")
-            // 在 OSSModel 代码中解析有自己的格式 所以接收到我方服务器后的数据要进行二次处理 AccessKeyId 等信息
-            let str = String(data: data, encoding: .utf8)
-            let jsonDic = jsonStringToDictionary(str!)
-            var respDic: [String: Any] = [:]
-            if jsonDic?.keys.contains("code") ?? false, "\(jsonDic?["code"] ?? "")" == "0" {
-                respDic = [
-                    "StatusCode": "200",
-                    "AccessKeyId": (jsonDic?["data"] as? [String: Any])?["AccessKeyId"] ?? accessKeyId,
-                    "AccessKeySecret": (jsonDic?["data"] as? [String: Any])?["AccessKeySecret"] ?? secretKeyId,
-                    "SecurityToken": (jsonDic?["data"] as? [String: Any])?["SecurityToken"] ?? securityToken,
-                    "Expiration": (jsonDic?["data"] as? [String: Any])?["Expiration"] ?? securityToken,
-                ]
-            }
-            let proStr = dictionaryToJsonString(respDic as [String: Any])
-            debugPrint("处理后准备给 OSS SDK数据 \(String(describing: proStr))")
-            let decodedData = proStr?.data(using: .utf8)
-            if decodedData != nil {
-                return decodedData
-            }
-            return data
-        }
-
-        // 2 拼装 request
-        let request = OSSMultipartUploadRequest()
-        // add by ak  set  contect type . doc https://help.aliyun.com/knowledge_detail/39522.html
-        request.contentType = fileURL.absoluteString.mimeType() // 媒体类型
-        request.uploadingFileURL = fileURL
-        request.bucketName = bucketName
-        request.objectKey = FileName
-        // 根据文件大小 设置 part size
-        var fileSize: UInt64 = 0
-        do {
-            let attr = try FileManager.default.attributesOfItem(atPath: fileURL.relativePath)
-            fileSize = attr[FileAttributeKey.size] as! UInt64
-
-        } catch {
-            debugPrint("取文件大小 Error: \(error)")
-            if aliOssHander != nil {
-                DispatchQueue.main.async { [weak self] in
-                    self?.aliOssHander!(isMatarialUpload, materialType, fileURL.absoluteString.pathExtension, 260, FileName, contentMD5, width, height, 0, 0, nil, fileURL, nil, "文件已丢失")
-                }
-            }
-        }
-        debugPrint("文件已经存在  \(fileURL) 文件大小 \(fileSize)")
-        var partSize: Int = 0
-        // sdk中规定kClientMaximumOfChunks = 5000;
-        let defaultChunkSize: UInt64 = 1024 * 1024
-        if ceil(Float(fileSize / defaultChunkSize)) <= 1 {
-            partSize = 500 * 1024
-        } else if ceil(Float(fileSize / defaultChunkSize)) < 5000 {
-            partSize = Int(fileSize / UInt64(ceil(Float(fileSize / defaultChunkSize))))
-        } else {
-            partSize = Int(ceil(Float(fileSize / 5000)))
-        }
-        debugPrint("partSize \(partSize)")
-        // 除最后一片外 不能小于 102400(100kb)
-        request.partSize = UInt(partSize)
-        request.uploadId = ossUploadID
-        request.uploadProgress = { [weak self] (bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) -> Void in
-            debugPrint("当前上传uploadProgress线程:\(Thread.isMainThread) ")
-            self?.paraseSpeedAndRestTime(bytesSent: bytesSent, totalBytesSent: totalBytesSent, totalBytesExpectedToSend: totalBytesExpectedToSend) { uploadSpeed, resttime in
-                if self?.aliOssProgressHander != nil {
-                    DispatchQueue.main.async { [weak self] in
-                        self?.aliOssProgressHander!(bytesSent, totalBytesSent, totalBytesExpectedToSend, resttime, uploadSpeed)
-                    }
-                }
-            }
-            // 多个界面都要处理上传进度 所以使用通知 ? 通知有回到主线?
-            // postNotification(name: cOSSUploadFileProgress,userInfo: ["bytesSent":bytesSent,"totalBytesSent":totalBytesSent,"totalBytesExpectedToSend":totalBytesExpectedToSend,"resttime":resttime])
-        }
-
-        // 3,设置 config
-        let conf = OSSClientConfiguration()
-        conf.timeoutIntervalForRequest = 30 // 连接超时,默认15秒
-        conf.maxConcurrentRequestCount = 5 // 最大并发请求书,默认5个
-        conf.maxRetryCount = 3 // 失败后最大重试次数,默认2次
-        // 打开后台上传
-        conf.enableBackgroundTransmitService = true
-        conf.backgroundSesseionIdentifier = getUniqueId(desc: "\(ossUploadID)\(fileURL.absoluteString)\(FileName)")
-        // 4,设置 clinet
-        let client = OSSClient(endpoint: endpoints[0], credentialProvider: provider, clientConfiguration: conf)
-        if !isMatarialUpload {
-            allTasks[FileName] = request
-        }
-        // 5,发起任务
-        let task = client.multipartUpload(request)
-
-        task.continue ({ [weak self] (osstask) -> Any? in
-            debugPrint("当前上传线程:\(Thread.isMainThread) ")
-            if osstask.error == nil {
-                debugPrint("上传成功")
-                // 文件URL的格式为:BucketName.Endpoint/ObjectName。
-                debugPrint(" 上传成功注意使用时拼接域名 url == \(FileName)")
-                request.callbackParam = ["code": 1, "objectKey": FileName, "msg": "上传成功"]
-                DispatchQueue.main.async { [weak self] in
-                    if self?.aliOssHander != nil {
-                        self?.aliOssHander!(isMatarialUpload, materialType, fileURL.absoluteString.pathExtension, 1, FileName, contentMD5, width, height, 0, 0, nil, fileURL, nil, "上传成功")
-                    }
-                }
-                // 如果在后台发送上传成功的本地通知
-                if !isMatarialUpload {
-                    DispatchQueue.main.async {
-                        if UIApplication.shared.applicationState == .background {
-                            sendUploadNotification(isSuccess: true)
-                        }
-                    }
-                    postNotification(name: cUploadSuccessKey, userInfo: ["code": 1, "objectKey": FileName, "msg": "上传成功"])
-                }
-                // 上传完成
-                var extParams:Dictionary<String,Any>?
-                if videoSource != nil && (videoSource?.count ?? 0) > 0 {
-                    extParams = ["source":videoSource ?? ""]
-                }
-                BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_success, pageSource: nil,extParams: extParams, commonParams: commonParams())
-            } else {
-                debugPrint("上传失败 \(osstask.error!)")
-
-                request.callbackParam = ["code": (osstask.error! as NSError).code, "objectKey": FileName, "msg": osstask.error?.localizedDescription ?? ""]
-                if self?.aliOssHander != nil {
-                    DispatchQueue.main.async { [weak self] in
-                        self?.aliOssHander!(isMatarialUpload, materialType, fileURL.absoluteString.pathExtension, (osstask.error! as NSError).code, FileName, contentMD5, width, height, 0, 0, nil, fileURL, nil, osstask.error?.localizedDescription)
-                    }
-                }
-                // 如果在后台发送上传失败的本地通知
-                if !isMatarialUpload {
-                    DispatchQueue.main.async {
-                        if UIApplication.shared.applicationState == .background {
-                            sendUploadNotification(isSuccess: false)
-                        }
-                    }
-                }
-                // 上传失败
-                var extParams:Dictionary<String,Any>?
-                if videoSource != nil && (videoSource?.count ?? 0) > 0 {
-                    extParams = ["source":videoSource ?? ""]
-                }
-                BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_fail, pageSource: nil,extParams: extParams, commonParams: commonParams())
-            }
-            return nil
-        })
-        // 开始上传
-        var extParams:Dictionary<String,Any>?
-        if videoSource != nil && (videoSource?.count ?? 0) > 0 {
-            extParams = ["source":videoSource ?? ""]
-        }
-        BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_start, pageSource: nil,extParams: extParams, commonParams: commonParams())
-        return .shared
-    }
-
-    /// add by ak  简单上传方式 本方法支持后台运行 设置支持后台时会把 DATA
-    /// - Parameters:
-    ///   - accessKeyId: <#accessKeyId description#>
-    ///   - secretKeyId: <#secretKeyId description#>
-    ///   - securityToken: <#securityToken description#>
-    ///   - bucketName: <#bucketName description#>
-    ///   - endpoint: oss host域名
-    ///   - objectKey: oss 资源地址
-    ///   - fileURL: 文件本地地址
-    ///   - data: 文件数据
-    ///   - fileExtensions: 文件后缀名 mp4/mp3
-    ///   - enableBackground: 是否支持后台下载
-    ///   - materialType: 素材类型
-    ///   - isMatarialUpload: 是否是素材上传
-    ///   - contentMD5: 素材内容MD5值 isMatarialUpload = true时传
-    ///   - width: 视频宽 isMatarialUpload = true时传
-    ///   - height: 视频高 isMatarialUpload = true时传
-    ///   - duration: 素材时长 isMatarialUpload = true时传
-    ///   - frameNumber: gif素材帧数 isMatarialUpload = true时传
-    ///   - netResourceUrl: 网络素材地址 isMatarialUpload = true时传
-    /// - Returns: <#description#>
-    public  func putObjectAsync(accessKeyId: String, secretKeyId: String, securityToken: String, bucketName: String, endpoint: [String], objectKey: String, fileURL: URL?, data: Data?, fileExtensions: String, enableBackground: Bool, materialType: StickerType = .VIDEO, isMatarialUpload: Bool = false, contentMD5: String = "", width: CGFloat = 0, height: CGFloat = 0, duration: CGFloat, frameNumber: Int, netResourceUrl: String? = nil,videoSource:String? = nil) -> PQAliOssUtil {
-        #if DEBUG
-            OSSLog.enable()
-        #endif
-        debugPrint("普通上传数据 参数 accessKeyId:\(accessKeyId) secretKeyId:\(secretKeyId) securityToken:\(securityToken) bucketName:\(bucketName) endpoint:\(endpoint) objectKey:\(objectKey) enableBackground:\(enableBackground) fileURL : \(fileURL!)")
-        if endpoint.count <= 0 || (endpoint.first?.count ?? 0) <= 0 {
-            debugPrint("endpoints 为空")
-            return .shared
-        }
-        let provider = OSSStsTokenCredentialProvider(accessKeyId: accessKeyId, secretKeyId: secretKeyId, securityToken: securityToken)
-//            let configuration = OSSClientConfiguration()
-//            if enableBackground {
-//                configuration.enableBackgroundTransmitService = true
-//                configuration.backgroundSesseionIdentifier = objectKey
-//            }
-//            configuration.timeoutIntervalForRequest = 60 // 连接超时,默认15秒
-//            configuration.maxConcurrentRequestCount = 20 // 最大并发请求书,默认5个
-//            configuration.maxRetryCount = 3 // 失败后最大重试次数,默认2次
-        startClient(accessKeyId: accessKeyId, secretKeyId: secretKeyId, securityToken: securityToken, endpoint: endpoint.first ?? "")
-        let request = OSSPutObjectRequest()
-        if fileURL != nil {
-            request.uploadingFileURL = fileURL!
-            request.contentType = fileURL!.absoluteString.mimeType() // 媒体类型
-        } else if data != nil {
-            request.uploadingData = data!
-            request.contentType = materialType.mimeType() // 媒体类型
-        }
-        request.bucketName = bucketName
-        request.objectKey = objectKey
-        // request.contentMd5 = contentMD5
-        request.uploadProgress = { (bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) -> Void in
-            var resttime: Int64 = 0
-            if self.oldTime == 0 {
-                self.oldTime = Int(Date().timeIntervalSince1970)
-            }
-            let nowTime = Int(Date().timeIntervalSince1970)
-            let pertime = Int(nowTime - self.oldTime)
-            if pertime != 0 {
-                var speed = totalBytesSent / Int64(pertime) // 单位b/s
-                if speed != 0 {
-                    resttime = ((totalBytesExpectedToSend - totalBytesSent) / speed)
-
-                    var units = "b/s" // 单位名称
-                    if speed / 1024 > 1 {
-                        speed = speed / 1024
-                        units = "k/s"
-                    }
-                    if speed / 1024 > 1 {
-                        speed = speed / 1024
-                        units = "M/s"
-                    }
-                    debugPrint("上传速度: \(speed)\(units)   还剩时间 \(resttime)")
-                }
-            }
-            // 多个界面都要处理上传进度 所以使用通知 ? 通知有回到主线?
-            postNotification(name: cOSSUploadFileProgress, userInfo: ["bytesSent": bytesSent, "totalBytesSent": totalBytesSent, "totalBytesExpectedToSend": totalBytesExpectedToSend, "resttime": resttime])
-        }
-        let task = client?.putObject(request)
-        if fileURL?.absoluteString.contains("_noise_") ?? false {
-            task?.continue ({ [weak self] (osstask) -> Any? in
-                debugPrint("当前上传线程:\(Thread.isMainThread) ")
-                if osstask.error == nil {
-                    debugPrint("上传成功")
-                    // 文件URL的格式为:BucketName.Endpoint/ObjectName。
-                    debugPrint(" 上传成功注意使用时拼接域名 url == \(objectKey)")
-                    request.callbackParam = ["code": 1, "objectKey": objectKey, "msg": "上传成功"]
-                    DispatchQueue.main.async { [weak self] in
-                        if self?.aliOssHander != nil {
-                            self?.aliOssHander!(isMatarialUpload, materialType, fileExtensions, 1, objectKey, contentMD5, width, height, duration, frameNumber, netResourceUrl, fileURL, data, "上传成功")
-                        }
-                    }
-                    // 如果在后台发送上传成功的本地通知
-                    if !isMatarialUpload {
-                        DispatchQueue.main.async {
-                            if UIApplication.shared.applicationState == .background {
-                                sendUploadNotification(isSuccess: true)
-                            }
-                        }
-                        postNotification(name: cUploadSuccessKey, userInfo: ["code": 1, "objectKey": objectKey, "msg": "上传成功"])
-                    }
-                    // 上传完成
-                    var extParams:Dictionary<String,Any>?
-                    if videoSource != nil && (videoSource?.count ?? 0) > 0 {
-                        extParams = ["source":videoSource ?? ""]
-                    }
-                    // 上传完成
-                    BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_success, pageSource: nil,extParams: extParams, commonParams: commonParams())
-                } else {
-                    debugPrint("上传失败 \(osstask.error!)")
-                    request.callbackParam = ["code": (osstask.error! as NSError).code, "objectKey": objectKey, "msg": osstask.error?.localizedDescription ?? ""]
-                    if self?.aliOssHander != nil {
-                        DispatchQueue.main.async { [weak self] in
-                            self?.aliOssHander!(isMatarialUpload, materialType, fileExtensions, (osstask.error! as NSError).code, objectKey, contentMD5, width, height, duration, frameNumber, netResourceUrl, fileURL, data, osstask.error?.localizedDescription)
-                        }
-                    }
-                    // 如果在后台发送上传失败的本地通知
-                    if !isMatarialUpload {
-                        DispatchQueue.main.async {
-                            if UIApplication.shared.applicationState == .background {
-                                sendUploadNotification(isSuccess: false)
-                            }
-                        }
-                    }
-                    // 上传失败
-                    var extParams:Dictionary<String,Any>?
-                    if videoSource != nil && (videoSource?.count ?? 0) > 0 {
-                        extParams = ["source":videoSource ?? ""]
-                    }
-                    BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_fail, pageSource: nil,extParams: extParams, commonParams: commonParams())
-                }
-                return nil
-            }).waitUntilFinished()
-        } else {
-            task?.continue ({ [weak self] (osstask) -> Any? in
-                debugPrint("当前上传线程:\(Thread.isMainThread) ")
-                if osstask.error == nil {
-                    debugPrint("上传成功")
-                    // 文件URL的格式为:BucketName.Endpoint/ObjectName。
-                    debugPrint(" 上传成功注意使用时拼接域名 url == \(objectKey)")
-                    request.callbackParam = ["code": 1, "objectKey": objectKey, "msg": "上传成功"]
-                    DispatchQueue.main.async { [weak self] in
-                        if self?.aliOssHander != nil {
-                            self?.aliOssHander!(isMatarialUpload, materialType, fileExtensions, 1, objectKey, contentMD5, width, height, duration, frameNumber, netResourceUrl, fileURL, data, "上传成功")
-                        }
-                    }
-                    // 如果在后台发送上传成功的本地通知
-                    if !isMatarialUpload {
-                        DispatchQueue.main.async {
-                            if UIApplication.shared.applicationState == .background {
-                                sendUploadNotification(isSuccess: true)
-                            }
-                        }
-                        postNotification(name: cUploadSuccessKey, userInfo: ["code": 1, "objectKey": objectKey, "msg": "上传成功"])
-                    }
-                    // 上传完成
-                    var extParams:Dictionary<String,Any>?
-                    if videoSource != nil && (videoSource?.count ?? 0) > 0 {
-                        extParams = ["source":videoSource ?? ""]
-                    }
-                    BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_success, pageSource: nil,extParams: extParams, commonParams: commonParams())
-                } else {
-                    debugPrint("上传失败 \(osstask.error!)")
-                    request.callbackParam = ["code": (osstask.error! as NSError).code, "objectKey": objectKey, "msg": osstask.error?.localizedDescription ?? ""]
-                    if self?.aliOssHander != nil {
-                        DispatchQueue.main.async { [weak self] in
-                            self?.aliOssHander!(isMatarialUpload, materialType, fileExtensions, (osstask.error! as NSError).code, objectKey, contentMD5, width, height, duration, frameNumber, netResourceUrl, fileURL, data, osstask.error?.localizedDescription)
-                        }
-                    }
-                    // 如果在后台发送上传失败的本地通知
-                    if !isMatarialUpload {
-                        DispatchQueue.main.async {
-                            if UIApplication.shared.applicationState == .background {
-                                sendUploadNotification(isSuccess: false)
-                            }
-                        }
-                    }
-                    // 上传失败
-                    var extParams:Dictionary<String,Any>?
-                    if videoSource != nil && (videoSource?.count ?? 0) > 0 {
-                        extParams = ["source":videoSource ?? ""]
-                    }
-                    BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_fail, pageSource: nil,extParams: extParams, commonParams: commonParams())
-                }
-                return nil
-            })
-        }
-        return .shared
-    }
-
-    /// 取消某个任务
-    /// - Parameter objectKey: 任务唯一标识
-    public  func putObjectCancel(objectKey: String) {
-        for key in allTasks.keys {
-            if key == objectKey {
-                allTasks[key]!.cancel()
-                allTasks.removeValue(forKey: key)
-            }
-        }
-    }
-
-    /// 解析上传速度及剩余时间
-    /// - Parameters:
-    ///   - bytesSent: <#bytesSent description#>
-    ///   - totalBytesSent: <#totalBytesSent description#>
-    ///   - totalBytesExpectedToSend: <#totalBytesExpectedToSend description#>
-    ///   - complateHandle: <#complateHandle description#>
-    /// - Returns: <#description#>
-    public  func paraseSpeedAndRestTime(bytesSent _: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64, complateHandle: (_ uploadSpeed: String, _ resttime: Int64) -> Void) {
-        let newInterfaceBytes = PQBridgeObject.getInterfaceBytes()
-        var interfaceBytes = abs(newInterfaceBytes - lastInterfaceBytes)
-        if interfaceBytes <= 0 {
-            interfaceBytes = 1
-        }
-        lastInterfaceBytes = newInterfaceBytes
-        let resttime = (totalBytesExpectedToSend - totalBytesSent) / interfaceBytes
-        debugPrint("interfaceBytes = \(interfaceBytes),totalBytesExpectedToSend = \(totalBytesExpectedToSend),totalBytesSent = \(totalBytesSent),")
-        complateHandle("\(PQBridgeObject.formatNetWork(interfaceBytes))", resttime)
-    }
-
-    override private init() {
-        super.init()
-    }
-
-    public override func copy() -> Any {
-        return self
-    }
-
-    public override func mutableCopy() -> Any {
-        return self
-    }
-}

+ 0 - 484
BFStuckPointKit/Classes/BFUtils/PQSingletoRealmUtil.swift

@@ -1,484 +0,0 @@
-//
-//  PQSingletoRealmUtil.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/7/7.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import RealmSwift
-import UIKit
-import BFCommonKit
-import BFMediaKit
-import BFUIKit
-
-public class PQSingletoRealmUtil: NSObject {
-    public  var schemaVersion : UInt64 = 40
-    public var realmEntry: Realm? {
-        let config = Realm.Configuration(
-            schemaVersion: schemaVersion,
-            migrationBlock: { _, oldSchemaVersion in
-                if oldSchemaVersion < 1 {}
-            }
-        )
-        Realm.Configuration.defaultConfiguration = config
-        do {
-            let realmEntry = try Realm(configuration: config, queue: DispatchQueue.main)
-            return realmEntry
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-realm创建失败:\(error)")
-        }
-        return nil
-    }
-
-    public static let shared = PQSingletoRealmUtil()
-
-    // 根据不同的用户ID 初始化不同的数据库 th1
-    public func getDraftDB(uid: String) -> Realm {
-        let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
-        let dbPath = docPath.appending("/\(uid)Draft.realm")
-        BFLog(message: "生成登录人数据库地址\(dbPath)")
-
-        var config = Realm.Configuration(
-            schemaVersion: schemaVersion,
-            migrationBlock: { _, oldSchemaVersion in
-                if oldSchemaVersion < 1 {}
-            }
-        )
-        config.fileURL = URL(string: dbPath)!
-        let defaultRealm = try! Realm(configuration: config)
-        return defaultRealm
-    }
-
-    /// 写入单个数据
-    /// - Parameter objects: <#objects description#>
-    /// - Returns: <#description#>
-    public func saveObject(object: Object) {
-        do {
-            try realmEntry?.write {
-                realmEntry?.add(object, update: .modified)
-                BFLog(message: "Realm-添加单个数据成功:\(object)")
-            }
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-添加单个数据失败:\(error)")
-        }
-    }
-
-    /// 写入多个数据
-    /// - Parameter objects: <#objects description#>
-    /// - Returns: <#description#>
-    public func saveObjects(objects: [Object]) {
-        do {
-            try realmEntry?.write {
-                realmEntry?.add(objects, update: .modified)
-                BFLog(message: "Realm-添加多个数据成功:\(objects)")
-            }
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-添加多个数据失败:\(error)")
-        }
-    }
-
-    /// 写入本地存储数据
-    /// - Parameter objects: <#objects description#>
-    /// - Returns: <#description#>
-    public func saveLocalSaveObject(uniqueId: String, isSelected: Bool) {
-        let currentObject = queryLocalStoreObjects(uniqueId: uniqueId)
-        if (currentObject?.count ?? 0) > 0 {
-            do {
-                try realmEntry?.write {
-                    currentObject?.first?.isSelected = isSelected
-                    (currentObject?.first as? PQLocalStoreModel)?.currentDate = systemCurrentDate()
-                    BFLog(message: "Realm-本地已存储数据更新成功:\(currentObject)")
-                }
-            } catch let error as NSError {
-                // handle error
-                BFLog(message: "Realm-本地已存储数据更新失败:\(error)")
-            }
-        } else {
-            let storeObject = PQLocalStoreModel()
-            storeObject.uniqueId = uniqueId
-            storeObject.isSelected = isSelected
-            // 未存在则保存
-            BFLog(message: "Realm-本地数据未存储,开始存储")
-            saveObject(object: storeObject)
-        }
-    }
-
-    /// 查询本地缓存数据
-    /// - Returns: <#description#>
-    public func queryLocalStoreObjects(uniqueId: String) -> Results<BFBaseModel>? {
-        return queryObjects(PQLocalStoreModel.self, filter: "uniqueId == '\(uniqueId)'")
-    }
-
-    /// 查询所有未过期视频缓存数据
-    /// - Returns: description
-    public func queryVideoObjects() -> Results<BFBaseModel>? {
-        // "isSelected == false AND date >= \(Int(Date.init().timeIntervalSince1970) - 24 * 60)"
-        return queryObjects(PQVideoListModel.self, filter: "isSelected == false")
-    }
-
-    /// 删除已缓存视频数据
-    /// - Returns: <#description#>
-    public func deleteAllCacheObject() {
-        guard let deleteObjecs = realmEntry?.objects(PQVideoListModel.self) else {
-            BFLog(message: "Realm-删除已缓存为空")
-            return
-        }
-        do {
-            try realmEntry?.write {
-                realmEntry?.delete(deleteObjecs)
-                BFLog(message: "Realm-删除已缓存视频成功")
-            }
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
-        }
-    }
-
-    /// 根据条件查询数据
-    /// - Parameters:
-    ///   - type: 类型
-    ///   - filter: <#filter description#>
-    /// - Returns: <#description#>
-    public func queryObjects(_ type: BFBaseModel.Type, filter: String) -> Results<BFBaseModel>? {
-        let puppies = realmEntry?.objects(type).filter(filter)
-        BFLog(message: "查询已缓存数据:type = \(type) \(puppies ?? nil)")
-        return puppies
-    }
-
-    public func deleteObject() {
-        guard let deleteObjecs = realmEntry?.objects(PQVideoListModel.self).filter("isSelected == true") else { return }
-        do {
-            try realmEntry?.write {
-                realmEntry?.delete(deleteObjecs)
-                BFLog(message: "Realm-删除已缓存视频成功")
-            }
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
-        }
-    }
-
-    /// 删除
-    /// - Returns: <#description#>
-    public func deleteObject(object: PQVideoListModel) {
-        let videoId: Int = object.videoId
-        guard let deleteObjecs = realmEntry?.objects(PQVideoListModel.self).filter("videoId == \(videoId)") else { return }
-        do {
-            try realmEntry?.write {
-                realmEntry?.delete(deleteObjecs)
-                BFLog(message: "Realm-删除已缓存视频成功")
-            }
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
-        }
-    }
-
-    public func deleteObject(_ type: BFBaseModel.Type, filter: String) {
-        guard let deleteObjecs = queryObjects(type, filter: filter) else { return }
-        do {
-            try realmEntry?.write {
-                realmEntry?.delete(deleteObjecs)
-                BFLog(message: "Realm-删除已缓存视频成功")
-            }
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
-        }
-    }
-
-    /// 更新缓存视频是否读取过
-    /// - Parameter object: <#object description#>
-    /// - Returns: <#description#>
-    public func updateObject(object: PQVideoListModel) {
-        guard let newObject = realmEntry?.objects(PQVideoListModel.self).filter("videoId == \(object.videoId)") else { BFLog(message: "更新 newObject 为空")
-            return
-        }
-        BFLog(message: "更新 newObject = \(newObject)")
-        do {
-            try realmEntry?.write {
-                newObject.first?.isSelected = true
-                BFLog(message: "Realm-更新缓存视频已播放成功:\(newObject)")
-            }
-        } catch let error as NSError {
-            // handle error
-            BFLog(message: "Realm-更新缓存视频已播放失败:\(error)")
-        }
-    }
-
-    override private init() {
-        super.init()
-    }
-
-    override public func copy() -> Any {
-        return self
-    }
-
-    override public func mutableCopy() -> Any {
-        return self
-    }
-
-    // MARK: - add by ak 数据库操作 V2 方法
-
-    // MARK: add
-
-    /// 添加一个
-    ///
-    /// - Parameter object: 添加元素
-    public func realmAdd(realm: Realm, object: Object) {
-        try! realm.write {
-            realm.add(object, update: .modified)
-        }
-    }
-
-    /// 添加多个
-    ///
-    /// - Parameter objects: 添加数组
-    public func realmAdds(realm: Realm, objects: [Object]) {
-        try! realm.write {
-            realm.add(objects, update: .modified)
-        }
-    }
-
-    // MARK: delete
-
-    /// 删除一个
-    ///
-    /// - Parameter object: 删除元素
-    public func realmDelete(realm: Realm, object: Object) {
-        try! realm.write {
-            realm.delete(object)
-        }
-    }
-
-    /// 删除多个
-    ///
-    /// - Parameter objects: 元素数组
-    public func realmDeletes(realm: Realm, objects: [Object]) {
-        try! realm.write {
-            realm.delete(objects)
-        }
-    }
-
-    /// 条件删除
-    ///
-    /// - Parameters:
-    ///   - object: 元素类型
-    ///   - predicate: 条件
-    public func realmDeletesWithPredicate(realm: Realm, object: Object.Type, predicate: NSPredicate) {
-        let results: [Object] = realmQueryWithParameters(realm: realm, object: object, predicate: predicate)
-        if results.count > 0 {
-            try! realm.write {
-                realm.delete(results)
-            }
-        }
-    }
-
-    /// 删除该类型所有
-    ///
-    /// - Parameter object: 元素类型
-    public func realmDeleteTypeList(realm: Realm, object: Object.Type) {
-        let objListResults = realmQueryWithType(realm: realm, object: object)
-        if objListResults.count > 0 {
-            try! realm.write {
-                realm.delete(objListResults)
-            }
-        }
-    }
-
-    /// 删除当前数据库所有
-    public func realmDeleteAll(realm: Realm) {
-        try! realm.write {
-            realm.deleteAll()
-        }
-    }
-
-    // MARK: update
-
-    /// 更新元素(元素必须有主键)
-    ///
-    /// - Parameter object: 要更新的元素
-    public func realmUpdte(realm: Realm, object _: Object) {
-        try! realm.write {
-//             realm.up(object, update: true)
-        }
-    }
-
-    /// 更新元素集合(元素必须有主键)
-    ///
-    /// - Parameter objects: 元素集合(集合内元素所有属性都要有值)
-    public func realmUpdtes(realm: Realm, objects _: [Object]) {
-        try! realm.write {
-//             realm.add(objects, update: true)
-        }
-    }
-
-    /// 更新操作 -> 对于realm搜索结果集当中的元素,在action当中直接负值即可修改
-    ///
-    /// - Parameter action:操作
-    public func realmUpdateWithTranstion(realm: Realm, action: (Bool) -> Void) {
-        try! realm.write {
-            action(true)
-        }
-    }
-
-    // MARK: query
-
-    /// 查询元素
-    /// - Parameter type: 元素类型
-    /// - Parameter filter: 查询条件
-    public func reamlQueryObjects(realm: Realm, _ type: Object.Type, filter: String) -> Results<Object>? {
-        let puppies = realm.objects(type).filter(filter)
-        BFLog(message: "查询已缓存数据:type = \(type) \(puppies)")
-        return puppies
-    }
-
-    public func reamlQueryObjectsV2(realm: Realm, _ type: Object.Type, filter: String) -> String {
-        var json: String?
-        try! realm.write {
-            let puppies: Results<Object> = realm.objects(type).filter(filter)
-            BFLog(message: "查询已缓存数据:type = \(type) \(puppies)")
-            if puppies.count > 0 {
-                json = (puppies.first as? PQEditProjectModel)!.toJSONString(prettyPrint: false)
-            }
-        }
-
-        return json ?? ""
-    }
-
-    /// 查询元素
-    ///
-    /// - Parameters:
-    ///   - object: 元素类型
-    /// - Returns: 查询结果
-    public func realmQueryWith(realm: Realm, object: Object.Type) -> [Object] {
-        let results = realmQueryWithType(realm: realm, object: object)
-        var resultsArray = [Object]()
-        if results.count > 0 {
-            for i in 0...results.count - 1 {
-                resultsArray.append(results[i])
-            }
-        }
-        return resultsArray
-    }
-
-    /// 查询元素
-    ///
-    /// - Parameters:
-    ///   - object: 元素类型
-    ///   - predicate: 查询条件
-    /// - Returns: 查询结果
-    public func realmQueryWithParameters(realm: Realm, object: Object.Type, predicate: NSPredicate) -> [Object] {
-        let results = realmQueryWith(realm: realm, object: object, predicate: predicate)
-        var resultsArray = [Object]()
-        if results.count > 0 {
-            for i in 0...results.count - 1 {
-                resultsArray.append(results[i])
-            }
-        }
-        return resultsArray
-    }
-
-    /// 分页查询
-    ///
-    /// - Parameters:
-    ///   - object: 查询类型
-    ///   - fromIndex: 起始页
-    ///   - pageSize: 每页多少个
-    /// - Returns: 查询结果
-    public func realmQueryWithParametersPage(realm: Realm, object: Object.Type, fromIndex: Int, pageSize: Int) -> [Object] {
-        let results = realmQueryWithType(realm: realm, object: object)
-        var resultsArray = [Object]()
-        if results.count <= pageSize * (fromIndex - 1) || fromIndex <= 0 {
-            return resultsArray
-        }
-        if results.count > 0 {
-            for i in pageSize * (fromIndex - 1)...fromIndex * pageSize - 1 {
-                resultsArray.append(results[i])
-            }
-        }
-        return resultsArray
-    }
-
-    /// 条件排序查询
-    ///
-    /// - Parameters:
-    ///   - object: 查询类型
-    ///   - predicate: 查询条件
-    ///   - sortedKey: 排序key
-    ///   - isAssending: 是否升序
-    /// - Returns: 查询结果
-    public func realmQueryWithParametersAndSorted(realm: Realm, object: Object.Type, predicate: NSPredicate, sortedKey: String, isAssending: Bool) -> [Object] {
-        let results = realmQueryWithSorted(realm: realm, object: object, predicate: predicate, sortedKey: sortedKey, isAssending: isAssending)
-        var resultsArray = [Object]()
-        if results.count > 0 {
-            for i in 0...results.count - 1 {
-                resultsArray.append(results[i])
-            }
-        }
-        return resultsArray
-    }
-
-    ///  分页条件排序查询
-    ///
-    /// - Parameters:
-    ///   - object: 查询类型
-    ///   - predicate: 查询条件
-    ///   - sortedKey: 排序key
-    ///   - isAssending: 是否升序
-    ///   - fromIndex: 起始页
-    ///   - pageSize: 每页多少个
-    /// - Returns: 查询结果
-    public func realmQueryWithParametersAndSortedAndPaged(realm: Realm, object: Object.Type, predicate: NSPredicate, sortedKey: String, isAssending: Bool, fromIndex: Int, pageSize: Int) -> [Object] {
-        let results = realmQueryWithSorted(realm: realm, object: object, predicate: predicate, sortedKey: sortedKey, isAssending: isAssending)
-        var resultsArray = [Object]()
-
-        if results.count <= pageSize * (fromIndex - 1) || fromIndex <= 0 {
-            return resultsArray
-        }
-
-        if results.count > 0 {
-            for i in pageSize * (fromIndex - 1)...fromIndex * pageSize - 1 {
-                resultsArray.append(results[i])
-            }
-        }
-        return resultsArray
-    }
-
-    // MARK: private method
-
-    /// 按类型查询
-    ///
-    /// - Parameter object: 查询元素类型
-    /// - Returns: 查询结果
-    public func realmQueryWithType(realm: Realm, object: Object.Type) -> Results<Object> {
-        return realm.objects(object)
-    }
-
-    /// 条件查询
-    ///
-    /// - Parameters:
-    ///   - object: 查询元素类型
-    ///   - predicate: 查询条件
-    /// - Returns: 查询结果
-    public func realmQueryWith(realm: Realm, object: Object.Type, predicate: NSPredicate) -> Results<Object> {
-        return realm.objects(object).filter(predicate)
-    }
-
-    /// 条件排序查询
-    ///
-    /// - Parameters:
-    ///   - object: 查询类型
-    ///   - predicate: 查询条件
-    ///   - sortedKey: 排序key
-    ///   - isAssending: 是否升序
-    /// - Returns: 查询结果
-    public func realmQueryWithSorted(realm: Realm, object: Object.Type, predicate: NSPredicate, sortedKey: String, isAssending: Bool) -> Results<Object> {
-        return realm.objects(object).filter(predicate)
-            .sorted(byKeyPath: sortedKey, ascending: isAssending)
-    }
-}

+ 1 - 0
BFStuckPointKit/Classes/BFUtils/PQSingletoVideoPlayer.swift

@@ -10,6 +10,7 @@
 import BFCommonKit
 import UIKit
 import BFAnalyzeKit
+import BFUploadKit
 
 public class PQSingletoVideoPlayer: NSObject {
     public static let shared = PQSingletoVideoPlayer()

+ 6 - 5
BFStuckPointKit/Classes/Controller/PQStuckPointEditerController.swift

@@ -6,15 +6,16 @@
 //  Copyright © 2021 BytesFlow. All rights reserved.
 //  功能:卡点音乐编辑界面
 
+import Foundation
+import Photos
+import UIKit
+import ObjectMapper
+import RealmSwift
 import BFAnalyzeKit
 import BFCommonKit
 import BFUIKit
 import BFMediaKit
-import Foundation
-import ObjectMapper
-import Photos
-import RealmSwift
-import UIKit
+import BFUploadKit
 
 class PQStuckPointEditerController: BFBaseViewController {
     // 是否导出视频成功

+ 6 - 5
BFStuckPointKit/Classes/Controller/PQStuckPointPublicController.swift

@@ -6,16 +6,17 @@
 //  Copyright © 2021 BytesFlow. All rights reserved.
 //
 
-import Alamofire
-import BFCommonKit
-import BFUIKit
-import Kingfisher
-import ObjectMapper
 import Photos
 import UIKit
+import Alamofire
 import WechatOpenSDK
+import Kingfisher
+import ObjectMapper
+import BFCommonKit
+import BFUIKit
 import BFMediaKit
 import BFAnalyzeKit
+import BFUploadKit
 
 // mdf by ak 按 UI图 下方操作区的高度是固定的, 其它区高度和设备自适应
 public let bottomOprationBgViewHeight: CGFloat = 322.0

+ 0 - 26
BFStuckPointKit/Classes/Extensions/OperationQueue+Ext.swift

@@ -1,26 +0,0 @@
-//
-//  OperationQueue+Ext.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/12/8.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import Foundation
-
-// MARK: - 操作队列扩展
-
-/// 操作队列扩展
-extension OperationQueue {
-    convenience init(qualityOfService: QualityOfService = .default,
-                     maxConcurrentOperationCount: Int = OperationQueue.defaultMaxConcurrentOperationCount,
-                     underlyingQueue: DispatchQueue? = nil,
-                     name: String? = nil)
-    {
-        self.init()
-        self.qualityOfService = qualityOfService
-        self.maxConcurrentOperationCount = maxConcurrentOperationCount
-        self.underlyingQueue = underlyingQueue
-        self.name = name
-    }
-}

+ 0 - 39
BFStuckPointKit/Classes/Extensions/Task+Ext.swift

@@ -1,39 +0,0 @@
-//
-//  Task+Ext.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/12/8.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import Foundation
-
-// MARK: - URLSessionDataTask添加url跟taskId
-
-/// URLSessionDataTask添加url跟taskId
-
-private var taskId_key: Void?
-private var url_key: Void?
-private var pathExtension_key: Void?
-
-extension URLSessionTask {
-    /// 任务url
-    var taskUrl: String {
-        set {
-            objc_setAssociatedObject(self, &url_key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-        get {
-            return objc_getAssociatedObject(self, &url_key) as? String ?? ""
-        }
-    }
-
-    /// 任务唯一标示
-    var taskId: String {
-        set {
-            objc_setAssociatedObject(self, &taskId_key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-        get {
-            return objc_getAssociatedObject(self, &taskId_key) as? String ?? ""
-        }
-    }
-}

+ 0 - 182
BFStuckPointKit/Classes/Model/PQLoginUserInfo.swift

@@ -1,182 +0,0 @@
-//
-//  BFLoginUserInfo.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/5/27.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-
-// MARK: - 登录用户信息
-
-/// 登录用户信息s
-public class BFLoginUserInfo: NSObject {
-    static public let shared = BFLoginUserInfo()
-    public var uid: String = "" // 账号
-    public  var userCode: String = "" // 账号
-    public var accessToken: String = "" // token
-    public var avatarUrl: String = "" // 头像
-    public var city: String = "" // 城市
-    public var province: String = "" // 省市
-    public  var country: String = "" // 国家
-    public  var phoneNumber: String = "" // 电话
-    public var openId: String = "" // 微信openId
-    public var nickName: String = "" // 昵称
-    public var gender: String = "" // 性别
-    public var expiredTime: String = "" // 过期时间
-    public var videos: String = "0" // 视频数
-    public  var idols: String = "0" // 关注数
-    public var fans: String = "0" // 粉丝数
-    public var otherSubscribes: String = "0" // 别人订阅我的数量
-    public  var userStatus: String = "1" // 1有效,2 已删除,3 已屏蔽,4 敏感
-    public var isVirtualUser: Bool = false // 是否是虚拟账号
-    public  var mid = getMachineCode() // 设备ID
-
-    @objc  public  func toString() -> String {
-        let json: [String: Any] = [
-            "accessToken": accessToken,
-            "avatarUrl": avatarUrl,
-            "city": city,
-            "country": country,
-            "gender": gender,
-            "nickName": nickName,
-            "openId": openId,
-            "phoneNumber": phoneNumber,
-            "province": province,
-            "uid": uid,
-            "userCode": userCode,
-            "expiredTime": expiredTime,
-            "videos": videos,
-            "idols": idols,
-            "fans": fans,
-            "userStatus": userStatus,
-            "isVirtualUser": isVirtualUser,
-            "mid": mid,
-        ]
-        return dictionaryToJsonString(json) ?? ""
-    }
-
-    override public init() {
-        super.init()
-        resetData(isClear: false)
-        if getUserDefaults(key: cMineVideos) != nil {
-            videos = getUserDefaults(key: cMineVideos) as! String
-        }
-        if getUserDefaults(key: cMineIdols) != nil {
-            idols = getUserDefaults(key: cMineIdols) as! String
-        }
-        if getUserDefaults(key: cMineFans) != nil {
-            fans = getUserDefaults(key: cMineFans) as! String
-        }
-        if getUserDefaults(key: cOtherSubscribes) != nil {
-            otherSubscribes = getUserDefaults(key: cOtherSubscribes) as! String
-        }
-        if getUserDefaults(key: cAvatarUrl) != nil {
-            avatarUrl = getUserDefaults(key: cAvatarUrl) as! String
-        }
-        if getUserDefaults(key: cUpdatePhone) != nil {
-            phoneNumber = getUserDefaults(key: cUpdatePhone) as! String
-        }
-    }
-
-    @objc  public  func resetData(isClear: Bool) {
-        if isClear {
-            UserDefaults.standard.removeObject(forKey: cUserInfoStorageKey)
-            UserDefaults.standard.removeObject(forKey: cMineVideos)
-            UserDefaults.standard.removeObject(forKey: cMineFans)
-            UserDefaults.standard.removeObject(forKey: cOtherSubscribes)
-            UserDefaults.standard.removeObject(forKey: cMineIdols)
-            UserDefaults.standard.removeObject(forKey: cAvatarUrl)
-            UserDefaults.standard.removeObject(forKey: cUpdatePhone)
-            UserDefaults.standard.synchronize()
-
-            accessToken = ""
-            avatarUrl = ""
-            city = ""
-            country = ""
-            gender = ""
-            nickName = ""
-            openId = ""
-            phoneNumber = ""
-            province = ""
-            uid = ""
-            userCode = ""
-            expiredTime = ""
-            videos = "0"
-            idols = "0"
-            fans = "0"
-            userStatus = "1"
-            isVirtualUser = false
-            mid = ""
-            return
-        }
-        let userInfo: [String: Any] = jsonStringToDictionary(UserDefaults.standard.string(forKey: cUserInfoStorageKey) ?? "") ?? [:]
-        updateData(userInfo: userInfo)
-    }
-
-    public  func updateData(userInfo: [String: Any]?) {
-        if userInfo != nil, userInfo?.count ?? 0 > 0 {
-            accessToken = "\(userInfo?["accessToken"] ?? "")"
-            if userInfo?.keys.contains("token") ?? false {
-                accessToken = "\(userInfo?["token"] ?? "")"
-            }
-            avatarUrl = "\(userInfo?["avatarUrl"] ?? "")"
-            city = "\(userInfo?["city"] ?? "")"
-            country = "\(userInfo?["country"] ?? "")"
-            gender = "\(userInfo?["gender"] ?? "")"
-            nickName = "\(userInfo?["nickName"] ?? "")"
-            openId = "\(userInfo?["openId"] ?? "")"
-            if userInfo?.keys.contains("phoneNumber") ?? false, !(userInfo?["phoneNumber"] is NSNull) {
-                phoneNumber = "\(userInfo?["phoneNumber"] ?? "")"
-            }
-            if userInfo?.keys.contains("userStatus") ?? false, !(userInfo?["userStatus"] is NSNull) {
-                userStatus = "\(userInfo?["userStatus"] ?? "")"
-            }
-            if userInfo?.keys.contains("mid") ?? false, !(userInfo?["mid"] is NSNull) {
-                mid = "\(userInfo?["mid"] ?? "")"
-            }
-            if userInfo?.keys.contains("isVirtualUser") ?? false, !(userInfo?["isVirtualUser"] is NSNull) {
-                isVirtualUser = (userInfo?["isVirtualUser"] as? Bool) ?? false
-            }
-            province = "\(userInfo?["province"] ?? "")"
-            uid = "\(userInfo?["uid"] ?? "")"
-            userCode = "\(userInfo?["userCode"] ?? "")"
-            expiredTime = "\(userInfo?["expiredTime"] ?? "")"
-            if getUserDefaults(key: cMineVideos) != nil {
-                videos = getUserDefaults(key: cMineVideos) as! String
-            }
-            if getUserDefaults(key: cAvatarUrl) != nil {
-                avatarUrl = getUserDefaults(key: cAvatarUrl) as! String
-            }
-            if getUserDefaults(key: cUpdatePhone) != nil {
-                phoneNumber = getUserDefaults(key: cUpdatePhone) as! String
-            }
-            if getUserDefaults(key: cMineIdols) != nil {
-                idols = getUserDefaults(key: cMineIdols) as! String
-            }
-            if getUserDefaults(key: cMineFans) != nil {
-                fans = getUserDefaults(key: cMineFans) as! String
-            }
-            if getUserDefaults(key: cOtherSubscribes) != nil {
-                otherSubscribes = getUserDefaults(key: cOtherSubscribes) as! String
-            }
-            BFConfig.shared.token = accessToken
-            BFConfig.shared.loginUid = uid
-            BFConfig.shared.uid = uid
-        }
-    }
-
-    public  func isLogin() -> Bool {
-        return accessToken.count > 0
-    }
-
-    public override func copy() -> Any {
-        return self
-    }
-
-    public override func mutableCopy() -> Any {
-        return self
-    }
-}

+ 0 - 176
BFStuckPointKit/Classes/Model/PQUserInfoModel.swift

@@ -1,176 +0,0 @@
-//
-//  PQUserInfoModel.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/5/27.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-import BFUIKit
-
-open class PQUserInfoModel: BFBaseModel {
-    public  var avatarUrl: String? // 头像地址
-    public var backgroundImage: String? // 背景图
-
-    public var bothFollow: Bool = false // 是否相互关注
-    public var fans: Int = 0 // 粉丝数
-    public var followed: Int = 0 // 是否关注
-    public var idols: Int = 0 // 关注的人数
-    public var introduction: String?
-    public var nickName: String? // 昵称
-
-    public var otherVideoShowCount: Int = 0
-    public var playCountTotal: Int = 0 // 用户视频总播放数,按人去重 ,
-    public var playCountFormatStr: String? // 用户视频总播放数,格式化后的值,前端直接显示 ,
-    public var positionType: Int = 0
-    public var sensitiveStatus: Int = 0
-    public var subscribeStatus: Int = 0 // 0:未订阅,1:已订阅
-    public var mySubscribes: Int = 0 // 我的订阅数
-    public var otherSubscribes: Int = 0 // 别人订阅我的数量
-    public var uid: Int = 0
-    public var uploadDate: String?
-    public var userType: Int = 0
-    public var videos: Int = 0 // 视频数
-    public var videosDescr: String = "0" // 视频数
-    public var vipStatus: Int = 0 // vip状态,0:不是vip,1:是vip
-    public var vipDesc: String? // vip身份描述
-    public var tagList: [String]? // 标签
-    public var picPathList: [[String: Any]]? // 推荐列表
-    public var isLoginUser: Bool = false // 是否是登录用户
-    public var gmtCreateTimestamp: Int = 0
-    public var intimacy: Int = 0
-    public var isBothFollow: Int = 0 // 是否相互关注 ,
-    public var isFollowed: Bool = false // 是否关注
-    public var lastTimestamp: Int = 0
-    public var latestSendvideoId: Int = 0
-    public var updated: Int = 0
-    public var favoriteCount: Int = 0 // 喜欢的视频数
-    public var shareCount: Int = 0 // 分享的视频数
-    public var isBanned: Bool = false // 是否被拉黑
-    public var tab_pageType: TAB_PAGETYPE = .TAB_PAGETYPE_NORMAL // 0-推荐 1-关注
-
-    required public init() {
-        super.init()
-    }
-
-    public override init(jsonDict: [String: Any]) {
-        super.init()
-        if jsonDict.keys.contains("avatarUrl") {
-            avatarUrl = "\(jsonDict["avatarUrl"] ?? "")"
-        }
-        if jsonDict.keys.contains("bothFollow") {
-            bothFollow = Bool("\(jsonDict["bothFollow"] ?? "")") ?? false
-        }
-        if jsonDict.keys.contains("fans") {
-            fans = Int("\(jsonDict["fans"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("followed") {
-            followed = Int("\(jsonDict["followed"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("idols") {
-            idols = Int("\(jsonDict["idols"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("introduction") {
-            introduction = "\(jsonDict["introduction"] ?? "0")"
-        }
-        if jsonDict.keys.contains("nickName") {
-            nickName = "\(jsonDict["nickName"] ?? "0")"
-        }
-        if jsonDict.keys.contains("otherVideoShowCount") {
-            otherVideoShowCount = Int("\(jsonDict["otherVideoShowCount"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("playCountTotal") {
-            playCountTotal = Int("\(jsonDict["playCountTotal"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("playCountFormatStr") {
-            playCountFormatStr = "\(jsonDict["playCountFormatStr"] ?? "0")"
-        }
-        if jsonDict.keys.contains("positionType") {
-            positionType = Int("\(jsonDict["positionType"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("favoriteCount") {
-            favoriteCount = Int("\(jsonDict["favoriteCount"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("shareCount") {
-            shareCount = Int("\(jsonDict["shareCount"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("sensitiveStatus") {
-            sensitiveStatus = Int("\(jsonDict["sensitiveStatus"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("subscribeStatus") {
-            subscribeStatus = Int("\(jsonDict["subscribeStatus"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("mySubscribes") {
-            mySubscribes = Int("\(jsonDict["mySubscribes"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("otherSubscribes") {
-            otherSubscribes = Int("\(jsonDict["otherSubscribes"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("uid") {
-            uid = Int("\(jsonDict["uid"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("uploadDate") {
-            uploadDate = "\(jsonDict["uploadDate"] ?? "0")"
-        }
-        if jsonDict.keys.contains("userType") {
-            userType = Int("\(jsonDict["userType"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("videos") {
-            videos = Int("\(jsonDict["videos"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("videosDescr") {
-            videosDescr = "\(jsonDict["videosDescr"] ?? "")"
-        }
-        if jsonDict.keys.contains("vipStatus") {
-            vipStatus = Int("\(jsonDict["vipStatus"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("tagList") {
-            tagList = jsonDict["tagList"] as? [String]
-        }
-        if jsonDict.keys.contains("picPathList") {
-            picPathList = jsonDict["picPathList"] as? [[String: Any]]
-        }
-        if jsonDict.keys.contains("vipDesc") {
-            vipDesc = "\(jsonDict["vipDesc"] ?? "")"
-        }
-        if jsonDict.keys.contains("isLoginUser") {
-            isLoginUser = Bool("\(jsonDict["isLoginUser"] ?? "")") ?? false
-        }
-        if jsonDict.keys.contains("gmtCreateTimestamp") {
-            gmtCreateTimestamp = Int("\(jsonDict["gmtCreateTimestamp"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("intimacy") {
-            intimacy = Int("\(jsonDict["intimacy"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("isBothFollow") {
-            isBothFollow = Int("\(jsonDict["isBothFollow"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("isFollowed") {
-            isFollowed = jsonDict["isFollowed"] as! Bool
-        }
-        if jsonDict.keys.contains("lastTimestamp") {
-            lastTimestamp = Int("\(jsonDict["lastTimestamp"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("latestSendvideoId") {
-            latestSendvideoId = Int("\(jsonDict["latestSendvideoId"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("updated") {
-            updated = Int("\(jsonDict["updated"] ?? "0")") ?? 0
-        }
-    }
-
-    /// 创建虚拟用户数据
-    /// - Parameter virtual: <#virtual description#>
-   public init(avatarIcon: String?, userName: String?) {
-        super.init()
-        avatarUrl = avatarIcon
-        nickName = userName
-        fans = Int(arc4random() % 10)
-        followed = Int(arc4random() % 10)
-        idols = Int(arc4random() % 10)
-        mySubscribes = Int(arc4random() % 10)
-        otherSubscribes = Int(arc4random() % 10)
-    }
-}

+ 0 - 380
BFStuckPointKit/Classes/Model/PQVideoListModel.swift

@@ -1,380 +0,0 @@
-//
-//  PQRecommVideoModel.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/5/26.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import BFCommonKit
-import UIKit
-import BFUIKit
-import BFAnalyzeKit
-
-public class PQVideoListModel: BFBaseModel, BFVideoItemProtocol {
-    
-    @objc public required init() {
-        super.init()
-    }
-
-    public var id: UInt64 = 0
-    public var headVideoId: String? // 当前的相关推荐视频是属于哪个视频的相关推荐,值为那个头部视频的videoId
-    public var auditStatus: Int = 0 // 审核状态 1 审核中,2 不通过 3 待修改,4 自己可见 5 通过 ,
-    public var barrageCount: Int = 0 // 弹幕数量
-    public var barrageSwitch: Int = 0 // 是否打开弹幕 1打开 -1关闭 ,
-    public var auditReason: String? // 审核不通过或者待修改的原因
-    public var barrage: Any? // 弹幕集合
-    public var chargeDetail: [String: Any]? // 收费的相关信息
-    public var commentCount: Int = 0 // 评论数量
-    public var coverImg: [String: Any]? // 封面对象 ,
-    public var cutVoStr: String? // h5剪切板内容 ,
-    public var descr: String? // 视频简介 ,
-    public var encryption: Int = 0 // 是否加密视频:0是1不是 ,
-    public var favorited: Bool = false // 是否收藏 ,
-    public var favoriteds: Int = 0 //  收藏数 ,
-    public var fileExtensions: String? // 视频后缀 ,
-    public var firstPicture: Bool = false // 封面是否是第一帧,false不是true是 ,
-    public var gmtCreate: String? // 创建时间 ,
-    public var gmtCreateDescr: String? // 发视频时间描述 ,
-    public var gmtCreateTimestamp: Int = 0 // 创建时间戳 ,
-    public var gmtModifie: String? // 修改时间 ,
-    public var gmtModifiedTimestamp: Int = 0 // 修改时间戳 ,
-    public var h5ShareImgPath: String? // h5分享图URL ,
-    public var hasShareSpaceData: Bool = false // 是否有分享空间数据,
-    public var height: CGFloat = 0 // 视频高 ,
-    public var isRecommendShare: Int = 0 // 是否有分发推荐的封面和标题 1 有 0 无 传空或者不传默认为0,
-    public var lastTimestamp: Int = 0 // 时间戳 ,
-    //  liteVideoData (LiteVideoDataVO, optional): lite数据,
-    public var measure: Int = 0
-    public var measureId: Int = 0
-    public var measureType: Int = 0 // 0 非流量池 1曝光池2普通推荐测试池3待推荐测试池 ,
-    public var playBeforeDay: Int = 0 // 播放时间距离今天的天数 ,
-    public var playCount: Int = 0 // 播放次数 ,
-    public var playCountFormatStr: String? //  用户视频总播放数,格式化后的值,前端直接显示 ,
-    public var playCountTotal: Int = 0 // 总播放次数 ,
-    public var playTime: Int = 0 // 播放时间 ,
-    public var processShareHeadLab: [String: Any]? // 视频分享片尾数据 ,
-    public var processShareTailLab: [String: Any]? // 视频分享片尾数据 ,
-    public var pwd: String? // 视频密码 ,
-    public var recommendId: String? // 推荐链路ID ,
-    public var recommendSource: Int = 0 // 0 默认 1 第四范式
-    public var flowPool: String?
-    public var recommendStatus: Int = 0 // 推荐状态 ,
-    public var rotate: Int = 0 // 旋转角度 ,
-    public var sampleJobId: String?
-    public var sampleRequestId: String?
-    public var sampleTotalTime: Int = 0
-    public var sampleTranscodeStatus: Int = 0
-    public var sampleTransedVideoPath: String?
-    public var sendBeforeDay: Int = 0 // 发视频距离今天的天数 ,
-    public var sensitiveMsg: String? // 敏感提示信息 ,
-    public var sensitiveStatus: Int = 0 //  内容敏感状态(0:未检验,1:不敏感,2:敏感,3:敏感已审) ,
-    public var shareCount: Int = 0 // 分享到朋友圈次数 ,
-    // add by ak 个人中心里我分享的视频列表返回的参数 e.g. 78C10B44-6892-42A8-AE69-F1B35F9E676F-534530
-    public var shareId: String? // 分享的 ID
-    public var shareCountFriend: Int = 0 // 分享到微信好友 ,
-    public var shareImgPath: String? // 分享图URL ,
-    public var shareLinkType: Int = 0 // 分享到微信好友的图片的链接的类型 ,
-    public var sharePageType: Int = 0 // 0 综合模块 1 feed流 ,
-    public var shareTitle: String? // 分享到微信好友的图片的title ,
-    public var showHotRecommend: Bool = false // 是否需要显示热门推荐 ,
-    public var size: Int = 0 //  大小 ,
-    public var status: Int = 0 // 数据状态,1 有效,2 已删除,3 已屏蔽,4 关注可见,5 分享可见 6 自己可见 ,
-    public var tabShareImgPath: String? // 转发分享图URL ,
-    public var thumbnailImagePath: String? // 缩略图URL ,
-    public var totalTime: Int = 0 // 视频时长 ,
-    public var totalTimeParas: String? // 视频时长十分秒 ,
-    public var transcodeStatus: Int = 0 // 转码状态:1-不需转码 2-转码中 3-转码完成 4-转码失败 ,
-    public var transcodeVOList: [Any]? // 多码率数据 ,
-    public var uid: Int = 0 // 视频的用户ID ,
-    public var user: [String: Any]? //  用户对象 ,
-    public var userInfo: PQUserInfoModel? //  用户对象 ,
-    public var videoCollectionId: Int = 0 // 视频所在的视频集ID ,
-    public var videoCoverSnapshotPath: String? // 原始封面图片 ,
-    public var videoPath: String? // 视频地址 ,
-    public var videoURL: String? // 视频地址 ,
-    public var videoReportMeta: String? // 视频上报数据,上报时原样返回 ,
-    public var videoShareJumpModel: [String: Any]? // 分享页跳转的信息 ,
-    public var width: CGFloat = 0 // 视频宽
-    public var itemHeight: CGFloat = 0 // 个人中心cell高
-    public var originImageH: CGFloat = 0 // 原始图片的宽
-    public var originImageW: CGFloat = 0 // 原始图片的高
-    public var imageH: CGFloat = 0 // 图片的高
-    public var imageW: CGFloat = 0 // 图片的宽
-    public var titleH: CGFloat = 0 // 标题的高
-    public var descH: CGFloat = 0 // 描述的高
-    public var titleFontSize: CGFloat = 0 // add by ak 标题字号
-    public var usnameW: CGFloat = 0 // add by ak 用户名宽度
-    public var rotationH: CGFloat = 0 // add by ak 三个推荐视频高度包括标题
-    public var watchInfoH: CGFloat = 0 // add by ak watch info 高度
-    public var watchInfoY: CGFloat = 0 // add by ak watch info Y 值
-    public var relationData: [PQVideoListModel]?
-    public var playProgress: Float64 = 0 // 已播放时长
-    public var duration: Float64 = 0 // 视频总时长
-    public var tab_pageType: TAB_PAGETYPE = .TAB_PAGETYPE_NORMAL // 0-推荐 1-关注
-    public var pageSource: PAGESOURCE = .sp_category
-    public var isVerticality: Bool = false
-    public var isShareList: Bool = false // 是否是分享列表
-
-    public var funcH: CGFloat = cDefaultMargin * 33
-    public var funcW: CGFloat = cDefaultMargin * 5
-    public var uplpadImage: UIImage? // 上传的图片封面
-    public var uplpadBucketKey: String? // 上传视频地址
-    public var uplpadStatus: Int = 0 // 上传视频状态  1-上传中 2-上传完成 3-上传失败 4-发布中 4-发布完成
-    public var uplpadRequest: OSSMultipartUploadRequest?
-    public var stsToken: [String: Any]? // 上传信息
-    public var localPath: String? // 地址
-    public var progress: Float = 0
-    public var projectId: String? // 项目ID-发布创作的视频时必传,会在进入创作工具页时生成,以app_no_projectdata为前缀
-    public var reCreateVideoData: PQReCreateModel? // 再创作数据
-    // 视频创作埋点数据
-    public var eventTrackData: PQVideoMakeEventTrackModel?
-    public var autoType: autoType? // autoType 自动动作的类型
-    // add by ak 发布视频来源类型
-    public var videoFromScene: videoFromScene = .UploadNormal
-    // extParams: 额外参数-传入发布页 - 主要中秋红包塞活动使用
-    public var extParams:String = ""
-    // 视频分类
-    public var categoryName: String = ""
-    // 视频分类图
-    public var categoryImage: String?
-    // 话题信息
-    public var topicData: [String: Any]?
-    // 垂直方向是否自动播放下一个
-    public var isVerticalAutoPlayNext: Bool = false
-    // 是否上报过
-    public var isViewExposureReport: Bool = false
-    override public init(jsonDict: [String: Any]) {
-        super.init(jsonDict: jsonDict)
-        if jsonDict.keys.contains("id") {
-            id = UInt64("\(jsonDict["id"] ?? "")") ?? 0
-        }
-        if jsonDict.keys.contains("videoPath") {
-            videoPath = "\(jsonDict["videoPath"] ?? "")"
-            videoURL = videoPath
-            if videoPath?.contains(".m3u8") ?? false {
-                videoURL = videoPath?.components(separatedBy: "?").first
-            }
-        }
-        if jsonDict.keys.contains("videoCoverSnapshotPath") {
-            videoCoverSnapshotPath = "\(jsonDict["videoCoverSnapshotPath"] ?? "")"
-            if (videoCoverSnapshotPath?.count ?? 0) > 0, !(videoCoverSnapshotPath?.contains("http") ?? false) {
-                videoCoverSnapshotPath = "https://rescdn.yishihui.com/" + videoCoverSnapshotPath!
-            }
-        }
-        if jsonDict.keys.contains("thumbnailImagePath") {
-            thumbnailImagePath = "\(jsonDict["thumbnailImagePath"] ?? "")"
-        }
-        if jsonDict.keys.contains("rotate") {
-            rotate = Int("\(jsonDict["rotate"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("descr") {
-            descr = "\(jsonDict["descr"] ?? "")"
-            if descr != nil, (descr?.count ?? 0) > 2, descr?.hasSuffix("\n") ?? false {
-                descr = String(descr?.prefix((descr?.count ?? 2) - 2) ?? "")
-            }
-        }
-        if jsonDict.keys.contains("favorited") {
-            favorited = jsonDict["favorited"] as! Bool
-        }
-        if jsonDict.keys.contains("firstPicture") {
-            firstPicture = jsonDict["firstPicture"] as! Bool
-        }
-        if jsonDict.keys.contains("shareImgPath") {
-            shareImgPath = "\(jsonDict["shareImgPath"] ?? "")"
-        }
-        if jsonDict.keys.contains("coverImg") {
-            coverImg = jsonDict["coverImg"] as? [String: Any]
-        }
-        if jsonDict.keys.contains("user") {
-            user = jsonDict["user"] as? [String: Any]
-            userInfo = PQUserInfoModel(jsonDict: user!)
-        }
-        if jsonDict.keys.contains("topicData") {
-            topicData = jsonDict["topicData"] as? [String: Any]
-        }
-        if jsonDict.keys.contains("topicInfo") {
-            topicData = jsonDict["topicInfo"] as? [String: Any]
-        }
-        if jsonDict.keys.contains("shareCountFriend") {
-            shareCountFriend = Int("\(jsonDict["shareCountFriend"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("shareId") {
-            shareId = "\(jsonDict["shareId"] ?? "")"
-        }
-        if jsonDict.keys.contains("shareCount") {
-            shareCount = Int("\(jsonDict["shareCount"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("favoriteds") {
-            favoriteds = Int("\(jsonDict["favoriteds"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("uid") {
-            uid = Int("\(jsonDict["uid"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("lastTimestamp") {
-            lastTimestamp = Int("\(jsonDict["lastTimestamp"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("auditStatus") {
-            auditStatus = Int("\(jsonDict["auditStatus"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("status") {
-            status = Int("\(jsonDict["status"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("auditReason") {
-            auditReason = "\(jsonDict["auditReason"] ?? "")"
-        }
-        if jsonDict.keys.contains("transcodeStatus") {
-            transcodeStatus = Int("\(jsonDict["transcodeStatus"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("playCountTotal") {
-            playCountTotal = Int("\(jsonDict["playCountTotal"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("measure") {
-            measure = Int("\(jsonDict["measure"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("measureId") {
-            measureId = Int("\(jsonDict["measureId"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("measureType") {
-            measureType = Int("\(jsonDict["measureType"] ?? "0")") ?? 0
-        }
-        if jsonDict.keys.contains("playCountFormatStr") {
-            playCountFormatStr = "\(jsonDict["playCountFormatStr"] ?? "")"
-        }
-        if jsonDict.keys.contains("recommendId") {
-            recommendId = "\(jsonDict["recommendId"] ?? "")"
-        }
-        if jsonDict.keys.contains("abInfoData") {
-            abInfoData = "\(jsonDict["abInfoData"] ?? "")"
-        }
-        if jsonDict.keys.contains("flowPool") {
-            flowPool = "\(jsonDict["flowPool"] ?? "")"
-        }
-        if jsonDict.keys.contains("totalTime") {
-            totalTime = Int("\(jsonDict["totalTime"] ?? "0")") ?? 0
-            totalTimeParas = Float64(totalTime).formatDurationToHMS()
-        }
-        if jsonDict.keys.contains("width") {
-            width = CGFloat(Float("\(jsonDict["width"] ?? 0)") ?? 0)
-            if rotate > 0 {
-                originImageH = width
-            } else {
-                originImageW = width
-            }
-        }
-        if jsonDict.keys.contains("height") {
-            height = CGFloat(Float("\(jsonDict["height"] ?? 0)") ?? 0)
-            if rotate > 0 {
-                originImageW = height
-            } else {
-                originImageH = height
-            }
-        }
-        if jsonDict.keys.contains("produceProjectDataV2"), ((jsonDict["produceProjectDataV2"] as? [String: Any])?.keys.count ?? 0) > 0 {
-            reCreateVideoData = PQReCreateModel(jsonDict: jsonDict["produceProjectDataV2"] as! [String: Any])
-            if reCreateVideoData?.canReproduce == 1 {
-                funcH = funcH + cDefaultMargin * 7
-            }
-            reCreateVideoData?.videoId = uniqueId
-        }
-        if coverImg != nil, coverImg?.count ?? 0 > 0 {
-            imageW = cScreenWidth
-            imageH = imageW * originImageH / originImageW
-            isVerticality = originImageH > originImageW
-            if imageH > cScreenHeigth {
-                imageH = cScreenHeigth
-                imageW = imageH * originImageW / originImageH
-            }
-        }
-        // 计算个人中心高度
-        var tempTitleH: CGFloat = -cDefaultMargin
-        if title != nil, (title?.count ?? 0) > 0 {
-            tempTitleH = sizeWithText(text: title ?? "", font: UIFont.systemFont(ofSize: 16), size: CGSize(width: (cScreenWidth - cDefaultMargin * 3) / 2, height: cDefaultMargin * 4)).height
-        }
-        itemHeight = (cScreenWidth - cDefaultMargin * 3) / 2 * originImageH / originImageW + tempTitleH + cDefaultMargin * 4.5
-
-        if title != nil, (title?.count ?? 0) > 0 {
-            titleH = sizeWithText(text: title ?? "", font: UIFont.systemFont(ofSize: 26, weight: .medium), size: CGSize(width: cScreenWidth - cDefaultMargin * 2, height: CGFloat.greatestFiniteMagnitude)).height + cDefaultMargin
-        }
-        if titleH > 70 {
-            titleH = 70
-            titleFontSize = cScreenWidth <= 320 ? 19 : 21
-        } else {
-            titleFontSize = 25
-        }
-
-        BFLog(message: "title \(String(describing: title))   titleH :\(titleH)  titleFontSize :\(titleFontSize)")
-
-        var isFollowed: Bool = false
-
-        if tab_pageType == .TAB_PAGETYPE_RECOMM {
-            isFollowed = userInfo?.followed != 1
-        } else {
-            isFollowed = true
-        }
-
-        let attM: CGFloat = cDefaultMargin * 4.5
-        usnameW = sizeWithText(text: userInfo?.nickName ?? "", font: UIFont.systemFont(ofSize: 16, weight: .medium), size: CGSize(width: !isFollowed ? (cScreenWidth - cDefaultMargin * 8) : (cScreenWidth - cDefaultMargin * 9 - attM), height: cDefaultMargin * 2)).width + cDefaultMargin * 2
-
-        BFLog(message: "nickname is \(userInfo?.nickName ?? "") '    'usnameW is \(usnameW) isFollowed is \(isFollowed)")
-
-        updateReommendAgent()
-
-        watchInfoY = -cDefaultMargin
-
-        BFLog(message: "watchInfoY11111 is \(watchInfoY)")
-    }
-
-    public func updateReommendAgent() {
-        // 计算相关推荐高度
-        var itemH: CGFloat = 0
-        var verticality: Bool = false
-        var haveTitle: Bool = false
-        if (relationData?.count ?? 0) > 0 {
-            for item in (relationData)! {
-                if item.imageH > item.imageW {
-                    verticality = true
-                    break
-                }
-                BFLog(message: "item.title  \(String(describing: item.title))")
-                if item.title != nil, (item.title?.count ?? 0) > 0 {
-                    haveTitle = true
-                    break
-                }
-            }
-        }
-        itemH = verticality ? 130 : (haveTitle ? 90 : 55)
-        itemH = (relationData?.count ?? 0) > 0 ? itemH : 0
-
-        BFLog(message: "itemH is: \(itemH) sss \(String(describing: relationData?.count))")
-
-        rotationH = itemH
-        // 描述部分
-        if (relationData?.count ?? 0) > 0, tab_pageType != .TAB_PAGETYPE_ATTEN {
-            watchInfoY = (isVerticality ? -cDefaultMargin : -(cDefaultMargin * 2 + rotationH))
-        } else {
-            watchInfoY = -cDefaultMargin
-        }
-
-        BFLog(message: "watchInfoY2222 is \(watchInfoY)")
-
-        let nomalH: CGFloat = cDefaultMargin * 1.5
-//        let likeH: CGFloat = favoriteds <= 0 ? 0 : nomalH
-        let likeH: CGFloat = 0
-        watchInfoH = cDefaultMargin * 2 + nomalH + likeH + cDefaultMargin
-        if reCreateVideoData != nil, reCreateVideoData?.canReproduce == 1 {
-            watchInfoH = watchInfoH + ((reCreateVideoData?.rhythmMusicFlag != 1 && (reCreateVideoData?.parentVideoId != nil)) ? cDefaultMargin * 8 : 43)
-        }
-        if descr != nil, !(descr?.isEmpty ?? true) {
-            if Thread.isMainThread {
-                descH = sizeTextFits(attributedText: NSMutableAttributedString(string: descr ?? ""), text: nil, numberOfLines: 5, font: UIFont.systemFont(ofSize: 14), maxSize: CGSize(width: cScreenWidth - funcW - cDefaultMargin * 3, height: CGFloat.greatestFiniteMagnitude)).height
-                watchInfoH = watchInfoH + descH
-            } else {
-                DispatchQueue.main.async { [weak self] in
-                    self?.descH = sizeTextFits(attributedText: NSMutableAttributedString(string: (self?.descr)!), text: nil, numberOfLines: 5, font: UIFont.systemFont(ofSize: 14), maxSize: CGSize(width: cScreenWidth - (self?.funcW ?? 0) - cDefaultMargin * 3, height: CGFloat.greatestFiniteMagnitude)).height
-                    self?.watchInfoH = (self?.watchInfoH ?? 0) + (self?.descH ?? 0)
-                }
-            }
-        }
-    }
-}

+ 0 - 259
BFStuckPointKit/Classes/SelectImage/PQImageCropVC.swift

@@ -1,259 +0,0 @@
-//
-//  PQImageCropVC.swift
-//  PQSpeed
-//
-//  Created by ak on 2020/8/3.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-// add by ak 主要功能 图片裁剪界面
-// e.g.
-// let image = UIImage(named:"img.jpg")!
-// let vc = PQImageCropVC(frame: (self.navigationController?.view.frame)!, image: image, aspectWidth:9, aspectHeight: 16)
-
-import BFUIKit
-import UIKit
-import BFCommonKit
-
-class PQImageCropVC: BFBaseViewController, UIScrollViewDelegate {
-    var uploadData: PQUploadModel?
-    var updataVideoData: PQVideoListModel? // 如果updataVideoData不为空则为修改视频
-    var aspectW: CGFloat!
-    var aspectH: CGFloat!
-    var img: UIImage!
-
-    var imageView: UIImageView!
-    var scrollView: UIScrollView!
-
-    var holeRect: CGRect!
-    var gap: CGFloat = 100 // 距屏幕边缘距离
-
-    required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") }
-
-    init(image: UIImage, aspectWidth: CGFloat, aspectHeight: CGFloat) {
-        super.init(nibName: nil, bundle: nil)
-        aspectW = aspectWidth
-        aspectH = aspectHeight
-        img = image
-        BFLog(message: "原图大小 \(img.size) aspectW:\(aspectW!) aspectH:\(aspectH!)")
-    }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        setupView()
-    }
-
-    func setupView() {
-        let holeWidth = view.frame.width - gap
-        BFLog(message: "aspectH :\(String(describing: aspectH))")
-        var holeHeight = holeWidth * aspectH / aspectW
-        if holeHeight.isNaN {
-            holeHeight = 0
-        }
-        if img.imageOrientation != .up {
-            UIGraphicsBeginImageContextWithOptions(img.size, false, img.scale)
-            var rect = CGRect.zero
-            rect.size = img.size
-            img.draw(in: rect)
-            img = UIGraphicsGetImageFromCurrentImageContext()
-            UIGraphicsEndImageContext()
-        }
-
-        holeRect = CGRect(x: 0, y: view.frame.height / 2 - holeHeight / 2, width: holeWidth, height: holeHeight)
-
-        imageView = UIImageView(image: img)
-        scrollView = UIScrollView(frame: CGRect(x: gap / 2.0, y: 0, width: holeWidth, height: holeHeight))
-        scrollView.center = view.center
-        scrollView.addSubview(imageView)
-        scrollView.showsVerticalScrollIndicator = false
-        scrollView.showsHorizontalScrollIndicator = false
-        scrollView.alwaysBounceHorizontal = true
-        scrollView.alwaysBounceVertical = true
-        scrollView.delegate = self
-        view.addSubview(scrollView)
-
-        // 设置最小 zoom 是防止在裁剪区出现黑边导致裁剪后的图不对
-        let minZoom = max(holeWidth / img.size.width, holeHeight / img.size.height)
-        BFLog(message: "minZoom is: \(minZoom)")
-
-        scrollView.minimumZoomScale = minZoom
-        scrollView.maximumZoomScale = minZoom * 4
-        // 后设置自动缩放
-        scrollView.setZoomScale(minZoom, animated: false)
-        scrollView.clipsToBounds = false
-        scrollView.contentOffset = CGPoint(x: (img.size.width * minZoom - holeWidth) / 2, y: (img.size.height * minZoom - holeHeight) / 2)
-
-        // 添加 mark layer
-        let cropView = UIView(frame: view.frame)
-        cropView.isUserInteractionEnabled = false
-        view.addSubview(cropView)
-        let layer = CAShapeLayer()
-        let clipWidth = holeWidth
-        let clipHeight = holeHeight
-
-        let cropAreaX = (cScreenWidth - clipWidth) / 2
-        let cropAreaY = (cScreenHeigth - clipHeight) / 2
-        let cropAreaWidth = clipWidth
-        let cropAreaHeight = clipHeight
-        let cropframe = CGRect(x: cropAreaX, y: cropAreaY, width: cropAreaWidth, height: cropAreaHeight)
-
-        let path = UIBezierPath(roundedRect: cropView.frame, cornerRadius: 0)
-        let cropPath = UIBezierPath(rect: cropframe)
-
-        path.append(cropPath)
-        layer.path = path.cgPath
-        layer.fillRule = CAShapeLayerFillRule.evenOdd
-        layer.fillColor = UIColor.black.cgColor
-        layer.opacity = 0.5
-        layer.frame = cropView.bounds
-        cropView.layer.addSublayer(layer)
-        view.bringSubviewToFront(cropView)
-
-        // 单独画线
-        let drawLine = DrawLine()
-        drawLine.setCropAreaLeft(cropAreaLeft: cropAreaX, cropAreaTop: cropAreaY, cropAreaRight: cropAreaX + cropAreaWidth, cropAreaBottom: cropAreaY + cropAreaHeight)
-        drawLine.frame = cropView.bounds
-        cropView.layer.addSublayer(drawLine)
-        view.bringSubviewToFront(cropView)
-
-        // 添加下边工具条
-        view.addSubview(bottomView)
-
-        // 显示引导
-        let haveShowGuid = getUserDefaults(key: cIsShowImageCropGuid)
-        if haveShowGuid == nil {
-//            let guid = PQGuidClipView(frame: view.frame)
-//            view.addSubview(guid)
-//            saveUserDefaults(key: cIsShowImageCropGuid, value: cIsShowImageCropGuid)
-        }
-    }
-
-    lazy var bottomView: UIView = {
-        let bottomView = UIView(frame: CGRect(x: 0, y: cScreenHeigth - cDevice_iPhoneTabBarHei, width: cScreenWidth, height: cDevice_iPhoneTabBarHei))
-        let deleteBtn = UIButton(frame: CGRect(x: cDefaultMargin, y: 0, width: cDevice_iPhoneTabBarHei, height: cDevice_iPhoneTabBarHei))
-        bottomView.backgroundColor = BFConfig.shared.styleBackGroundColor
-        deleteBtn.setImage(imageInUIKit(by: "icon_detail_back"), for: .normal)
-        deleteBtn.addTarget(self, action: #selector(tappedClose), for: .touchUpInside)
-
-        bottomView.addSubview(deleteBtn)
-
-        let selecteBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: cDevice_iPhoneTabBarHei))
-        selecteBtn.setTitle("裁剪封面", for: .normal)
-        selecteBtn.setTitleColor(.black, for: .normal)
-        selecteBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
-
-        bottomView.addSubview(selecteBtn)
-        selecteBtn.center.x = bottomView.center.x
-
-        let nextBtn = UIButton(frame: CGRect(x: bottomView.frame.width - 100, y: (cDevice_iPhoneTabBarHei - 40) / 2, width: 80, height: 40))
-        nextBtn.addCorner(corner: 20)
-        nextBtn.setTitle("确定", for: .normal)
-        nextBtn.addTarget(self, action: #selector(tappedCrop), for: .touchUpInside)
-        nextBtn.setTitleColor(UIColor.white, for: .normal)
-        nextBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
-        nextBtn.backgroundColor = UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue)
-        bottomView.addSubview(nextBtn)
-
-        return bottomView
-    }()
-
-    // MARK: scrollView delegate
-
-    func viewForZooming(in _: UIScrollView) -> UIView? {
-        BFLog(message: "viewForZooming")
-        // 是imageView的容器,实现这个代理保证图片的放大拖动交互
-        return imageView
-    }
-
-    func scrollViewDidZoom(_ scrollView: UIScrollView) {
-        BFLog(message: "scrollViewDidZoom")
-        let gapToTheHole = scrollView.frame.height / 2 - holeRect.height / 2
-        scrollView.contentInset = UIEdgeInsets(top: gapToTheHole, left: 0, bottom: gapToTheHole, right: 0)
-    }
-
-    // 返回
-    @objc func tappedClose() {
-        BFLog(message: "返回")
-        // add by ak bugfix 图片超出 返回异常
-        navigationController?.popViewController(animated: true)
-    }
-
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        scrollView.isHidden = false
-    }
-
-    override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        scrollView.isHidden = true
-    }
-
-    // 裁剪
-    @objc func tappedCrop() {
-        BFLog(message: "开始裁剪图片")
-
-        // 根据scrollView缩放系数和偏移量 对原图进行裁剪
-        var imgX: CGFloat = 0
-        if scrollView.contentOffset.x > 0 {
-            imgX = scrollView.contentOffset.x / scrollView.zoomScale
-        }
-
-        let gapToTheHole: CGFloat = 0
-        var imgY: CGFloat = 0
-        if scrollView.contentOffset.y + 0 > 0 {
-            imgY = (scrollView.contentOffset.y + gapToTheHole) / scrollView.zoomScale
-        }
-
-        let imgW = holeRect.width / scrollView.zoomScale
-        let imgH = holeRect.height / scrollView.zoomScale
-
-        print("IMG x: \(imgX) y: \(imgY) w: \(imgW) h: \(imgH)")
-
-        let cropRect = CGRect(x: imgX, y: imgY, width: imgW, height: imgH)
-        let imageRef = img.cgImage!.cropping(to: cropRect)
-        let croppedImage = UIImage(cgImage: imageRef!)
-        //  这个方法是使用view 截屏
-        //  let croppedImage : UIImage = scrollView.graphicsGetImage() ?? img
-        BFLog(message: "croppedImage\(croppedImage.size)")
-
-        postNotification(name: cSelectedImageSuccessKey, userInfo: ["image": croppedImage])
-
-        let publicVideoVC = navigationController?.viewControllers.first(where: { (vc) -> Bool in
-            vc is PQStuckPointPublicController
-        })
-        if publicVideoVC != nil {
-            navigationController?.popToViewController(publicVideoVC!, animated: true)
-        } else {
-            navigationController?.popViewController(animated: true)
-        }
-    }
-}
-
-class DrawLine: CAShapeLayer {
-    var mCropAreaLeft: CGFloat = 0
-    var mCropAreaTop: CGFloat = 0
-    var mCropAreaRight: CGFloat = cScreenWidth
-    var mCropAreaBottom: CGFloat = 0
-
-    let mLineWidth: CGFloat = 7
-
-    func setCropAreaLeft(cropAreaLeft: CGFloat, cropAreaTop: CGFloat, cropAreaRight: CGFloat, cropAreaBottom: CGFloat) {
-        mCropAreaLeft = cropAreaLeft
-        mCropAreaTop = cropAreaTop
-        mCropAreaRight = cropAreaRight
-        mCropAreaBottom = cropAreaBottom
-
-        setNeedsDisplay()
-    }
-
-    override func draw(in ctx: CGContext) {
-        UIGraphicsPushContext(ctx)
-
-        ctx.setStrokeColor(UIColor.white.cgColor)
-        ctx.setLineWidth(mLineWidth)
-        ctx.addRect(CGRect(x: mCropAreaLeft, y: mCropAreaTop, width: mCropAreaRight - mCropAreaLeft, height: mCropAreaBottom - mCropAreaTop))
-        // 必和路径
-        ctx.strokePath()
-
-        UIGraphicsPopContext()
-    }
-}

+ 0 - 52
BFStuckPointKit/Classes/SelectImage/PQImageSelectedController.swift

@@ -1,52 +0,0 @@
-//
-//  PQImageSelectedController.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/8/14.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-import BFUIKit
-
-open class PQImageSelectedController: PQUploadController {
-    public var updataVideoData: PQVideoListModel? // 如果updataVideoData不为空则为修改视频
-    open override func viewDidLoad() {
-        super.viewDidLoad()
-        emptyData?.title = "哦呜~ 你没有可上传的图片~"
-        emptyData?.emptyImageName = "icon_authorError"
-        // Do any additional setup after loading the view.
-    }
-
-    @objc open override func btnClick(sender: UIButton) {
-        switch sender.tag {
-        case 1: // 返回
-            navigationController?.popViewController(animated: true)
-        case 2: // 筛选
-            showCollects()
-        case 3: // 下一步
-            if selectedData == nil {
-                cShowHUB(superView: nil, msg: "请选择图片")
-                return
-            }
-            PQPHAssetVideoParaseUtil.requestAssetOringinImage(asset: (selectedData?.asset)!) { [weak self] _, _, image, _ in
-                if image != nil {
-                    self?.selectedData?.image = image
-                }
-                self?.selectedData?.videoBucketKey = self?.uploadData?.videoBucketKey
-                let vc = PQImageCropVC(image: (self?.selectedData?.image)!, aspectWidth: self?.videoWidth ?? 0.0, aspectHeight: self?.videoHeight ?? 0.0)
-                self?.selectedData?.duration = self?.uploadData?.duration ?? 0.0
-
-                self?.selectedData?.localPath = self?.uploadData?.localPath
-                vc.uploadData = self?.selectedData
-                vc.updataVideoData = self?.updataVideoData
-                self?.navigationController?.pushViewController(vc, animated: true)
-            }
-        case 4: // 播放
-            break
-        default:
-            break
-        }
-    }
-}

+ 0 - 130
BFStuckPointKit/Classes/SelectImage/PQSelecteVideoItemCell.swift

@@ -1,130 +0,0 @@
-//
-//  PQSelecteVideoItemCell.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/8/1.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import Photos
-import UIKit
-import BFCommonKit
-import BFUIKit
-
-class PQSelecteVideoItemCell: UICollectionViewCell {
-    var representedAssetIdentifier: String!
-    lazy var videoImageView: UIImageView = {
-        let videoImageView = UIImageView()
-        videoImageView.contentMode = .scaleAspectFill
-        videoImageView.clipsToBounds = true
-        return videoImageView
-    }()
-
-    lazy var placeHoldeImageView: UIImageView = {
-        let placeHoldeImageView = UIImageView()
-        placeHoldeImageView.image = UIImage(named: "cut_place")
-        placeHoldeImageView.clipsToBounds = true
-        return placeHoldeImageView
-    }()
-
-    lazy var timeLab: UILabel = {
-        let timeLab = UILabel()
-        timeLab.font = UIFont.systemFont(ofSize: 11)
-        timeLab.textColor = UIColor.white
-        timeLab.text = "00:00"
-        return timeLab
-    }()
- 
-    lazy var seleImage: UIImageView = {
-        let seleImage = UIImageView(image:UIImage.moduleImage(named: "icon_upload_do", moduleName: "BFStuckPointKit",isAssets: false))
-        return seleImage
-    }()
-
-    lazy var bgView: UIView = {
-        let bgView = UIView()
-        bgView.backgroundColor = UIColor.init(red: 61.0 / 255.0 , green: 193.0 / 255.0 , blue: 193.0 / 255.0, alpha: 0.6)
-        return bgView
-    }()
-
-    @objc class func selecteVideoItemCell(collectionView: UICollectionView, indexPath: IndexPath) -> PQSelecteVideoItemCell {
-        let cell: PQSelecteVideoItemCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PQSelecteVideoItemCell", for: indexPath) as! PQSelecteVideoItemCell
-        return cell
-    }
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        contentView.addSubview(videoImageView)
-        videoImageView.addSubview(timeLab)
-        videoImageView.addSubview(placeHoldeImageView)
-        contentView.addSubview(bgView)
-        bgView.addSubview(seleImage)
-        bgView.isHidden = !isSelected
-    }
-
-    required init?(coder _: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    var uploadData: PQUploadModel? {
-        didSet {
-            addData()
-            addLayout()
-        }
-    }
-
-    var thubImage: UIImage? {
-        didSet {
-            addData()
-            videoImageView.image = thubImage
-            addLayout()
-        }
-    }
-
-    func addData() {
-        videoImageView.contentMode = uploadData?.contentMode ?? .scaleAspectFill
-        if uploadData?.contentMode == .scaleAspectFit {
-            addCorner(corner: 6)
-        } else {
-            addCorner(corner: 0)
-        }
-        if uploadData?.image != nil {
-            videoImageView.image = uploadData?.image
-        } else if uploadData?.imageUrl != nil, (uploadData?.imageUrl.count ?? 0) > 0 {
-            netImage(url: uploadData?.imageUrl ?? "", mainView: videoImageView)
-//        }else if(uploadData?.asset != nil){
-//            PQPHAssetVideoParaseUtil.requestAssetImage(asset: (uploadData?.asset)!, itemSize: CGSize.init(width: 0, height: 0)) { [weak self](image, info) in
-//                self?.videoImageView.image = image
-//            }
-        } else {
-            videoImageView.image = nil
-        }
-        timeLab.text = (uploadData?.asset?.duration ?? 0).formatDurationToHMS()
-        timeLab.isHidden = (uploadData?.asset?.duration ?? 0) <= 0.0
-        bgView.isHidden = !(uploadData?.isSelected ?? false)
-        videoImageView.backgroundColor = (((uploadData?.videoWidth ?? 0) < (uploadData?.videoHeight ?? 0)) || (uploadData?.image == nil && (uploadData?.imageUrl == nil || (uploadData?.imageUrl.count ?? 0) <= 0))) ? UIColor.hexColor(hexadecimal: "#212223") : UIColor.black
-        placeHoldeImageView.isHidden = !(uploadData?.image == nil && (uploadData?.imageUrl == nil || (uploadData?.imageUrl.count ?? 0) <= 0))
-    }
-
-    func addLayout() {
-        placeHoldeImageView.snp.remakeConstraints { make in
-            make.width.equalTo(28)
-            make.height.equalTo(24)
-            make.center.equalToSuperview()
-        }
-        videoImageView.snp.remakeConstraints { make in
-            make.top.bottom.left.right.equalToSuperview()
-        }
-        timeLab.snp.makeConstraints { make in
-            make.bottom.equalTo(videoImageView).offset(-cDefaultMargin / 2)
-            make.right.equalTo(videoImageView).offset(-cDefaultMargin / 2)
-        }
-        bgView.snp.makeConstraints { make in
-            make.size.equalToSuperview()
-        }
-        seleImage.snp.makeConstraints { make in
-            make.width.height.equalTo(23)
-            make.right.equalToSuperview().offset(-cDefaultMargin)
-            make.top.equalToSuperview().offset(cDefaultMargin)
-        }
-    }
-}

+ 0 - 993
BFStuckPointKit/Classes/SelectImage/PQUploadController.swift

@@ -1,993 +0,0 @@
-//
-//  PQUploadViewController.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/8/1.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import MobileCoreServices
-import Photos
-import UIKit
-import BFCommonKit
-import BFUIKit
-import BFAnalyzeKit
-
-let playerHeaderH: CGFloat = cScreenWidth * (250 / 375)
-
-open class PQUploadController: BFBaseViewController {
-    // 最大的宽度
-    public var maxWidth: CGFloat = cScreenWidth
-    // 最大的高度
-    public var maxHeight: CGFloat = adapterWidth(width: 300)
-    public var jumptoPublicHandle:((_ selectData:PQUploadModel?) -> Void)?
-    // 画面比例
-    public var aspectRatio: aspectRatio?
-    public var preViewSize: CGSize {
-        if aspectRatio == nil, (isMember(of: PQUploadController.self) && selectedData == nil) || (!isMember(of: PQUploadController.self) && uploadData == nil) {
-            return CGSize(width: maxHeight, height: maxHeight)
-        }
-        if selectedData != nil {
-            aspectRatio = .origin(width: CGFloat(videoData[lastSeletedIndex?.item ?? 0].videoWidth), height: CGFloat(videoData[lastSeletedIndex?.item ?? 0].videoHeight))
-        } else if aspectRatio == nil {
-            aspectRatio = .origin(width: CGFloat(uploadData?.videoWidth ?? maxHeight), height: CGFloat(uploadData?.videoHeight ?? maxHeight))
-        }
-        switch aspectRatio {
-        case let .origin(width, height):
-            var tempHeight: CGFloat = 0
-            var tempWidth: CGFloat = 0
-            if width > height {
-                tempHeight = (maxWidth * height / width)
-                tempWidth = maxWidth
-            } else {
-                tempHeight = maxHeight
-                tempWidth = (maxHeight * width / height)
-            }
-            if tempHeight.isNaN || tempWidth.isNaN {
-                return CGSize.zero
-            } else {
-                return CGSize(width: tempWidth, height: tempHeight)
-            }
-        case .oneToOne:
-            if maxWidth > maxHeight {
-                return CGSize(width: maxHeight, height: maxHeight)
-            } else {
-                return CGSize(width: maxWidth, height: maxWidth)
-            }
-        case .sixteenToNine:
-            return CGSize(width: maxWidth, height: maxWidth * 9.0 / 16.0)
-        case .nineToSixteen:
-            return CGSize(width: maxHeight * 9.0 / 16.0, height: maxHeight)
-        default:
-            break
-        }
-        return CGSize(width: maxHeight, height: maxHeight)
-    }
-
-    // 上传入口类型
-    public var sourceType: videoUploadSourceType = .videoUpload
-    // 制作视频项目Id
-    public var makeVideoProjectId: String?
-    // 再创作数据
-    public var reCreateData: PQReCreateModel?
-    // 视频创作埋点数据
-    public var eventTrackData: PQVideoMakeEventTrackModel?
-    // 制作视频草稿Id
-    public var makeVideoDraftboxId: String?
-    // 制作视频草稿结构化数据
-    public var makeVideoSdata: String?
-    public var isAssetImage: Bool = false // 是否请求的是图片
-    public var videoWidth: CGFloat = 0 // 视频宽
-    public var videoHeight: CGFloat = 0 // 视频高
-    public var isLoop: Bool = true // 是否循环播放
-    public var playerItem: AVPlayerItem? // 当前播放item
-    public var videoOutput: AVPlayerItemVideoOutput?
-    let itemSize = CGSize(width: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale, height: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale)
-    public var categoryH: CGFloat = cDefaultMargin * 40 // 相簿高度
-
-    public var videoData: [PQUploadModel] = Array<PQUploadModel>.init()
-
-    public var categoryData: [PQUploadModel] = Array<PQUploadModel>.init()
-
-    // 当前选中的数据
-    public var selectedData: PQUploadModel?
-    // 确定上传的数据
-    public var uploadData: PQUploadModel?
-    public var catagerySelectedIndex: IndexPath = IndexPath(item: 0, section: 0) // 更多图库选择
-
-    public var isJumpToAuthorization: Bool = false // 是否跳到授权
-    public var lastSeletedIndex: IndexPath? // 上次选中的index
-    public lazy var imageManager: PHCachingImageManager = {
-        (PHCachingImageManager.default() as? PHCachingImageManager) ?? PHCachingImageManager()
-    }()
-
-    public var allPhotos: PHFetchResult<PHAsset>!
-    public var previousPreheatRect = CGRect.zero
-
-    public var smartAlbums: PHFetchResult<PHAssetCollection>!
-    public var userCollections: PHFetchResult<PHCollection>!
-    public let sectionLocalizedTitles = ["", NSLocalizedString("Smart Albums", comment: ""), NSLocalizedString("Albums", comment: "")]
-    public lazy var fetchOptions: PHFetchOptions = {
-        let fetchOptions = PHFetchOptions()
-        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
-        fetchOptions.predicate = NSPredicate(format: "mediaType = %d", !isAssetImage ? PHAssetMediaType.video.rawValue : PHAssetMediaType.image.rawValue)
-        return fetchOptions
-    }()
-
-    public lazy var imagesOptions: PHImageRequestOptions = {
-        let imagesOptions = PHImageRequestOptions()
-        imagesOptions.isSynchronous = true
-        imagesOptions.isNetworkAccessAllowed = false
-        imagesOptions.deliveryMode = .opportunistic
-        imagesOptions.resizeMode = .fast
-        imagesOptions.progressHandler = { _, _, _, info in
-            BFLog(message: "progressHandler = \(info)")
-        }
-        return imagesOptions
-    }()
-
-    public lazy var singleImageOptions: PHImageRequestOptions = {
-        let singleImageOptions = PHImageRequestOptions()
-        singleImageOptions.isSynchronous = true
-        singleImageOptions.isNetworkAccessAllowed = false
-        singleImageOptions.deliveryMode = .highQualityFormat
-        return singleImageOptions
-    }()
-
-    public lazy var backBtn: UIButton = {
-        let backBtn = UIButton(type: .custom)
-        backBtn.frame = CGRect(x: 0, y: cDevice_iPhoneStatusBarHei, width: cDefaultMargin * 4, height: cDefaultMargin * 4)
-        backBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -5, right: 0)
-        backBtn.setImage(UIImage(named: "ic_close_black"), for: .normal)
-        backBtn.addTarget(self, action: #selector(backBtnClick), for: .touchUpInside)
-        return backBtn
-    }()
-
-    public var anthorEmptyData: BFEmptyModel? = {
-        let anthorEmptyData = BFEmptyModel()
-        anthorEmptyData.title = "开始上传"
-        anthorEmptyData.summary = "要开始上传视频,请先授予相册使用权限"
-        anthorEmptyData.emptyImageName = "icon_authorError"
-        return anthorEmptyData
-    }()
-
-    public var emptyData: BFEmptyModel? = {
-        let emptyData = BFEmptyModel()
-        emptyData.title = "哦呜~ 你没有可上传的视频~"
-        emptyData.emptyImageName = "video_empty"
-        return emptyData
-    }()
-
-    public lazy var emptyRemindView: BFEmptyRemindView = {
-        let emptyRemindView = BFEmptyRemindView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei))
-        emptyRemindView.isHidden = true
-        emptyRemindView.emptyData = anthorEmptyData
-        view.addSubview(emptyRemindView)
-        emptyRemindView.fullRefreshBloc = { [weak self, weak emptyRemindView] _, _ in
-            self?.isJumpToAuthorization = true
-            if emptyRemindView?.refreshBtn.currentTitle == "授予权限" {
-                openAppSetting()
-            }
-        }
-        return emptyRemindView
-    }()
-
-    public lazy var collectionView: UICollectionView = {
-        let layout = UICollectionViewFlowLayout()
-        layout.sectionInset = UIEdgeInsets.zero
-        let collectionView = UICollectionView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei), collectionViewLayout: layout)
-        collectionView.showsVerticalScrollIndicator = false
-        collectionView.register(PQSelecteVideoItemCell.self, forCellWithReuseIdentifier: "PQSelecteVideoItemCell")
-        collectionView.delegate = self
-        collectionView.dataSource = self
-        if #available(iOS 11.0, *) {
-            collectionView.contentInsetAdjustmentBehavior = .never
-        } else {
-            automaticallyAdjustsScrollViewInsets = false
-        }
-        collectionView.backgroundColor = UIColor.hexColor(hexadecimal: "#191919")
-        return collectionView
-    }()
-
-    public lazy var categoryCollectionView: UICollectionView = {
-        let layout = UICollectionViewFlowLayout()
-        layout.sectionInset = UIEdgeInsets.zero
-        let categoryCollectionView = UICollectionView(frame: CGRect(x: 0, y: -categoryH, width: cScreenWidth, height: categoryH), collectionViewLayout: layout)
-        categoryCollectionView.showsVerticalScrollIndicator = false
-        categoryCollectionView.register(PQAssetCategoryCell.self, forCellWithReuseIdentifier: "PQAssetCategoryCell")
-        categoryCollectionView.delegate = self
-        categoryCollectionView.dataSource = self
-        if #available(iOS 11.0, *) {
-            categoryCollectionView.contentInsetAdjustmentBehavior = .never
-        } else {
-            automaticallyAdjustsScrollViewInsets = false
-        }
-        categoryCollectionView.backgroundColor = BFConfig.shared.editCoverimageSelectedbackgroundColor
-        return categoryCollectionView
-    }()
-
-    public lazy var categoryView: UIView = {
-        let categoryView = UIView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei))
-        categoryView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
-        let bgView = UIView(frame: CGRect(x: 0, y: categoryH, width: categoryView.frame.width, height: categoryView.frame.height - categoryH))
-        let ges = UITapGestureRecognizer(target: self, action: #selector(cancelClick))
-        bgView.addGestureRecognizer(ges)
-        categoryView.addSubview(bgView)
-        categoryView.isHidden = true
-        return categoryView
-    }()
-
-    public lazy var avPlayer: AVPlayer = {
-        let avPlayer = AVPlayer()
-        NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: avPlayer.currentItem, queue: .main) { [weak self] notify in
-            BFLog(message: "AVPlayerItemDidPlayToEndTime = \(notify)")
-            avPlayer.seek(to: CMTime.zero)
-            if self?.isLoop ?? false, bf_getCurrentViewController()?.isMember(of: PQUploadController.self) ?? false {
-                if self?.playerLayer.superlayer == nil {
-                    self?.playerHeaderView.layer.insertSublayer(self!.playerLayer, at: 0)
-                }
-                avPlayer.play()
-            } else {
-                self?.sliderView.setValue(1.0, animated: false)
-                self?.playBtn.isHidden = false
-            }
-        }
-        NotificationCenter.default.addObserver(forName: .AVPlayerItemNewErrorLogEntry, object: avPlayer.currentItem, queue: .main) { notify in
-            BFLog(message: "AVPlayerItemNewErrorLogEntry = \(notify)")
-        }
-        NotificationCenter.default.addObserver(forName: .AVPlayerItemFailedToPlayToEndTime, object: avPlayer.currentItem, queue: .main) { notify in
-            BFLog(message: "AVPlayerItemFailedToPlayToEndTime = \(notify)")
-        }
-        NotificationCenter.default.addObserver(forName: .AVPlayerItemPlaybackStalled, object: avPlayer.currentItem, queue: .main) { notify in
-            BFLog(message: "AVPlayerItemPlaybackStalled = \(notify)")
-        }
-        avPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: .main) { [weak self] _ in
-            let progress = CMTimeGetSeconds(avPlayer.currentItem?.currentTime() ?? CMTime.zero) / CMTimeGetSeconds(avPlayer.currentItem?.duration ?? CMTime.zero)
-            self?.sliderView.setValue(Float(progress), animated: false)
-            if progress >= 1, !(self?.isLoop ?? false) {
-                self?.sliderView.setValue(Float(progress), animated: false)
-                self?.playBtn.isHidden = false
-            }
-        }
-        return avPlayer
-    }()
-
-    public lazy var playerLayer: AVPlayerLayer = {
-        let playerLayer = AVPlayerLayer(player: avPlayer)
-        playerLayer.frame = CGRect(origin: CGPoint.zero, size: preViewSize)
-        return playerLayer
-    }()
-
-    public lazy var sliderView: BFPlayerSlider = {
-        let sliderView = BFPlayerSlider(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei + maxHeight, width: view.frame.width, height: cDefaultMargin))
-        let thbImage = UIImage(named: "icon_point")
-        sliderView.setMinimumTrackImage(thbImage, for: .normal)
-        sliderView.setMaximumTrackImage(thbImage, for: .normal)
-        sliderView.setThumbImage(thbImage, for: .highlighted)
-        sliderView.setThumbImage(thbImage, for: .normal)
-        sliderView.maximumTrackTintColor = UIColor.clear
-        sliderView.addTarget(self, action: #selector(sliderValueDidChanged(sender:)), for: .valueChanged)
-        sliderView.minimumTrackTintColor = UIColor.white
-        sliderView.isHidden = true
-        sliderView.backgroundColor = UIColor.black
-        return sliderView
-    }()
-
-    public lazy var playBtn: UIButton = {
-        let playBtn = UIButton(type: .custom)
-        playBtn.frame = CGRect(x: (preViewSize.width - cDefaultMargin * 5) / 2, y: (preViewSize.height - cDefaultMargin * 5) / 2, width: cDefaultMargin * 5, height: cDefaultMargin * 5)
-        playBtn.setImage(UIImage(named: "icon_video_play_big"), for: .normal)
-        playBtn.tag = 4
-        playBtn.isHidden = true
-        playBtn.isUserInteractionEnabled = false
-        // playBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
-        return playBtn
-    }()
-
-    public var playerHeaderView: UIImageView = {
-        let playerHeaderView = UIImageView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: 0))
-        playerHeaderView.isUserInteractionEnabled = true
-        playerHeaderView.contentMode = .scaleAspectFit
-        playerHeaderView.clipsToBounds = true
-        playerHeaderView.backgroundColor = UIColor.black
-        return playerHeaderView
-    }()
-
-    public lazy var selecteBtn: UIButton = {
-        let selecteBtn = UIButton(frame: CGRect(x: deleteBtn.frame.maxX + cDefaultMargin, y: 0, width: cScreenWidth - nextBtn.frame.width - deleteBtn.frame.maxX - cDefaultMargin * 5, height: cDevice_iPhoneTabBarHei))
-        selecteBtn.titleLabel?.lineBreakMode = .byTruncatingTail
-        selecteBtn.setTitle("全部", for: .normal)
-        selecteBtn.setImage(UIImage(named: "icon_uploadVideo_more"), for: .normal)
-        selecteBtn.setTitleColor(UIColor.white, for: .normal)
-        selecteBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
-        selecteBtn.tag = 2
-        selecteBtn.imagePosition(at: .right, space: cDefaultMargin / 2)
-        selecteBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
-        return selecteBtn
-    }()
-
-    public lazy var deleteBtn: UIButton = {
-        let deleteBtn = UIButton(frame: CGRect(x: cDefaultMargin, y: 0, width: cDefaultMargin * 4, height: cDevice_iPhoneTabBarHei))
-        deleteBtn.setImage(UIImage(named: "upload_delete"), for: .normal)
-        deleteBtn.tag = 1
-        deleteBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
-        return deleteBtn
-    }()
-
-    public lazy var nextBtn: UIButton = {
-        let nextBtn = UIButton(frame: CGRect(x: 0, y: (cDevice_iPhoneTabBarHei - cDefaultMargin * 3) / 2, width: cDefaultMargin * 6, height: cDefaultMargin * 3))
-        nextBtn.addCorner(corner: 3)
-        nextBtn.setTitle("下一步", for: .normal)
-        nextBtn.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .medium)
-        nextBtn.tag = 3
-        nextBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
-        nextBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#333333")
-        nextBtn.setTitleColor(UIColor.hexColor(hexadecimal: "#999999"), for: .normal)
-        return nextBtn
-    }()
-
-    public lazy var bottomView: UIView = {
-        let bottomView = UIView(frame: CGRect(x: 0, y: cDefaultMargin * 2, width: cScreenWidth, height: cDevice_iPhoneNavBarHei))
-        bottomView.addSubview(selecteBtn)
-        bottomView.backgroundColor = UIColor.hexColor(hexadecimal: "#191919")
-        selecteBtn.center.y = nextBtn.center.y
-        bottomView.addSubview(deleteBtn)
-        bottomView.addSubview(nextBtn)
-        nextBtn.frame.origin.x = bottomView.frame.width - nextBtn.frame.width - cDefaultMargin * 2
-        return bottomView
-    }()
-
-    open override func viewDidLoad() {
-        super.viewDidLoad()
-
-        view.backgroundColor = BFConfig.shared.editCoverimageSelectedbackgroundColor
-        navHeadImageView?.backgroundColor = BFConfig.shared.editCoverimageSelectedbackgroundColor
-        lineView?.backgroundColor = BFConfig.shared.editCoverimageSelectedbackgroundColor
-        addSubViews()
-        bottomView.backgroundColor = BFConfig.shared.editCoverimageSelectedbackgroundColor
-        loadLocalData()
-    }
-
-    deinit {
-        //        PHPhotoLibrary.shared().unregisterChangeObserver(self)
-    }
-
-    open override func viewDidDisappear(_ animated: Bool) {
-        super.viewDidDisappear(animated)
-        if !isAssetImage {
-            avPlayer.pause()
-            playBtn.isHidden = false
-        }
-    }
-
-    open override func viewWillAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        if !isAssetImage {
-            if selectedData != nil {
-                playBtn.isHidden = true
-                if playerLayer.superlayer == nil {
-                    playerHeaderView.layer.insertSublayer(playerLayer, at: 0)
-                }
-                avPlayer.play()
-            }
-        }
-        addPlayerItemObserver()
-    }
-
-    open override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        removePlayerItemObserver()
-    }
-
-    open func addSubViews() {
-        view.addSubview(collectionView)
-        navHeadImageView?.addSubview(bottomView)
-        if !isAssetImage {
-            view.addSubview(playerHeaderView)
-            view.addSubview(sliderView)
-            let ges = UITapGestureRecognizer(target: self, action: #selector(playPreVideo))
-            playerHeaderView.addGestureRecognizer(ges)
-            playerHeaderView.addSubview(playBtn)
-            playerHeaderView.layer.insertSublayer(playerLayer, at: 0)
-        }
-        PQNotification.addObserver(self, selector: #selector(didBecomeActiveNotification), name: UIApplication.didBecomeActiveNotification, object: nil)
-    }
-
-    open func loadLocalData() {
-        let authStatus = PHPhotoLibrary.authorizationStatus()
-        if authStatus == .notDetermined {
-            // 第一次触发授权 alert
-            PHPhotoLibrary.requestAuthorization { [weak self] (status: PHAuthorizationStatus) -> Void in
-                if status == .authorized {
-                    if (self?.allPhotos == nil) || (self?.allPhotos.count ?? 0) <= 0 {
-                        self?.loadPhotoData()
-                    }
-                    if self?.backBtn != nil {
-                        self?.backBtn.removeFromSuperview()
-                    }
-                } else {
-                    DispatchQueue.main.async { [weak self] in
-                        self?.emptyRemindView.isHidden = false
-                        self?.emptyRemindView.refreshBtn.isHidden = false
-                        self?.emptyRemindView.refreshBtn.setTitle("授予权限", for: .normal)
-                        if self?.backBtn.superview == nil {
-                            self?.view.addSubview((self?.backBtn)!)
-                        } else {
-                            self?.backBtn.isHidden = false
-                        }
-                    }
-                }
-            }
-        } else if authStatus == .authorized {
-            if allPhotos == nil || allPhotos.count <= 0 {
-                loadPhotoData()
-            }
-            if backBtn.superview != nil {
-                backBtn.removeFromSuperview()
-            }
-
-        } else {
-            emptyRemindView.isHidden = false
-            emptyRemindView.refreshBtn.isHidden = false
-            emptyRemindView.refreshBtn.setTitle("授予权限", for: .normal)
-            if backBtn.superview == nil {
-                view.addSubview(backBtn)
-            } else {
-                backBtn.isHidden = false
-            }
-        }
-    }
-
-    open func loadPhotoData() {
-        DispatchQueue.main.async { [weak self] in
-            BFLoadingHUB.shared.showHUB(superView: self!.view, isVerticality: false)
-        }
-        DispatchQueue.global().async { [weak self] in
-            self?.allPhotos = PHAsset.fetchAssets(with: self?.fetchOptions)
-            DispatchQueue.main.async { [weak self] in
-                if self?.view != nil {
-                    BFLoadingHUB.shared.dismissHUB(superView: self!.view)
-                }
-                self?.collectionView.reloadData()
-                if (self?.allPhotos.count ?? 0) <= 0 {
-                    self?.emptyRemindView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei - cDevice_iPhoneTabBarHei)
-                    self?.emptyRemindView.emptyData = self?.emptyData
-                    self?.emptyRemindView.isHidden = false
-                } else {
-                    self?.emptyRemindView.isHidden = true
-                }
-                if (self?.allPhotos.count ?? 0) > 0 {
-                    let tempData = PQUploadModel()
-                    tempData.title = "全部"
-                    tempData.categoryList = self!.allPhotos
-                    self?.categoryData.insert(tempData, at: 0)
-                }
-                self?.updateCachedAssets()
-            }
-        }
-        PHPhotoLibrary.shared().register(self)
-
-        DispatchQueue.global().async { [weak self] in
-            self?.smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
-            self?.smartAlbums?.enumerateObjects { [weak self] assCollection, _, _ in
-                if assCollection.localizedTitle != "最近删除" {
-                    self?.convertCollection(collection: assCollection)
-                }
-            }
-            self?.userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
-            self?.userCollections.enumerateObjects { assCollection, index, point in
-                BFLog(message: "userCollections == \(assCollection),index = \(index),point = \(point)")
-                if assCollection is PHAssetCollection {
-                    if assCollection.localizedTitle != "最近删除" {
-                        self?.convertCollection(collection: assCollection as? PHAssetCollection)
-                    }
-                }
-            }
-        }
-        if !isAssetImage {
-            // 视频上传相关上报
-            BFEventTrackAdaptor.baseReportUpload(businessType: .bt_pageView, objectType: .ot_pageView, pageSource: .sp_upload_videoSelect, extParams: ["source": videoUploadSourceType.videoUpload.rawValue, "projectId": "", "draftboxId": ""],commonParams: commonParams())
-        }
-    }
-
-    // 转化处理获取到的相簿
-    open func convertCollection(collection: PHAssetCollection?) {
-        if collection == nil {
-            return
-        }
-        DispatchQueue.global().async { [weak self] in
-            let assetsFetchResult = PHAsset.fetchAssets(in: collection!, options: self?.fetchOptions)
-            if assetsFetchResult.count > 0 {
-                let tempData = PQUploadModel()
-                tempData.title = collection?.localizedTitle
-                tempData.categoryList = assetsFetchResult
-                if tempData.categoryList.count > 0 {
-                    self?.categoryData.append(tempData)
-                }
-                BFLog(message: "assetsFetchResult = \(assetsFetchResult)")
-            }
-        }
-    }
-
-    @objc open func btnClick(sender: UIButton) {
-        switch sender.tag {
-        case 1: // 返回
-            navigationController?.popViewController(animated: true)
-            if !isAssetImage {
-                // 视频上传相关上报
-                BFEventTrackAdaptor.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_up_backBtn, pageSource: .sp_upload_videoSelect, extParams: ["source": videoUploadSourceType.videoUpload.rawValue, "projectId": "", "draftboxId":""],commonParams: commonParams())
-            }
-        case 2: // 筛选
-            showCollects()
-        case 3: // 下一步
-            if selectedData == nil {
-                cShowHUB(superView: nil, msg: isAssetImage ? "请选择图片" : "请选择视频")
-                return
-            }
-            if !isAssetImage {
-                avPlayer.pause()
-                playBtn.isHidden = false
-                if jumptoPublicHandle != nil {
-                    uploadData?.videoFromScene = .UploadNormal
-                    jumptoPublicHandle!(selectedData)
-                }
-                // 视频上传相关上报
-                BFEventTrackAdaptor.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_up_nextBtn, pageSource: .sp_upload_videoSelect, extParams: ["source": videoUploadSourceType.videoUpload.rawValue, "projectId": "", "draftboxId": ""],commonParams: commonParams())
-                return
-            }
-            imageManager.requestImage(for: (selectedData?.asset)!, targetSize: itemSize, contentMode: .aspectFill, options: nil) { [weak self] image, _ in
-                self?.selectedData?.image = image
-                let vc = PQImageCropVC(image: (self?.selectedData?.image)!, aspectWidth: self?.videoWidth ?? 0.0, aspectHeight: self?.videoHeight ?? 0.0)
-                vc.uploadData = self?.selectedData
-                self?.navigationController?.pushViewController(vc, animated: true)
-            }
-        case 4: // 播放
-            playBtn.isHidden = true
-            if playerLayer.superlayer == nil {
-                playerHeaderView.layer.insertSublayer(playerLayer, at: 0)
-            }
-            avPlayer.play()
-        default:
-            break
-        }
-    }
-
-    @objc public func showCollects() {
-        if categoryData.count <= 0 {
-            return
-        }
-        categoryCollectionView.reloadData()
-        if categoryView.superview == nil {
-            view.insertSubview(categoryView, belowSubview: navHeadImageView!)
-            categoryView.addSubview(categoryCollectionView)
-            showCategoryView()
-            return
-        }
-        if categoryView.isHidden {
-            showCategoryView()
-        } else {
-            cancelClick()
-        }
-    }
-
-    @objc public func showCategoryView() {
-        categoryView.isHidden = false
-        categoryView.alpha = 0
-        view.bringSubviewToFront(categoryView)
-        view.bringSubviewToFront(bottomView)
-        UIView.animate(withDuration: 0.3, animations: {
-            self.categoryCollectionView.frame = CGRect(x: 0, y: 0, width: cScreenWidth, height: self.categoryH)
-            self.categoryView.alpha = 1
-        }) { _ in
-        }
-    }
-
-    @objc func cancelClick() {
-        UIView.animate(withDuration: 0.3, animations: {
-            self.categoryCollectionView.frame = CGRect(x: 0, y: -self.categoryH, width: cScreenWidth, height: self.categoryH)
-            self.categoryView.alpha = 0
-        }) { _ in
-            self.categoryView.isHidden = true
-        }
-    }
-
-    @objc open func playPreVideo() {
-        playBtn.isHidden = !playBtn.isHidden
-        if playBtn.isHidden {
-            if playerLayer.superlayer == nil {
-                playerHeaderView.layer.insertSublayer(playerLayer, at: 0)
-            }
-            avPlayer.play()
-        } else {
-            avPlayer.pause()
-        }
-    }
-
-    @objc func sliderValueDidChanged(sender: UISlider) {
-        avPlayer.seek(to: CMTime(value: CMTimeValue(sender.value * Float(CMTimeGetSeconds(avPlayer.currentItem?.duration ?? CMTime.zero))), timescale: 1))
-    }
-
-    @objc open func didBecomeActiveNotification() {
-        if isJumpToAuthorization {
-            loadLocalData()
-            isJumpToAuthorization = false
-        }
-    }
-
-    open func isPublishEnabled() {
-        if selectedData != nil {
-            nextBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#EE0051")
-            nextBtn.setTitleColor(UIColor.white, for: .normal)
-        } else {
-            nextBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#333333")
-            nextBtn.setTitleColor(UIColor.hexColor(hexadecimal: "#999999"), for: .normal)
-        }
-    }
-}
-
-extension PQUploadController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate {
-    open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection _: Int) -> Int {
-        if collectionView == self.collectionView {
-            return allPhotos == nil ? videoData.count : allPhotos.count
-        }
-        return categoryData.count
-    }
-
-    open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        if collectionView == self.collectionView {
-            let cell = PQSelecteVideoItemCell.selecteVideoItemCell(collectionView: collectionView, indexPath: indexPath)
-            if videoData.count <= indexPath.item, allPhotos != nil {
-                let itemData = PQUploadModel()
-                // itemData.image = UIImage.init(named: "cut_place")
-                let asset = allPhotos.object(at: indexPath.item)
-                itemData.asset = asset
-                itemData.duration = asset.duration
-                videoData.append(itemData)
-            }
-            if videoData.count > indexPath.item {
-                let itemData = videoData[indexPath.item]
-                cell.uploadData = itemData
-                if itemData.image == nil, itemData.asset != nil {
-                    cell.representedAssetIdentifier = itemData.asset?.localIdentifier
-                    imageManager.requestImage(for: itemData.asset!, targetSize: itemSize, contentMode: .aspectFill, options: nil) {[weak self, weak cell] image, info in
-                        if info?.keys.contains("PHImageResultIsDegradedKey") ?? false, "\(info?["PHImageResultIsDegradedKey"] ?? "0")" == "0", cell?.representedAssetIdentifier == itemData.asset?.localIdentifier {
-                            if image != nil {
-                                itemData.image = image
-                                cell?.videoImageView.image = image
-                            } else if image == nil, info?.keys.contains("PHImageResultIsInCloudKey") ?? false {
-                                let option = PHImageRequestOptions()
-                                option.isNetworkAccessAllowed = true
-                                option.resizeMode = .fast
-                                self?.imageManager.requestImageData(for: itemData.asset!, options: option) {[weak cell] data, _, _, _ in
-                                    if data != nil {
-                                        let image = UIImage(data: data!)
-                                        itemData.image = image
-                                        cell?.videoImageView.image = image
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            } else {
-                cell.uploadData = PQUploadModel()
-            }
-            return cell
-        } else {
-            let cell = PQAssetCategoryCell.assetCategoryCell(collectionView: collectionView, indexPath: indexPath)
-            let itemData = categoryData[indexPath.item]
-            let asset = itemData.categoryList.object(at: 0)
-            if itemData.image == nil {
-                cell.representedAssetIdentifier = asset.localIdentifier
-                imageManager.requestImage(for: asset, targetSize: itemSize, contentMode: .aspectFill, options: nil) {[weak cell] image, info in
-                    if info?.keys.contains("PHImageResultIsDegradedKey") ?? false, "\(info?["PHImageResultIsDegradedKey"] ?? "0")" == "0", cell?.representedAssetIdentifier == asset.localIdentifier {
-                        itemData.image = image
-                        cell?.uploadData = itemData
-                    }
-                }
-            } else {
-                cell.uploadData = itemData
-            }
-            cell.isSelected = indexPath == catagerySelectedIndex
-            return cell
-        }
-    }
-
-    open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        if collectionView == self.collectionView {
-            if videoData.count <= indexPath.item {
-                return
-            }
-            let itemData = videoData[indexPath.item]
-            if !isAssetImage, (itemData.asset?.duration ?? 0) < 5.0 {
-                cShowHUB(superView: nil, msg: "请选择大于5s的视频")
-                return
-            }
-            let ratio = Float(itemData.asset?.pixelWidth ?? 0) / Float(itemData.asset?.pixelHeight ?? 1)
-            if ratio < 0.4 || ratio > 4.2 {
-                cShowHUB(superView: nil, msg: "暂不支持该比例的素材")
-                return
-            }
-            if lastSeletedIndex != nil, lastSeletedIndex != indexPath {
-                let lastData = videoData[lastSeletedIndex!.item]
-                lastData.isSelected = false
-                collectionView.reloadItems(at: [lastSeletedIndex!])
-            }
-            lastSeletedIndex = indexPath
-            if itemData.isSelected {
-                itemData.isSelected = false
-                selectedData = nil
-                if !isAssetImage {
-                    avPlayer.pause()
-                    playBtn.isHidden = false
-                    sliderView.isHidden = true
-                    UIView.animate(withDuration: 0.5, animations: { [weak self] in
-                        self?.playerHeaderView.frame = CGRect(x: 0, y: -(self?.preViewSize.height ?? 0) - cDevice_iPhoneNavBarAndStatusBarHei, width: self?.preViewSize.width ?? 0, height: self?.preViewSize.height ?? 0)
-                        self?.sliderView.frame.origin.y = self?.playerHeaderView.frame.maxY ?? 0
-                        self?.playerHeaderView.center.x = self?.view.center.x ?? 0
-                        self?.collectionView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei)
-                    }) { _ in
-                    }
-                }
-            } else {
-                itemData.isSelected = true
-                let itemData = videoData[indexPath.item]
-                if !isAssetImage {
-                    selectedData = nil
-                    sliderView.setValue(0, animated: false)
-                    // 加载中...
-                    BFLoadingHUB.shared.showHUB(superView: playerHeaderView)
-                    avPlayer.pause()
-                    avPlayer.replaceCurrentItem(with: nil)
-                    playerLayer.removeFromSuperlayer()
-                    PQPHAssetVideoParaseUtil.parasToAVPlayerItem(phAsset: itemData.asset!, isHighQuality: true) { [weak self] playerItem, fileSize, info in
-                        if playerItem == nil || fileSize > maxUploadSize {
-                            if fileSize > maxUploadSize {
-                                cShowHUB(superView: nil, msg: "请选择小于10G的视频")
-                            } else {
-                                cShowHUB(superView: nil, msg: (info != nil && (info?.keys.contains("PHImageResultIsInCloudKey") ?? false) && "\(info?["PHImageResultIsInCloudKey"] ?? "1")" == "1") ? "暂不支持iCloud中的视频" : "此视频已损坏或已删除无法播放")
-                            }
-                            self?.videoData[(self?.lastSeletedIndex?.item)!].isSelected = false
-                            self?.collectionView.reloadItems(at: [(self?.lastSeletedIndex)!])
-                            self?.lastSeletedIndex = nil
-                            self?.selectedData = nil
-                            DispatchQueue.main.async { [weak self] in
-                                self?.sliderView.isHidden = true
-                                if (self?.playerHeaderView.frame.minY ?? 0.0) >= 0.0 {
-                                    UIView.animate(withDuration: 0.5, animations: { [weak self] in
-                                        self?.playerHeaderView.frame = CGRect(x: 0, y: -(self?.preViewSize.height ?? 0) - cDevice_iPhoneNavBarAndStatusBarHei, width: self?.preViewSize.width ?? 0, height: self?.preViewSize.height ?? 0)
-                                        self?.sliderView.frame.origin.y = self?.playerHeaderView.frame.maxY ?? 0
-                                        self?.playerHeaderView.center.x = self?.view.center.x ?? 0
-                                        self?.collectionView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei)
-                                    }) { _ in
-                                    }
-                                }
-                            }
-                            // 加载中...
-                            if self?.playerHeaderView != nil {
-                                BFLoadingHUB.shared.dismissHUB(superView: (self?.playerHeaderView)!)
-                            }
-                            return
-                        }
-                        DispatchQueue.main.async { [weak self] in
-                            self?.selectedData = itemData
-                            self?.selectedData?.localPath = (playerItem?.asset as! AVURLAsset).url.absoluteString
-                            self?.selectedData?.duration = (playerItem?.asset as! AVURLAsset).duration.seconds
-                            // 移除监听
-                            self?.removePlayerItemObserver()
-                            self?.playerItem = playerItem
-                            // 添加监听
-                            self?.addPlayerItemObserver()
-                            self?.playBtn.isHidden = true
-                            self?.avPlayer.replaceCurrentItem(with: playerItem)
-                            if self?.playerLayer.superlayer == nil {
-                                self?.playerHeaderView.layer.insertSublayer(self!.playerLayer, at: 0)
-                            }
-                            self?.avPlayer.play()
-//                            self?.playerHeaderView.image = itemData.image
-
-                            let tracks = (playerItem?.asset as? AVURLAsset)?.tracks(withMediaType: .video)
-                            if tracks != nil, (tracks?.count ?? 0) > 0 {
-                                let videoTrack = tracks?.first
-                                let transform = videoTrack?.preferredTransform
-                                let width: CGFloat = CGFloat(transform?.a ?? 0.0) * CGFloat(videoTrack?.naturalSize.width ?? 0.0) + CGFloat(transform?.c ?? 0.0) * CGFloat(videoTrack?.naturalSize.height ?? 0.0)
-                                let height: CGFloat = CGFloat(transform?.b ?? 0.0) * CGFloat(videoTrack?.naturalSize.width ?? 0.0) + CGFloat(transform?.d ?? 0.0) * CGFloat(videoTrack?.naturalSize.height ?? 0.0)
-                                self?.selectedData?.videoWidth = abs(width)
-                                self?.selectedData?.videoHeight = abs(height)
-                            } else {
-                                self?.selectedData?.videoWidth = CGFloat(self?.selectedData?.asset?.pixelWidth ?? 0)
-                                self?.selectedData?.videoHeight = CGFloat(self?.selectedData?.asset?.pixelHeight ?? 0)
-                            }
-                            self?.isPublishEnabled()
-                            self?.playerHeaderView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: self?.preViewSize.width ?? 0, height: self?.preViewSize.height ?? 0)
-                            if self?.playerHeaderView != nil {
-                                BFLoadingHUB.shared.showHUB(superView: (self?.playerHeaderView)!)
-                            }
-                            self?.playerHeaderView.center.x = self?.view.center.x ?? 0
-                            self?.sliderView.frame.origin.y = self?.playerHeaderView.frame.maxY ?? 0
-                            self?.collectionView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei + CGFloat(self?.preViewSize.height ?? 0) + cDefaultMargin * 1.5, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei - CGFloat(self?.preViewSize.height ?? 0) - cDefaultMargin * 1.5)
-                            self?.collectionView.scrollToItem(at: indexPath, at: .top, animated: true)
-                            self?.sliderView.isHidden = false
-                            self?.playBtn.frame.origin = CGPoint(x: (CGFloat(self?.preViewSize.width ?? 0) - CGFloat(cDefaultMargin * 5)) / 2, y: (CGFloat(self?.preViewSize.height ?? 0) - CGFloat(cDefaultMargin * 5)) / 2)
-                            self?.playerLayer.frame = self?.playerHeaderView.bounds ?? CGRect.zero
-                        }
-                    }
-                } else {
-                    selectedData = itemData
-                }
-            }
-            isPublishEnabled()
-            collectionView.reloadItems(at: [indexPath])
-        } else {
-            videoData.removeAll()
-            self.collectionView.setContentOffset(CGPoint.zero, animated: true)
-            self.collectionView.reloadData()
-            allPhotos = categoryData[indexPath.item].categoryList
-            catagerySelectedIndex = indexPath
-            selecteBtn.setTitle(categoryData[indexPath.item].title, for: .normal)
-            selecteBtn.imagePosition(at: .right, space: cDefaultMargin / 2)
-            if !isAssetImage {
-                playBtn.isHidden = false
-                sliderView.isHidden = true
-                avPlayer.pause()
-                if selectedData != nil {
-                    selectedData = nil
-                    UIView.animate(withDuration: 0.5, animations: { [weak self] in
-                        self?.playerHeaderView.frame = CGRect(x: 0, y: -(self?.preViewSize.height ?? 0) - cDevice_iPhoneNavBarAndStatusBarHei, width: self?.preViewSize.width ?? 0, height: self?.preViewSize.height ?? 0)
-                        self?.playerHeaderView.center.x = self?.view.center.x ?? 0
-                        self?.sliderView.frame.origin.y = self?.playerHeaderView.frame.maxY ?? 0
-                        self?.collectionView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei)
-                    }) { _ in
-                    }
-                }
-            }
-            lastSeletedIndex = nil
-            isPublishEnabled()
-            if allPhotos.count <= 0 {
-                emptyRemindView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei - cDevice_iPhoneTabBarHei)
-                emptyRemindView.emptyData = emptyData
-                emptyRemindView.isHidden = false
-            } else {
-                emptyRemindView.isHidden = true
-            }
-            self.collectionView.reloadData()
-            cancelClick()
-        }
-    }
-
-    open func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, sizeForItemAt _: IndexPath) -> CGSize {
-        if collectionView == self.collectionView {
-            return CGSize(width: (cScreenWidth - cDefaultMargin) / 3, height: (cScreenWidth - cDefaultMargin) / 3)
-        }
-        return CGSize(width: collectionView.frame.width, height: cDefaultMargin * 8)
-    }
-
-    open func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, minimumLineSpacingForSectionAt _: Int) -> CGFloat {
-        if collectionView == self.collectionView {
-            return cDefaultMargin / 2
-        }
-        return 0
-    }
-
-    open func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, minimumInteritemSpacingForSectionAt _: Int) -> CGFloat {
-        if collectionView == self.collectionView {
-            return cDefaultMargin / 2
-        }
-        return 0
-    }
-
-    open func scrollViewDidScroll(_: UIScrollView) {
-        // 这里是不是有用的?
-//        if bf_getCurrentViewController() is PQUploadController || bf_getCurrentViewController() is PQImageSelectedController {
-//            if scrollView == collectionView {
-//                updateCachedAssets()
-//            } else {
-//                BFLog(message: "contentOffset = \(scrollView.contentOffset),contentSize = \(scrollView.contentSize)")
-//                if scrollView.contentOffset.y > ((scrollView.contentSize.height - scrollView.frame.height) + cDefaultMargin * 10) {
-//                    cancelClick()
-//                }
-//            }
-//        }
-    }
-}
-
-extension PQUploadController {
-    /// 添加监听
-    /// - Parameter playerItem: <#playerItem description#>
-    /// - Returns: <#description#>
-    func addPlayerItemObserver() {
-        playerItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil)
-    }
-
-    /// 移除监听
-    /// - Returns: <#description#>
-    func removePlayerItemObserver() {
-        playerItem?.removeObserver(self, forKeyPath: "status")
-    }
-
-    open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) {
-        if object is AVPlayerItem, keyPath == "status" {
-            BFLog(message: "(object as! AVPlayerItem).status = \((object as! AVPlayerItem).status.rawValue)")
-            BFLoadingHUB.shared.dismissHUB(superView: playerHeaderView)
-            switch (object as! AVPlayerItem).status {
-            case .unknown:
-                break
-            case .readyToPlay:
-                break
-            case .failed:
-                break
-            default:
-                break
-            }
-        }
-    }
-
-    private func resetCachedAssets() {
-        imageManager.stopCachingImagesForAllAssets()
-        previousPreheatRect = .zero
-    }
-
-    private func updateCachedAssets() {
-        if allPhotos != nil, allPhotos.count <= 0 {
-            return
-        }
-        guard isViewLoaded, view.window != nil else { return }
-        let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size)
-        let preheatRect = visibleRect.insetBy(dx: 0, dy: -0.5 * visibleRect.height)
-        let delta = abs(preheatRect.midY - previousPreheatRect.midY)
-        guard delta > view.bounds.height / 3 else { return }
-        let (addedRects, removedRects) = differencesBetweenRects(previousPreheatRect, preheatRect)
-        let addedAssets = addedRects
-            .flatMap { rect in collectionView.indexPathsForElements(in: rect) }
-            .map { indexPath in allPhotos.object(at: indexPath.item) }
-        let removedAssets = removedRects
-            .flatMap { rect in collectionView.indexPathsForElements(in: rect) }
-            .map { indexPath in allPhotos.object(at: indexPath.item) }
-        imageManager.startCachingImages(for: addedAssets,
-                                        targetSize: itemSize, contentMode: .aspectFill, options: nil)
-        imageManager.stopCachingImages(for: removedAssets,
-                                       targetSize: itemSize, contentMode: .aspectFill, options: nil)
-
-        previousPreheatRect = preheatRect
-    }
-
-    private func differencesBetweenRects(_ old: CGRect, _ new: CGRect) -> (added: [CGRect], removed: [CGRect]) {
-        if old.intersects(new) {
-            var added = [CGRect]()
-            if new.maxY > old.maxY {
-                added += [CGRect(x: new.origin.x, y: old.maxY,
-                                 width: new.width, height: new.maxY - old.maxY)]
-            }
-            if old.minY > new.minY {
-                added += [CGRect(x: new.origin.x, y: new.minY,
-                                 width: new.width, height: old.minY - new.minY)]
-            }
-            var removed = [CGRect]()
-            if new.maxY < old.maxY {
-                removed += [CGRect(x: new.origin.x, y: new.maxY,
-                                   width: new.width, height: old.maxY - new.maxY)]
-            }
-            if old.minY < new.minY {
-                removed += [CGRect(x: new.origin.x, y: old.minY,
-                                   width: new.width, height: new.minY - old.minY)]
-            }
-            return (added, removed)
-        } else {
-            return ([new], [old])
-        }
-    }
-}
-
-extension PQUploadController: PHPhotoLibraryChangeObserver {
-    public func photoLibraryDidChange(_ changeInstance: PHChange) {
-        // Change notifications may be made on a background queue. Re-dispatch to the
-        // main queue before acting on the change as we'll be updating the UI.
-        DispatchQueue.main.sync { [weak self] in
-            // Check each of the three top-level fetches for changes.
-            if allPhotos != nil, changeInstance.changeDetails(for: allPhotos) != nil {
-                self?.categoryData.removeAll()
-                self?.loadPhotoData()
-            }
-        }
-    }
-}

+ 0 - 107
BFStuckPointKit/Classes/View/PQAssetCategoryCell.swift

@@ -1,107 +0,0 @@
-//
-//  PQAssetCategoryCell.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/8/4.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-import BFUIKit
-
-public class PQAssetCategoryCell: UICollectionViewCell {
-    public var representedAssetIdentifier: String!
-    lazy public var videoImageView: UIImageView = {
-        let videoImageView = UIImageView()
-        videoImageView.addCorner(corner: 4)
-        videoImageView.contentMode = .scaleAspectFill
-        return videoImageView
-    }()
-
-    lazy public var categoryNameLab: UILabel = {
-        let categoryNameLab = UILabel()
-        categoryNameLab.font = UIFont.systemFont(ofSize: 14)
-        categoryNameLab.textColor = BFConfig.shared.styleTitleColor
-        return categoryNameLab
-    }()
-
-    lazy public var countLab: UILabel = {
-        let countLab = UILabel()
-        countLab.font = UIFont.systemFont(ofSize: 14)
-        countLab.textColor = BFConfig.shared.styleTitleColor
-        return countLab
-    }()
-
-    lazy public var seleImage: UIImageView = {
-        let seleImage = UIImageView()
-        seleImage.tintColor = BFConfig.shared.styleTitleColor
-        seleImage.image = BFStuckPointImage(by: "icon_uploadVideo_do")?.withRenderingMode(.alwaysTemplate)//UIImage.moduleImage(named: , moduleName: "BFStuckPointKit",isAssets: false)?.withRenderingMode(.alwaysTemplate)
-        seleImage.isHidden = true
-        return seleImage
-    }()
-
-    @objc class public func assetCategoryCell(collectionView: UICollectionView, indexPath: IndexPath) -> PQAssetCategoryCell {
-        let cell: PQAssetCategoryCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PQAssetCategoryCell", for: indexPath) as! PQAssetCategoryCell
-        return cell
-    }
-
-    override public init(frame: CGRect) {
-        super.init(frame: frame)
-        contentView.addSubview(videoImageView)
-        contentView.addSubview(categoryNameLab)
-        contentView.addSubview(countLab)
-        contentView.addSubview(seleImage)
-    }
-
-    override public var isSelected: Bool {
-        didSet {
-            seleImage.isHidden = !isSelected
-        }
-    }
-
-    required public init?(coder _: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    public var uploadData: PQUploadModel? {
-        didSet {
-            addData()
-            addLayout()
-        }
-    }
-
-    public func addData() {
-        videoImageView.image = uploadData?.image
-        categoryNameLab.text = "\(uploadData?.title ?? "")"
-        countLab.text = "(\(uploadData?.categoryList.count ?? 0))"
-    }
-
-    public func addLayout() {
-        let margin: CGFloat = 12
-        let imageW: CGFloat = 66
-        let countW: CGFloat = sizeWithText(text: countLab.text ?? "", font: UIFont.systemFont(ofSize: 14), size: CGSize(width: cScreenWidth - imageW - margin * 6, height: cDefaultMargin * 2)).width + cDefaultMargin
-        let maxW: CGFloat = cScreenWidth - margin - imageW - margin - countW - margin - 13 - margin
-        videoImageView.snp.makeConstraints { make in
-            make.left.equalToSuperview().offset(margin)
-            make.width.height.equalTo(imageW)
-            make.centerY.equalToSuperview()
-        }
-        categoryNameLab.snp.makeConstraints { make in
-            make.left.equalTo(videoImageView.snp.right).offset(margin)
-            make.width.lessThanOrEqualTo(maxW)
-            make.centerY.equalToSuperview()
-        }
-        countLab.snp.remakeConstraints { make in
-            make.left.equalTo(categoryNameLab.snp.right)
-            make.centerY.equalToSuperview()
-            make.width.equalTo(countW)
-        }
-        seleImage.snp.makeConstraints { make in
-            make.centerY.equalToSuperview()
-            make.right.equalToSuperview().offset(-margin)
-            make.width.equalTo(13)
-            make.height.equalTo(10)
-        }
-    }
-}

+ 0 - 84
BFStuckPointKit/Classes/View/PQBaseVideoInfoView.swift

@@ -1,84 +0,0 @@
-//
-//  PQMessageVideoInfoView.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/11/12.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import BFCommonKit
-import BFMediaKit
-import BFUIKit
-import UIKit
-
-open class PQBaseVideoInfoView: UIView {
-    public lazy var imageView: UIImageView = {
-        let imageView = UIImageView(image: UIImage.moduleImage(named: "msg_default", moduleName: "BFStuckPointKit", isAssets: false))
-        imageView.addCorner(corner: 4)
-        imageView.contentMode = .scaleAspectFill
-        return imageView
-    }()
-
-    public lazy var videoTagView: UIImageView = {
-        let videoTagView = UIImageView(image: UIImage.moduleImage(named: "msg_video_tag", moduleName: "BFStuckPointKit", isAssets: false))
-        return videoTagView
-    }()
-
-    public lazy var titleLab: UILabel = {
-        let titleLab = UILabel()
-        titleLab.textColor = UIColor.hexColor(hexadecimal: "#CCCCCC")
-        titleLab.numberOfLines = 3
-        titleLab.font = UIFont(name: "PingFangSC", size: 13)
-        return titleLab
-    }()
-
-    override public init(frame: CGRect) {
-        super.init(frame: frame)
-        addSubview(imageView)
-        addSubview(titleLab)
-        imageView.addSubview(videoTagView)
-        backgroundColor = UIColor.hexColor(hexadecimal: "#171718")
-    }
-
-    public required init?(coder _: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    open var videoData: PQVideoListModel? {
-        didSet {
-            addData()
-            addLayout()
-        }
-    }
-
-    open func addData() {
-        // 这里会crash
-        let coverImg = (videoData?.videoCoverSnapshotPath != nil && (videoData?.videoCoverSnapshotPath?.count ?? 0) > 0) ? videoData?.videoCoverSnapshotPath ?? "" : (videoData?.coverImg?["coverImgPath"] as? String ?? "")
-        imageView.setNetImage(url: coverImg, placeholder: UIImage.moduleImage(named: "msg_default", moduleName: "BFStuckPointKit", isAssets: false)!)
-        titleLab.text = videoData?.title
-    }
-
-    open func addLayout() {
-        let margin: CGFloat = 12
-        let imageH: CGFloat = 57
-        let imageW: CGFloat = imageH * (100.0 / 57.0)
-        let tagW: CGFloat = 21
-        let tagH: CGFloat = 23
-        imageView.snp.makeConstraints { make in
-            make.left.equalToSuperview().offset(margin)
-            make.width.equalTo(imageW)
-            make.height.equalTo(imageH)
-            make.centerY.equalToSuperview()
-        }
-        videoTagView.snp.makeConstraints { make in
-            make.right.bottom.equalToSuperview().offset(-3)
-            make.width.equalTo(tagW)
-            make.height.equalTo(tagH)
-        }
-        titleLab.snp.makeConstraints { make in
-            make.top.equalTo(imageView)
-            make.left.equalTo(imageView.snp.right).offset(margin)
-            make.right.equalToSuperview().offset(-margin)
-        }
-    }
-}

+ 1 - 0
BFStuckPointKit/Classes/ViewModel/PQBaseViewModel.swift

@@ -12,6 +12,7 @@ import ObjectMapper
 import RealmSwift
 import BFCommonKit
 import BFNetRequestKit
+import BFUploadKit
 import BFMediaKit
 
 public class PQBaseViewModel: NSObject {

+ 0 - 77
BFStuckPointKit/Classes/ViewModel/PQDownloadFileManager.swift

@@ -1,77 +0,0 @@
-//
-//  PQDownloadFileManager.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/12/9.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-import BFMediaKit
-
-class PQDownloadFileManager: NSObject {
-    /// 创建文件
-    /// - Parameter url: 原地址
-    /// - Returns: <#description#>
-    class func createDownloadFilePath(url: String, fileExtensionType: FileExtensionType?) -> String {
-        let fileManager = FileManager.default
-        let filePath = downloadFileLocalPath(url: url, fileExtensionType: fileExtensionType)
-        if !fileManager.fileExists(atPath: filePath) {
-            let isFinished = fileManager.createFile(atPath: filePath, contents: nil, attributes: nil)
-            BFLog(message: "生成本地地址:\(url),localPath = \(filePath),isFinished:\(isFinished)")
-        } else {
-            BFLog(message: "已存在本地地址:\(url),localPath = \(filePath)")
-        }
-        return filePath
-    }
-
-    /// 获取文件本地存储地址
-    /// - Parameter url: 原地址
-    /// - Returns: <#description#>
-    class func downloadFileLocalPath(url: String, fileExtensionType: FileExtensionType?) -> String {
-        if url.hasPrefix(downloadDirectory) {
-            return url
-        }
-        let type: String = fileExtensionType?.rawValue ?? url.pathExtension
-        BFLog(message: "localPath : \(downloadDirectory + url.md5 + (type.count > 0 ? ".\(type)" : ""))")
-        return downloadDirectory + url.md5 + (type.count > 0 ? ".\(type)" : "")
-    }
-
-    /// 获取已缓存大小
-    /// - Parameter url: <#url description#>
-    /// - Returns: <#description#>
-    class func downloadFileLength(url: String, fileExtensionType: FileExtensionType?) -> Int64 {
-        let fileManager = FileManager.default
-        let filePath = downloadFileLocalPath(url: url, fileExtensionType: fileExtensionType)
-        if fileManager.fileExists(atPath: filePath) {
-            let att = try? fileManager.attributesOfItem(atPath: filePath)
-            return Int64((att?[FileAttributeKey.size] as? UInt64) ?? 0)
-        }
-        return 0
-    }
-
-    /// 移除已下载文件
-    /// - Parameter url: <#url description#>
-    /// - Returns: <#description#>
-    class func removeDownloadFile(url: String, fileExtensionType: FileExtensionType?) {
-        let fileManager = FileManager.default
-        var path = url
-        if !path.hasPrefix(downloadDirectory) {
-            path = downloadFileLocalPath(url: url, fileExtensionType: fileExtensionType)
-        }
-        if fileManager.fileExists(atPath: path) {
-            BFLog(message: "删除本地文件 == \(path)")
-            try? fileManager.removeItem(atPath: path)
-        }
-    }
-
-    /// 获取下载的总数量
-    /// - Returns: <#description#>
-    class func downloadTotalFile() -> [String]? {
-        let fileManager = FileManager.default
-        let subpaths = fileManager.subpaths(atPath: downloadDirectory)
-        BFLog(message: "已下载的总文件 == \(subpaths ?? [])")
-        return subpaths
-    }
-}

+ 0 - 228
BFStuckPointKit/Classes/ViewModel/PQDownloadManager.swift

@@ -1,228 +0,0 @@
-//
-//
-//  PQDownloadManager.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/8/28.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-import BFNetRequestKit
-import BFMediaKit
-
-// MARK: - 下载管理
-
-/// 下载管理
-
-open class PQDownloadManager: NSObject {
-    static public let shared = PQDownloadManager()
-    public let maxDownloadCount: Int = 1000 // 最大的下载数量
-    public var batchDownloadData: [String: Any] = Dictionary<String, Any>.init() // 批量下载数据
-    lazy public var sessionManager: PQSessionManager = {
-        let sessionManager = PQSessionManager("downloadConfiguration")
-        return sessionManager
-    }()
-
-    /// <#Description#>
-    /// - Parameters:
-    ///   - url: <#url description#>
-    ///   - name: <#name description#>
-    ///   - pathExtension: <#name description#>
-    ///   - imageURL: <#imageURL description#>
-    ///   - progressHandle: <#progressHandle description#>
-    ///   - stateHandle: <#stateHandle description#>
-    /// - Returns: <#description#>
-    public func download(url: String, name: String? = nil, fileExtensionType: FileExtensionType?, imageURL: String? = nil, progressHandle: @escaping ProgressHandle, stateHandle: @escaping StateHandle) {
-        BFLog(message: "开始下载文件:\(url)")
-        let subfile = PQDownloadFileManager.downloadTotalFile()
-        let newFileExtensionType: FileExtensionType = fileExtensionType ?? (FileExtensionType(rawValue: url.pathExtension) ?? FileExtensionType.normal)
-        if (subfile?.count ?? 0) > 0 && (subfile?.count ?? 0) > maxDownloadCount {
-            PQDownloadFileManager.removeDownloadFile(url: downloadDirectory + (subfile?.first)!, fileExtensionType: newFileExtensionType)
-        }
-        if !isValidURL(url: url) {
-            BFLog(message: "文件地址为空:\(url)")
-            return
-        }
-        let taskId = url.md5
-        let absolutePath = url + ".\(newFileExtensionType.rawValue)"
-        let localPath = PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: newFileExtensionType)
-        let downloadLenght: Int64 = PQDownloadFileManager.downloadFileLength(url: absolutePath, fileExtensionType: newFileExtensionType)
-        let downloadingTask: PQDownloadModel? = sessionManager.downloadTaskDatas.keys.contains(taskId) ? sessionManager.downloadTaskDatas[taskId] : nil
-        var totalLength: Int64 = 0
-        if downloadingTask != nil {
-            totalLength = downloadingTask?.totalLength ?? 0
-        }
-        if downloadLenght > 0, (downloadingTask != nil && downloadingTask?.state == .compelte) || (totalLength > 0 && totalLength > downloadLenght) {
-            progressHandle(1, downloadLenght, totalLength)
-            BFLog(message: "文件已下载完成:\(url),downloadLenght = \(downloadLenght),totalLength = \(totalLength)")
-            downloadingTask?.state = .compelte
-            downloadingTask?.progress = 1
-            postNotification(name: cDownloadMatrialSuccessKey, userInfo: ["code": "1", "url": url, "localPath": localPath, "fileExtensionType": newFileExtensionType])
-            stateHandle(.compelte, url, localPath, nil)
-            return
-        }
-        if downloadingTask != nil {
-            var request = URLRequest(url: URL(string: url)!)
-            request.setValue("bytes=%lld-\(downloadLenght)", forHTTPHeaderField: "Range")
-            request.setValue("Accept-Encoding", forHTTPHeaderField: "identity")
-            let task = sessionManager.session?.dataTask(with: request)
-            task?.taskUrl = url
-            task?.taskId = taskId
-            downloadingTask?.task = task
-            downloadingTask?.task?.resume()
-            BFLog(message: "下载任务已存在继续下载:\(url),localPath = \(localPath)")
-        } else {
-            createDirectory(path: downloadDirectory)
-            PQDownloadFileManager.removeDownloadFile(url: absolutePath, fileExtensionType: newFileExtensionType)
-            BFLog(message: "URL(string: url)! ==\(URL(string: url)!)")
-            var request = URLRequest(url: URL(string: url)!)
-//            request.setValue("bytes=%lld-\(downloadLenght)", forHTTPHeaderField: "Range")
-            request.setValue("Accept-Encoding", forHTTPHeaderField: "identity")
-            let task = sessionManager.session?.dataTask(with: request)
-            task?.taskUrl = url
-            task?.taskId = taskId
-            task?.resume()
-
-            let tempModel = PQDownloadModel()
-            tempModel.sourceURL = url
-            tempModel.fileExtensionType = newFileExtensionType
-            tempModel.progress = 0
-            tempModel.state = .downloading
-            tempModel.name = name
-            tempModel.imageURL = imageURL
-            tempModel.progressHandle = progressHandle
-            tempModel.stateHandle = stateHandle
-            tempModel.task = task
-            BFLog(message: "新建下载任务:\(url),localPath = \(PQDownloadFileManager.downloadFileLocalPath(url: url, fileExtensionType: newFileExtensionType)),taskID:\(taskId)  tempModel\(String(describing: tempModel.sourceURL))")
-            if !sessionManager.downloadTaskDatas.keys.contains(taskId) {
-                sessionManager.downloadTaskDatas[taskId] = tempModel
-            }
-        }
-    }
-
-    /// 批量下载
-    /// - Parameters:
-    ///   - uniqueId: 每个批量下载唯一id
-    ///   - urls: 需要下载urls
-    ///   - downloadHandle: <#downloadHandle description#>
-    /// - Returns: <#description#>
-    public  func batchDownload(uniqueId: String, urls: [PQDownloadModel], downloadHandle: @escaping (_ isSuccess: downloadState, _ msg: String?, _ data: [String: Any]?) -> Void) {
-        BFLog(message: "urls count is \(urls.count)")
-        if urls.count <= 0 {
-            return
-        }
-        if batchDownloadData.keys.contains(uniqueId) {
-            BFLog(message: "这组任务已经在下载中\(uniqueId)")
-            downloadHandle(.downloading, nil, nil)
-            return
-        }
-        let dispatchGroup = DispatchGroup()
-        var downloadInfo: [String: Any] = ["dispatchGroup": dispatchGroup]
-        for downloadUrl in urls {
-            if isValidURL(url: downloadUrl.sourceURL) {
-                DispatchQueue.global().async(group: dispatchGroup, execute: DispatchWorkItem(block: {
-                    dispatchGroup.enter()
-                    PQDownloadManager.shared.download(url: downloadUrl.sourceURL ?? "", fileExtensionType: downloadUrl.fileExtensionType) { _, _, _ in
-
-                    } stateHandle: { _, _, _, _ in
-                    }
-                }))
-            }
-        }
-        downloadInfo["urls"] = urls
-        downloadInfo["count"] = urls.count
-        PQDownloadManager.shared.batchDownloadData[uniqueId] = downloadInfo
-        dispatchGroup.notify(queue: DispatchQueue.main) {
-            BFLog(message: "所有的已请求完成,tempArr = \(PQDownloadManager.shared.batchDownloadData[uniqueId] ?? [])")
-            postNotification(name: cBatchDownloadMatrialSuccessKey, userInfo: ["uniqueId": uniqueId, "urls": PQDownloadManager.shared.batchDownloadData[uniqueId] ?? []])
-
-            PQDownloadManager.shared.batchDownloadData.removeValue(forKey: uniqueId)
-        }
-    }
-
-    /// 下载素材成功的通知
-    /// - Parameter notification: <#notification description#>
-    /// - Returns: <#description#>
-    @objc public func downloadMarial(notification: Notification) {
-        let userInfo = notification.userInfo
-        let url = userInfo?["url"] as? String
-        let localPath = userInfo?["localPath"] as? String
-        let code = userInfo?["code"] as? String
-        BFLog(message: "目前下载的任务组数 \(PQDownloadManager.shared.batchDownloadData.keys)")
-        PQDownloadManager.shared.batchDownloadData.forEach { _, value in
-            var downloadInfo: [String: Any]? = value as? [String: Any]
-            let urlsArr: [PQDownloadModel]? = downloadInfo?["urls"] as? [PQDownloadModel]
-            let dispatchGroup: DispatchGroup? = downloadInfo?["dispatchGroup"] as? DispatchGroup
-            var count: Int = downloadInfo?["count"] as? Int ?? 0
-            if (urlsArr?.count ?? 0) > 0 {
-                urlsArr?.forEach { downloadModel in
-                    if downloadModel.sourceURL == url {
-                        if code == "1" {
-                            downloadModel.filePath = localPath
-                        }
-                        BFLog(message: "count = \(count)")
-                        if count > 0 {
-                            BFLog(message: "leave = \(count)")
-                            count = count - 1
-                            downloadInfo?["count"] = count
-                            let dispatchGroupCount = dispatchGroup.debugDescription.components(separatedBy: ",").filter { $0.contains("count") }.first?.components(separatedBy: CharacterSet.decimalDigits.inverted).compactMap { Int($0) }.first
-                            BFLog(message: "dispatchGroup count is \(String(describing: dispatchGroupCount))")
-                            dispatchGroup?.leave()
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /// 下载背景音乐
-    /// - Parameters:
-    ///   - url: <#url description#>
-    ///   - completionHandler: <#completionHandler description#>
-    /// - Returns: <#description#>
-    public class func downLoadFile(url: String, completionHandler: @escaping (_ filePath: String?, _ error: Error?) -> Void) {
-        // 创建目录
-        createDirectory(path: bgMusicDirectory)
-        let filePath = bgMusicDirectory + url.md5 + ".mp3"
-        let data = try? Data(contentsOf: NSURL.fileURL(withPath: filePath))
-        if FileManager.default.fileExists(atPath: filePath) && (data?.count ?? 0) > 0 {
-            DispatchQueue.main.async {
-                completionHandler(filePath, nil)
-            }
-        } else {
-            let session = URLSession.shared
-            let request = URLRequest(url: URL(string: url)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 30.0)
-            let dataTask = session.downloadTask(with: request) { url, _, error in
-                if url != nil {
-                    if FileManager.default.fileExists(atPath: filePath) {
-                        try? FileManager.default.removeItem(atPath: filePath)
-                    }
-                    try? FileManager.default.moveItem(at: url!, to: URL(fileURLWithPath: filePath))
-                    DispatchQueue.main.async {
-                        completionHandler(filePath, nil)
-                    }
-                } else {
-                    DispatchQueue.main.async {
-                        completionHandler(nil, error)
-                    }
-                }
-            }
-            dataTask.resume()
-        }
-    }
-
-    override private init() {
-        super.init()
-        addNotification(self, selector: #selector(downloadMarial(notification:)), name: cDownloadMatrialSuccessKey, object: nil)
-    }
-
-    open override func copy() -> Any {
-        return self
-    }
-
-    open override func mutableCopy() -> Any {
-        return self
-    }
-}

+ 0 - 191
BFStuckPointKit/Classes/ViewModel/PQSessionManager.swift

@@ -1,191 +0,0 @@
-//
-//  PQSessionManager.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/12/8.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import UIKit
-import BFCommonKit
-import BFNetRequestKit
-import BFMediaKit
-
-open class PQSessionManager: NSObject {
-    public var downloadTaskDatas: [String: PQDownloadModel] = Dictionary<String, PQDownloadModel>.init()
-    public var dispatchQueue: DispatchQueue! // 线程
-    public var session: URLSession? // sesstion
-    public var identifier: String = "" // 标示
-    public var completionHandler: (() -> Void)? // 完成回调
-    public lazy var configuration: URLSessionConfiguration = { // sesstion 配置
-        //        let configuration = URLSessionConfiguration.background(withIdentifier: identifier)
-        let configuration = URLSessionConfiguration.default
-        configuration.isDiscretionary = false
-        configuration.timeoutIntervalForRequest = 30 // 请求超时时长,默认是60s
-        configuration.timeoutIntervalForResource = 7 * 24 * 60 * 60 // 资源超时时长,默认是7天,也就是说资源要在7天内到达
-        configuration.httpMaximumConnectionsPerHost = 20
-        configuration.allowsCellularAccess = true // 是否支持蜂窝网络下载
-        if #available(iOS 13, *) {
-            configuration.allowsConstrainedNetworkAccess = true // 是否使用受限制的网络
-            configuration.allowsExpensiveNetworkAccess = true // 是否使用昂贵的网络
-        }
-        return configuration
-    }()
-
-    public init(_ identifier: String,
-                configuration: URLSessionConfiguration? = nil,
-                dispatchQueue: DispatchQueue = DispatchQueue(label: "com.piaoquan.pqspeed.dispatchQueue"))
-    {
-        super.init()
-        let bundleIdentifier = Bundle.main.bundleIdentifier ?? "com.piaoquan.pqspeed"
-        if configuration != nil {
-            self.configuration = configuration!
-        }
-        self.identifier = "\(bundleIdentifier).\(identifier)"
-        self.dispatchQueue = dispatchQueue
-        createSession()
-    }
-
-    func createSession() {
-        let delegateQueue = OperationQueue(maxConcurrentOperationCount: 4, underlyingQueue: dispatchQueue, name: "com.piaoquan.pqspeed.delegateQueue")
-        session = URLSession(configuration: configuration, delegate: self, delegateQueue: delegateQueue)
-    }
-}
-
-extension PQSessionManager: URLSessionDataDelegate {
-    /// 收到请求响应
-    /// - Parameters:
-    ///   - session: <#session description#>
-    ///   - dataTask: <#dataTask description#>
-    ///   - response: <#response description#>
-    ///   - completionHandler: <#completionHandler description#>
-   public func urlSession(_: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
-        let taskId = dataTask.taskId
-        let taskUrl = dataTask.taskUrl
-        let downloadData = downloadTaskDatas[taskId]
-        let fileExtensionType: FileExtensionType = downloadData?.fileExtensionType ?? (FileExtensionType(rawValue: taskUrl.pathExtension) ?? FileExtensionType.normal)
-        let absolutePath = taskUrl + ".\(fileExtensionType.rawValue)"
-        let expectedLength: Int64 = response.expectedContentLength
-        let downloadedLength: Int64 = PQDownloadFileManager.downloadFileLength(url: absolutePath, fileExtensionType: fileExtensionType)
-        let totalLength: Int64 = expectedLength
-        if totalLength == 0 {
-            if downloadData?.progressHandle != nil {
-                downloadData?.progressHandle!(0, downloadedLength, totalLength)
-            }
-            if downloadData?.stateHandle != nil {
-                downloadData?.stateHandle!(.error, taskUrl, PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), PQError(msg: "下载文件为空", code: 0))
-            }
-            BFLog(message: "收到下载请求-下载文件为空:\(taskUrl),localPath = \(PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType))")
-            return
-        }
-        // 创建文件地址
-        let filePath = PQDownloadFileManager.createDownloadFilePath(url: absolutePath, fileExtensionType: fileExtensionType)
-        let fileHandle: FileHandle? = FileHandle(forWritingAtPath: filePath)
-        downloadData?.downloadLength = downloadedLength
-        downloadData?.totalLength = totalLength
-        downloadData?.fileHandle = fileHandle
-        downloadData?.filePath = filePath
-        downloadData?.mimeType = response.mimeType
-        if downloadData?.name == nil {
-            downloadData?.name = response.suggestedFilename
-        }
-        BFLog(message: "收到下载请求-下载文件:downloadedLength = \(downloadedLength),localPath = \(filePath),totalLength = \(totalLength),expectedLength = \(expectedLength)")
-        completionHandler(.allow)
-    }
-
-    /// 收到数据
-    /// - Parameters:
-    ///   - session: <#session description#>
-    ///   - dataTask: <#dataTask description#>
-    ///   - data: <#data description#>
-    public func urlSession(_: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
-        let taskId = dataTask.taskId
-        let taskUrl = dataTask.taskUrl
-        let downloadData = downloadTaskDatas[taskId]
-        let fileExtensionType: FileExtensionType = downloadData?.fileExtensionType ?? (FileExtensionType(rawValue: taskUrl.pathExtension) ?? FileExtensionType.normal)
-        let absolutePath = taskUrl + ".\(fileExtensionType.rawValue)"
-        BFLog(message: "收到下载请求-收到data taskId = \(taskId),data = \(data),totalBytes = \(downloadData?.totalLength ?? 0),download = \(PQDownloadFileManager.downloadFileLength(url: absolutePath, fileExtensionType: fileExtensionType))")
-
-        if downloadData != nil {
-            downloadData?.fileHandle?.seekToEndOfFile()
-            downloadData?.fileHandle?.write(data)
-            downloadData?.downloadLength = (downloadData?.downloadLength ?? 0) + Int64(data.count)
-            let progress = Float(downloadData?.downloadLength ?? 0) / Float(downloadData?.totalLength ?? 1)
-            downloadData?.progress = progress
-            downloadData?.state = .downloading
-            if downloadData?.progressHandle != nil {
-                downloadData?.progressHandle!(progress, downloadData?.downloadLength, downloadData?.totalLength)
-            }
-            if downloadData?.stateHandle != nil {
-                downloadData?.stateHandle!(.downloading, taskUrl, PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), nil)
-            }
-        }
-    }
-
-    /// 下载完成/终止
-    /// - Parameters:
-    ///   - session: <#session description#>
-    ///   - task: <#task description#>
-    ///   - error: <#error description#>
-    public func urlSession(_: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
-        let taskId = task.taskId
-        let taskUrl = task.taskUrl
-        let downloadData = downloadTaskDatas[taskId]
-        var fileExtensionType: FileExtensionType = downloadData?.fileExtensionType ?? (FileExtensionType(rawValue: taskUrl.pathExtension) ?? FileExtensionType.normal)
-        let absolutePath = taskUrl + ".\(fileExtensionType.rawValue)"
-        downloadData?.fileHandle?.closeFile()
-        BFLog(message: "收到下载请求-下载完成 taskId = \(taskId),error = \(error ?? PQError(msg: ""))")
-        downloadData?.fileHandle = nil
-        if downloadData?.realFileExtensionType != nil, downloadData?.fileExtensionType != nil, downloadData?.realFileExtensionType != downloadData?.fileExtensionType {
-            try? FileManager.default.moveItem(atPath: PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), toPath: PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: downloadData?.realFileExtensionType))
-            fileExtensionType = (downloadData?.realFileExtensionType)!
-        }
-
-        // mdf by ak 当下载的视频 FPS 不是30帧时 要处理到30 FPS
-        if downloadData?.fileExtensionType == .mp4, AVURLAsset(url: URL(fileURLWithPath: PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType)), options: avAssertOptions).tracks(withMediaType: .video).first?.nominalFrameRate != 30 {
-            let oldVideoPath = PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType)
-
-            let outVideoPath = downloadDirectory + "export_temp" + oldVideoPath.replacingOccurrences(of: downloadDirectory, with: "")
-
-            BFLog(message: "下载视频 FPS 不是30帧 要处理 oldVideoPath is \(oldVideoPath) \n outVideoPath is\(outVideoPath)")
-
-            NXAVAssetExportSession().exportAsynchronouslyWithCompletionHandler(inFilePath: oldVideoPath, outFilePath: outVideoPath, frameDuration: CMTime(value: 1, timescale: 30)) { _ in
-
-                do {
-                    // 1,delete old file
-                    try FileManager.default.removeItem(at: URL(fileURLWithPath: oldVideoPath))
-                    // 2,用新文件覆盖老文件路径
-                    try FileManager.default.moveItem(atPath: outVideoPath, toPath: oldVideoPath)
-
-                } catch {
-                    // No-op
-                }
-
-                BFLog(message: "clear data movie outFilePath is \(String(describing: oldVideoPath))")
-
-                postNotification(name: cDownloadMatrialSuccessKey, userInfo: ["code": error != nil ? "0" : "1", "url": task.taskUrl, "localPath": error != nil ? "" : PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), "fileExtensionType": fileExtensionType])
-                if downloadData?.stateHandle != nil {
-                    if error != nil {
-                        downloadData?.state = .error
-                        downloadData?.stateHandle!(.error, taskUrl, PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), PQError(msg: error?.localizedDescription, code: 0))
-                    } else {
-                        downloadData?.state = .compelte
-                        downloadData?.stateHandle!(.compelte, taskUrl, PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), nil)
-                    }
-                }
-            }
-
-        } else {
-            postNotification(name: cDownloadMatrialSuccessKey, userInfo: ["code": error != nil ? "0" : "1", "url": task.taskUrl, "localPath": error != nil ? "" : PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), "fileExtensionType": fileExtensionType])
-            if downloadData?.stateHandle != nil {
-                if error != nil {
-                    downloadData?.state = .error
-                    downloadData?.stateHandle!(.error, taskUrl, PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), PQError(msg: error?.localizedDescription, code: 0))
-                } else {
-                    downloadData?.state = .compelte
-                    downloadData?.stateHandle!(.compelte, taskUrl, PQDownloadFileManager.downloadFileLocalPath(url: absolutePath, fileExtensionType: fileExtensionType), nil)
-                }
-            }
-        }
-    }
-}

+ 0 - 160
BFStuckPointKit/Classes/ViewModel/PQUploadViewModel.swift

@@ -1,160 +0,0 @@
-//
-//  PQUploadViewModel.swift
-//  PQSpeed
-//
-//  Created by SanW on 2020/8/4.
-//  Copyright © 2020 BytesFlow. All rights reserved.
-//
-
-import BFCommonKit
-import BFNetRequestKit
-import UIKit
-import BFUIKit
-import BFAnalyzeKit
-
-public class PQUploadViewModel: NSObject {
-    /// 发布视频
-    /// - Parameters:
-    ///   - projectId 项目ID-发布创作的视频时必传,会在进入创作工具页时生成,以app_no_projectdata为前缀
-    ///   - fileExtensions 视频封装格式 -必传
-    ///   - title: 标题
-    ///   - videoPath: 视频地址
-    ///   - coverImgPath: 封面地址
-    ///   - descr: 描述
-    ///   - videoFromScene 视频来源场景 1:普通上传 2:创作工具,3:普通上传转创作工具,4:后台转换加工,5:卡点视频制作
-    /// - Returns: <#description#>
-    public class func publishVideo(projectId: String?, fileExtensions: String?, title: String, videoPath: String, coverImgPath: String?, descr: String, videoFromScene: videoFromScene, reCreateData: PQReCreateModel?, eventTrackData: PQVideoMakeEventTrackModel?, topicId: String? = nil,extParams:String? = nil, completeHander: @escaping (_ videoData: PQVideoListModel?, _ jsonDict: [String: Any]?, _ msg: String?) -> Void) {
-        BFLog(message: "AKAKAAKprojectId is\(String(describing: projectId)) videoFromScene is \(videoFromScene)")
-        var params: [String: Any] = ["title": title, "fileExtensions": fileExtensions ?? "application/octet-stream", "videoPath": videoPath, "descr": descr, "viewStatus": 1, "produceProjectId": (projectId ?? "") as String, "videoFromScene": videoFromScene.rawValue]
-        if coverImgPath != nil, (coverImgPath?.count ?? 0) > 0 {
-            params["coverImgPath"] = coverImgPath
-        }
-        if topicId != nil, (topicId?.count ?? 0) > 0 {
-            params["topicId"] = topicId
-        }
-        if extParams != nil && (extParams?.count ?? 0) > 0 {
-            params["reserve"] = extParams!
-        }
-        
-        BFNetRequestAdaptor.postRequestData(url: PQENVUtil.shared.longvideoapi + videoSendUrl, parames: params, commonParams: commonParams()) { response, _, error, _ in
-            if error != nil {
-                completeHander(nil, nil, error?.msg)
-                return
-            }
-            var jsonDict = (response as! [String: Any])
-            jsonDict["title"] = title
-            jsonDict["auditStatus"] = 1
-            jsonDict["uid"] = BFLoginUserInfo.shared.uid
-            let tempModel = PQVideoListModel(jsonDict: jsonDict)
-            tempModel.uid = Int(BFLoginUserInfo.shared.uid) ?? 0
-            tempModel.auditStatus = 1
-            completeHander(tempModel, jsonDict, nil)
-            // 发布成功
-            var extParams: [String: Any] = ["source": (projectId != nil && (projectId?.count ?? 0) > 0) ? "videoCompose" : "videoUpload", "projectId": projectId ?? ""]
-            if reCreateData != nil {
-                extParams["projectId"] = reCreateData?.projectId ?? ""
-                extParams["parentVideoId"] = reCreateData?.videoId ?? ""
-                extParams["parentProjectId"] = reCreateData?.parentProjectId ?? ""
-                extParams["rootProjectId"] = reCreateData?.rootProjectId ?? ""
-            }
-            BFEventTrackAdaptor.baseReportUpload(businessType: .bt_up_process, objectType: .ot_up_publishSuccess, pageSource: nil, extParams: extParams,commonParams: commonParams())
-            if projectId != nil {
-                PQBaseViewModel.reportSendVideo(projectId!, tempModel.uniqueId ?? "", videoFromScene: videoFromScene) { isSuccess, _ in
-                    if !isSuccess {
-                        PQBaseViewModel.reportSendVideo(projectId!, tempModel.uniqueId ?? "", videoFromScene: videoFromScene) { isSuccess, _ in
-                            if !isSuccess {
-                                PQBaseViewModel.reportSendVideo(projectId!, tempModel.uniqueId ?? "", videoFromScene: videoFromScene) { isSuccess, _ in
-                                    if !isSuccess {}
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            if eventTrackData != nil {
-                eventTrackData?.title = title
-                eventTrackData?.videoDes = descr
-                eventTrackData?.videoId = tempModel.uniqueId
-                eventTrackData?.coverUrl = coverImgPath
-                BFEventTrackAdaptor.baseReportUpload(logType: .st_log_type_videoProduction, businessType: nil, objectType: nil, pageSource: nil, eventData: eventTrackData?.toParams(),commonParams: commonParams())
-            }
-        }
-    }
-
-    /// 修改视频
-    /// - Parameters:
-    ///   - title: 标题
-    ///   - videoId: 视频id
-    ///   - coverImgPath: 图片地址
-    ///   - descr: 描述
-    ///   - completeHander: <#completeHander description#>
-    /// - Returns: <#description#>
-    public class func updateVideo(title: String, videoId: String, coverImgPath: String, descr: String,topicId:Int64? = nil, completeHander: @escaping (_ response:[String:Any]?,_ videoData: PQVideoListModel?, _ msg: String?) -> Void) {
-        var params : Dictionary<String,Any> = ["title": title, "videoId": videoId, "coverImgPath": coverImgPath, "descr": descr, "viewStatus": 1, "barrageSwitch": 1]
-        if topicId != nil && (topicId ?? 0) > 0 {
-            params["topicId"] = topicId!
-        }
-        BFNetRequestAdaptor.postRequestData(url: PQENVUtil.shared.longvideoapi + updateVideoUrl, parames: params, commonParams: commonParams()) { response, _, error, _ in
-            if error != nil {
-                completeHander(nil,nil, error?.msg)
-                return
-            }
-            // 1015
-            let tempModel = PQVideoListModel(jsonDict: response as! [String: Any])
-            tempModel.auditStatus = 1
-            completeHander(response as? [String: Any],tempModel, nil)
-        }
-    }
-
-    /// 获取视频封面
-    /// - Parameters:
-    ///   - videoId: 视频ID
-    ///   - videoPath: 视频地址
-    ///   - totalTime: 总时长
-    ///   - completeHander: <#completeHander description#>
-    /// - Returns: <#description#>
-    public class func vodeoCoverImageList(videoId: String, videoPath: String, totalTime: Int, videoHeight: CGFloat, videoWidth: CGFloat, completeHander: @escaping (_ coverImages: [PQUploadModel]?, _ msg: String?) -> Void) {
-        BFNetRequestAdaptor.postRequestData(url: PQENVUtil.shared.longvideoapi + vodeoCoverImageUrl, parames: ["id": videoId, "videoPath": videoPath, "totalTime": totalTime], commonParams: commonParams()) { response, _, error, _ in
-            if error != nil {
-                completeHander(nil, error?.msg)
-                return
-            }
-            var coverImages: [PQUploadModel] = Array<PQUploadModel>.init()
-            let data: [String: Any]? = response as? [String: Any]
-            if data != nil, data?.keys.contains("videoCoverImages") ?? false {
-                let videoCoverImages: [String]? = data?["videoCoverImages"] as? [String]
-                if videoCoverImages != nil, (videoCoverImages?.count ?? 0) > 0 {
-                    for item in videoCoverImages! {
-                        let tempItem = PQUploadModel()
-                        tempItem.contentMode = .scaleAspectFit
-                        tempItem.videoHeight = videoHeight
-                        tempItem.videoWidth = videoWidth
-                        tempItem.imageUrl = item
-                        coverImages.append(tempItem)
-                    }
-                }
-            }
-            completeHander(coverImages, nil)
-        }
-    }
-    
-    /// - Parameter completeHander: completeHander description
-    public class func getStsToken(completeHander: @escaping (_ userInfo: [String: Any]?, _ msg: String?) -> Void) {
-        BFNetRequestAdaptor.postRequestData(url: PQENVUtil.shared.longvideoapi + getStsTokenUrl, parames: ["fileType": "2", "type": 1], commonParams: commonParams()) { response, _, error, _ in
-            if error != nil {
-                completeHander(nil, error?.msg)
-                return
-            }
-            completeHander(response as? [String: Any], nil)
-        }
-    }
-    
-    /// 获取OSS
-    /// - Parameter completeHander: <#completeHander description#>
-    /// - Returns: <#description#>
-    public class func ossTempToken(completeHander: @escaping (_ userInfo: [String: Any]?, _ msg: String?) -> Void) {
-        BFNetRequestAdaptor.postRequestData(url: PQENVUtil.shared.longvideoapi + ossTempTokenUrl, parames: ["type": "2", "fileType": "1"], commonParams: commonParams()) { response, _, _, _ in
-            completeHander(response as? [String: Any], nil)
-        }
-    }
-}

+ 2 - 0
Example/BFStuckPointKit.xcodeproj/project.pbxproj

@@ -279,6 +279,7 @@
 				"${BUILT_PRODUCTS_DIR}/BFCommonKit/BFCommonKit.framework",
 				"${BUILT_PRODUCTS_DIR}/BFNetRequestKit/BFNetRequestKit.framework",
 				"${BUILT_PRODUCTS_DIR}/BFUIKit/BFUIKit.framework",
+				"${BUILT_PRODUCTS_DIR}/BFUploadKit/BFUploadKit.framework",
 				"${BUILT_PRODUCTS_DIR}/FDFullscreenPopGesture/FDFullscreenPopGesture.framework",
 				"${BUILT_PRODUCTS_DIR}/KeychainAccess/KeychainAccess.framework",
 				"${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework",
@@ -302,6 +303,7 @@
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFCommonKit.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFNetRequestKit.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFUIKit.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFUploadKit.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FDFullscreenPopGesture.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/KeychainAccess.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework",

+ 2 - 0
Example/Podfile

@@ -13,6 +13,8 @@ target 'BFStuckPointKit_Example' do
   pod 'BFMaterialKit',          :path => '../../../BFMaterialKit/Trunk'
   pod 'BFMediaKit',             :path => '../../../BFMediaKit/Trunk'
   pod 'BFAnalyzeKit',           :path => '../../../BFAnalyzeKit/Trunk'
+  pod "BFUploadKit" ,           :path => '../../../BFUploadKit/Trunk'
+  
   target 'BFStuckPointKit_Tests' do
     inherit! :search_paths
 

+ 13 - 3
Example/Podfile.lock

@@ -51,13 +51,13 @@ PODS:
   - BFNetRequestKit (1.0.1):
     - Alamofire (= 5.4.4)
   - BFStuckPointKit (0.1.0):
-    - AliyunOSSiOS (= 2.10.10)
     - BFAnalyzeKit
     - BFCommonKit
     - BFMaterialKit
     - BFMediaKit
     - BFNetRequestKit
     - BFUIKit
+    - BFUploadKit
     - Bugly (= 2.5.90)
     - LMJHorizontalScrollText (= 2.0.2)
     - MJRefresh (~> 3.0)
@@ -102,6 +102,12 @@ PODS:
     - RealmSwift (= 10.7.6)
     - SnapKit (~> 5.0)
     - SVProgressHUD (~> 2.0)
+  - BFUploadKit (0.1.0):
+    - AliyunOSSiOS (= 2.10.10)
+    - BFAnalyzeKit
+    - BFCommonKit
+    - BFNetRequestKit
+    - BFUIKit
   - Bugly (2.5.90)
   - FDFullscreenPopGesture (1.1)
   - KeychainAccess (4.2.2)
@@ -141,6 +147,7 @@ DEPENDENCIES:
   - BFNetRequestKit (from `../../../BFNetRequestKit/Trunk`)
   - BFStuckPointKit (from `../`)
   - BFUIKit (from `../../../BFUIKit/Trunk`)
+  - BFUploadKit (from `../../../BFUploadKit/Trunk`)
 
 SPEC REPOS:
   https://github.com/CocoaPods/Specs.git:
@@ -180,6 +187,8 @@ EXTERNAL SOURCES:
     :path: "../"
   BFUIKit:
     :path: "../../../BFUIKit/Trunk"
+  BFUploadKit:
+    :path: "../../../BFUploadKit/Trunk"
 
 SPEC CHECKSUMS:
   Alamofire: f3b09a368f1582ab751b3fff5460276e0d2cf5c9
@@ -189,8 +198,9 @@ SPEC CHECKSUMS:
   BFMaterialKit: 0a15786e2a55587f1b2b4b74c0bff5321ebf3630
   BFMediaKit: 84a6f93a937e09a1b5b8ef56759a24d7c293b09e
   BFNetRequestKit: 1d074023eafe7c272fab4ed3a608e685902235d0
-  BFStuckPointKit: f1c94ed421f5f1b4bfe20775ce542e587550a085
+  BFStuckPointKit: 833444e54fdd30812b452b650a905eafcfe90aa0
   BFUIKit: f209190fb92c8f9050554ac5950a2e4852e8a481
+  BFUploadKit: 92ca3512d8dcf7d9a941c68bbba7f31c56323314
   Bugly: 88bc32c0acc6fef7b74d610f0319ee7560d6b9fe
   FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0
   KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
@@ -209,6 +219,6 @@ SPEC CHECKSUMS:
   TXLiteAVSDK_Player: 2b60edf893a8e82165a5e4b961a6cb347b10be4a
   WechatOpenSDK-Swift: 18a8f7b12e745c30acc013f72a9f8a25aad6e216
 
-PODFILE CHECKSUM: 41253a5ed5537e1f684add7b416e88be93d3812f
+PODFILE CHECKSUM: d413fdcc5220f8d5b6bb7e61ac746deedc91e067
 
 COCOAPODS: 1.11.2