123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- //
- // BaseWebViewUIViewController.swift
- // O2Platform
- //
- // Created by 刘振兴 on 2016/10/11.
- // Copyright © 2016年 zoneland. All rights reserved.
- //
- import UIKit
- import WebKit
- import CocoaLumberjack
- import QuickLook
- protocol BaseWebViewUIViewControllerJSDelegate {
- func closeUIViewWindow()
- func actionBarLoaded(show: Bool)
- }
- protocol O2WKScriptMessageHandlerImplement {
- func userController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
- }
- class BaseWebViewUIViewController: O2BaseForRotateUIViewController {
-
- var webView:WKWebView!
- var delegate: BaseWebViewUIViewControllerJSDelegate?
- var o2WKScriptHandlers: [String : O2WKScriptMessageHandlerImplement] = [:]
-
- //定位用
- var locationCallBack: (String?) -> Void = {(result) in }
- private var locService: BMKLocationManager?
- private var searchAddress: BMKGeoCodeSearch?
-
-
- //继承的子类如果要添加MessageHandler必须在theWebView方法前使用
- func addScriptMessageHandler(key: String, handler: O2WKScriptMessageHandlerImplement) {
- o2WKScriptHandlers[key] = handler
- }
-
-
-
- open func theWebView(){
- let baseJsHandler = O2BaseJsMessageHandler(viewController: self)
- // bbs 回复
- addScriptMessageHandler(key: "ReplyAction", handler: baseJsHandler)
- // protal已经存在ActionBar
- addScriptMessageHandler(key: "actionBarLoaded", handler: baseJsHandler)
- // 打开工作 {"work":"", "workCompleted":"", "title":""}
- addScriptMessageHandler(key: "openO2Work", handler: baseJsHandler)
- // 4个分类 task taskCompleted read readCompleted
- addScriptMessageHandler(key: "openO2WorkSpace", handler: baseJsHandler)
- // 打开cms appId
- addScriptMessageHandler(key: "openO2CmsApplication", handler: baseJsHandler)
- // 打开cms docId docTitle
- addScriptMessageHandler(key: "openO2CmsDocument", handler: baseJsHandler)
- // 打开meeting
- addScriptMessageHandler(key: "openO2Meeting", handler: baseJsHandler)
- // 打开 calendar
- addScriptMessageHandler(key: "openO2Calendar", handler: baseJsHandler)
- // 打开扫一扫
- addScriptMessageHandler(key: "openScan", handler: baseJsHandler)
-
- addScriptMessageHandler(key: "openO2Alert", handler: baseJsHandler)
- // 打开钉钉
- addScriptMessageHandler(key: "openDingtalk", handler: baseJsHandler)
- // 关闭当前UIViewController
- addScriptMessageHandler(key:"closeNativeWindow", handler: baseJsHandler)
- // 表单的图片控件
- addScriptMessageHandler(key: "uploadImage2FileStorage", handler: baseJsHandler)
- // 打印日志
- addScriptMessageHandler(key: "o2mLog", handler: baseJsHandler)
-
- //o2m.notification
- let o2Notification = O2JsApiNotification(viewController: self)
- addScriptMessageHandler(key: "o2mNotification", handler: o2Notification)
- //o2m.util
- let o2Util = O2JsApiUtil(viewController: self)
- addScriptMessageHandler(key: "o2mUtil", handler: o2Util)
- // o2m.biz
- let biz = O2JsApiBizUtil(viewController: self)
- addScriptMessageHandler(key: "o2mBiz", handler: biz)
-
- setupWebView()
- }
-
-
- public func setupWebView() {
- let userContentController = WKUserContentController()
- //cookie脚本
- if let cookies = HTTPCookieStorage.shared.cookies {
- let script = getJSCookiesString(cookies: cookies)
- let cookieScript = WKUserScript(source: script, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
- userContentController.addUserScript(cookieScript)
- }
- // console.log 打印到ios log debug用
- let consoleLog = "console.log = (function(oriLogFunc){return function(str){window.webkit.messageHandlers.o2mLog.postMessage(str);oriLogFunc.call(console,str);} })(console.log);"
- let logScript = WKUserScript(source: consoleLog, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
- userContentController.addUserScript(logScript)
- let webViewConfig = WKWebViewConfiguration()
- webViewConfig.userContentController = userContentController
- //加入js-app message handler
- for item in o2WKScriptHandlers {
- userContentController.add(self, name: item.key)
- }
- self.webView = WKWebView(frame: self.view.frame, configuration: webViewConfig)
- /// 设置 userAgent
- self.webView.evaluateJavaScript("navigator.userAgent") { (result, err) in
- if let ua = result as? String {
- self.webView.customUserAgent = "\(ua) o2oa"
- }
- }
-
- }
-
- ///Generates script to create given cookies
- public func getJSCookiesString(cookies: [HTTPCookie]) -> String {
- var result = ""
- let dateFormatter = DateFormatter()
- dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC") as TimeZone?
- dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss zzz"
-
- for cookie in cookies {
- result += "document.cookie='\(cookie.name)=\(cookie.value); domain=\(cookie.domain); path=\(cookie.path); "
- if let date = cookie.expiresDate {
- result += "expires=\(dateFormatter.string(from: date)); "
- }
- if (cookie.isSecure) {
- result += "secure; "
- }
- result += "'; "
- }
- return result
- }
-
-
- // MARK: - 文件预览
- //预览文件
- private lazy var previewVC: CloudFilePreviewController = {
- return CloudFilePreviewController()
- }()
- // 文件预览
- func previewDoc(path: String) {
- let currentURL = NSURL(fileURLWithPath: path)
- if QLPreviewController.canPreview(currentURL) {
- self.previewVC.currentFileURLS.removeAll()
- self.previewVC.currentFileURLS.append(currentURL)
- self.previewVC.reloadData()
- self.pushVC(self.previewVC)
- } else {
- self.showError(title: "当前文件类型不支持预览!")
- }
- }
-
-
- // MARK: - 旋转屏幕
- // 此参数由外部传入,并且在要在构造控制器时传入
- fileprivate var _isLandscape = false
- override var _prefersStatusBarHidden_: Bool? {
- return false
- }
-
- override var _supportedInterfaceOrientations_: UIInterfaceOrientationMask? {
- return _isLandscape ? .landscapeRight: .portrait
- }
-
- override var _preferredInterfaceOrientationForPresentation_: UIInterfaceOrientation? {
- return _isLandscape ? .landscapeRight: .portrait
- }
- override var isForbidInteractivePopGesture: Bool {
- return _isLandscape
- }
-
- // MARK: - 控制旋转
- fileprivate func updateOrientationIfNeeded(_ force: Bool = false) {
- if _isLandscape {
- toLandscapeOrientation(force)
- } else {
- toPortraitOrientation(force)
- }
- }
-
- fileprivate func toLandscapeOrientation(_ force: Bool = false) {
- guard force || !_isLandscape else {
- return
- }
- UIRotateUtils.shared.rotateToLandscape()
- }
-
- fileprivate func toPortraitOrientation(_ force: Bool = false) {
- guard force || _isLandscape else {
- return
- }
- UIRotateUtils.shared.rotateToPortrait()
- }
- // 点击 “旋转” 按钮
- @objc func onChangeOrientationBtnTapped(_ any: Any?) {
- DDLogDebug("旋转屏幕 \(_isLandscape)")
- // 核心控制
- _isLandscape = !_isLandscape
- if _isLandscape {
- toLandscapeOrientation(true)
- } else {
- toPortraitOrientation(true)
- }
- }
-
- }
- extension BaseWebViewUIViewController: WKScriptMessageHandler {
-
- public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
- let name = message.name
- if let handler = o2WKScriptHandlers[name] {
- handler.userController(userContentController, didReceive: message)
- }else {
- let err = "没有找到对应的key,key:\(name)"
- self.showError(title: err)
- }
- }
- }
- extension BaseWebViewUIViewController: BMKLocationManagerDelegate, BMKGeoCodeSearchDelegate {
- public func startLocation() {
- //开始定位
- locService = BMKLocationManager()
- if locService == nil {
- locService?.desiredAccuracy = kCLLocationAccuracyBest
- //设置返回位置的坐标系类型
- locService?.coordinateType = .BMK09LL
- //设置距离过滤参数
- locService?.distanceFilter = kCLDistanceFilterNone;
- //设置预期精度参数
- locService?.desiredAccuracy = kCLLocationAccuracyBest;
- //设置应用位置类型
- locService?.activityType = .automotiveNavigation
- //设置是否自动停止位置更新
- locService?.pausesLocationUpdatesAutomatically = false
- //定位返回geo地址信息
- locService?.locatingWithReGeocode = true
- //后台定位
- locService?.allowsBackgroundLocationUpdates = true
- }
- if searchAddress == nil {
- searchAddress = BMKGeoCodeSearch()
- }
- searchAddress?.delegate = self
- locService?.delegate = self
- locService?.startUpdatingLocation()
- }
-
- public func stopLocation() {
- locService?.stopUpdatingLocation()
- locService?.delegate = nil
- searchAddress?.delegate = nil
- }
-
- public func bmkLocationManager(_ manager: BMKLocationManager, didUpdate location: BMKLocation?, orError error: Error?) {
- if let loc = location?.location {
- DDLogDebug("当前位置,\(loc.coordinate.latitude),\(loc.coordinate.longitude)")
- //根据经纬度搜索到地址
- let re = BMKReverseGeoCodeSearchOption()
- re.location = CLLocationCoordinate2D(latitude: loc.coordinate.latitude, longitude: loc.coordinate.longitude)
- let _ = searchAddress?.reverseGeoCode(re)
-
- } else {
- DDLogError("没有获取到定位信息!!!!!")
- }
- }
-
- public func bmkLocationManager(_ manager: BMKLocationManager, didFailWithError error: Error?) {
- DDLogError("定位错误:\(String(describing: error?.localizedDescription))")
- }
-
- public func onGetReverseGeoCodeResult(_ searcher: BMKGeoCodeSearch?, result: BMKReverseGeoCodeSearchResult?, errorCode error: BMKSearchErrorCode) {
- //发送定位的实时位置及名称信息
- if let location = result?.location {
- var r = O2DeviceLocationResult()
- r.latitude = location.latitude
- r.longitude = location.longitude
- r.address = result?.address ?? "没有获取到地址!"
- locationCallBack(r.toJSONString())
- }else {
- var r = O2DeviceLocationResult()
- r.address = "没有获取到地址!"
- locationCallBack(r.toJSONString())
- DDLogError("搜索地址失败, \(error)")
- }
- //结束定位
- self.stopLocation()
- }
-
- public func onGetGeoCodeResult(_ searcher: BMKGeoCodeSearch!, result: BMKGeoCodeSearchResult!, errorCode error: BMKSearchErrorCode) {
- if Int(error.rawValue) == 0 {
- DDLogDebug("result \(String(describing: result))")
- } else {
- DDLogDebug("result error errorCode = \(Int(error.rawValue))")
- }
- }
- }
|