// // TradeViewController.swift // MTP2_iOS // // Created by Handy_Cao on 2020/10/29. // Copyright © 2020 Muchinfo. All rights reserved. // import UIKit import SDWebImage import NVActivityIndicatorView import WHToast /// 购买视图容器控制类 class TradeViewController: BaseViewController { // MARK: - 属性列表 /// 公司名称 @IBOutlet weak var company: UILabel! /// 标题 @IBOutlet weak var goodsName: UILabel! /// 商品图片 @IBOutlet weak var goodsImage: UIImageView! /// 单号 @IBOutlet weak var orderNo: UILabel! /// 资金提示信息 @IBOutlet weak var amountTips: UILabel! /// 提示信息 @IBOutlet weak var tips: UILabel! /// 金额范围 @IBOutlet weak var priceRange: UILabel! /// 价格 @IBOutlet weak var price: UILabel! /// 购买价格 @IBOutlet weak var priceField: IBNumberEditText! { didSet { priceField.valueType = 2 priceField.delegate = self } } /// 购买数量 @IBOutlet weak var qtyField: IBNumberEditText! { didSet { qtyField.valueType = 1 qtyField.delegate = self } } /// 卖家列表 @IBOutlet weak var tableView: UITableView! /// 高度 @IBOutlet weak var tableViewHeightConstraint: NSLayoutConstraint! /// 提交 @IBOutlet weak var submit: UIButton! /// 提交 @IBOutlet weak var refresh: UIButton! /// CellIdentifier let CellIdentifier = "Trade_Cell" /// 商品数据 override var takeInfo: Any? { didSet { guard let obj = takeInfo as? MoGoodsInfo else { return } DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.5) { /// 显示商品详情数据信息 self.showGoodsDetailInfo(obj) /// 行情订阅 self.subscriptQuote() } } } /// 卖家挂牌委托单数据 var orderDetails: [MoHsbyGoodsOrderDetail] = [] { didSet { /// 刷新列表数据 self.tableView.reloadData() /// 重新设置高度约束 self.tableViewHeightConstraint.constant = CGFloat(orderDetails.count)*50.0 /// 是否隐藏提示 self.tips.isHidden = orderDetails.count != 0 /// setTitle self.submit.setTitle(orderDetails.count == 0 ? "发布求购" : "提交订单", for: .normal) /// orderTips orderTips.isHidden = orderDetails.count == 0 } } /// 提示信息 @IBOutlet weak var orderTips: UILabel! /// 委托数量 var orderQty: Int = 0 { didSet { qtyField.currentIntNumbers = orderQty /// 计算购买金额 self.calculate() } } // MARK: - 生命周期相关 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. /// UI界面初始化 buildView() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) /// 隐藏导航栏 self.navigationController?.setNavigationBarHidden(false, animated: true) /// 侦听行情推送广播 MTP2BusinessCore.shared.broadcastManager?.addBroadcastListener(owner: self, action: .ReceiveTradeQuote) { [unowned self] in /// 异常情况 guard let goodsQuoteInfo = $0.object as? [(goodsHqCode: String, exchHqCode: String)], goodsQuoteInfo.count != 0, let goodsManager = MTP2BusinessCore.shared.goodsManager, let goods = self.takeInfo as? MoGoodsInfo else { return } /// 更新商品行情信息 goodsQuoteInfo.forEach { if $0.goodsHqCode == goods.goodscode, let goodsInfo = goodsManager.goodsInfos.first(where: {$0.goodsid == goods.goodsid}) { DispatchQueue.main.async { /// 更新价格 self.price.text = "\(goods.currencysign) \(goodsInfo.getLast() == 0.0 ? "\(goods.last)" : goodsInfo.getLast().toString(reserve: goodsInfo.decimalplace))" if goods.moQuoteInfo?.timeStamp != nil { /// 当前价格 self.priceField.currentDoubleNumbers = goodsInfo.getLast() == 0.0 ? goods.last : goodsInfo.getLast() } } } } } } deinit { /// 移出行情广播 MTP2BusinessCore.shared.broadcastManager?.removeBroadcastListener(owner: self, forName: .ReceiveTradeQuote) } // MARK: - 数据初始化 /// UI界面初始化 fileprivate func buildView() { /// addLoadingView self.addLoadingView() } /// 显示商品详情数据信息 /// - Parameter obj: obj fileprivate func showGoodsDetailInfo(_ obj: MoGoodsInfo) { /// 异常 guard let accountManager = MTP2BusinessCore.shared.accountManager else { return } /// 商品名称 self.goodsName.text = obj.goodsname /// 商品编号 self.orderNo.text = obj.goodscode /// 商品价格 self.price.text = "\(obj.currencysign) \(obj.getLast() == 0.0 ? obj.last : obj.getLast())" /// 价格范围 priceRange.text = "\(obj.limitdown)<= 价格范围 <= \(obj.limitup)" /// 供应商名称 company.text = obj.vendorname /// 输入框价格 priceField.incrementDoubleNum = obj.stepvalue priceField.minDoubleNum = obj.limitdown priceField.maxDoubleNum = obj.limitup priceField.decimalPlace = obj.decimalplace priceField.currentDoubleNumbers = obj.getLast() == 0.0 ? obj.last : obj.getLast() /// 查询对手买家挂牌信息 self.requestQueryHsbyGoodsOrderDetails(obj.last.toString(reserve: 2)) /// 输入步进值 qtyField.incrementIntNum = obj.lotsize qtyField.minIntNum = obj.lotsize qtyField.currentIntNumbers = obj.lotsize qtyField.maxIntNum = obj.buymaxqty == 0 ? Int.max : obj.buymaxqty /// 查询资金信息 accountManager.loginQueryReq(queryItem: "1,2") { (isComplete, error) in DispatchQueue.main.async { /// 计算购买金额 self.calculate() } } /// 商品图片 guard let url = StringUtils.getImageUrl(obj.picurls) else { return } goodsImage.sd_setImage(with: url, placeholderImage: UIImage(named: "placeholder_image"), options: .queryDiskDataSync, context: nil) } // MARK: - 交互相关 /// UITextField输入值发生改变响应事件 /// - Parameter sender: sender @IBAction func onValueChanged(_ sender: UITextField) {} /// onButtonPressed /// - Parameter sender: sender @IBAction fileprivate func onButtonPressed(_ sender: UIControl) { switch sender { case submit: let isListing = !tableView.visibleCells.contains { (cell) -> Bool in return (cell as? TradeCell)?.isCheck ?? false } /// 有对手委托单得时候必须选一个 if isListing, orderDetails.count != 0 { WHToast.showError(withMessage: "请选择卖家", duration: 1.5, finishHandler: {}) return } if isListing { /// 买挂牌 doListingTrade() } else { /// 买摘牌 doDeListingTrade() } case refresh: /// 刷新按钮 /// 更新单据 self.requestQueryHsbyGoodsOrderDetails(priceField.currentDoubleNumbers.toString(reserve: 2)) default: break } } // MARK: - 接口请求 /// 买挂牌提交请求方法 fileprivate func doListingTrade() { /// 异常 guard let tradeManager = MTP2BusinessCore.shared.tradeManager, let obj = takeInfo as? MoGoodsInfo, check() else { return } /// 构建交易参数 let tradeParam = MoTradeParam() /// 买卖方向 tradeParam.buyOrSell = .ORDERDIRECTION_BUY /// 数量 tradeParam.orderQty = Double(qtyField.currentIntNumbers) /// 挂牌价格 tradeParam.orderPrice = priceField.currentDoubleNumbers /// 挂牌点选类型 tradeParam.delistingType = .DELISTINGTYPE_SELECTED /// 点选成交 tradeParam.listingSelectType = .LISTINGSELECTTYPE_LISTING /// 有效类型 tradeParam.validType = .VALIDTYPE_DR /// 下单类型 tradeParam.buildType = .BUILDTYPE_OPEN /// 时间有效类型 tradeParam.timevalidType = .VALIDTYPE_DR /// 市场编号 tradeParam.marketID = obj.marketid /// 商品ID tradeParam.goodsID = obj.goodsid /// 开启Loading NVActivityIndicatorPresenter.sharedInstance.startAnimating(ActivityData(message: "购买中......", type: .ballClipRotate, color: UIColor.loding(), backgroundColor: .clear), NVActivityIndicatorView.DEFAULT_FADE_IN_ANIMATION) tradeManager.tradeCommision(tradeParam: tradeParam) { [weak self] (isSuccess, error, orderNo) in DispatchQueue.main.async { /// dismisss loding..... NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) if isSuccess { /// 返回上次视图 WHToast.showSuccess(withMessage: "请求成功", duration: 1.5) { self?.navigationController?.popViewController(animated: true) } } else { WHToast.showError(withMessage: "请求失败,\(ErrorUtils.getDesc(errorCode: error?.retCode ?? -99999) ?? "未知错误")", duration: 1.5, finishHandler: {}) } } } } /// 买摘牌提交请求方法 fileprivate func doDeListingTrade() { /// 异常 guard let tradeManager = MTP2BusinessCore.shared.tradeManager, let obj = takeInfo as? MoGoodsInfo, check() else { return } let group = DispatchGroup() /// 开启Loading NVActivityIndicatorPresenter.sharedInstance.startAnimating(ActivityData(message: "购买中......", type: .ballClipRotate, color: UIColor.loding(), backgroundColor: .clear), NVActivityIndicatorView.DEFAULT_FADE_IN_ANIMATION) /// 构建交易参数 let tradeParam = MoTradeParam() /// 买卖方向 tradeParam.buyOrSell = .ORDERDIRECTION_BUY /// 挂牌点选类型 tradeParam.delistingType = .DELISTINGTYPE_SELECTED /// 点选成交 tradeParam.listingSelectType = .LISTINGSELECTTYPE_DELISTING /// 有效类型 tradeParam.validType = .VALIDTYPE_DR /// 下单类型 tradeParam.buildType = .BUILDTYPE_OPEN /// 时间有效类型 tradeParam.timevalidType = .VALIDTYPE_DR /// 市场编号 tradeParam.marketID = obj.marketid /// 商品ID tradeParam.goodsID = obj.goodsid for cell in tableView.visibleCells { if let cell = cell as? TradeCell, cell.isCheck { /// 挂牌价格 tradeParam.orderPrice = cell.model?.orderprice ?? 0.0 /// 关联单号 tradeParam.relatedID = UInt64(cell.model?.orderid ?? "0") ?? 0 /// 数量 tradeParam.orderQty = Double(cell.qtyField.currentIntNumbers) group.enter() tradeManager.tradeCommision(tradeParam: tradeParam) { (isSuccess, error, orderNo) in group.leave() } } } group.notify(queue: DispatchQueue.main) { /// dismisss loding..... NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) WHToast.showSuccess(withMessage: "委托已提交,请前往我的单据页面查看!", duration: 1.5, finishHandler: { self.navigationController?.popViewController(animated: true) }) } } /// 查询商品对应委托单的数据信息 /// - Parameter price: 价格 fileprivate func requestQueryHsbyGoodsOrderDetails(_ price: String?) { /// 异常 guard let orderManager = MTP2BusinessCore.shared.orderManager, let obj = takeInfo as? MoGoodsInfo else { return } /// startAnimating self._anim?.startAnimating() /// 发送请求 orderManager.requestQueryHsbyGoodsOrderDetails(obj.goodsid, price) { (isComplete, error, orderDetails) in DispatchQueue.main.async { /// stopAnimating self._anim?.stopAnimating() if isComplete { /// 更新数据 self.orderDetails = orderDetails ?? [] } else { self.orderDetails = [] WHToast.showError(withMessage: "数据更新失败,原因:\(error?.retMsg ?? "未知错误")", duration: 1.5, finishHandler: {}) } } } } /// 合规性校验 /// - Returns: Bool fileprivate func check() -> Bool { /// 请输入委托价格 guard priceField.currentDoubleNumbers != 0.0 else { WHToast.showError(withMessage: "请输入委托价格", duration: 1.5, finishHandler: {}) return false } /// 委托价格不在范围内 let detail = takeInfo as? MoGoodsInfo if priceField.currentDoubleNumbers < (detail?.limitdown ?? 0.0) || (priceField.currentDoubleNumbers > detail?.limitup ?? 0.0) { WHToast.showError(withMessage: "\(detail?.limitdown ?? 0.0)<=委托价格<=\(detail?.limitup ?? 0.0)", duration: 1.5, finishHandler: {}) return false } /// 请输入交易数量 if qtyField.currentIntNumbers == 0 { WHToast.showError(withMessage: "请输入交易数量", duration: 1.5, finishHandler: {}) return false } /// 委托数量不能大于 if qtyField.currentIntNumbers > qtyField.maxIntNum { WHToast.showError(withMessage: "交易数量应小于等于\(qtyField.maxIntNum)", duration: 1.5, finishHandler: {}) return false } return true } // MARK: - 订阅行情相关 var uuid: String = UUID().uuidString /// 行情订阅 private func subscriptQuote() { var goodsCodes = Set() if let goods = self.takeInfo as? MoGoodsInfo { goodsCodes.insert(goods.goodscode) } guard let quoteSubscriptManager = MTP2BusinessCore.shared.quoteSubscriptManager else { return } quoteSubscriptManager.updateQuoteSubcriptGoods(uuid: uuid, goodsCode: goodsCodes) } // MARK: - 计算相关 /// 计算相关 fileprivate func calculate() { /// 异常 guard let obj = takeInfo as? MoGoodsInfo, let accountManager = MTP2BusinessCore.shared.accountManager, let taAccountInfo = accountManager.getCurrentTAAccountInfo() else { return } let amount = (priceField.currentDoubleNumbers*Double(qtyField.currentIntNumbers)*obj.agreeUnit).toDownString(reserve: obj.decimalplace) /// 期末余额 let blance = taAccountInfo.currentBalance-(taAccountInfo.freezeMargin+taAccountInfo.otherFreezeMargin+taAccountInfo.freezeCharge) amountTips.text = "购买金额:\(amount) 可用金额:\(blance.toDownString(reserve: 2))" } } extension TradeViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return orderDetails.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier, for: indexPath) as! TradeCell cell.model = orderDetails[indexPath.row] cell.isCheck = false cell.block = { (_ model: MoHsbyGoodsOrderDetail?, _ isCheck: Bool, _ qty: Int) in var qty: Int = 0 self.tableView.visibleCells.forEach { (cell) in if (cell as! TradeCell).isCheck { qty += (cell as! TradeCell).qtyField.currentIntNumbers } } self.orderQty = qty /// 输入框是否可用 self.qtyField.isUserInteractionEnabled = !self.tableView.visibleCells.contains(where: { (cell) -> Bool in return ((cell as? TradeCell)?.isCheck ?? false) }) } /// 最小交易数量 if let obj = takeInfo as? MoGoodsInfo { cell.qtyField.incrementIntNum = obj.lotsize cell.qtyField.minIntNum = obj.lotsize } return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 50.0 } } extension TradeViewController: IBNumberEditTextDelegate { func numberInputViewDidEndEditing(_ numberInputView: IBNumberEditText) { if numberInputView == priceField { let orderPrice = numberInputView.currentDoubleNumbers /// 更新单据 self.requestQueryHsbyGoodsOrderDetails(orderPrice.toString(reserve: 2)) } else { calculate() } } func numberInputView(_ numberInputView: IBNumberEditText, _ buttonType: NumberInputViewButtonType) { if numberInputView == priceField { let orderPrice = numberInputView.currentDoubleNumbers /// 更新单据 self.requestQueryHsbyGoodsOrderDetails(orderPrice.toString(reserve: 2)) } calculate() } func IBNumberEditText(textField: UITextField) {} } class TradeCell: BaseTableViewCell { // MARK: - 属性列表 /// bgView @IBOutlet weak var bgView: UIView! /// checkBox @IBOutlet weak var checkBox: UIButton! /// accountName @IBOutlet weak var accountName: UILabel! /// price @IBOutlet weak var price: UILabel! /// qty @IBOutlet weak var qty: UILabel! /// checkBox @IBOutlet weak var qtyField: IBNumberEditText! { didSet { qtyField.valueType = 1 qtyField.delegate = self } } /// 数据模型 override var model: MoHsbyGoodsOrderDetail? { didSet { /// 异常 guard let obj = model else { return } /// 数量范围 qtyField.maxIntNum = obj.enableqty if let vc = self.superController() as? MyUnusedViewController { /// 我的闲置 qtyField.minIntNum = vc.myGoods?.lotsize ?? 1 qtyField.incrementIntNum = vc.myGoods?.lotsize ?? 1 qtyField.currentIntNumbers = obj.enableqty } else { let lotSize = ((self.superController() as? TradeViewController)?.takeInfo as? MoGoodsInfo)?.lotsize ?? 1 qtyField.minIntNum = lotSize qtyField.incrementIntNum = lotSize qtyField.currentIntNumbers = lotSize } /// 客户名称 accountName.text = obj.customername /// 委托价格 price.text = "\(obj.currencysign)\(obj.orderprice)" /// 委托数量 qty.text = "\(obj.enableqty)\(obj.goodunit)" } } /// 是否勾选 var isCheck: Bool = false { didSet { /// 异常 guard let obj = model else { return } /// setImage checkBox.setImage(UIImage(named: isCheck ? "check_selected" : "check_normal"), for: .normal) /// 执行回调 if let callBack = block { callBack(obj, isCheck, qtyField.currentIntNumbers) } /// 设置交互色 bgView.backgroundColor = UIColorFromHex(rgbValue: isCheck ? 0xecf3fd : 0xf7f7f7) /// 是否可用 qtyField.isUserInteractionEnabled = isCheck } } /// 回调块 var block: ((_ model: MoHsbyGoodsOrderDetail?, _ isCheck: Bool, _ qty: Int) -> Void)? /// onButtonPressed /// - Parameter sender: sender @IBAction func onButtonPressed(_ sender: UIButton) { switch sender { case checkBox: isCheck = !isCheck default: return } } } extension TradeCell: IBNumberEditTextDelegate { /// 不做任何处理 func IBNumberEditText(textField: UITextField) {} func numberInputView(_ numberInputView: IBNumberEditText, _ buttonType: NumberInputViewButtonType) { isCheck = true } func numberInputViewDidEndEditing(_ numberInputView: IBNumberEditText) { isCheck = true } }