GoodsDetailViewController.swift 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. //
  2. // GoodsDetailViewController.swift
  3. // MTP2_iOS
  4. //
  5. // Created by Handy_Cao on 2020/10/30.
  6. // Copyright © 2020 Muchinfo. All rights reserved.
  7. //
  8. import UIKit
  9. import WHToast
  10. import WebKit
  11. import MediaPlayer
  12. import SwiftyAttributes
  13. import IBAnimatable
  14. /// 商品详情视图容器控制类
  15. class GoodsDetailViewController: BaseViewController {
  16. // MARK: - 属性列表
  17. /// 商品名称
  18. @IBOutlet weak var goodsName: UILabel!
  19. /// 商品代码
  20. @IBOutlet weak var goodsCode: UILabel!
  21. /// 媒体视图
  22. @IBOutlet weak var videoView: UIView!
  23. /// 媒体视图容器控制View
  24. lazy var mediaView: TSVideoPlayback = {
  25. return $0
  26. }(TSVideoPlayback(frame: CGRect(x: 0.0, y: 0.0, width: self.view.width, height: self.view.width*0.78)))
  27. /// 商品价格
  28. @IBOutlet weak var price: IBLabel!
  29. /// 供应商
  30. @IBOutlet weak var vendorname: UILabel!
  31. /// 卖家
  32. @IBOutlet weak var customername: UILabel!
  33. /// 交易按钮
  34. @IBOutlet weak var trade: IBButton! {
  35. didSet {
  36. trade.setTitle(MTP2BusinessCore.shared.getLoginStatus() ? "立即购买" : "未登录", for: .normal)
  37. }
  38. }
  39. /// 交易按钮
  40. @IBOutlet weak var tradeView: AnimatableView!
  41. /// 客服按钮
  42. @IBOutlet weak var customer: UIButton!
  43. /// 收藏按钮
  44. @IBOutlet weak var favorite: UIButton!
  45. /// 发行单位
  46. @IBOutlet weak var issuer: UILabel!
  47. /// 发行数量
  48. @IBOutlet weak var preQty: UILabel!
  49. /// 日期范围
  50. @IBOutlet weak var dateRange: UILabel!
  51. /// 网页视图用来加载商品详情信息
  52. @IBOutlet weak var webView: WKWebView! {
  53. didSet {
  54. webView.uiDelegate = self
  55. webView.navigationDelegate = self
  56. webView.scrollView.showsVerticalScrollIndicator = false
  57. webView.scrollView.showsHorizontalScrollIndicator = false
  58. webView.scrollView.isScrollEnabled = false
  59. webView.isOpaque = false
  60. }
  61. }
  62. /// 高度约束
  63. @IBOutlet weak var webViewLayoutConstraint: NSLayoutConstraint!
  64. /// 折线图
  65. @IBOutlet weak var chartView: UIStackView!
  66. /// 折线图
  67. @IBOutlet weak var lineChartView: LHYChartView! {
  68. didSet {
  69. /// 初始化视图
  70. lineChartView.initNew()
  71. /// 是否默认选中第一个
  72. lineChartView.isShowFirstPaoPao = false
  73. /// 是否默认选中第一个
  74. lineChartView.isShowLastPaoPao = true
  75. /// 是否有网格
  76. lineChartView.isGrid = true
  77. /// 是否可以浮动
  78. lineChartView.isFloating = false
  79. /// 显示多少行
  80. lineChartView.row = 6
  81. /// 显示多少列
  82. self.lineChartView.xRow = 10
  83. /// 设置X轴坐标字体大小
  84. lineChartView.x_Font = .font_8
  85. /// 设置Y轴坐标字体大小
  86. lineChartView.y_Font = .font_8
  87. /// 设置Y轴坐标字体颜色
  88. lineChartView.y_Color = UIColorFromHex(rgbValue: 0x4f6a8f)
  89. /// 设置X轴坐标字体颜色
  90. lineChartView.x_Color = UIColorFromHex(rgbValue: 0x4f6a8f)
  91. /// 边框标线颜色
  92. lineChartView.borderLineColor = UIColorFromHex(rgbValue: 0x4f6a8f)
  93. /// 设置X轴数据间隔
  94. lineChartView.xmargin = 45
  95. /// 设置背景颜色
  96. lineChartView.backgroundColor = .white
  97. /// 设置泡泡的背景色
  98. lineChartView.paopaoBackGroundColor = UIColorFromHex(rgbValue: 0x88a2bc, alpha: 1)
  99. /// 中间标线颜色
  100. lineChartView.middleLineColor = UIColorFromHex(rgbValue: 0xffffff, alpha: 1)
  101. /// 边框三角颜色
  102. lineChartView.borderTriangleColor = UIColorFromHex(rgbValue: 0x9f6c66)
  103. /// 设置标线颜色
  104. lineChartView.markColor = UIColorFromHex(rgbValue: 0x9f6c66)
  105. /// 设置泡泡的标题颜色
  106. lineChartView.paopaoTitleColor = UIColorFromHex(rgbValue: 0xffffff)
  107. /// 设置折线样式
  108. lineChartView.chartViewStyle = .moreClickLine
  109. /// 设置图层效果
  110. lineChartView.chartLayerStyle = .gradient
  111. /// 设置折现效果
  112. lineChartView.lineLayerStyle = .gradient
  113. /// 渐变效果的颜色组
  114. /// 渐变开始比例
  115. lineChartView.proportion = 0.5;
  116. /// 折线图是否从零点开始画
  117. lineChartView.hiddenZreo = false
  118. /// 单位
  119. lineChartView.unitStyle = .million
  120. /// 设置颜色
  121. lineChartView.leftColorStrArr = ["#6dd89c"];
  122. }
  123. }
  124. /// 价格视图
  125. @IBOutlet weak var priceView: UIImageView!
  126. /// 数据模型
  127. var model: MoGoodsInfo? {
  128. didSet {
  129. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.3) {
  130. /// 异常
  131. guard let obj = self.model else { return }
  132. /// 热卖商品 挂牌点选
  133. if obj.trademode == .TRADEMODE_LISTING_SELECT {
  134. /// 不需要显示这些字段
  135. self.issuer.removeFromSuperview()
  136. ///移出preQty
  137. self.preQty.removeFromSuperview()
  138. /// 移出dateRange
  139. self.dateRange.removeFromSuperview()
  140. /// 移出customername
  141. self.customername.removeFromSuperview()
  142. /// 查询商品详情
  143. self.requestQueryHsbyListingGoodsDetail(obj.goodsid)
  144. /// 查询历史数据信息
  145. self.requestHistoryDatas()
  146. /// 行情订阅
  147. self.shouldSubscriptGoodsCodes = self.visibleGoodsCodes
  148. } else if obj.trademode == .TRADEMODE_TRADEMODE_CPTRADE_LS { /// 挂牌预售
  149. /// 移出customername
  150. self.customername.removeFromSuperview()
  151. /// 移出视图
  152. self.chartView.removeFromSuperview()
  153. self.requestQueryHsbyPreGoodsDetail(obj.goodsid)
  154. } else { /// 商城
  155. /// 不需要显示这些字段
  156. self.issuer.removeFromSuperview()
  157. ///移出preQty
  158. self.preQty.removeFromSuperview()
  159. /// 移出dateRange
  160. self.dateRange.removeFromSuperview()
  161. /// 移出视图
  162. self.chartView.removeFromSuperview()
  163. /// 未登录不需要显示商家信息
  164. if !MTP2BusinessCore.shared.getLoginStatus() {
  165. /// 移出customername
  166. self.customername.removeFromSuperview()
  167. }
  168. /// 查询商城商品详情信息
  169. MTP2BusinessCore.shared.getLoginStatus() ? self.requestQueryHsbyMarketGoodsDetail(obj.orderid) : self.requestQueryHsbyVisitorMarketGoodsDetail(obj.goodsid)
  170. }
  171. }
  172. }
  173. }
  174. /// 商品详情
  175. var goodsDetail: MoGoodsInfo? {
  176. didSet {
  177. /// 显示商品详情信息
  178. showGoodsDetail(goodsDetail)
  179. }
  180. }
  181. /// 是否为我的收藏
  182. var isFavorite: Bool = false {
  183. didSet {
  184. favorite.setImage(UIImage(named: isFavorite ? "favorited" : "favorite"), for: .normal)
  185. }
  186. }
  187. // MARK: - 生命周期
  188. override func viewDidLoad() {
  189. super.viewDidLoad()
  190. // Do any additional setup after loading the view.
  191. /// UI界面初始化
  192. buildView()
  193. /// 数据初始化
  194. initData()
  195. }
  196. override func viewWillAppear(_ animated: Bool) {
  197. super.viewWillAppear(animated)
  198. /// 隐藏导航栏
  199. self.navigationController?.setNavigationBarHidden(true, animated: true)
  200. /// 商城商品不需要行情
  201. if self.model?.trademode == .TRADEMODE_LISTING_SELECT {
  202. /// 侦听行情推送广播
  203. MTP2BusinessCore.shared.broadcastManager?.addBroadcastListener(owner: self, action: .ReceiveTradeQuote) { [weak self] in
  204. guard let quoteGoodsInfos = $0.object as? [(goodsHqCode: String, exchHqCode: String)] else { return }
  205. DispatchQueue.main.async {
  206. /// 有数据
  207. if quoteGoodsInfos.count != 0 {
  208. if quoteGoodsInfos.first(where: { $0.goodsHqCode == self?.model?.goodscode }) != nil {
  209. if let obj = MTP2BusinessCore.shared.goodsManager?.goodsInfos.first(where: {$0.goodscode == self?.model?.goodscode}),
  210. obj.trademode == .TRADEMODE_LISTING_SELECT {
  211. self?.price.attributedText = ("热卖价:\(obj.currencysign)".withFont(.font_13)+(" \((obj.getLast() == 0.0 ? obj.last : obj.getLast()).toDownString(reserve: obj.decimalplace))").withFont(.font_20)).withTextColor(.white)
  212. }
  213. }
  214. }
  215. }
  216. }
  217. }
  218. }
  219. deinit {
  220. /// 商城商品不需要行情
  221. if self.model?.trademode == .TRADEMODE_LISTING_SELECT {
  222. /// 清除广播侦听
  223. MTP2BusinessCore.shared.broadcastManager?.removeBroadcastListener(owner: self, forName: .ReceiveTradeQuote)
  224. }
  225. /// 清楚缓存
  226. self.mediaView.clearCache()
  227. }
  228. // MARK: - 初始化
  229. /// UI界面初始化
  230. fileprivate func buildView() {
  231. /// 添加每天视图
  232. self.videoView.addSubview(mediaView)
  233. /// loding......
  234. addLoadingView()
  235. }
  236. /// 数据初始化
  237. fileprivate func initData() {
  238. /// 判断是否为我的藏品
  239. self.isFavorite = MTP2BusinessCore.shared.goodsManager?.favGoodsIds?.contains(where: {$0 == model?.goodsid}) ?? false
  240. }
  241. /// 显示商品详情信息
  242. /// - Parameter detail: detail
  243. fileprivate func showGoodsDetail(_ detail: MoGoodsInfo?) {
  244. /// 异常
  245. guard let obj = detail else { return }
  246. /// 商品名称
  247. goodsName.text = obj.goodsname
  248. /// 商品代码
  249. goodsCode.attributedText = ("商品代码 ".withTextColor(UIColorFromHex(rgbValue: 0x999999))+obj.goodscode.withTextColor(UIColorFromHex(rgbValue: 0x333333))).withFont(.font_13)
  250. /// 供应商
  251. vendorname.attributedText = ("供 应 商 ".withTextColor(UIColorFromHex(rgbValue: 0x999999)) + obj.vendorname.withTextColor(UIColorFromHex(rgbValue: 0x333333))).withFont(.font_13)
  252. /// 价格视图
  253. priceView.image = UIImage(named: obj.goodsstatus == 3 ? "image_blued_grident" : "image_read_grident")
  254. /// 二级市场
  255. if obj.trademode == .TRADEMODE_LISTING_SELECT {
  256. /// 价格
  257. price.attributedText = ("热卖价:\(obj.currencysign)".withFont(.font_13)+(" \((obj.getLast() == 0.0 ? obj.last : obj.getLast()).toDownString(reserve: obj.decimalplace))").withFont(.font_20)).withTextColor(.white)
  258. } else if obj.trademode == .TRADEMODE_TRADEMODE_HSBY_SHOP { /// 商城
  259. /// 价格
  260. price.attributedText = ("热卖价:\(obj.currencysign)".withFont(.font_13)+(" \(obj.goodsprice.toDownString(reserve: obj.decimalplace))").withFont(.font_20)).withTextColor(.white)
  261. /// 发行单位
  262. if MTP2BusinessCore.shared.getLoginStatus() {
  263. customername.attributedText = ("卖 家 ".withTextColor(UIColorFromHex(rgbValue: 0x999999))+obj.customername.withTextColor(UIColorFromHex(rgbValue: 0x333333))).withFont(.font_13)
  264. }
  265. } else { /// 产能预售
  266. /// 发行单位
  267. issuer.attributedText = ("发行单位 ".withTextColor(UIColorFromHex(rgbValue: 0x999999))+"\(obj.customername)".withTextColor(UIColorFromHex(rgbValue: 0x333333))).withFont(.font_13)
  268. /// 发行数量
  269. preQty.attributedText = ("发行数量 ".withTextColor(UIColorFromHex(rgbValue: 0x999999))+"\(obj.presaleqty)\(obj.goodunit)".withTextColor(UIColorFromHex(rgbValue: 0x333333))).withFont(.font_13)
  270. /// 抢购价
  271. price.attributedText = (("抢 购 价: "+"\(obj.currencysign)").withFont(.font_13)+"\(obj.refprice)".withFont(.font_20)).withTextColor(.white)
  272. /// 日期范围
  273. dateRange.attributedText = ("抢购日期 ".withTextColor(UIColorFromHex(rgbValue: 0x999999))+"\(DateUtils.getTDateString(obj.listingdate, "yyyy/MM/dd")) 至 \(DateUtils.getTDateString(obj.lasttradedate, "yyyy/MM/dd"))".withTextColor(UIColorFromHex(rgbValue: 0x333333))).withFont(.font_13)
  274. /// 上市的才可以交易
  275. trade.isEnabled = obj.goodsstatus == 3
  276. /// 判断其是否已登录
  277. trade.setTitle(MTP2BusinessCore.shared.getLoginStatus() ? (obj.goodsstatus == 3 ? "立即购买" : "未开售") : "未登录", for: .normal)
  278. tradeView.startColor = obj.goodsstatus == 3 ? UIColorFromHex(rgbValue: 0xdf7e58) : .lightGray
  279. tradeView.endColor = obj.goodsstatus == 3 ? UIColorFromHex(rgbValue: 0xdf5958) : .lightGray
  280. }
  281. /// 商品详情
  282. let goodsdesc = NSString(string: obj.goodsdesc).replacingOccurrences(of: "./uploadFile", with: (MTP2BusinessCore.shared.address?.openApiUrl ?? "")+"/uploadFile")
  283. webView.loadHTMLString(goodsdesc, baseURL: Bundle.main.bundleURL)
  284. /// 管理端
  285. guard let managerUrl = MTP2BusinessCore.shared.address?.openApiUrl, managerUrl != "" else { return }
  286. /// 商品图片
  287. var urls = obj.picurls.components(separatedBy: ",")
  288. let videourls = obj.videourls.components(separatedBy: ",")
  289. if videourls.first != "" {
  290. urls.insert(contentsOf: videourls.map { (url) -> String in
  291. if url.hasPrefix("./") {
  292. return managerUrl+NSString(string: url).replacingOccurrences(of: "./", with: "/")
  293. }
  294. return url
  295. }, at: 0)
  296. }
  297. /// 设置媒体介质
  298. if urls.count != 0 {
  299. self.mediaView.setWithIsVideo(obj.videourls == "" ? TSDETAILTYPEIMAGE : TSDETAILTYPEVIDEO, andDataArray: urls.map { (url) -> String in
  300. if url.hasPrefix("./") { return managerUrl+NSString(string: url).replacingOccurrences(of: "./", with: "/") }
  301. return url
  302. })
  303. }
  304. }
  305. // MARK: - 交互相关
  306. /// onButtonPressed
  307. /// - Parameter sender: sender
  308. @IBAction fileprivate func onButtonPressed(_ sender: UIControl) {
  309. switch sender {
  310. case trade: /// 立即购买
  311. guard let obj = model else { return }
  312. if obj.trademode == ETradeMode.TRADEMODE_LISTING_SELECT { /// 商品热卖
  313. push(storyboardName: "Quote", storyboardId: "Trade", takeInfo: goodsDetail)
  314. } else if obj.trademode == ETradeMode.TRADEMODE_TRADEMODE_HSBY_SHOP { /// 商城
  315. push(storyboardName: "Quote", storyboardId: "PaymentOrder", takeInfo: goodsDetail)
  316. } else {
  317. if MTP2BusinessCore.shared.getLoginStatus() { /// 新品预售
  318. let preTraderController = self.viewController(name: "Quote", identifier: "PreTrade") as! PreTradeViewController
  319. /// 商品详情
  320. preTraderController.takeInfo = goodsDetail
  321. preTraderController.modalPresentationStyle = .overCurrentContext
  322. preTraderController.modalTransitionStyle = .crossDissolve
  323. /// 回调块
  324. preTraderController.disBlock = { (_ orderId: String?, _ amount: Double, _ payOrder: MoMyPayOrders?) in
  325. /// 异常
  326. guard let paymentController = self.viewController(name: "Order", identifier: "Payment") as? PaymentViewController else { return }
  327. /// 待付款单据
  328. paymentController.myPayOrder = payOrder
  329. /// 页面跳转
  330. self.navigationController?.pushViewController(paymentController, animated: true)
  331. }
  332. self.present(preTraderController, animated: true, completion: {})
  333. } else { /// 未登录
  334. let login = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Login")
  335. self.navigationController?.pushViewController(login, animated: true)
  336. }
  337. }
  338. case favorite: /// 收藏
  339. /// 未登录
  340. if !MTP2BusinessCore.shared.getLoginStatus() {
  341. let login = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Login")
  342. self.navigationController?.pushViewController(login, animated: true)
  343. return
  344. }
  345. /// 异常
  346. guard let obj = model else { return }
  347. if isFavorite { /// 删除收藏
  348. self.removeUserFavoriteGoods(obj.goodsid)
  349. } else { /// 添加收藏
  350. self.AddUserFavoriteGoods(obj.goodsid)
  351. }
  352. default:
  353. break
  354. }
  355. }
  356. // MARK: - 接口请求
  357. /// 服务端查询二级市场商品详情请求方法
  358. /// - Parameter goodsID: goodsID
  359. fileprivate func requestQueryHsbyListingGoodsDetail(_ goodsID: Int) {
  360. /// 异常
  361. guard let goodsManager = MTP2BusinessCore.shared.goodsManager else { return }
  362. /// startAnimating
  363. _anim?.startAnimating()
  364. /// 发送请求
  365. goodsManager.requestQueryHsbyListingGoodsDetail(goodsID) { (isComplete, error, detail) in
  366. DispatchQueue.main.async {
  367. /// stopAnimating
  368. self._anim?.stopAnimating()
  369. if isComplete {
  370. /// 查询成功
  371. self.goodsDetail = detail
  372. } else {
  373. WHToast.showMessage("数据加载失败,原因:\(error?.retMsg ?? "未知错误")", duration: 1.5, finishHandler: {})
  374. }
  375. }
  376. }
  377. }
  378. /// 服务端查询一级市场商品详情请求方法
  379. /// - Parameter goodsID: goodsID
  380. fileprivate func requestQueryHsbyPreGoodsDetail(_ goodsID: Int) {
  381. /// 异常
  382. guard let goodsManager = MTP2BusinessCore.shared.goodsManager else {
  383. return
  384. }
  385. /// startAnimating
  386. _anim?.startAnimating()
  387. /// 发送请求
  388. goodsManager.requestQueryHsbyPreGoodsDetail(goodsID) { (isComplete, error, detail) in
  389. DispatchQueue.main.async {
  390. /// stopAnimating
  391. self._anim?.stopAnimating()
  392. if isComplete {
  393. /// 查询成功
  394. self.goodsDetail = detail
  395. } else {
  396. WHToast.showMessage("数据加载失败,原因:\(error?.retMsg ?? "未知错误")", duration: 1.5, finishHandler: {})
  397. }
  398. }
  399. }
  400. }
  401. /// 服务端查询商城商品详情请求方法
  402. /// - Parameter orderID: orderID
  403. fileprivate func requestQueryHsbyMarketGoodsDetail(_ orderID: String) {
  404. /// 异常
  405. guard let goodsManager = MTP2BusinessCore.shared.goodsManager else { return }
  406. /// startAnimating
  407. _anim?.startAnimating()
  408. /// 发送请求
  409. goodsManager.requestQueryHsbyMarketGoodsDetail(orderID, callback: { (isComplete, error, detail) in
  410. DispatchQueue.main.async {
  411. /// stopAnimating
  412. self._anim?.stopAnimating()
  413. if isComplete {
  414. /// 查询成功
  415. self.goodsDetail = detail
  416. } else {
  417. WHToast.showMessage("数据加载失败,原因:\(error?.retMsg ?? "未知错误")", duration: 1.5, finishHandler: {})
  418. }
  419. }
  420. })
  421. }
  422. /// 服务端查询游客商城商品详情请求方法
  423. /// - Parameter orderID: orderID
  424. fileprivate func requestQueryHsbyVisitorMarketGoodsDetail(_ goodsID: Int) {
  425. /// 异常
  426. guard let goodsManager = MTP2BusinessCore.shared.goodsManager else { return }
  427. /// startAnimating
  428. _anim?.startAnimating()
  429. /// 发送请求
  430. goodsManager.requestQueryHsbyVisitorMarketGoodsDetail(goodsID, callback: { (isComplete, error, detail) in
  431. DispatchQueue.main.async {
  432. /// stopAnimating
  433. self._anim?.stopAnimating()
  434. if isComplete {
  435. /// 查询成功
  436. self.goodsDetail = detail
  437. } else {
  438. WHToast.showMessage("数据加载失败,原因:\(error?.retMsg ?? "未知错误")", duration: 1.5, finishHandler: {})
  439. }
  440. }
  441. })
  442. }
  443. /// 添加用户藏品数据信息请求接口
  444. /// - Parameter goodsID: 商品代码
  445. fileprivate func AddUserFavoriteGoods(_ goodsID: Int) {
  446. /// 异常
  447. guard let goodsManager = MTP2BusinessCore.shared.goodsManager else { return }
  448. /// 发送请求
  449. goodsManager.requestAddUserFavoriteGoods(goodsID) { (_, _) in
  450. DispatchQueue.main.async {
  451. WHToast.showSuccess(withMessage: "添加成功", duration: 1.5, finishHandler: {})
  452. self.isFavorite = !self.isFavorite
  453. }
  454. }
  455. }
  456. /// 移出用户藏品数据信息请求接口
  457. /// - Parameter goodsID: 商品代码
  458. fileprivate func removeUserFavoriteGoods(_ goodsID: Int) {
  459. /// 异常
  460. guard let goodsManager = MTP2BusinessCore.shared.goodsManager else { return }
  461. /// 发送请求
  462. goodsManager.requestRemoveUserFavoriteGoods(goodsID) { (_, _) in
  463. DispatchQueue.main.async {
  464. WHToast.showSuccess(withMessage: "移出成功", duration: 1.5, finishHandler: {})
  465. self.isFavorite = !self.isFavorite
  466. }
  467. }
  468. }
  469. /// 获取历史数据请求
  470. fileprivate func requestHistoryDatas() {
  471. /// 异常
  472. guard let quoteManager = MTP2BusinessCore.shared.quoteManager else {
  473. return
  474. }
  475. /// 查询历史服务数据
  476. quoteManager.requestQueryHistoryDatas(.MinutesDay, model?.goodscode ?? "", nil, nil, 400, true) { (isComplete, error, historyDatas) in
  477. DispatchQueue.main.async {
  478. if isComplete, historyDatas?.count != 0 {
  479. let xs = historyDatas?.map({ (obj) -> String in
  480. return DateUtils.getTDateString(obj.ts, "MM-dd")
  481. })
  482. let max = historyDatas?.sorted(by: { (obj1, obj2) -> Bool in
  483. return obj1.c > obj2.c
  484. }).first?.c ?? 0.0
  485. let ys = [historyDatas?.map({ (obj) -> String in
  486. return obj.c.description
  487. })]
  488. /// 折线图数据
  489. self.lineChartView.leftDataArr = ys as [Any]
  490. /// 底部日期
  491. self.lineChartView.dataArrOfX = xs
  492. /// 泡泡标题
  493. self.lineChartView.paopaoTitleArray = xs
  494. /// 泡泡数据
  495. self.lineChartView.paopaoDataArray = ys as [Any]
  496. /// 最大值
  497. self.lineChartView.max = CGFloat(max*1.2)
  498. /// 最小值
  499. self.lineChartView.min = CGFloat(historyDatas?.sorted(by: { (obj1, obj2) -> Bool in
  500. return obj1.c < obj2.c
  501. }).first?.c ?? 0.0)
  502. /// 开始画图
  503. self.lineChartView.show()
  504. } else {
  505. /// 移出视图
  506. self.chartView.removeFromSuperview()
  507. }
  508. }
  509. }
  510. }
  511. // MARK: - Navigation
  512. // In a storyboard-based application, you will often want to do a little preparation before navigation
  513. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  514. // Get the new view controller using segue.destination.
  515. // Pass the selected object to the new view controller.
  516. if segue.identifier == "ShowCustomer" {
  517. (segue.destination as? CustomerViewController)?.goodsDetail = self.goodsDetail
  518. }
  519. }
  520. // MARK: - 订阅行情相关
  521. var uuid: String = UUID().uuidString
  522. var shouldSubscriptGoodsCodes: Set<String>? {
  523. didSet {
  524. guard let quoteSubscriptManager = MTP2BusinessCore.shared.quoteSubscriptManager else { return }
  525. quoteSubscriptManager.updateQuoteSubcriptGoods(uuid: uuid, goodsCode: shouldSubscriptGoodsCodes ?? [])
  526. }
  527. }
  528. var visibleGoodsCodes: Set<String> {
  529. var goodsCodes = Set<String>()
  530. goodsCodes.insert(self.model?.goodscode ?? "")
  531. return goodsCodes
  532. }
  533. }
  534. // MARK: - WKUIDelegate, WKNavigationDelegate
  535. extension GoodsDetailViewController: WKUIDelegate, WKNavigationDelegate {
  536. func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
  537. /// 图片缩放比例不正确问题
  538. webView.evaluateJavaScript("""
  539. var imgs = document.getElementsByTagName("img")
  540. for (var i = 0; i < imgs.length; i++) {
  541. imgs[i].setAttribute('width', '100%')
  542. }
  543. """,completionHandler: nil)
  544. webView.evaluateJavaScript("""
  545. var oMeta = document.createElement('meta');
  546. oMeta.content = 'width=device-width, initial-scale=1, user-scalable=0';
  547. oMeta.name = 'viewport';
  548. document.getElementsByTagName('head')[0].appendChild(oMeta);
  549. """,completionHandler: nil)
  550. /// 动态计算webView内容高度
  551. webView.evaluateJavaScript("document.body.scrollHeight") { [unowned self] (result, error) in
  552. if let tempHeight: Double = result as? Double {
  553. UIView.animate(withDuration: 0.5) {
  554. self.webViewLayoutConstraint.constant = CGFloat(tempHeight)
  555. }
  556. }
  557. }
  558. /// 设置webView 内容背景色
  559. webView.evaluateJavaScript("document.getElementsByTagName('body')[0].style.background='#FFFFFF'") { (result, error) in }
  560. }
  561. func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
  562. WHToast.showError(withMessage: error.localizedDescription, duration: 1.5, finishHandler: {})
  563. }
  564. func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
  565. /// 设置webView 内容背景色
  566. webView.evaluateJavaScript("document.getElementsByTagName('body')[0].style.background='#FFFFFF'") { (result, error) in }
  567. }
  568. }
  569. // MARK: - UIScrollViewDelegate
  570. extension GoodsDetailViewController: UIScrollViewDelegate {
  571. func scrollViewDidScroll(_ scrollView: UIScrollView) {
  572. if scrollView.contentOffset.y >= 20.0 {
  573. self.navigationController?.setNavigationBarHidden(false, animated: true)
  574. } else {
  575. self.navigationController?.setNavigationBarHidden(true, animated: true)
  576. }
  577. }
  578. }
  579. // MARK: - TSVideoPlaybackDelegate
  580. extension GoodsDetailViewController: TSVideoPlaybackDelegate, SDPhotoBrowserDelegate {
  581. func videoView(_ view: TSVideoPlayback!, didSelectItemAtIndexPath index: Int) {
  582. let browser = SDPhotoBrowser()
  583. browser.currentImageIndex = index-1
  584. browser.sourceImagesContainerView = self.mediaView.scrolView
  585. browser.delegate = self
  586. browser.show()
  587. }
  588. /// 预告视图
  589. func photoBrowser(_ browser: SDPhotoBrowser!, placeholderImageFor index: Int) -> UIImage! {
  590. return UIImage(named: "placeholder_image")
  591. }
  592. }