// // ScheduleDetailVC.swift // QuickLocation // // Created by 八条 on 2026/6/25. // import UIKit import RxSwift import RxCocoa import RxDataSources import ObjectMapper class ScheduleDetailVC: BaseViewController { fileprivate var rootView: ScheduleDetailView! override func loadView() { rootView = ScheduleDetailView(frame: UIScreen.main.bounds) view = rootView } private var viewModel: ScheduleDetailViewModel override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. setupData() bindViewModel() reactiveAction() requestFollowList() viewModel.loadPointData() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) rootView.vipTipsLab.text = AppContextManager.shared.vip > 1 ? "" : "升级 VIP,可查看具体人员与节点" } private func reactiveAction() { rootView.operateBtn.rx.tap.subscribe(onNext: { _ in guard let model = self.viewModel.scheduModel else { return } if model.is_own { AppRouter.push(Route.createSchedule, userInfo: ["scheduleJson": model.toJSON()]) } else { self.requestSetFollow(id: model.id, op: self.rootView.operateBtn.isSelected) } }).disposed(by: disposeBag) rootView.routeBtn.rx.tap.subscribe(onNext: { _ in guard let model = self.viewModel.scheduModel else { return } AppRouter.push(Route.itineraryDetail, userInfo: ["scheduleJson": model.toJSON()]) }).disposed(by: disposeBag) rootView.vipTipsLab.rx.tapGesture.subscribe(onNext: { _ in AppRouter.push(Route.vipRecharge) }).disposed(by: disposeBag) } private func bindViewModel() { viewModel.output.sectionedItems .bind(to: rootView.collectionView.rx.items(dataSource: dataSource)) .disposed(by: disposeBag) viewModel.output.pointSectionedItems .bind(to: rootView.tableView.rx.items(dataSource: tableViewDataSource)) .disposed(by: disposeBag) } private func setupData() { guard let model = viewModel.scheduModel else { return } rootView.dateLab.text = rootView.dateLab.getDateInterval2String(date: "\(model.timestamp / 1000)", dateFormat: "yyyy年MM月dd日") rootView.creatorIcon.image = model.userIcon var operateName = "" if model.is_own { operateName = "编辑行程" } else { operateName = "关注行程" rootView.operateBtn.isSelected = model.is_follow } rootView.operateBtn.setTitle(operateName, for: .normal) } // MARK: - API private func requestFollowList() { DLToast.showLoading() ItineraryService.queryFollowList(id: viewModel.routeId).subscribe(onNext: { response in DLToast.dismiss() self.viewModel.loadViewedData(response.list) self.rootView.noDataLab.isHidden = response.list.count > 0 }, onError: { _ in }).disposed(by: disposeBag) } private func requestSetFollow(id: String, op: Bool) { DLToast.showLoading() ItineraryService.follow(id: id, op: op ? 2 : 1).subscribe(onNext: { response in DLToast.dismiss() DLToast.show(text: op ? "已取消" : "已关注此行程, \n行程路线将自动添加到您的行程列表。") self.rootView.operateBtn.isSelected = !op }, onError: { _ in }).disposed(by: disposeBag) } // MARK: - dataSource private lazy var dataSource: RxCollectionViewSectionedReloadDataSource = { RxCollectionViewSectionedReloadDataSource { datasource, collectionView, indexPath, model in let cell: ViewedCell = collectionView.dequeueReusableCell(for: indexPath) cell.configure(model) return cell } }() lazy private var tableViewDataSource: RxTableViewSectionedReloadDataSource = { return RxTableViewSectionedReloadDataSource( configureCell: { (dataSource, tableView, indexPath, item) in switch item { case let .point(model): let cell: SchedulePointDetailCell = tableView.dequeueReusableCell(for: indexPath) cell.configure(model: model, index: indexPath.section, total: dataSource.sectionModels.count) return cell case let .event(model): let cell: SchedulePointEventCell = tableView.dequeueReusableCell(for: indexPath) cell.configure(model: model, index: indexPath.section, total: dataSource.sectionModels.count) return cell } } ) }() // MARK: - Init init(routeId: String, scheduleJson: [String: Any]) { self.viewModel = ScheduleDetailViewModel(routeId: routeId, model: scheduleJson.isEmpty ? nil : ScheduleModel.init(JSON: scheduleJson)) super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }