// // ExposureViewController.swift // MTP2_iOS // // Created by Muchinfo on 2021/1/5. // Copyright © 2021 Muchinfo. All rights reserved. // import UIKit import JXSegmentedView import IBAnimatable import WHToast import GTMRefresh /// 敞口视图容器控制类 class ExposureViewController: BaseCollectionViewController { // MARK: - 属性列表 /// 主滚动视图 @IBOutlet weak var mainScrollView: UIScrollView! /// 历史内容装载视图 @IBOutlet weak var hisContetnView: UIView! { didSet { hisContetnView.isHidden = true } } /// 内容装载视图 @IBOutlet weak var contetnView: UIStackView! { didSet { contetnView.isHidden = false } } /// 期货明细 @IBOutlet weak var futures: UIButton! /// 现货明细 @IBOutlet weak var spot: UIButton! /// 交易下单 @IBOutlet weak var trade: UIButton! /// 实时敞口数据 var exposures: [MoRealExposure] = [] { didSet { /// 左边数据 leftDatas = exposures.map { (obj) -> String in /// 合同编号和采购销售名称 return "\(obj.middleGoodsName)"+"\n\(obj.middleGoodsCode)" } /// 右边数据 rightDatas = exposures.map { (obj) -> [String] in let e = obj.enumdicname.isBlank() return ["\(obj.hedgeqty.toUpString())\(e)\n\(obj.arbitrageqty.toUpString())\(e)", "\(obj.totalSpotQty.toUpString())\(e)\n\(obj.diffSpotQty.toUpString())\(e)", "\(obj.diffHedgeQty.toUpString())\(e)\n\(obj.diffArbitrageQty.toUpString())\(e)", "\((obj.middleGoodsHedgeRatio*100.0).toUpString())%\n\((obj.needarbitrageratio*100.0).toUpString())%", "\(obj.needhedgeqty.toUpString())\(e)\n\(obj.needarbitrageqty.toUpString())\(e)", "\(obj.totalNeedHedgeQty.toUpString())\(e)\n\(obj.diffSpotHedgeQty.toUpString())\(e)", "\(obj.totalFutureQty.toUpString())\(e)\n\(obj.diffFutuQty.toUpString())\(e)", "\(obj.needHedgeExposoure.toUpString())\(e)\n\(obj.diffExposoureQty.toUpString())\(e)", "\(obj.totalExposure.toUpString())\(e)\n\(obj.diffqty.toUpString())\(e)"] } /// 刷新右侧列表数据 rightTableView.reloadData() /// 无数据按钮 noDataButton.isHidden = exposures.count != 0 } } /// 敞口现货头寸 var exposureSpots: [MoExposureSpot] = [] { didSet { /// 左边数据 leftDatas = exposureSpots.map { (obj) -> String in /// 合同编号和采购销售名称 return "\(obj.wrstandardname)" } /// 右边数据 rightDatas = exposureSpots.map { (obj) -> [String] in let e = obj.enumdicname.isBlank() return ["\(obj.oritoalspotqty.toUpString())\(e)", "\(obj.increaseqty.toUpString())\(e)\n\(obj.decreaseqty.toUpString())\(e)", "\(obj.totalspotqty.toUpString())\(e)"] } /// 刷新右侧列表数据 rightTableView.reloadData() /// 无数据按钮 noDataButton.isHidden = exposureSpots.count != 0 } } /// 敞口期货头寸 var hedgePositions: [MoExposureHedgePosition] = [] { didSet { /// 左边数据 leftDatas = hedgePositions.map { (obj) -> String in /// 合同编号和采购销售名称 return "\(obj.goodsname)"+"\n\(obj.goodscode)" } /// 右边数据 rightDatas = hedgePositions.map { (obj) -> [String] in return ["\(obj.totalydqty.toUpString())手", "\(obj.increaseqty.toUpString())手\n\(obj.decreaseqty.toUpString())手", "\(obj.totalcurqty.toUpString())手"] } /// 刷新右侧列表数据 rightTableView.reloadData() /// 无数据按钮 noDataButton.isHidden = hedgePositions.count != 0 } } /// 历史敞口视图 lazy var hisExposure: HisExposuresViewController = { $0.view.frame = hisContetnView.bounds return $0 } (self.viewController("Exposure", "HisExposures") as! HisExposuresViewController) /// AutoTimerID let AutoTimerID = "RealExposureTimer" /// 权限菜单 var roleTitles: [String] { get { var titles: [String] = [] /// 权限控制 guard let commonManager = MTP2BusinessCore.shared.commonManager else { return titles } if commonManager.containMenu(key: "client_exposure_real") { titles.append("实时敞口") } if commonManager.containMenu(key: "client_exposure_spot") { titles.append("现货头寸") } if commonManager.containMenu(key: "client_exposure_future") { titles.append("期货头寸") } if commonManager.containMenu(key: "client_exposure_his") { titles.append("历史敞口") } return titles } } // MARK: - 生命周期 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. /// loding addLoadingView() /// 菜单 dataSource.titles = roleTitles segmentedView.dataSource = dataSource segmentedView.reloadData() /// 判断其权限控制 if let commonManager = MTP2BusinessCore.shared.commonManager { /// 交易下单 trade.isHidden = !commonManager.containMenu(key: "client_exposure_trade") /// 期货明细 futures.isHidden = !commonManager.containMenu(key: "client_exposure_futuresdetail") /// 现货明细 spot.isHidden = !commonManager.containMenu(key: "client_exposure_spotdetail") } /// 分页回调 segmentBlock = { (_ index: Int, _ segment: JXSegmentedView) in switch self.roleTitles[index] { case "实时敞口": /// 查询实时敞口 self.reloadData(0) case "现货头寸": /// 查询现货头寸 self.reloadData(1) case "期货头寸": /// 查询期货头寸 self.reloadData(2) default: break } /// 内容视图 self.contetnView.isHidden = self.roleTitles[index] == "历史敞口" /// 历史视图 if self.roleTitles[index] == "历史敞口" { if !self.hisContetnView.subviews.contains(self.hisExposure.view) { self.hisContetnView.addSubview(self.hisExposure.view) self.addChild(self.hisExposure) self.hisExposure.didMove(toParent: self) self.noDataButton.isHidden = true } } else { /// 移出 if self.hisContetnView.subviews.contains(self.hisExposure.view) { self.hisExposure.view.removeFromSuperview() self.hisExposure.removeFromParent() } } self.hisContetnView.isHidden = self.roleTitles[index] != "历史敞口" } /// 选中回调 selectBlock = { (_ row: Int?) in if self.roleTitles[self.segmentedView.selectedIndex] != "实时敞口" { /// 头寸选中 self.performSegue(withIdentifier: "ShowPositionSpotFutureDetail", sender: self.segmentedView.selectedIndex == 1 ? OperatorType.cashFlow : OperatorType.futuresFlow) } else{ /// 判断选中位置 if let index = self.selectedRow, let cell = self.rightTableView.cellForRow(at: IndexPath(row: index.row, section: 0)) as? RightCell { /// 判断Cell相对于view所处的位置 let rectInTableView = self.rightTableView.rectForRow(at: IndexPath(row: index.row, section: 0)) /// 获取 let rectInSuperview = self.rightTableView.convert(rectInTableView, to: self.view) /// 数据显示 /// 获取对应的位置 self.operationView.top = rectInSuperview.origin.y + cell.collectionView.height + 5.0 /// 是否隐藏 self.operationView.isHidden = !index.isExpland } } } if roleTitles.count != 0 { /// 下拉刷新 mainScrollView.gtm_addRefreshHeaderView(refreshHeader: DefaultGTMRefreshHeader()) { /// 查询实时数据 self.reloadData(self.segmentedView.selectedIndex) } /// 默认选中第一个 segmentedView.defaultSelectedIndex = 0 segmentedView.delegate?.segmentedView(segmentedView, didSelectedItemAt: 0) } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) /// 重新请求数据 reloadData(segmentedView.selectedIndex) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) /// 列头高度 columnWidth = 100.0 /// 开启定时器刷新 startAutoTimer() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) /// 取消定时器刷新 stopAutoTimer() } // MARK: - 交互相关 /// onButtonPressed /// - Parameters: /// - sender: sender @IBAction fileprivate func onButtonPressed(_ sender: UIButton) { switch sender { case futures, spot: /// 实时敞口-现货期货明细 self.performSegue(withIdentifier: "ShowExposureSpotFutureDetail", sender: sender == futures ? OperatorType.futuresFlow : OperatorType.cashFlow) case trade: /// 期货下单 /// 跳转期货下单方法 doFutureTrade() default: break } } /// 跳转期货下单方法 fileprivate func doFutureTrade() { /// 异常 guard let goodsManager = MTP2BusinessCore.shared.goodsManager, let goodsInfos = goodsManager.goodsInfos, let row = selectedRow?.row else { return } /// 获取对应的主力合约商品信息 goodsManager.queryExposureGoods(middlegoodsid: exposures[row].middleGoodsID, callback: { isSuccess, er, objs in DispatchQueue.main.async { /// 获取主力合约商品失败 if !isSuccess { WHToast.showMessage("获取主力合约信息失败,原因:\(er?.retMsg ?? "查询超时")", duration: ToastTimer, finishHandler: {}) return } /// 默认带主力合约数据 if let obj = goodsInfos.first(where: {$0.goodsid == objs?.first?.goodsid}) { self.push("Futures", "ATPTrader", obj) } else { self.push("Futures", "ATPTrader", nil) } } }) } // MARK: - 接口请求 /// 刷新数据信息 /// - Parameter type: 类型 fileprivate func reloadData(_ type: Int) { /// 历史敞口不做处理 if roleTitles[segmentedView.selectedIndex] == "历史敞口" { /// 结束下拉刷新 mainScrollView.endRefreshing() return } /// 异常 guard let commonManager = MTP2BusinessCore.shared.commonManager, let spotManager = MTP2BusinessCore.shared.spotManager else { return } /// startAnimating _anim?.startAnimating() /// group let group = DispatchGroup() /// 定义列头 var key = "" /// group group.enter() /// 查询类型 switch roleTitles[type] { case "实时敞口": /// 实时敞口 key = "table_mobile_exposure_realtime" /// 允许选中 canSelected = true /// 清空数据 exposures = [] /// 查询实时敞口数据 spotManager.queryRealtimeExposure { (isSuccess, er, objs) in DispatchQueue.main.async { /// 查询失败 if !isSuccess { self.exposures = [] WHToast.showMessage("数据查询失败,原因:\(er?.retMsg ?? "查询超时")", duration: ToastTimer, finishHandler: {}) return } /// 数据赋值 self.exposures = objs ?? [] } group.leave() } case "现货头寸": /// 现货头寸 key = "table_mobile_exposure_spotposition" /// 不允许选中 canSelected = false /// 清空数据 exposureSpots = [] /// 查询敞口现货头寸 spotManager.queryExposureSpot { (isSuccess, er, objs) in DispatchQueue.main.async { /// 查询失败 if !isSuccess { self.exposureSpots = [] WHToast.showMessage("数据查询失败,原因:\(er?.retMsg ?? "查询超时")", duration: ToastTimer, finishHandler: {}) return } /// 数据赋值 self.exposureSpots = objs ?? [] } group.leave() } default: /// 期货头寸 key = "table_mobile_exposure_futuresposition" /// 不允许选中 canSelected = false /// 清空数据 hedgePositions = [] /// queryExposureHedgePosition spotManager.queryExposureHedgePosition { (isSuccess, er, objs) in DispatchQueue.main.async { /// 查询失败 if !isSuccess { self.hedgePositions = [] WHToast.showMessage("数据查询失败,原因:\(er?.retMsg ?? "查询超时")", duration: ToastTimer, finishHandler: {}) return } /// 数据赋值 self.hedgePositions = objs ?? [] } group.leave() } } group.enter() /// 查询列头信息 commonManager.queryTableDefine(tableKey: key) { (isSuccess, er, objs) in DispatchQueue.main.async { /// 查询失败 if !isSuccess { WHToast.showMessage("数据查询失败,原因:\(er?.retMsg ?? "查询超时")", duration: ToastTimer, finishHandler: {}) return } /// 数据 self.columnHeaders = objs?.first?.columns.sorted(by: { (obj1, obj2) -> Bool in return obj1.orderindex String in return obj.columntitle.replacingOccurrences(of: "\\n", with: "\n") }) ?? [] } group.leave() } group.notify(queue: .main) { /// 结束下拉刷新 self.mainScrollView.endRefreshing() /// stopAnimating self._anim?.stopAnimating() } } // MARK: - 定时器相关 /// 定时器刷新 fileprivate func startAutoTimer() { /// 每隔30秒自动刷新一次 MCGCDTimer.shared.scheduledDispatchTimer(WithTimerName: AutoTimerID, timeInterval: 30, queue: .global(), repeats: true, isNowRun: false) { DispatchQueue.main.async { self.reloadData(self.segmentedView.selectedIndex) } } } /// 取消定时器刷新 fileprivate func stopAutoTimer() { MCGCDTimer.shared.cancleTimer(WithTimerName: AutoTimerID) } // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. if segue.identifier == "ShowExposureSpotFutureDetail", let f = segue.destination as? ExposureSpotFutureDetailViewController, let row = selectedRow?.row, exposures.count != 0 { /// 实时敞口 - 期货现货明细 f.realExposure = exposures[row] if let type = sender as? OperatorType { /// title f.navigationItem.title = "实时敞口-\(type == .cashFlow ? "现货" : "期货")明细" f.operatorType = type } } else if segue.identifier == "ShowPositionSpotFutureDetail", let p = segue.destination as? PositionSpotFutureDetailViewController,let row = selectedRow?.row { /// 头寸-期货现货明细 if ((sender as! OperatorType) == .cashFlow) { /// 现货明细 p.exposureSpot = exposureSpots[row] } else { /// 期货明细 p.hedgePosition = hedgePositions[row] } if let type = sender as? OperatorType { /// title p.navigationItem.title = "\(type == .cashFlow ? "现货" : "期货")头寸-\(type == .cashFlow ? "现货" : "期货")明细" p.operatorType = type } } } }