TodoTaskDetailViewController.swift 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129
  1. //
  2. // TodoTaskDetailViewController.swift
  3. // O2Platform
  4. //
  5. // Created by 刘振兴 on 16/7/31.
  6. // Copyright © 2016年 zoneland. All rights reserved.
  7. //
  8. import UIKit
  9. import WebKit
  10. import Alamofire
  11. import AlamofireImage
  12. import AlamofireObjectMapper
  13. import SwiftyJSON
  14. import ObjectMapper
  15. import CocoaLumberjack
  16. import Photos
  17. import QuickLook
  18. struct TodoTaskJS {
  19. static let DATA_TASK = "JSON.encode(layout.appForm.businessData.task);"
  20. static let DATA_READ = "JSON.encode(layout.appForm.businessData.read);"
  21. static let DATA_OPINION = "JSON.encode(layout.appForm.getOpinion());"
  22. static let DATA_CONTROL = "JSON.encode(layout.appForm.businessData.control);"
  23. static let DATA_WORK_TITLE = "JSON.encode(layout.appForm.businessData.work.title);"
  24. static let DATA_WORK = "JSON.encode(layout.appForm.businessData.work);"
  25. static let DATA_BUSINESS = "JSON.encode(layout.appForm.getData());"
  26. static let CHECK_FORM = "layout.appForm.formValidation(null, null)"
  27. static func getDataWithJS(_ webView:UIWebView,jscode:String) -> [String:AnyObject] {
  28. let str = webView.stringByEvaluatingJavaScript(from: jscode)
  29. //let data = str?.dataUsingEncoding(NSUTF8StringEncoding)
  30. let json = JSON.init(parseJSON: str!)
  31. return json.dictionaryObject! as [String : AnyObject]
  32. }
  33. }
  34. class TodoTaskDetailViewController: BaseWebViewUIViewController {
  35. @IBOutlet weak var progress: UIProgressView!
  36. @IBOutlet weak var webViewContainer: UIView!
  37. var qlController = TaskAttachmentPreviewController()
  38. //是否是已办
  39. open var isWorkCompeleted:Bool = false
  40. open var workId:String?
  41. var toolbarView: UIToolbar!
  42. var taskProcess = TaskProcess()
  43. let group = DispatchGroup()
  44. /// backFlag = 1来自MainTask,backFlag = 2来自TodoTask 3是show dis
  45. var backFlag:Int = 0
  46. var loadUrl:String?
  47. var isJSExecuted:Bool = true
  48. var hasToolbar:Bool = false
  49. var todoTask:TodoTask? {
  50. didSet {
  51. var url:String?
  52. if let workId = todoTask?.work, workId != "" {
  53. url = AppDelegate.o2Collect.genrateURLWithWebContextKey(DesktopContext.DesktopContextKey, query: DesktopContext.todoDesktopQuery, parameter: ["##workid##":workId as AnyObject])
  54. self.isWorkCompeleted = false
  55. self.workId = workId
  56. }else if let workCompletedId = todoTask?.workCompleted, workCompletedId != "" {
  57. url = AppDelegate.o2Collect.genrateURLWithWebContextKey(DesktopContext.DesktopContextKey, query: DesktopContext.todoedDestopQuery, parameter: ["##workCompletedId##":workCompletedId as AnyObject])
  58. self.isWorkCompeleted = true
  59. self.workId = workCompletedId
  60. }
  61. self.loadUrl = url
  62. }
  63. }
  64. var myTask: [String : AnyObject]?
  65. var myRead: [String : AnyObject]?
  66. var myControl: [String : AnyObject]?
  67. var myNewControls: [WorkNewActionItem] = []
  68. var moreActionMenus: O2WorkMoreActionSheet? = nil
  69. var myTitle: String?
  70. override func viewDidLoad() {
  71. super.viewDidLoad()
  72. // 返回按钮重新定义
  73. self.navigationItem.hidesBackButton = true
  74. self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "icon_fanhui"), style: .plain, target: self, action: #selector(goBack))
  75. self.navigationItem.leftItemsSupplementBackButton = true
  76. // 文档查看器
  77. self.qlController.dataSource = qlController
  78. self.qlController.delegate = qlController
  79. //toolbar
  80. self.toolbarView = UIToolbar(frame: CGRect(x: 0, y: self.view.height - 44, width: self.view.width, height: 44))
  81. self.automaticallyAdjustsScrollViewInsets = false
  82. myTitle = todoTask?.title
  83. if myTitle != nil {
  84. title = myTitle
  85. }
  86. //添加工作页面特殊的js处理
  87. addScriptMessageHandler(key: "closeWork", handler: self)
  88. addScriptMessageHandler(key: "appFormLoaded", handler: self)
  89. addScriptMessageHandler(key: "uploadAttachment", handler: self)
  90. addScriptMessageHandler(key: "downloadAttachment", handler: self)
  91. addScriptMessageHandler(key: "replaceAttachment", handler: self)
  92. addScriptMessageHandler(key: "openDocument", handler: self)
  93. self.theWebView()
  94. }
  95. override func viewWillAppear(_ animated: Bool) {
  96. super.viewWillAppear(animated)
  97. //监控进度
  98. webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
  99. }
  100. override func viewWillDisappear(_ animated: Bool) {
  101. super.viewWillDisappear(animated)
  102. webView.removeObserver(self, forKeyPath: "estimatedProgress")
  103. }
  104. override func theWebView(){
  105. super.theWebView()
  106. self.webViewContainer.addSubview(self.webView)
  107. self.webView.translatesAutoresizingMaskIntoConstraints = false
  108. let top = NSLayoutConstraint(item: self.webView, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.webViewContainer, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 0)
  109. let bottom = NSLayoutConstraint(item: self.webView, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.webViewContainer, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: 0)
  110. let trailing = NSLayoutConstraint(item: self.webView, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.webViewContainer, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: 0)
  111. let leading = NSLayoutConstraint(item: self.webView, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.webViewContainer, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1, constant: 0)
  112. self.webViewContainer.addConstraints([top, bottom, trailing, leading])
  113. webView.navigationDelegate = self
  114. webView.uiDelegate = self
  115. DDLogDebug("url:\(String(describing: loadUrl))")
  116. webView.load(Alamofire.request(loadUrl!).request!)
  117. webView.allowsBackForwardNavigationGestures = true
  118. }
  119. override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  120. if keyPath == "estimatedProgress" {
  121. progress.isHidden = webView.estimatedProgress == 1
  122. progress.setProgress(Float(webView.estimatedProgress), animated: true)
  123. }
  124. }
  125. override func didReceiveMemoryWarning() {
  126. super.didReceiveMemoryWarning()
  127. // Dispose of any resources that can be recreated.
  128. }
  129. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  130. if segue.identifier == "showTodoProcessSegue" {
  131. let destVC = segue.destination as! TodoTaskProcessViewController
  132. //传递到下一步
  133. destVC.backFlag = backFlag
  134. destVC.taskProcess = self.taskProcess
  135. }
  136. }
  137. /**
  138. 提交后返回此处,在此执行是返回首页还是待办处理页
  139. - parameter segue:
  140. */
  141. @IBAction func processBackMe(_ segue:UIStoryboardSegue){
  142. goBack()
  143. }
  144. //MARK: - private func
  145. @objc func goBack() {
  146. DDLogDebug("backFlag = \(backFlag)")
  147. switch backFlag {
  148. case 1:
  149. self.performSegue(withIdentifier: "backMainTask", sender: nil)
  150. break
  151. // case 2:
  152. // self.performSegue(withIdentifier: "backToTodoTask", sender: nil)
  153. // break
  154. //5是处理内容管理创建过来的流程 因为有一个创建页面 所以需要跳两层回去
  155. case 4, 5:
  156. if let index = self.navigationController?.viewControllers.firstIndex(of: self) {
  157. DDLogDebug("返回两层。。。。。")
  158. if let secVC = self.navigationController?.viewControllers.get(at: index - 2) {
  159. self.navigationController?.popToViewController(secVC, animated: true)
  160. }else {
  161. DDLogError("返回两层 错误 没有获取到VC。。。。。")
  162. self.navigationController?.popViewController(animated: true)
  163. }
  164. }else {
  165. DDLogError("返回两层 错误 当前index。。。。。")
  166. self.navigationController?.popViewController(animated: true)
  167. }
  168. break
  169. default: // 3,4都用隐藏 除非删除 删除结束有特殊处理了。
  170. self.navigationController?.popViewController(animated: true)
  171. break
  172. }
  173. }
  174. @objc func itemBtnDocDeleteAction() {
  175. DDLogDebug("btnDeleteDoc Click")
  176. showDefaultConfirm(title: "提示", message: "确认要删除这个文档吗,删除后无法恢复?", okHandler: { (action) in
  177. self.showLoading(title: "删除中...")
  178. let url = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskContext.taskDataContextKey, query: TaskContext.taskWorkDeleteQuery, parameter: ["##id##":self.workId! as AnyObject])
  179. Alamofire.request(url!,method:.delete, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
  180. switch response.result {
  181. case .success(let val):
  182. //DDLogDebug(val)
  183. let json = JSON(val)
  184. if json["type"] == "success" {
  185. self.showSuccess(title: "删除成功")
  186. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3, execute: {
  187. // 删除之后没有这个工作了,所以直接返回列表 防止返回到已办的TodoedTaskViewController
  188. if self.backFlag == 4 {
  189. self.backFlag = 2
  190. }
  191. self.goBack()
  192. })
  193. }else{
  194. DDLogError(json.description)
  195. self.showError(title: "删除失败")
  196. }
  197. case .failure(let err):
  198. DDLogError(err.localizedDescription)
  199. self.showError(title: "删除失败")
  200. }
  201. }
  202. })
  203. }
  204. @objc func itemBtnDocSaveAction() {
  205. DDLogDebug("btnSaveDoc Click")
  206. self.showLoading(title: "保存中...")
  207. self.setupData()
  208. group.notify(queue: DispatchQueue.main) {
  209. if self.isJSExecuted {
  210. let url = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskContext.taskDataContextKey, query: TaskContext.taskDataSaveQuery, parameter: ["##id##":self.taskProcess.workId! as AnyObject])
  211. Alamofire.request(url!,method:.put, parameters: self.taskProcess.businessDataDict!, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
  212. switch response.result {
  213. case .success(let val):
  214. //DDLogDebug(val)
  215. let json = JSON(val)
  216. if json["type"] == "success" {
  217. self.showSuccess(title: "保存成功")
  218. }else{
  219. DDLogError(json.description)
  220. self.showError(title: "保存失败")
  221. }
  222. case .failure(let err):
  223. DDLogError(err.localizedDescription)
  224. self.showError(title: "保存失败")
  225. }
  226. }
  227. }else{
  228. self.showError(title: "保存失败")
  229. }
  230. }
  231. }
  232. //提供给TodoTaskProcessViewController使用的 提交之前也要验证一次表单,根据传入的路由和意见来判断表单
  233. @objc func checkFormBeforeProcessSubmit(routeName:String, opinion:String, callback: @escaping (Bool) -> Void) {
  234. let js = "layout.appForm.formValidation('\(routeName)', '\(opinion)')"
  235. DDLogDebug("执行验证:\(js)")
  236. webView.evaluateJavaScript(js) { (data, err) in
  237. if let str = data {
  238. if str is Bool {
  239. callback((str as! Bool))
  240. }else {
  241. let isVaild = str as? String
  242. if isVaild == "true" {
  243. callback(true)
  244. }else {
  245. callback(false)
  246. }
  247. }
  248. }else {
  249. DDLogError("没有返回值。。。。。。。。。")
  250. callback(false)
  251. }
  252. }
  253. }
  254. @objc func itemBtnNextProcessAction() {
  255. DDLogDebug("btnNext Process")
  256. //校验表单
  257. webView.evaluateJavaScript(TodoTaskJS.CHECK_FORM) { (data, err) in
  258. if let str = data {
  259. let isVaild = str as! Bool
  260. if isVaild == true {
  261. self.setupData()
  262. self.group.notify(queue: DispatchQueue.main, execute: {
  263. self.performSegue(withIdentifier: "showTodoProcessSegue", sender: nil)
  264. })
  265. }else{
  266. DDLogError("表单验证失败。。。。。。。。。。。。")
  267. self.showError(title: "表单验证失败,请正确填写表单内容")
  268. }
  269. }else {
  270. DDLogError("没有返回值。。。。。。。。。")
  271. self.showError(title: "表单验证失败,请正确填写表单内容")
  272. }
  273. }
  274. // let str = self.todoWebView.stringByEvaluatingJavaScript(from: TodoTaskJS.CHECK_FORM)
  275. // //let str = "true"
  276. // if str == "true" {
  277. // DDLogDebug("next Step")
  278. // self.setupData()
  279. // self.performSegue(withIdentifier: "showTodoProcessSegue", sender: nil)
  280. // }
  281. }
  282. @objc func itemBtnReadDocAction() {
  283. DDLogDebug("readButtonAction")
  284. let url = AppDelegate.o2Collect.generateURLWithAppContextKey(ReadContext.readContextKey, query: ReadContext.readProcessing, parameter: ["##id##":(todoTask?.id)! as AnyObject])
  285. self.showLoading(title: "提交中...")
  286. Alamofire.request(url!, method:.post, parameters: myRead, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
  287. switch response.result {
  288. case .success(let val):
  289. DDLogDebug(JSON(val).description)
  290. let json = JSON(val)
  291. if json["type"]=="success"{
  292. self.showSuccess(title: "提交成功")
  293. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3, execute: {
  294. self.goBack()
  295. })
  296. }else {
  297. DDLogError(json["message"].description)
  298. self.showError(title: "提交失败")
  299. }
  300. case .failure(let err):
  301. DDLogError(err.localizedDescription)
  302. self.showError(title: "提交失败")
  303. }
  304. }
  305. }
  306. @objc func itemBtnRetractDocAction() {
  307. DDLogDebug("撤回开始。。。")
  308. let url = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskedContext.taskedContextKey, query: TaskedContext.taskedRetractQuery, parameter: ["##work##":(self.workId)! as AnyObject])
  309. self.showLoading(title: "提交中...")
  310. Alamofire.request(url!, method:.put, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
  311. switch response.result {
  312. case .success(let val):
  313. DDLogDebug(JSON(val).description)
  314. let json = JSON(val)
  315. if json["type"]=="success"{
  316. self.showSuccess(title: "提交成功")
  317. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3, execute: {
  318. self.goBack()
  319. })
  320. }else {
  321. DDLogError(json["message"].description)
  322. self.showError(title: "提交失败")
  323. }
  324. case .failure(let err):
  325. DDLogError(err.localizedDescription)
  326. self.showError(title: "提交失败")
  327. }
  328. }
  329. }
  330. // 网页加载完成后,获取表单数据 判断是什么表单 待办 待阅 已办 已阅
  331. private func loadDataFromWork() {
  332. // 加载read 对象 如果是待阅工作 设置已阅时需要用到
  333. group.enter()
  334. DispatchQueue.main.async(group: group, execute: DispatchWorkItem(block: {
  335. DDLogDebug("执行 \(TodoTaskJS.DATA_READ)")
  336. self.webView.evaluateJavaScript(TodoTaskJS.DATA_READ, completionHandler: { (data, err) in
  337. if err == nil && data != nil {
  338. let json = JSON.init(parseJSON: data as! String)
  339. self.myRead = json.dictionaryObject! as [String: AnyObject]
  340. }else {
  341. DDLogError(String(describing: err))
  342. }
  343. self.group.leave()
  344. })
  345. }))
  346. // 加载control 是否能撤回
  347. group.enter()
  348. DispatchQueue.main.async(group: group, execute: DispatchWorkItem(block: {
  349. DDLogDebug("执行 \(TodoTaskJS.DATA_CONTROL)")
  350. self.webView.evaluateJavaScript(TodoTaskJS.DATA_CONTROL, completionHandler: { (data, err) in
  351. if err == nil && data != nil {
  352. let json = JSON.init(parseJSON: (data as! String))
  353. DDLogDebug("control: \(data as! String)")
  354. self.myControl = json.dictionaryObject! as [String: AnyObject]
  355. }else {
  356. DDLogError(String(describing: err))
  357. }
  358. self.group.leave()
  359. })
  360. }))
  361. if myTitle == nil || myTitle!.trim().isEmpty {
  362. group.enter()
  363. DispatchQueue.main.async(group: group, execute: DispatchWorkItem(block: {
  364. DDLogDebug("执行 \(TodoTaskJS.DATA_WORK_TITLE)")
  365. self.webView.evaluateJavaScript(TodoTaskJS.DATA_WORK_TITLE, completionHandler: { (data, err) in
  366. if err == nil && data != nil {
  367. self.myTitle = data as? String
  368. self.title = self.myTitle ?? ""
  369. }else {
  370. DDLogError(String(describing: err))
  371. }
  372. self.group.leave()
  373. })
  374. }))
  375. }
  376. group.notify(queue: DispatchQueue.main) {
  377. self.setupToolbarItems()
  378. }
  379. }
  380. //20190522 新版底部操作栏
  381. private func setupToolbarItemsNew() {
  382. var items: [UIBarButtonItem] = []
  383. let spaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
  384. if self.myNewControls.count > 0 {
  385. let action = self.myNewControls[0]
  386. let firstButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  387. firstButton.setTitle(action.text, for: .normal)
  388. firstButton.setTitleColor(base_color, for: .normal)
  389. firstButton.addTapGesture { (tap) in
  390. self.clickNewActionButton(action: action)
  391. }
  392. let firstButtonItem = UIBarButtonItem(customView: firstButton)
  393. items.append(spaceItem)
  394. items.append(firstButtonItem)
  395. items.append(spaceItem)
  396. }
  397. if self.myNewControls.count > 1 {
  398. let action = self.myNewControls[1]
  399. let secondButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  400. secondButton.setTitle(action.text, for: .normal)
  401. secondButton.setTitleColor(base_color, for: .normal)
  402. secondButton.addTapGesture { (tap) in
  403. self.clickNewActionButton(action: action)
  404. }
  405. let secondButtonItem = UIBarButtonItem(customView: secondButton)
  406. items.append(spaceItem)
  407. items.append(secondButtonItem)
  408. items.append(spaceItem)
  409. }
  410. // 更多按钮
  411. if self.myNewControls.count > 2 {
  412. let moreButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  413. moreButton.setImage(UIImage(named: "icon_more_s"), for: .normal)
  414. moreButton.addTapGesture { (tap) in
  415. self.moreActionMenus?.show()
  416. }
  417. let moreButtonItem = UIBarButtonItem(customView: moreButton)
  418. items.append(moreButtonItem)
  419. self.moreActionMenus = O2WorkMoreActionSheet(moreControls: self.myNewControls) { item in
  420. self.clickNewActionButton(action: item)
  421. }
  422. }
  423. if items.count > 0 {
  424. self.layoutBottomBar(items: items)
  425. }
  426. }
  427. //新版操作按钮点击动作
  428. private func clickNewActionButton(action: WorkNewActionItem) {
  429. DDLogDebug("click .....\(action.text)")
  430. let actionScript = action.actionScript
  431. if actionScript != "" {
  432. let jsExc = "layout.app.appForm._runCustomAction(\(actionScript))"
  433. DDLogDebug(jsExc)
  434. DispatchQueue.main.async {
  435. self.webView.evaluateJavaScript(jsExc) { (data, err) in
  436. DDLogDebug("actionScript excute finish!!!!")
  437. }
  438. }
  439. }else {
  440. let control = action.control
  441. switch control {
  442. case "allowDelete":
  443. self.itemBtnDocDeleteAction()
  444. break
  445. case "allowSave":
  446. self.itemBtnDocSaveAction()
  447. break
  448. case "allowProcessing":
  449. self.itemBtnNextProcessAction()
  450. break
  451. case "allowReadProcessing":
  452. self.itemBtnReadDocAction()
  453. break
  454. case "allowRetract":
  455. self.itemBtnRetractDocAction()
  456. break
  457. default:
  458. let jsExc = "layout.app.appForm[\"\(action.action)\"]()"
  459. DDLogDebug(jsExc)
  460. DispatchQueue.main.async {
  461. self.webView.evaluateJavaScript(jsExc) { (data, err) in
  462. DDLogDebug("actionScript excute finish!!!!")
  463. }
  464. }
  465. }
  466. }
  467. }
  468. private func setupToolbarItems() {
  469. DDLogDebug("setupToolbarItems 处理底部按钮, 根据control")
  470. if self.myNewControls.count > 0 { //新版操作按钮
  471. self.setupToolbarItemsNew()
  472. }else {
  473. var items: [UIBarButtonItem] = []
  474. if self.myControl != nil {
  475. let spaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
  476. if let allowDelete = self.myControl!["allowDelete"] as? Bool {
  477. if allowDelete { //删除工作
  478. DDLogDebug("删除工作。。。。。。。。。。。。。。。。。。。。。。安装按钮")
  479. let deleteBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  480. deleteBtn.setTitle("删除", for: .normal)
  481. deleteBtn.setTitleColor(base_color, for: .normal)
  482. deleteBtn.addTapGesture { (tap) in
  483. self.itemBtnDocDeleteAction()
  484. }
  485. let deleteItem = UIBarButtonItem(customView: deleteBtn)
  486. items.append(spaceItem)
  487. items.append(deleteItem)
  488. items.append(spaceItem)
  489. }
  490. }
  491. if let allowSave = self.myControl!["allowSave"] as? Bool {
  492. if allowSave {// 保存工作
  493. DDLogDebug("保存工作。。。。。。。。。。。。。。。。。。。。。。安装按钮")
  494. let saveBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  495. saveBtn.setTitle("保存", for: .normal)
  496. saveBtn.setTitleColor(base_color, for: .normal)
  497. saveBtn.addTapGesture { (tap) in
  498. self.itemBtnDocSaveAction()
  499. }
  500. let saveItem = UIBarButtonItem(customView: saveBtn)
  501. items.append(spaceItem)
  502. items.append(saveItem)
  503. items.append(spaceItem)
  504. }
  505. }
  506. if let allowProcessing = self.myControl!["allowProcessing"] as? Bool {
  507. if allowProcessing { // 待办工作
  508. DDLogDebug("待办工作。。。。。。。。。。。。。。。。。。。。。。安装按钮")
  509. let processingBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  510. processingBtn.setTitle("继续流转", for: .normal)
  511. processingBtn.setTitleColor(base_color, for: .normal)
  512. processingBtn.addTapGesture { (tap) in
  513. self.itemBtnNextProcessAction()
  514. }
  515. let processingItem = UIBarButtonItem(customView: processingBtn)
  516. items.append(spaceItem)
  517. items.append(processingItem)
  518. items.append(spaceItem)
  519. }
  520. }
  521. if let allowReadProcessing = self.myControl!["allowReadProcessing"] as? Bool {
  522. if allowReadProcessing { // 待阅 工作
  523. DDLogDebug("待阅工作。。。。。。。。。。。。。。。。。。。。。。安装按钮")
  524. let readBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  525. readBtn.setTitle("已阅", for: .normal)
  526. readBtn.setTitleColor(base_color, for: .normal)
  527. readBtn.addTapGesture { (tap) in
  528. self.itemBtnReadDocAction()
  529. }
  530. let readItem = UIBarButtonItem(customView: readBtn)
  531. items.append(spaceItem)
  532. items.append(readItem)
  533. items.append(spaceItem)
  534. }
  535. }
  536. if let allowRetract = self.myControl!["allowRetract"] as? Bool {
  537. if allowRetract { // 撤回
  538. DDLogDebug("可以撤回。。。。。。。。。。。。。。。。。。。。。。安装按钮")
  539. let retractBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  540. retractBtn.setTitle("撤回", for: .normal)
  541. retractBtn.setTitleColor(base_color, for: .normal)
  542. retractBtn.addTapGesture { (tap) in
  543. self.itemBtnRetractDocAction()
  544. }
  545. let retractItem = UIBarButtonItem(customView: retractBtn)
  546. items.append(spaceItem)
  547. items.append(retractItem)
  548. items.append(spaceItem)
  549. }
  550. }
  551. self.layoutBottomBar(items: items)
  552. NSLog("\(self.view.subviews)");
  553. }else {
  554. DDLogError("没有control 数据异常 按钮无法计算。。。。")
  555. }
  556. }
  557. }
  558. private func layoutBottomBar(items: [UIBarButtonItem]) {
  559. if items.count > 0 {
  560. self.toolbarView.items = items
  561. self.hasToolbar = true
  562. self.view.addSubview(self.toolbarView)
  563. self.toolbarView.translatesAutoresizingMaskIntoConstraints = false
  564. let heightC = NSLayoutConstraint(item: self.toolbarView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 0.0, constant: 44)
  565. self.toolbarView.addConstraint(heightC)
  566. let bottom = NSLayoutConstraint(item: self.toolbarView, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: 0)
  567. let trailing = NSLayoutConstraint(item: self.toolbarView, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: 0)
  568. let leading = NSLayoutConstraint(item: self.toolbarView, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1, constant: 0)
  569. self.view.addConstraints([bottom, leading, trailing])
  570. self.view.constraints.forEach { (constraint) in
  571. if constraint.identifier == "webViewBottomConstraint" {
  572. self.view.removeConstraint(constraint)
  573. }
  574. }
  575. let webcTop = NSLayoutConstraint(item: self.webViewContainer, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.toolbarView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 0)
  576. self.view.addConstraint(webcTop)
  577. self.view.layoutIfNeeded()
  578. }
  579. }
  580. /**
  581. * 读取从页面载入的业务及流程数据,建立数据模型
  582. */
  583. func setupData(){
  584. group.enter()
  585. DispatchQueue.main.async(group: group, execute: DispatchWorkItem(block: {
  586. DDLogInfo("opinion queue .....")
  587. self.webView.evaluateJavaScript(TodoTaskJS.DATA_OPINION, completionHandler: { (data, err) in
  588. if err == nil && data != nil {
  589. let opinion = data as! String
  590. DDLogInfo("opinion: \(opinion)")
  591. if opinion == "\"\"" {
  592. self.taskProcess.opinion = ""
  593. }else {
  594. let json = JSON.init(parseJSON: opinion)
  595. let oJson = json.dictionaryObject as [String : AnyObject]?
  596. let op = oJson?["opinion"] as? String
  597. self.taskProcess.opinion = op
  598. }
  599. }else {
  600. DDLogError(String(describing: err))
  601. }
  602. self.group.leave()
  603. })
  604. }))
  605. group.enter()
  606. DispatchQueue.main.async(group: group, execute: DispatchWorkItem(block: {
  607. DDLogDebug("taskQueue 1")
  608. self.webView.evaluateJavaScript(TodoTaskJS.DATA_TASK) { (data, err) in
  609. if err == nil && data != nil {
  610. DDLogDebug("taskQueue complete")
  611. let json = JSON.init(parseJSON: data as! String)
  612. self.taskProcess.taskDict = json.dictionaryObject! as [String : AnyObject]
  613. self.taskProcess.taskId = self.taskProcess.taskDict!["id"] as? String
  614. self.taskProcess.decisonList = self.taskProcess.taskDict!["routeNameList"] as? [String]
  615. }else{
  616. DDLogError(String(describing: err))
  617. self.isJSExecuted = false
  618. }
  619. self.group.leave()
  620. }
  621. }))
  622. group.enter()
  623. DispatchQueue.main.async(group: group, execute: DispatchWorkItem(block: {
  624. DDLogDebug("workQueue 1")
  625. self.webView.evaluateJavaScript(TodoTaskJS.DATA_WORK) { (data, err) in
  626. if err == nil && data != nil {
  627. DDLogDebug("workQueue complete")
  628. let json = JSON.init(parseJSON: data as! String)
  629. self.taskProcess.workDict = json.dictionaryObject! as [String : AnyObject]
  630. self.taskProcess.workId = self.taskProcess.workDict!["id"] as? String
  631. }else{
  632. DDLogError(String(describing: err))
  633. self.isJSExecuted = false
  634. }
  635. self.group.leave()
  636. }
  637. }))
  638. group.enter()
  639. DispatchQueue.main.async(group: group, execute: DispatchWorkItem(block: {
  640. DDLogDebug("businessQueue 1")
  641. self.webView.evaluateJavaScript(TodoTaskJS.DATA_BUSINESS) { (data, err) in
  642. if err == nil && data != nil {
  643. DDLogDebug("businessQueue complete")
  644. let json = JSON.init(parseJSON: data as! String)
  645. self.taskProcess.businessDataDict = json.dictionaryObject! as [String : AnyObject]
  646. //do {
  647. //}catch{
  648. //DDLogError("set routeNameList Error")
  649. //}
  650. }else{
  651. DDLogError(String(describing: err))
  652. self.isJSExecuted = false
  653. }
  654. self.group.leave()
  655. }
  656. }))
  657. }
  658. }
  659. //MARK: - extension
  660. extension TodoTaskDetailViewController:WKNavigationDelegate,WKUIDelegate {
  661. func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
  662. DDLogDebug("didStartProvisionalNavigation")
  663. }
  664. func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
  665. DDLogDebug("didCommit")
  666. }
  667. func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
  668. DDLogDebug("didFinish")
  669. }
  670. func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
  671. DDLogDebug("didFail")
  672. DDLogError(error.localizedDescription)
  673. self.showError(title: "工作加载异常!")
  674. }
  675. }
  676. extension TodoTaskDetailViewController: O2WKScriptMessageHandlerImplement {
  677. func userController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
  678. let name = message.name
  679. switch name {
  680. case "closeWork":
  681. DDLogError("执行了closeWork。。。。。。。。。。")
  682. self.goBack()
  683. break
  684. case "appFormLoaded":
  685. DDLogDebug("appFormLoaded 当前方法已经弃用。。。。")
  686. // if let newControls = (message.body as? NSString) {
  687. // let str = newControls as String
  688. // DDLogDebug("appFormLoaded , controls :\(str)")
  689. // if str != "true" {
  690. // myNewControls.removeAll()
  691. // if let controls = [WorkNewActionItem].deserialize(from: str) {
  692. // controls.forEach { (item) in
  693. // if item != nil {
  694. // myNewControls.append(item!)
  695. // }
  696. // }
  697. // }
  698. // }
  699. // }
  700. // self.loadDataFromWork()
  701. break
  702. case "uploadAttachment":
  703. ZonePermissions.requestImagePickerAuthorization(callback: { (zoneStatus) in
  704. if zoneStatus == ZoneAuthorizationStatus.zAuthorizationStatusAuthorized {
  705. let site = (message.body as! NSDictionary)["site"]
  706. self.uploadAttachment(site as! String)
  707. }else {
  708. //显示
  709. self.gotoApplicationSettings(alertMessage: "需要照片允许访问权限,是否跳转到手机设置页面开启相机权限?")
  710. }
  711. })
  712. break
  713. case "downloadAttachment":
  714. let attachmentId = (message.body as! NSDictionary)["id"]
  715. self.downloadAttachment(attachmentId as! String)
  716. break
  717. case "replaceAttachment":
  718. let attachmentId = (message.body as! NSDictionary)["id"] as! String
  719. let site = (message.body as! NSDictionary)["site"] as? String
  720. self.replaceAttachment(attachmentId, site ?? "")
  721. break
  722. case "openDocument":
  723. let url = (message.body as! NSString)
  724. self.downloadDocumentAndPreview(String(url))
  725. break
  726. default:
  727. DDLogError("未知方法名:\(name)!")
  728. break
  729. }
  730. }
  731. //上传附件
  732. private func uploadAttachment(_ site:String){
  733. //选择附件上传
  734. let updloadURL = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskContext.taskContextKey, query: TaskContext.todoTaskUploadAttachmentQuery, parameter: ["##workId##":workId as AnyObject])
  735. self.uploadAttachment(site, uploadURL: updloadURL!)
  736. }
  737. private func uploadAttachment(_ site:String,uploadURL url:String){
  738. let vc = FileBSImagePickerViewController()
  739. bs_presentImagePickerController(vc, animated: true,
  740. select: { (asset: PHAsset) -> Void in
  741. // User selected an asset.
  742. // Do something with it, start upload perhaps?
  743. }, deselect: { (asset: PHAsset) -> Void in
  744. // User deselected an assets.
  745. // Do something, cancel upload?
  746. }, cancel: { (assets: [PHAsset]) -> Void in
  747. // User cancelled. And this where the assets currently selected.
  748. }, finish: { (assets: [PHAsset]) -> Void in
  749. for asset in assets {
  750. switch asset.mediaType {
  751. case .audio:
  752. DDLogDebug("Audio")
  753. case .image:
  754. let options = PHImageRequestOptions()
  755. options.isSynchronous = true
  756. options.deliveryMode = .fastFormat
  757. options.resizeMode = .none
  758. PHImageManager.default().requestImageData(for: asset, options: options, resultHandler: { (imageData, result, imageOrientation, dict) in
  759. //DDLogDebug("result = \(result) imageOrientation = \(imageOrientation) \(dict)")
  760. let fileURL = dict?["PHImageFileURLKey"] as! URL
  761. DispatchQueue.main.async {
  762. self.showLoading(title: "上传中...")
  763. }
  764. DispatchQueue.global(qos: .userInitiated).async {
  765. Alamofire.upload(multipartFormData: { (mData) in
  766. //mData.append(fileURL, withName: "file")
  767. mData.append(imageData!, withName: "file", fileName: fileURL.lastPathComponent, mimeType: "application/octet-stream")
  768. let siteData = site.data(using: String.Encoding.utf8, allowLossyConversion: false)
  769. mData.append(siteData!, withName: "site")
  770. }, to: url, encodingCompletion: { (encodingResult) in
  771. switch encodingResult {
  772. case .success(let upload, _, _):
  773. debugPrint(upload)
  774. upload.responseJSON {
  775. respJSON in
  776. switch respJSON.result {
  777. case .success(let val):
  778. let attachId = JSON(val)["data"]["id"].string!
  779. DispatchQueue.main.async {
  780. //ProgressHUD.showSuccess("上传成功")
  781. let callJS = "layout.appForm.uploadedAttachment(\"\(site)\", \"\(attachId)\")"
  782. self.webView.evaluateJavaScript(callJS, completionHandler: { (result, err) in
  783. self.showSuccess(title: "上传成功")
  784. })
  785. }
  786. case .failure(let err):
  787. DispatchQueue.main.async {
  788. DDLogError(err.localizedDescription)
  789. self.showError(title: "上传失败")
  790. }
  791. break
  792. }
  793. }
  794. case .failure(let errType):
  795. DispatchQueue.main.async {
  796. DDLogError(errType.localizedDescription)
  797. self.showError(title: "上传失败")
  798. }
  799. }
  800. })
  801. }
  802. })
  803. case .video:
  804. DDLogDebug("Unknown")
  805. case .unknown:
  806. DDLogDebug("Unknown")
  807. }
  808. }
  809. }, completion: nil)
  810. }
  811. //下载预览附件
  812. private func downloadAttachment(_ attachmentId:String){
  813. //生成两个URL,一个获取附件信息,一个链接正式下载
  814. var infoURL:String?,downURL:String?
  815. if isWorkCompeleted {
  816. infoURL = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskedContext.taskedContextKey, query: TaskedContext.taskedGetAttachmentInfoQuery, parameter: ["##attachmentId##":attachmentId as AnyObject,"##workcompletedId##":workId as AnyObject])
  817. downURL = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskedContext.taskedContextKey, query: TaskedContext.taskedGetAttachmentQuery, parameter:["##attachmentId##":attachmentId as AnyObject,"##workcompletedId##":workId as AnyObject])
  818. }else{
  819. infoURL = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskContext.taskContextKey, query: TaskContext.todoTaskGetAttachmentInfoQuery, parameter: ["##attachmentId##":attachmentId as AnyObject,"##workId##":workId as AnyObject])
  820. downURL = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskContext.taskContextKey, query: TaskContext.todoTaskGetAttachmentQuery, parameter:["##attachmentId##":attachmentId as AnyObject,"##workId##":workId as AnyObject])
  821. }
  822. self.showAttachViewInController(infoURL!, downURL!)
  823. }
  824. private func showAttachViewInController(_ infoURL:String,_ downURL:String){
  825. self.showLoading(title: "下载中...")
  826. DDLogDebug("infoUrl:\(infoURL) ,down url:\(downURL)")
  827. Alamofire.request(infoURL).responseJSON { (response) in
  828. switch response.result {
  829. case .success(let val):
  830. //DDLogDebug(JSON(val).description)
  831. let info = Mapper<O2TaskAttachmentInfo>().map(JSONString: JSON(val).description)
  832. //执行下载
  833. let destination: DownloadRequest.DownloadFileDestination = { _, _ in
  834. let documentsURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
  835. let fileURL = documentsURL.appendingPathComponent((info?.data?.name)!)
  836. return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
  837. }
  838. Alamofire.download(downURL, to: destination).response(completionHandler: { (response) in
  839. if response.error == nil , let fileurl = response.destinationURL?.path {
  840. //打开文件
  841. self.hideLoading()
  842. self.previewAttachment(fileurl)
  843. }else{
  844. DispatchQueue.main.async {
  845. self.showError(title: "预览文件出错")
  846. }
  847. }
  848. })
  849. break
  850. case .failure(let err):
  851. DDLogError(err.localizedDescription)
  852. DispatchQueue.main.async {
  853. self.showError(title: "预览文件出错")
  854. }
  855. break
  856. }
  857. }
  858. }
  859. //替换附件
  860. private func replaceAttachment(_ attachmentId:String, _ site:String){
  861. //替换结束后回调js名称
  862. let replaceURL = AppDelegate.o2Collect.generateURLWithAppContextKey(TaskContext.taskContextKey, query: TaskContext.todoTaskUpReplaceAttachmentQuery, parameter: ["##attachmentId##":attachmentId as AnyObject,"##workId##":workId as AnyObject])!
  863. self.replaceAttachment(site, attachmentId, replaceURL: replaceURL)
  864. }
  865. /**
  866. * 下载公文 并阅览
  867. **/
  868. private func downloadDocumentAndPreview(_ url: String) {
  869. DDLogDebug("文档下载地址:\(url)")
  870. self.showLoading(title: "下载中...")
  871. // 文件地址
  872. let localFileDestination: DownloadRequest.DownloadFileDestination = { _, response in
  873. let documentsURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
  874. let fileURL = documentsURL.appendingPathComponent(response.suggestedFilename!)
  875. // 有重名文件就删除重建
  876. return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
  877. }
  878. Alamofire.download(url, to: localFileDestination).response(completionHandler: { (response) in
  879. if response.error == nil , let fileurl = response.destinationURL?.path {
  880. DDLogDebug("文件地址:\(fileurl)")
  881. let newUrl = self.dealDocFileSaveAsDocx(fileUrl: response.destinationURL!)
  882. DDLogDebug("处理过的文件地址:\(newUrl.path)")
  883. //打开文件
  884. self.hideLoading()
  885. self.previewAttachment(newUrl.path)
  886. }else{
  887. let msg = response.error?.localizedDescription ?? ""
  888. DDLogError("下载文件出错,\(msg)")
  889. DispatchQueue.main.async {
  890. self.showError(title: "预览文件出错")
  891. }
  892. }
  893. })
  894. }
  895. private func replaceAttachment(_ site:String,_ attachmentId:String,replaceURL url:String){
  896. let vc = FileBSImagePickerViewController()
  897. bs_presentImagePickerController(vc, animated: true,
  898. select: { (asset: PHAsset) -> Void in
  899. // User selected an asset.
  900. // Do something with it, start upload perhaps?
  901. }, deselect: { (asset: PHAsset) -> Void in
  902. // User deselected an assets.
  903. // Do something, cancel upload?
  904. }, cancel: { (assets: [PHAsset]) -> Void in
  905. // User cancelled. And this where the assets currently selected.
  906. }, finish: { (assets: [PHAsset]) -> Void in
  907. for asset in assets {
  908. switch asset.mediaType {
  909. case .audio:
  910. DDLogDebug("Audio")
  911. case .image:
  912. let options = PHImageRequestOptions()
  913. options.isSynchronous = true
  914. options.deliveryMode = .fastFormat
  915. options.resizeMode = .none
  916. PHImageManager.default().requestImageData(for: asset, options: options, resultHandler: { (imageData, result, imageOrientation, dict) in
  917. //DDLogDebug("result = \(result) imageOrientation = \(imageOrientation) \(dict)")
  918. let fileURL = dict?["PHImageFileURLKey"] as! URL
  919. DispatchQueue.main.async {
  920. self.showLoading(title: "上传中...")
  921. }
  922. DispatchQueue.global(qos: .userInitiated).async {
  923. Alamofire.upload(multipartFormData: { (mData) in
  924. //mData.append(fileURL, withName: "file")
  925. mData.append(imageData!, withName: "file", fileName: fileURL.lastPathComponent, mimeType: "application/octet-stream")
  926. let siteData = site.data(using: String.Encoding.utf8, allowLossyConversion: false)
  927. mData.append(siteData!, withName: "site")
  928. }, usingThreshold: SessionManager.multipartFormDataEncodingMemoryThreshold, to: url, method: .put, headers: nil, encodingCompletion: { (encodingResult) in
  929. switch encodingResult {
  930. case .success(let upload, _, _):
  931. debugPrint(upload)
  932. upload.responseJSON {
  933. respJSON in
  934. switch respJSON.result {
  935. case .success( _):
  936. //let attachId = JSON(val)["data"]["id"].string!
  937. DispatchQueue.main.async {
  938. //ProgressHUD.showSuccess("上传成功")
  939. let callJS = "layout.appForm.replacedAttachment(\"\(site)\", \"\(attachmentId)\")"
  940. self.webView.evaluateJavaScript(callJS, completionHandler: { (result, err) in
  941. self.showSuccess(title: "替换成功")
  942. })
  943. }
  944. case .failure(let err):
  945. DispatchQueue.main.async {
  946. DDLogError(err.localizedDescription)
  947. self.showError(title: "替换失败")
  948. }
  949. break
  950. }
  951. }
  952. case .failure(let errType):
  953. DispatchQueue.main.async {
  954. DDLogError(errType.localizedDescription)
  955. self.showError(title: "替换失败")
  956. }
  957. }
  958. })
  959. }
  960. })
  961. case .video:
  962. let options = PHVideoRequestOptions()
  963. options.deliveryMode = .fastFormat
  964. options.isNetworkAccessAllowed = true
  965. options.progressHandler = { (progress,err, stop,dict) in
  966. DDLogDebug("progress = \(progress) dict = \(String(describing: dict))")
  967. }
  968. PHImageManager.default().requestAVAsset(forVideo: asset, options: options, resultHandler: { (avAsset, avAudioMx, dict) in
  969. })
  970. case .unknown:
  971. DDLogDebug("Unknown")
  972. }
  973. }
  974. }, completion: nil)
  975. }
  976. private func previewAttachment(_ url:String){
  977. let currentURL = NSURL(fileURLWithPath: url)
  978. if QLPreviewController.canPreview(currentURL) {
  979. qlController.currentFileURLS.removeAll(keepingCapacity: true)
  980. qlController.currentFileURLS.append(currentURL)
  981. qlController.reloadData()
  982. if #available(iOS 10, *) {
  983. let navVC = ZLNormalNavViewController(rootViewController: qlController)
  984. qlController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "关闭", style: .plain, target: qlController, action: #selector(qlController.qlCloseWindow))
  985. self.presentVC(navVC)
  986. }else{
  987. self.pushVC(qlController)
  988. }
  989. }else{
  990. self.showError(title: "此文件无法预览,请在PC端查看")
  991. }
  992. }
  993. //处理特殊情况 docx的文件有可能是doc 需要判断下文件信息头
  994. private func dealDocFileSaveAsDocx(fileUrl: URL) -> URL {
  995. if fileUrl.pathExtension == "docx" {
  996. if let data = try? Data(contentsOf: fileUrl) {
  997. let mimeType = Swime.mimeType(data: data)
  998. if mimeType?.type == .msi {
  999. let newURL = fileUrl.appendingPathExtension("doc")
  1000. do {
  1001. DDLogDebug("copy 了一个 文件。。。。。。")
  1002. try FileManager.default.copyItem(at: fileUrl, to: newURL)
  1003. return newURL
  1004. }catch {
  1005. DDLogError(error.localizedDescription)
  1006. }
  1007. }
  1008. }
  1009. }
  1010. return fileUrl
  1011. }
  1012. }