TodoTaskDetailViewController.swift 59 KB

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