// // HomeViewController.swift // MTP2_iOS // // Created by Muchinfo on 2020/12/30. // Copyright © 2020 Muchinfo. All rights reserved. // import UIKit import SDCycleScrollView import JXSegmentedView import WHToast import GTMRefresh import SwiftyAttributes import SwiftDate import DeviceKit import IBAnimatable import SafariServices import NVActivityIndicatorView import SDWebImage /// 首页视图容器控制类 class HomeViewController: BaseViewController { // MARK: - 属性列表 /// 标题 @IBOutlet weak var titleButton: UIButton! /// 标题 @IBOutlet weak var account: UIButton! /// 主滚动视图 @IBOutlet weak var scrollView: UIScrollView! /// 轮播图 @IBOutlet weak var sdCycle: SDCycleScrollView! { didSet { sdCycle.bannerImageViewContentMode = .scaleAspectFill sdCycle.autoScrollTimeInterval = 5.0 sdCycle.autoScroll = true sdCycle.showPageControl = true sdCycle.infiniteLoop = true sdCycle.scrollDirection = .horizontal sdCycle.delegate = self self.sdCycle.localizationImageNamesGroup = banners } } /// 菜单项约束视图 @IBOutlet weak var menuStackView: UIStackView! /// 菜单项高度约束 @IBOutlet weak var menuLayoutConstraint: NSLayoutConstraint! /// 分页高度约束 @IBOutlet weak var pageLayoutConstraint: NSLayoutConstraint! /// 菜单项集合视图 @IBOutlet weak var menuCollectionView: UICollectionView! { didSet { /// 设置约束 menuCollectionView.setCollectionViewLayout(layout, animated: true) } } /// 类目 @IBOutlet weak var segmentedView: JXSegmentedView! { didSet { segmentedView.dataSource = dataSource segmentedView.indicators = [indicator] segmentedView.delegate = self } } /// 公告列表 @IBOutlet weak var tableView: UITableView! /// 列表高度约束 @IBOutlet weak var heightLayoutConstraint: NSLayoutConstraint! /// 页签 @IBOutlet weak var pageControl: UIPageControl! /// 菜单项约束 lazy var layout: HorizontalPageFlowlayout = { $0.setParams(columnSpacing: 10.0, rowSpacing: 0.0, edgeInsets: UIEdgeInsets(top: 10.0, left: 10.0, bottom: 0.0, right: 10.0)) $0.minimumInteritemSpacing = 0 $0.minimumLineSpacing = 0 $0.scrollDirection = .horizontal return $0 } (HorizontalPageFlowlayout(rowCount: 2, itemCountPerRow: Device.current.isPad ? 5 : 4)) /// 通用layout lazy var noLayout: UICollectionViewFlowLayout = { $0.minimumInteritemSpacing = 0 $0.minimumLineSpacing = 0 $0.scrollDirection = .horizontal return $0 } (UICollectionViewFlowLayout()) /// MSG_CELl let cellIdentifier = "MSG_CELl" /// 集合视图 let collectionCellIdentifier = "MENU_CELL" /// 公告数据 var notices: [MoNotice] = [] { didSet { heightLayoutConstraint.constant = CGFloat(notices.count > 5 ? notices.count : 5)*65.0 /// 刷新列表数据 tableView.reloadData() } } /// 新闻资讯数据信息 var news: [MoSiteColumnDetail] = [] { didSet { heightLayoutConstraint.constant = CGFloat(news.count > 5 ? news.count : 5)*65.0 /// 刷新列表数据 tableView.reloadData() } } /// 菜单项 var menus: [(image: String, title: String, type: MenuType, badge: Int)] = [] { didSet { /// 显示菜单项 menuCollectionView.reloadData() } } /// 本地轮播图 var banners: [Any] { get { switch MTP2BusinessCore.shared.address?.oem { case "qhj": return [UIImage(named: "qhj_banner_01") as Any] default: return [UIImage(named: "banner01") as Any] } } } /// 广告配置信息 var configs: [MoImageConfigs] = [] { didSet { /// 数据 let paths = configs.map({ (model) -> String in return model.imagepath.getUrlString() }) sdCycle.imageURLStringsGroup = paths } } // MARK: - 生命周期 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. /// 不需要返回按钮 addBackBarButtonItem(true) /// 异常 let oem = MTP2BusinessCore.shared.address?.oem /// titles dataSource.titles = oem?.lowercased() == "qyfg" ? ["公告", "研报", "资讯"] : ["资讯", "公告", "消息"] segmentedView.defaultSelectedIndex = 0 segmentedView.reloadData() segmentedView.delegate?.segmentedView(segmentedView, didSelectedItemAt: 0) /// gtm_addRefreshHeaderView scrollView.gtm_addRefreshHeaderView(refreshHeader: DefaultGTMRefreshHeader()) { [weak self] in /// 请求数据 self?.requestHomePageDatas() } /// 请求数据 DispatchQueue.main.asyncAfter(deadline: .now()+1.0) { /// 请求数据 self.requestHomePageDatas() } /// 异常 guard let accountManager = MTP2BusinessCore.shared.accountManager, let commonManager = MTP2BusinessCore.shared.commonManager, let loginQuery = accountManager.loginQuery, let userInfo = loginQuery.userInfo else { return } /// 标题按钮 if let root = accountManager.rootUserAccountInfo { titleButton.setAttributedTitle(root.accountname.withFont(.font_15).withTextColor(.white), for: .normal) } else { titleButton.setAttributedTitle(app_Name.withFont(.font_15).withTextColor(.white), for: .normal) } if let login = loginQuery.loginAccount { /// 账户信息 account.setAttributedTitle("\(login.accountname)".withFont(.font_10).withTextColor(.white), for: .normal) } else { /// 账户信息 account.setAttributedTitle("\(userInfo.customername)".withFont(.font_10).withTextColor(.white), for: .normal) } /// 判断其权限控制 var datas: [(image: String, title: String, type: MenuType, badge: Int)] = [] /// 判断其是否有客户资料权限 if commonManager.containMenu(key: "client_customer") || commonManager.containMenu(key: "client_qhjkhzl") { datas.append((image: "home_menu_khzl", title: "客户资料", .khzl, 0)) } /// 判断其是否有账户管理权限 if commonManager.containMenu(key: "client_accountmanage") { datas.append((image: "home_menu_zhgl", title: "账户管理", .zhgl, 0)) } /// 判断其是否有商品信息权限 if commonManager.containMenu(key: "client_deliverygoods") { datas.append((image: "home_menu_spxx", title: "商品信息", .spxx, 0)) } /// 判断其是否有仓库信息权限 if commonManager.containMenu(key: "client_warehouse") { datas.append((image: "home_menu_ckxx", title: "仓库信息", .ckxx, 0)) } /// 判断其是否有现货审核权限 if commonManager.containMenu(key: "client_spotsaduit") { datas.append((image: "home_menu_xhht", title: "现货审核", .xhsh, 0)) } /// 判断其是否有财务审核权限 if commonManager.containMenu(key: "client_finance") { datas.append((image: "home_menu_cwgl", title: "财务审核", .cwgl, 0)) } /// 判断其是否有库存审核权限 if commonManager.containMenu(key: "client_stock") { datas.append((image: "home_menu_kcsh", title: "库存审核", .kcsh, 0)) } /// 判断其是否有库存管理权限 if commonManager.containMenu(key: "client_stock_manage") { datas.append((image: "home_menu_kcgl", title: "库存管理", .kcgl, 0)) } /// 判断其是否有交易查询权限 if commonManager.containMenu(key: "client_traderflow") { datas.append((image: "home_menu_jycx", title: "交易查询", .jycx, 0)) } /// 判断其是否有现货市价权限 if commonManager.containMenu(key: "client_spotmarketprice") { datas.append((image: "home_menu_xhsj", title: "现货市价", .xhsj, 0)) } /// 判断其是否有交易主体权限 if commonManager.containMenu(key: "client_trademain") { datas.append((image: "home_menu_jyzt", title: "交易主体", .jyzt, 0)) } /// 判断其是否有审核设置权限 if commonManager.containMenu(key: "client_aduitsetting") { datas.append((image: "home_menu_shsz", title: "审核设置", .shsz, 0)) } /// 判断其是否有审核设置权限 if commonManager.containMenu(key: "client_mobile_varietiesparameteraduit") { datas.append((image: "home_menu_fgsh", title: "风管审核", .fgsh, 0)) } /// 判断其是否有千海金-交易查询权限 if commonManager.containMenu(key: "client_qhjjycx") { datas.append((image: "home_menu_jycx", title: "交易查询", .qhjjycx, 0)) } /// 判断其是否有千海金-定投管理权限 if commonManager.containMenu(key: "client_qhjdtgl") { datas.append((image: "home_menu_dtgl", title: "定投管理", .dtgl, 0)) } /// 判断其是否有千海金-资金信息权限 if commonManager.containMenu(key: "client_qhjzjxx") { datas.append((image: "home_menu_zjxx", title: "资产信息", .zjxx, 0)) } /// 判断其是否有千海金-充值提现权限 if commonManager.containMenu(key: "client_qhjcztx") { datas.append((image: "home_menu_cztx", title: "充值提现", .cztx, 0)) } menus = datas /// 显示页签个数 pageControl.numberOfPages = Int(menus.count/8)+1 pageLayoutConstraint.constant = menus.count <= 8 ? 0.0 : 25.0 pageControl.isHidden = menus.count <= 8 /// 隐藏菜单视图 menuStackView.isHidden = menus.count == 0 /// 重置高度约束 menuLayoutConstraint.constant = menus.count == 0 ? 0.0 : 175.0 /// 小于4个菜单项 if menus.count <= 4 { menuLayoutConstraint.constant = 90.0 menuCollectionView.setCollectionViewLayout(noLayout, animated: true) } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) /// 解决bug if UIDevice.current.orientation != .portrait { /// 强制设置成竖屏 UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") /// 重新设置一下 (UIApplication.shared.keyWindow?.rootViewController as? MainTabBarController)?.selectedIndex = 0 } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) /// 查询待办事项 queryPendingAuditInfo() } // MARK: - 交互相关 /// onBarButtonItemPressed /// - Parameter sender: sender @IBAction func onBarButtonItemPressed(_ sender: UIBarButtonItem) { push("Settings", "Settings") } /// onValueChanged /// - Parameter sender: sender @IBAction func onValueChanged(_ sender: UIPageControl) { /// 设定滚动位置 menuCollectionView.setContentOffset(CGPoint(x: CGFloat(sender.currentPage)*menuCollectionView.width, y: menuCollectionView.contentOffset.y), animated: true) } // MARK: - 数据查询 /// 查询首页数据信息 fileprivate func requestHomePageDatas() { /// 异常 guard let commonManager = MTP2BusinessCore.shared.commonManager else { return } let group = DispatchGroup() /// startAnimating _anim?.startAnimating() /// 发送请求 group.enter() /// 查询轮播图 commonManager.queryImageConfigs { (isSuccess, error, imageConfigs) in DispatchQueue.main.async { if isSuccess, imageConfigs?.count != 0 { /// 数据赋值 self.configs = imageConfigs ?? [] } else { self.configs = [] self.sdCycle.localizationImageNamesGroup = self.banners } } group.leave() } group.notify(queue: .main) { /// stopAnimating self._anim?.stopAnimating() /// endRefreshing self.scrollView.endRefreshing() } } /// 查询公告数据信息 fileprivate func requestNotices() { /// 异常 guard let commonManager = MTP2BusinessCore.shared.commonManager else { return } /// 清空数据 防止崩溃 news = [] /// 消息类型 let msgType = dataSource.titles[segmentedView.selectedIndex] == "公告" ? 1 : 2 /// 查询公告 commonManager.queryNotice(page: nil, pageSize: nil, msgType: msgType) { (isSuccess, er, objs) in DispatchQueue.main.async { if !isSuccess { /// 清空数据 self.notices = [] WHToast.showMessage("公告数据查询错误,原因:\(ErrorUtils.desc(er?.retCode))", duration: ToastTimer, finishHandler: {}) return } /// 公告和消息 self.notices = objs ?? [] } } } /// 查询新闻资讯数据信息 fileprivate func querySiteColumnDetail() { /// 异常 guard let commonManager = MTP2BusinessCore.shared.commonManager else { return } /// 清空数据 防止崩溃 notices = [] /// 查询新闻资讯数据信息 commonManager.querySiteColumnDetail { isSuccess, er, objs in DispatchQueue.main.async { if !isSuccess { /// 清空数据 self.news = [] WHToast.showMessage("新闻资讯数据查询错误,原因:\(ErrorUtils.desc(er?.retCode))", duration: ToastTimer, finishHandler: {}) return } /// 数据赋值 self.news = objs ?? [] } } } /// 查询待办事项 fileprivate func queryPendingAuditInfo() { /// 异常 guard let commonManager = MTP2BusinessCore.shared.commonManager else { return } /// 查询待办事项 commonManager.queryPendingAuditInfo { (isSuccess, error) in DispatchQueue.main.async { if isSuccess, let info = commonManager.auditInfo { var datas = self.menus /// 客户资料 if var menu = datas.first(where: {$0.type == .khzl}), let index = datas.firstIndex(where: {$0.type == .khzl}) { menu.badge = info.userqty datas.replaceSubrange(index...index, with: [menu]) } /// 现货审核 if var menu = datas.first(where: {$0.type == .xhsh}), let index = datas.firstIndex(where: {$0.type == .xhsh}) { menu.badge = (info.hedgeplanqty+info.businessdjqty+info.businessjsqty+info.spotcontractqty) datas.replaceSubrange(index...index, with: [menu]) } /// 财务审核 if var menu = datas.first(where: {$0.type == .cwgl}), let index = datas.firstIndex(where: {$0.type == .cwgl}) { menu.badge = info.businessfpqty+info.businesskxqty datas.replaceSubrange(index...index, with: [menu]) } /// 库存审核 if var menu = datas.first(where: {$0.type == .kcsh}), let index = datas.firstIndex(where: {$0.type == .kcsh}) { menu.badge = info.areastockqty datas.replaceSubrange(index...index, with: [menu]) } self.menus = datas } } } } // 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 == "ShowMsgDetail", let d = segue.destination as? MessageDetailViewController, let notice = sender as? MoNotice { /// 公告详情 d.takeInfo = notice } else if segue.identifier == "ShowNewsDetail", let n = segue.destination as? NewsDetailViewController, let site = sender as? MoSiteColumnDetail { /// 新闻资讯详情 n.takeInfo = site } } } // MARK: - JXSegmentedViewDelegate extension HomeViewController: JXSegmentedViewDelegate { /// didSelectedItemAt /// - Parameters: /// - segmentedView: segmentedView /// - index: index func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) { if dataSource.titles.count != 0 { switch dataSource.titles[index] { case "资讯": /// 查询新闻资讯数据信息 querySiteColumnDetail() case "公告", "消息": /// 查询消息数据 requestNotices() default: /// 目前没有研报 notices = [] } } } } // MARK: - UITableViewDelegate、UITableViewDataSource extension HomeViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataSource.titles[segmentedView.selectedIndex] == "资讯" ? news.count : notices.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! MSGCell cell.model = dataSource.titles[segmentedView.selectedIndex] == "资讯" ? news[indexPath.row] : notices[indexPath.row] return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 65.0 } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { /// 新闻资讯 if dataSource.titles[segmentedView.selectedIndex] == "资讯" { self.performSegue(withIdentifier: "ShowNewsDetail", sender: news[indexPath.row]) } else { self.performSegue(withIdentifier: "ShowMsgDetail", sender: notices[indexPath.row]) } } } // MARK: - UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout extension HomeViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return menus.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionCellIdentifier, for: indexPath) as! MenuCollectionCell cell.model = menus[indexPath.item] return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { switch menus[indexPath.item].type { case .khzl: /// 客户资料 push("Customer", "CustomerInfo") case .xhsh: /// 现货审核 push("SpotsAduit", "SpotsAduit") case .cwgl: /// 财务管理 push("SpotsAduit", "Financial") case .spxx: /// 商品信息 push("Varieties", "GoodsVarieties") case .jycx: /// 交易查询 push("Futures", "TradeFlow") case .ckxx: /// 仓库信息 push("Stock", "WareHouse") case .kcgl: /// 库存管理 push("Stock", "StockManager") case .kcsh: /// 库存审核 push("Stock", "InOutStockAduit") case .zhgl: /// 账户管理 push("Account", "AccountManager") case .xhsj: /// 现货市价 push("Spots", "SpotMarketPrice") case .shsz: /// 审核设置 push("SpotsAduit", "AduitSetting") case .jyzt: /// 交易主体 push("Account", "TradeMain") case .fgsh: /// 风管审核 push("Varieties", "VarietiesParameterAduit") case .ckhq: /// 参考行情 let quote = viewController("QHJQuote", "BJBQuote") as! BJBQuoteViewController quote.title = "参考行情" quote.isQhj = false self.navigationController?.pushViewController(quote, animated: true) case .wymh: /// 云融大宗 我要买货 if let main = (UIApplication.shared.delegate as? AppDelegate)?.window?.rootViewController as? MainTabBarController { main.selectedIndex = 1 } case .wyys: /// 云融大宗 我要预售 if let main = (UIApplication.shared.delegate as? AppDelegate)?.window?.rootViewController as? MainTabBarController { main.selectedIndex = 4 if let mine = (main.selectedViewController as? BaseNavigationController)?.viewControllers[0] as? YrdzMineViewController { /// 跳转到预售仓单 DispatchQueue.main.asyncAfter(deadline: .now()+0.3) { mine.collectionView.delegate?.collectionView?(mine.collectionView, didSelectItemAt: IndexPath(item: 1, section: 0)) } } } case .qhjjycx, .zjxx: /// 交易查询 资金信息 if let tr = viewController("QHJOrder", "QhjOrderMain") as? QhjOrderMainViewController { let trn = BaseNavigationController(rootViewController: tr) trn.modalTransitionStyle = .crossDissolve trn.modalPresentationStyle = .overFullScreen let index = menus[indexPath.item].type == .qhjjycx ? 4 : 5 /// 默认显示卖出 DispatchQueue.main.asyncAfter(deadline: .now()+0.3) { tr.segmentedView.defaultSelectedIndex = index tr.segmentedView.reloadData() tr.segmentedView.delegate?.segmentedView(tr.segmentedView, didSelectedItemAt: index) } self.present(trn, animated: true, completion: {}) } case .dtgl: /// 定投管理 push("QHJOrder", "AutoInvestment") case .cztx: /// 充值提现 push("QHJBank", "InOutCharge") case .lygl: /// 履约管理 if let main = (UIApplication.shared.delegate as? AppDelegate)?.window?.rootViewController as? MainTabBarController { main.selectedIndex = 4 if let mine = (main.selectedViewController as? BaseNavigationController)?.viewControllers[0] as? YrdzMineViewController { /// 跳转到履约管理 DispatchQueue.main.asyncAfter(deadline: .now()+0.3) { mine.collectionView.delegate?.collectionView?(mine.collectionView, didSelectItemAt: IndexPath(item: 3, section: 0)) } } } default: break } } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = collectionView.width/(Device.current.isPad ? 5 : 4) return CGSize(width: width, height: 70.0) } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { /// FIXME: 暂时性处理代码 pageControl.currentPage = scrollView.contentOffset.x > 0 ? 1 : 0 } } // MARK: - SFSafariViewControllerDelegate extension HomeViewController: SFSafariViewControllerDelegate { func safariViewControllerDidFinish(_ controller: SFSafariViewController) { controller.dismiss(animated: true, completion: {}) } } // MARK: - SDCycleScrollViewDelegate extension HomeViewController: SDCycleScrollViewDelegate { func cycleScrollView(_ cycleScrollView: SDCycleScrollView!, didSelectItemAt index: Int) { /// 广告跳转 if configs.count != 0, configs[index].urltype == 1, configs[index].url != "" { let urlString = !configs[index].url.lowercased().hasPrefix("http://") ? ("http://"+configs[index].url) : configs[index].url guard let url = URL(string: urlString) else { return } let safriViewController = SFSafariViewController(url: url) safriViewController.delegate = self self.present(safriViewController, animated: true, completion: {}) } } } // MARK: - MSGCell class MSGCell: BaseTableViewCell { /// 公告类型 @IBOutlet weak var msgType: UIImageView! /// 公告标题 @IBOutlet weak var title: UITextView! /// 公告详情 @IBOutlet weak var detail: UILabel! /// 发布时间 @IBOutlet weak var date: UILabel! /// model override var model: Any? { didSet { /// 时间 var stime: Date = Date() switch model { case is MoNotice: /// 公告消息 let obj = model as! MoNotice /// 公告标题 title.text = obj.title /// 公告详情 detail.text = obj.content /// 类型 msgType.image = UIImage(named: obj.msgtype != 1 ? "msg_notice" : "msg_bulletin") /// 发布时间 stime = obj.scheduletime.getTDateString().toDate(formatter: "yyyy-MM-dd HH:mm:ss") ?? Date() default: /// 新闻资讯 let obj = model as! MoSiteColumnDetail /// 新闻标题 title.text = obj.title /// 公告详情 detail.text = obj.brief /// 发布时间 stime = obj.creaedate.toDate(formatter: "yyyy-MM-dd HH:mm:ss") ?? Date() } if stime.isToday { date.text = stime.getString(formatter: "HH:mm") } else if stime.isYesterday { date.text = "昨天 \(stime.getString(formatter: "HH:mm"))" } else { date.text = stime.getString(formatter: "MM-dd") } } } } // MARK: - UI元素: UICollectionViewCell /// MenuCollectionCell 主页功能cell class MenuCollectionCell: AnimatableCollectionViewCell { /// 图标 @IBOutlet weak var imageView: UIImageView! /// 标题 @IBOutlet weak var title: UILabel! /// badgeView @IBOutlet weak var badge: UILabel! { didSet { badge.layer.cornerRadius = badge.width*0.5 badge.layer.masksToBounds = true } } /// 数据Mo类 var model: (image: String, title: String, type: MenuType, badge: Int)? { didSet { /// 数据异常 guard let obj = model else { return } /// 图片信息 if obj.image.hasPrefix("./uploadFile"), let url = URL(string: obj.image.getUrlString()) { imageView.sd_setImage(with: url, completed: nil) } else { imageView.image = UIImage(named: obj.image) } /// 标题 title.text = obj.title /// 是否隐藏 badge.isHidden = obj.badge == 0 /// 显示数字 badge.text = obj.badge > 99 ? "99+" : "\(obj.badge)" } } }