// // SPHomeV2ViewController.swift // MoviaBox // // Created by 长沙佳儿 on 2025/6/18. // import UIKit class SPHomeV2ViewController: SPViewController { private lazy var viewModel: SPHomeViewModel = SPHomeViewModel() private lazy var requestGroup = DispatchGroup() private var isSetupUI = false //MARK: UI属性 private lazy var logoImageView: UIImageView = { let imageView = UIImageView(image: UIImage(named: "logo_icon_01")) imageView.setContentHuggingPriority(.required, for: .horizontal) imageView.setContentCompressionResistancePriority(.required, for: .horizontal) return imageView }() private lazy var searchButton: SPHomeSearchButton = { let button = SPHomeSearchButton() button.addTarget(self, action: #selector(handleSearchButton), for: .touchUpInside) return button }() private lazy var allButton: UIButton = { let button = UIButton(type: .custom) button.setImage(UIImage(named: "all_icon_01"), for: .normal) button.setContentHuggingPriority(.required, for: .horizontal) button.setContentCompressionResistancePriority(.required, for: .horizontal) button.addTarget(self, action: #selector(handleAllButton), for: .touchUpInside) return button }() private lazy var rewardButton: UIButton = { let button = UIButton(type: .custom) button.setImage(UIImage(named: "reward_icon_01"), for: .normal) button.setContentHuggingPriority(.required, for: .horizontal) button.setContentCompressionResistancePriority(.required, for: .horizontal) button.addTarget(self, action: #selector(handleRewardButton), for: .touchUpInside) return button }() private lazy var pageParam: WMZPageParam = { let param = WMZPageParam() param.wTitleArr = ["1"] param.wViewController = { [weak self] index in return SPHomeChildController() } param.wTopSuspension = true //顶部可下拉 param.wBounces = true param.wMenuHeight = 0 param.wBgColor = .clear param.wCustomNaviBarY = { _ in return 0 } param.wCustomTabbarY = { _ in return 0 } param.wCustomDataViewTopOffset = 0 return param }() private lazy var pageView: WMZPageView = { let y = kSPStatusbarHeight + 10 + 32 + 34 let width = kSPScreenWidth let height = kSPScreenHeight - y - kSPTabBarHeight let pageView = WMZPageView(frame: CGRect(x: 0, y: y, width: width, height: height), param: pageParam, parentReponder: self) pageView.param = pageParam pageView.backgroundColor = .clear pageView.downSc?.backgroundColor = .clear pageView.downSc?.dataSource = self pageView.downSc?.isScrollEnabled = true pageView.downSc?.separatorStyle = .none pageView.downSc?.register(SPHomeBannerContentCell.self, forCellReuseIdentifier: SPHomeContentModel.ContentKey.banner.rawValue) pageView.downSc?.register(SPHomeHistoryContentCell.self, forCellReuseIdentifier: SPHomeContentModel.ContentKey.history.rawValue) pageView.downSc?.register(SPHomeNineSquareContentCell.self, forCellReuseIdentifier: SPHomeContentModel.ContentKey.nineSquare.rawValue) pageView.downSc?.register(SPHomeCategoryContentCell.self, forCellReuseIdentifier: SPHomeContentModel.ContentKey.category1.rawValue) pageView.downSc?.register(SPHomeHotContentCell.self, forCellReuseIdentifier: SPHomeContentModel.ContentKey.hot.rawValue) pageView.downSc?.sp_addRefreshHeader(block: { [weak self] in self?.handleHeaderRefresh(nil) }) return pageView }() private var headerView: SPHomeHeaderView? private lazy var playHistoricalView: SPHomePlayHistoricalView = { let view = SPHomePlayHistoricalView() view.isHidden = true return view }() override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) if SPNetworkReachabilityManager.manager.isReachable == true { updateAllData(completer: nil) _setupUI() } else { setEmptyView() } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.setNavigationBarHidden(true, animated: true) } override func viewDidAppear(_ animated: Bool) { if hasViewDidAppear { requestPlayHistory() } super.viewDidAppear(animated) self.headerView?.isDidAppear = self.isDidAppear } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) self.headerView?.isDidAppear = self.isDidAppear } override func handleHeaderRefresh(_ completer: (() -> Void)?) { updateAllData { [weak self] in self?.pageView.downSc?.sp_endHeaderRefreshing() } } // override func handleFooterRefresh(_ completer: (() -> Void)?) { // requestListDataArr(page: self.viewModel.page + 1) { [weak self] in //// self?.collectionView.sp_endFooterRefreshing() // } // } } extension SPHomeV2ViewController { private func _setupUI() { if isSetupUI { return } isSetupUI = true // view.addSubview(logoImageView) view.addSubview(searchButton) view.addSubview(allButton) view.addSubview(rewardButton) view.addSubview(pageView) view.addSubview(playHistoricalView) // logoImageView.snp.makeConstraints { make in // make.left.equalToSuperview().offset(16) // make.centerY.equalTo(searchButton) // } searchButton.snp.makeConstraints { make in // make.left.equalTo(logoImageView.snp.right).offset(6) make.left.equalToSuperview().offset(16) // make.right.equalToSuperview().offset(-16) make.right.equalTo(allButton.snp.left).offset(-4) make.top.equalToSuperview().offset(kSPStatusbarHeight + 10) } allButton.snp.makeConstraints { make in make.centerY.equalTo(searchButton) // make.right.equalToSuperview().offset(-16) make.right.equalTo(rewardButton.snp.left).offset(-1) } rewardButton.snp.makeConstraints { make in make.centerY.equalTo(searchButton) make.right.equalToSuperview().offset(-16) } playHistoricalView.snp.makeConstraints { make in make.left.equalToSuperview().offset(16) make.centerX.equalToSuperview() make.bottom.equalToSuperview().offset(-4) } } } extension SPHomeV2ViewController { @objc private func handleSearchButton() { let vc = SPSearchViewController() self.navigationController?.pushViewController(vc, animated: true) } ///设置无网空页面 private func setEmptyView() { if SPNetworkReachabilityManager.manager.isReachable != true { self.addNoNetworkEmptyView { [weak self] in self?.updateEmptyState() } } } @objc private func reachabilityDidChangeNotification() { updateEmptyState() } ///更新空白页面状态 private func updateEmptyState() { if SPNetworkReachabilityManager.manager.isReachable == true { self._setupUI() if viewModel.isEmptyData { self.updateAllData(completer: nil) } self.removeNoNetworkEmptyView() } } @objc private func handleAllButton() { let vc = SPAllViewController() self.navigationController?.pushViewController(vc, animated: true) } @objc private func handleRewardButton() { let vc = SPRewardsViewController() self.navigationController?.pushViewController(vc, animated: true) } } //MARK: -------------- UITableViewDelegate UITableViewDataSource -------------- extension SPHomeV2ViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let model = self.viewModel.contentArr[indexPath.row] let key = model.key ?? .banner let cell = tableView.dequeueReusableCell(withIdentifier: key.rawValue, for: indexPath) as! SPHomeContentCell cell.contentModel = model return cell } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.viewModel.contentArr.count } } extension SPHomeV2ViewController { private func updateAllData(completer: (() -> Void)?) { self.requestGroup.enter() requestModuleData { [weak self] in self?.requestGroup.leave() } self.requestGroup.enter() requestPlayHistory { [weak self] in self?.requestGroup.leave() } self.requestGroup.enter() requestListDataArr(page: 1) { [weak self] in self?.requestGroup.leave() } self.requestGroup.enter() requestCategoryShortList(id: "3") { [weak self] in self?.requestGroup.leave() } // self.requestGroup.enter() // requestCategoryShortList(id: "1") { [weak self] in // self?.requestGroup.leave() // } self.requestGroup.notify(queue: DispatchQueue.main) { completer?() } } ///获取模版数据 包括banner 九宫格等 private func requestModuleData(completer: (() -> Void)? = nil) { SPHomeAPI.requestHomeModuleData { [weak self] model in guard let self = self else { return } if let model = model { self.viewModel.moduleModel = model self.pageView.downSc?.reloadData() } self.updateEmptyState() completer?() } } ///甜宠ID= 3 ///虐恋ID=1 private func requestCategoryShortList(id: String, completer: (() -> Void)?) { SPVideoAPI.requestCategoryShortList(page: 1, id: id) { [weak self] listModel in guard let self = self else { return } if let list = listModel?.list { if id == "3" { self.viewModel.categoryDataArr1 = list } else { self.viewModel.categoryDataArr2 = list } self.pageView.downSc?.reloadData() } self.updateEmptyState() completer?() } } ///获取播放记录 private func requestPlayHistory(completer: (() -> Void)? = nil) { SPVideoAPI.requestPlayHistoryList(page: 1) { [weak self] listModel in guard let self = self else { return } if let list = listModel?.list { self.viewModel.playHistoryArr = list self.pageView.downSc?.reloadData() if let model = listModel?.list?.first { self.playHistoricalView.model = model self.playHistoricalView.isHidden = false } } self.updateEmptyState() completer?() } } ///获取列表数据 private func requestListDataArr(page: Int, completer: (() -> Void)?) { SPHomeAPI.requestHomeList(page: page) { [weak self] listModel in guard let self = self else { return } if let list = listModel?.list { if page == 1 { self.viewModel.dataArr.removeAll() } self.viewModel.dataArr += list // self.collectionView.reloadData() self.viewModel.page = page } self.updateEmptyState() completer?() } } }