Commit 87740d337d7cf74c387c2d679841ebcbfcdecf07

Authored by “张旭”
1 parent 496f57e2

首页-历史图片-图片的保存和分享

metaCode.xcodeproj/project.pbxproj
... ... @@ -151,6 +151,8 @@
151 151 1965FA3E2AFB176E00F0F435 /* CNLiveShopAddGoodsSingleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1965FA3D2AFB176E00F0F435 /* CNLiveShopAddGoodsSingleView.swift */; };
152 152 1965FA402AFB38AA00F0F435 /* CNLiveAddGoodsSelectUploadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1965FA3F2AFB38AA00F0F435 /* CNLiveAddGoodsSelectUploadImageView.swift */; };
153 153 1965FA422AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1965FA412AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift */; };
  154 + 1969E1AD2C92E98700E4185E /* CNHomeWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1969E1AC2C92E98700E4185E /* CNHomeWebViewController.swift */; };
  155 + 1969E1AF2C942F4400E4185E /* CNLivePhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1969E1AE2C942F4400E4185E /* CNLivePhotoManager.swift */; };
154 156 197325D22BB11C18002E41A3 /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197325D12BB11C18002E41A3 /* DatabaseManager.swift */; };
155 157 1975636E2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1975636D2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift */; };
156 158 197563712C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197563702C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift */; };
... ... @@ -503,6 +505,8 @@
503 505 1965FA3D2AFB176E00F0F435 /* CNLiveShopAddGoodsSingleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveShopAddGoodsSingleView.swift; sourceTree = "<group>"; };
504 506 1965FA3F2AFB38AA00F0F435 /* CNLiveAddGoodsSelectUploadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveAddGoodsSelectUploadImageView.swift; sourceTree = "<group>"; };
505 507 1965FA412AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveGoodsCategoryController.swift; sourceTree = "<group>"; };
  508 + 1969E1AC2C92E98700E4185E /* CNHomeWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNHomeWebViewController.swift; sourceTree = "<group>"; };
  509 + 1969E1AE2C942F4400E4185E /* CNLivePhotoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLivePhotoManager.swift; sourceTree = "<group>"; };
506 510 197325D12BB11C18002E41A3 /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; };
507 511 1975636D2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveVitaeWorkDetailController.swift; sourceTree = "<group>"; };
508 512 197563702C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveVitaeWorkCell.swift; sourceTree = "<group>"; };
... ... @@ -1033,6 +1037,7 @@
1033 1037 children = (
1034 1038 19123FC02ABC11170075C883 /* CNWebViewController.swift */,
1035 1039 194455A02B6B3310006C5A2A /* CNWebView.swift */,
  1040 + 1969E1AC2C92E98700E4185E /* CNHomeWebViewController.swift */,
1036 1041 );
1037 1042 path = WebController;
1038 1043 sourceTree = "<group>";
... ... @@ -1515,6 +1520,7 @@
1515 1520 792E57DA2A3AE9F4005834DB /* CNLiveCommonQiniuTool.swift */,
1516 1521 1938BD462B4FD5A500390A34 /* CNLiveIntegralAlertTool.swift */,
1517 1522 197563762C5C80D9004E0F42 /* HeroNetworkImageProvider.swift */,
  1523 + 1969E1AE2C942F4400E4185E /* CNLivePhotoManager.swift */,
1518 1524 );
1519 1525 path = Util;
1520 1526 sourceTree = "<group>";
... ... @@ -2250,6 +2256,7 @@
2250 2256 197563752C5B62FE004E0F42 /* CNLiveViateWorkModelLayout.swift in Sources */,
2251 2257 19DFE64B2C4516B000E428AE /* CNLiveDigitalResumeSecCell.swift in Sources */,
2252 2258 19DFE6462C41099900E428AE /* CNLiveVitaeModel.swift in Sources */,
  2259 + 1969E1AF2C942F4400E4185E /* CNLivePhotoManager.swift in Sources */,
2253 2260 19CC4D472ADD006600308E2A /* CNDownSlideSingleCourseCell.swift in Sources */,
2254 2261 192ED46D2C51FA360057244C /* CNLiveVitaeVocationalCertificateController.swift in Sources */,
2255 2262 191733232B14601A007BCC04 /* CNLivePlayerProgressSlider.swift in Sources */,
... ... @@ -2451,6 +2458,7 @@
2451 2458 19AB90642BB412C700B6A79B /* CNLiveDownslideOperationManager.swift in Sources */,
2452 2459 7991723A2AF091E100DC01A8 /* CNLiveShopOrderListViewController.swift in Sources */,
2453 2460 798A44F02A305BC200815935 /* UIButton+CNLiveExtensions.swift in Sources */,
  2461 + 1969E1AD2C92E98700E4185E /* CNHomeWebViewController.swift in Sources */,
2454 2462 1938BD342B4B968300390A34 /* CNLiveHomePageDuanJuCell.swift in Sources */,
2455 2463 192ED4872C575EC90057244C /* CNLiveVitaeAddWorkFirCell.swift in Sources */,
2456 2464 191733522B2C4CEA007BCC04 /* CNLivePickerSelectDateTools.swift in Sources */,
... ... @@ -2632,7 +2640,7 @@
2632 2640 CODE_SIGN_ENTITLEMENTS = metaCode/metaCode.entitlements;
2633 2641 CODE_SIGN_IDENTITY = "Apple Development";
2634 2642 CODE_SIGN_STYLE = Automatic;
2635   - CURRENT_PROJECT_VERSION = 1.1.4.24.09.04.11;
  2643 + CURRENT_PROJECT_VERSION = 1.1.4.24.09.14.12;
2636 2644 DEBUG_INFORMATION_FORMAT = dwarf;
2637 2645 DEVELOPMENT_TEAM = 94X49GG3ZW;
2638 2646 ENABLE_BITCODE = NO;
... ... @@ -2888,7 +2896,7 @@
2888 2896 CODE_SIGN_ENTITLEMENTS = metaCode/metaCode.entitlements;
2889 2897 CODE_SIGN_IDENTITY = "Apple Development";
2890 2898 CODE_SIGN_STYLE = Automatic;
2891   - CURRENT_PROJECT_VERSION = 1.1.4.24.09.04.11;
  2899 + CURRENT_PROJECT_VERSION = 1.1.4.24.09.14.12;
2892 2900 DEVELOPMENT_TEAM = 94X49GG3ZW;
2893 2901 ENABLE_BITCODE = NO;
2894 2902 ENABLE_MODULE_VERIFIER = NO;
... ...
metaCode/Classes/Common/Base/CNLiveBaseTabBarViewController.swift
... ... @@ -52,7 +52,9 @@ class CNLiveBaseTabBarViewController: UITabBarController
52 52 // MARK: - 控制器的信息
53 53 func setUpTabBar() {
54 54  
55   - let homeVC = CNLiveAuthViewController.init()
  55 +// let homeVC = CNLiveAuthViewController.init()
  56 + let homeVC = CNHomeWebViewController()
  57 + homeVC.url = URL(string: "https://wjjh5.cnlive.com/chatgpt/#/")
56 58 let authVC = CNMetaCodeHomePageController.init()
57 59 let mineVC = CNLiveMineViewController.init()
58 60  
... ...
metaCode/Classes/Common/Base/CNLiveBaseViewController.swift
... ... @@ -83,13 +83,15 @@ class CNLiveBaseViewController: UIViewController {
83 83 set {
84 84 _leftNavBtns = newValue
85 85 var lastBtn : UIButton? = nil
86   - _leftNavBtns.forEach { btn in
87   - btn.removeFromSuperview()
88   - topNavView.addSubview(btn)
89   - btn.frame = CGRect(x: lastBtn != nil ? CGRectGetMaxX(lastBtn!.frame) : CNLiveBaseViewController.kTopNavLeftRightOffset, y: topNavViewHeight - btn.height, width: btn.width, height: btn.height)
90   - lastBtn = btn
  86 + if _leftNavBtns.count > 0{
  87 + _leftNavBtns.forEach { btn in
  88 + btn.removeFromSuperview()
  89 + topNavView.addSubview(btn)
  90 + btn.frame = CGRect(x: lastBtn != nil ? CGRectGetMaxX(lastBtn!.frame) : CNLiveBaseViewController.kTopNavLeftRightOffset, y: topNavViewHeight - btn.height, width: btn.width, height: btn.height)
  91 + lastBtn = btn
  92 + }
  93 + leftNavSpace = CGRectGetMaxX(lastBtn!.frame)
91 94 }
92   - leftNavSpace = CGRectGetMaxX(lastBtn!.frame)
93 95 viewWillLayoutSubviews()
94 96 }
95 97 }
... ... @@ -102,13 +104,13 @@ class CNLiveBaseViewController: UIViewController {
102 104 set {
103 105 _rightNavBtns = newValue
104 106 var lastBtn : UIButton? = nil
105   - _rightNavBtns.forEach { btn in
106   - btn.removeFromSuperview()
107   - topNavView.addSubview(btn)
108   - btn.frame = CGRect(x: lastBtn != nil ? (lastBtn!.origin.x - btn.width) : (topNavView.width - CNLiveBaseViewController.kTopNavLeftRightOffset - btn.width), y: topNavViewHeight - btn.height, width: btn.width, height: btn.height)
109   - lastBtn = btn
110   - }
111 107 if _rightNavBtns.count > 0{
  108 + _rightNavBtns.forEach { btn in
  109 + btn.removeFromSuperview()
  110 + topNavView.addSubview(btn)
  111 + btn.frame = CGRect(x: lastBtn != nil ? (lastBtn!.origin.x - btn.width) : (topNavView.width - CNLiveBaseViewController.kTopNavLeftRightOffset - btn.width), y: topNavViewHeight - btn.height, width: btn.width, height: btn.height)
  112 + lastBtn = btn
  113 + }
112 114 rightNavSpace = CGRectGetMaxX(lastBtn!.frame)
113 115 }
114 116 viewWillLayoutSubviews()
... ...
metaCode/Classes/Common/Util/CNLivePhotoManager.swift 0 → 100644
  1 +//
  2 +// CNLivePhotoManager.swift
  3 +// metaCode
  4 +//
  5 +// Created by zx on 2024/9/13.
  6 +//
  7 +import UIKit
  8 +import Photos
  9 +
  10 +class CNLivePhotoManager: NSObject {
  11 +
  12 + // MARK: - 权限请求
  13 +
  14 + func requestPhotoLibraryPermission(completion: ((PHAuthorizationStatus) -> Void)? = nil) {
  15 + PHPhotoLibrary.requestAuthorization { status in
  16 + DispatchQueue.main.async {
  17 + completion?(status)
  18 + switch status {
  19 + case .authorized:
  20 + print("Access granted by user")
  21 + case .denied, .restricted:
  22 + print("User denied access")
  23 + case .notDetermined:
  24 + // 这种情况理论上不会发生,因为已经调用了requestAuthorization
  25 + break
  26 + case .limited:
  27 + break
  28 + @unknown default:
  29 + fatalError()
  30 + }
  31 + }
  32 + }
  33 + }
  34 +
  35 + // MARK: - 下载图片
  36 +
  37 + func downloadImage(from url: URL, completion: @escaping (UIImage?, Error?) -> Void) {
  38 + URLSession.shared.dataTask(with: url) { data, response, error in
  39 + guard let data = data, error == nil else {
  40 + completion(nil, error)
  41 + return
  42 + }
  43 +
  44 + DispatchQueue.main.async {
  45 + let image = UIImage(data: data)
  46 + completion(image, nil)
  47 + }
  48 + }.resume()
  49 + }
  50 +
  51 + // MARK: - 保存图片到相册
  52 + @objc func saveImage(_ image: UIImage, completion: @escaping (Bool) -> Void){
  53 +// UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
  54 + UIImageWriteToSavedPhotosAlbum(image, self, #selector(imageSaved(_:error:context:)), nil)
  55 + }
  56 + @objc func imageSaved(_ image: UIImage, error: Error?, context: UnsafeMutableRawPointer?){
  57 + if error != nil{
  58 + //false
  59 + showMessage(message: "保存失败")
  60 + return
  61 + }
  62 + //true
  63 + showMessage(message: "保存成功")
  64 + }
  65 +
  66 +
  67 + // MARK: - 示例用法
  68 +
  69 + func saveImageFromURL(url: URL) {
  70 + self.requestPhotoLibraryPermission { status in
  71 + guard status == .authorized else {
  72 + return
  73 + }
  74 +
  75 + self.downloadImage(from: url) { image, error in
  76 + guard let image = image, error == nil else {
  77 + print("Failed to download image: \(error?.localizedDescription ?? "Unknown error")")
  78 + return
  79 + }
  80 + self.saveImage(image) { isSucc in
  81 + if isSucc{
  82 +
  83 + }
  84 + }
  85 + }
  86 + }
  87 + }
  88 +}
  89 +
... ...
metaCode/Classes/Main/HomePage/Controller/WebController/CNHomeWebViewController.swift 0 → 100644
  1 +//
  2 +// CNHomeWebViewController.swift
  3 +// metaCode
  4 +//
  5 +// Created by zx on 2023/9/21.
  6 +// 首页
  7 +
  8 +import Foundation
  9 +import WebKit
  10 +import WebViewJavascriptBridge
  11 +import CNLiveShareToolKit
  12 +import CommonCrypto
  13 +import CNLiveBusinessTools
  14 +import SKPhotoBrowser
  15 +
  16 +class CNHomeWebViewController:CNLiveBaseViewController ,WKNavigationDelegate{
  17 +
  18 + var bridge:WKWebViewJavascriptBridge?
  19 + var currentUrl:String = ""//当前网页的url
  20 +
  21 + lazy var webView: CNWebView = {
  22 + let configuration = WKWebViewConfiguration()
  23 + configuration.allowsInlineMediaPlayback = true
  24 + let preferences = WKPreferences()
  25 + preferences.javaScriptCanOpenWindowsAutomatically = true
  26 + preferences.javaScriptEnabled = true
  27 + configuration.preferences.minimumFontSize = 0.0
  28 + configuration.preferences = preferences
  29 + configuration.userContentController = WKUserContentController()
  30 + let webView = CNWebView(frame: CGRectMake(0, KNavigationHeight, Width, Height-KNavigationHeight), configuration: configuration, url: _url)
  31 + webView.cnWebView.scrollView.showsVerticalScrollIndicator = false
  32 + webView.cnWebView.scrollView.showsHorizontalScrollIndicator = false
  33 + webView.isCNWebController = true
  34 + return webView
  35 + }()
  36 +
  37 + var _url:URL?
  38 + var url:URL? {
  39 + get{
  40 + return _url
  41 + }
  42 + set{
  43 + _url = newValue!
  44 + }
  45 + }
  46 +
  47 + deinit {
  48 + self.webView.cnWebView.stopLoading()
  49 + self.webView.cnWebView.navigationDelegate = nil
  50 + self.webView.cnWebView.uiDelegate = nil
  51 + self.webView.webViewRemoveScriptMessageHandler()
  52 + print("WKWebView dealloc")
  53 + }
  54 +
  55 + override func viewDidDisappear(_ animated: Bool) {
  56 + super.viewDidDisappear(animated)
  57 + self.h5StopVideoPlayer()
  58 + }
  59 + override func viewWillLayoutSubviews() {
  60 + super.viewWillLayoutSubviews()
  61 + homeTopNavView.frame = CGRect(x: 0, y: 0, width: view.width, height:topNavViewHeight)// topNavViewHeight + get_system_statusBar_height())
  62 + let lrSpace = 0.0
  63 + homeTitleLabel.frame = CGRect(x: CGFloat(Int(lrSpace)) , y: topNavViewHeight - get_system_nav_ui_height() - topNavViewSubUIContentOffsetY, width: topNavView.width - (lrSpace * 2), height: get_system_nav_ui_height())
  64 + homeTopLine.frame = CGRect(x: 0, y: topNavViewHeight - 1, width: topNavView.width, height: 1)
  65 + }
  66 +
  67 + public lazy var homeTopNavView: UIView = {
  68 + let topNavView = UIView.init(frame: CGRect(x: 0, y: 0, width: view.width, height: topNavViewHeight))
  69 + topNavView.backgroundColor = HexColor("#F7F8FA")
  70 + return topNavView
  71 + }()
  72 +
  73 + public lazy var homeTitleLabel: UILabel = {
  74 + let titleLabel = UILabel.init(frame: CGRectMake(0, topNavView.height - get_system_nav_ui_height(), topNavView.frame.size.width, get_system_nav_ui_height()))
  75 + titleLabel.textColor = HexColor("#333333")
  76 + titleLabel.font = Font_18_Fit
  77 + titleLabel.textAlignment = .center
  78 + titleLabel.text = "AI 智能体"
  79 + return titleLabel
  80 + }()
  81 +
  82 + public lazy var homeTopLine: UIImageView = {
  83 + let topLine = UIImageView.init(frame: CGRect(x: 0, y: topNavView.height - 1, width: view.width, height: 1))
  84 + topLine.backgroundColor = .clear
  85 + return topLine
  86 + }()
  87 + override func viewDidLoad() {
  88 + super.viewDidLoad()
  89 + navigationBarHidden = true
  90 +
  91 + self.topNavViewHeight = get_system_nav_height()
  92 + view.addSubview(homeTopNavView)
  93 + homeTopNavView.addSubview(homeTitleLabel)
  94 + homeTopNavView.addSubview(homeTopLine)
  95 +
  96 + self.view.addSubview(self.webView)
  97 + self.webView.webControllerUpdateNavBlock = { [weak self] isFinish , title,isDecidePolicy ,urlStr in
  98 + if isFinish{
  99 + }else if isDecidePolicy{
  100 + }
  101 + }
  102 + self.webView.webControllerBackNavBlock = { [weak self] in
  103 + self?.navigationController?.popViewController(animated: true)
  104 + }
  105 + self.webView.webControllerUpdateCurrentUrlBlock = { [weak self] currentUrlStr in
  106 + self!.currentUrl = currentUrlStr
  107 + }
  108 + self.webView.snp.makeConstraints { make in
  109 + make.top.equalTo(get_system_nav_height())
  110 + make.left.right.bottom.equalToSuperview()
  111 + }
  112 + }
  113 +
  114 + func h5StopVideoPlayer(){
  115 + // call h5停止播放视频
  116 + let data: [String: Any] = ["stop": true]
  117 + self.bridge?.callHandler("wjjStopVideoPlayer", data: data, responseCallback: { responseData in
  118 + print("wjjStopVideoPlayer:\(responseData ?? "")")
  119 + })
  120 + }
  121 +
  122 +}
... ...
metaCode/Classes/Main/HomePage/Controller/WebController/CNWebView.swift
... ... @@ -13,6 +13,7 @@ import CommonCrypto
13 13 import CNLiveBusinessTools
14 14 import SKPhotoBrowser
15 15 import CNLivePayCostModule
  16 +import UIKit
16 17  
17 18 //返回 Web控制器回调
18 19 typealias cnWebControllerBackNavBlock = ()->Void
... ... @@ -316,6 +317,50 @@ class CNWebView:UIView,WKNavigationDelegate, WKScriptMessageHandler{
316 317  
317 318 })
318 319  
  320 + //h5拉起原生跳转新webView
  321 + self.bridge?.registerHandler("ymOpenNewWebview", handler: { data, responseCallback in
  322 + print("js call oc\(data)")
  323 + let dic = data as! Dictionary<String, Any>
  324 + if let urlStr = dic["url"] as? String{
  325 + let webVC = CNWebViewController()
  326 + webVC.url = URL(string: urlStr)
  327 + navigationViewController().pushViewController(webVC, animated: true)
  328 + }
  329 + })
  330 +
  331 + //h5拉起原生保存图片
  332 + self.bridge?.registerHandler("ymSaveImage", handler: { data, responseCallback in
  333 + print("js call oc\(data)")
  334 + let dic = data as! Dictionary<String, Any>
  335 + if let urlStr = dic["src"] as? String{
  336 + let photoManager = CNLivePhotoManager()
  337 + photoManager.saveImageFromURL(url: URL(string: urlStr)!)
  338 + }
  339 +
  340 + })
  341 + //h5拉起原生分享图片
  342 + self.bridge?.registerHandler("ymShareImage", handler: { data, responseCallback in
  343 + print("js call oc\(data)")
  344 + let dic = data as! Dictionary<String, Any>
  345 + if let urlStr = dic["src"] as? String{
  346 + URLSession.shared.dataTask(with: URLRequest(url: URL(string: urlStr) ?? URL(fileURLWithPath: ""))) { data, response, error in
  347 + guard let data = data, error == nil else {
  348 + return
  349 + }
  350 +
  351 + DispatchQueue.main.async {
  352 + let image = UIImage(data: data)
  353 + CNLiveShareManager.showShareViewWithParam(forShareTitle: "", shareUrl: "", shareDesc:"", shareImage: image, screenFull: false, hiddenWjj: true, hiddenQQ: false, hiddenWB: true, hiddenLifeCircle: true, hiddenWechatCircle: false, hiddenWechat: false, hiddenSafari: true, formVC: currentViewController(), topImage: [], topTitles: [], platformType: .all) { title in
  354 +
  355 + } completerBlock: { resultType, platformType, typeString in
  356 + if resultType == .succ{
  357 +
  358 + }
  359 + }
  360 + }
  361 + }.resume()
  362 + }
  363 + })
319 364 }
320 365  
321 366 // MARK: - 检查url
... ...