TodoTaskDetailViewController.swift 56 KB

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