// // ScenicSettlementViewControllers.swift // suixinkan // // Created by Codex on 2026/6/26. // import UIKit /// 景区结算申请页。 final class ScenicSettlementViewController: ModuleTableViewController { private let viewModel = ScenicSettlementViewModel() private let amountField = UITextField() private let remarkField = UITextField() /// 视图加载完成后的 UI 初始化与数据绑定。 override func viewDidLoad() { title = "景区结算" navigationItem.rightBarButtonItem = UIBarButtonItem( title: "提交", style: .done, target: self, action: #selector(submit) ) super.viewDidLoad() setupHeader() wireViewModel(viewModel) { } } /// 初始化Header相关 UI 或状态。 private func setupHeader() { amountField.placeholder = "结算金额" amountField.borderStyle = .roundedRect amountField.keyboardType = .decimalPad remarkField.placeholder = "备注" remarkField.borderStyle = .roundedRect let stack = UIStackView(arrangedSubviews: [amountField, remarkField]) stack.axis = .vertical stack.spacing = 8 stack.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 96) stack.layoutMargins = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16) stack.isLayoutMarginsRelativeArrangement = true tableView.tableHeaderView = stack } /// table行Count相关逻辑。 override func tableRowCount() -> Int { viewModel.options.count } /// 配置Cell展示内容。 override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) { let option = viewModel.options[indexPath.row] cell.configure(title: option.name, subtitle: option.selected ? "已选择" : nil) cell.accessoryType = option.selected ? .checkmark : .none } /// didSelectTableRow 回调处理。 override func didSelectTableRow(at indexPath: IndexPath) { viewModel.toggleScenic(id: viewModel.options[indexPath.row].id) } /// 刷新Content。 override func reloadContent() async { await viewModel.load( api: services.scenicPermissionAPI, existingScenics: services.accountContext.scenicScopes ) } /// 提交。 @objc private func submit() { viewModel.amountText = amountField.text ?? "" viewModel.remarkText = remarkField.text ?? "" Task { let success = await viewModel.submit(api: services.scenicSettlementAPI) if success { services.toastCenter.show("提交成功") navigationController?.popViewController(animated: true) } else if let message = viewModel.message { services.toastCenter.show(message) } } } } extension ScenicSettlementViewModel: ViewModelBindable {} /// 景区结算审核页。 final class ScenicSettlementReviewViewController: ModuleTableViewController { private let viewModel = ScenicSettlementReviewViewModel() /// 视图加载完成后的 UI 初始化与数据绑定。 override func viewDidLoad() { title = "结算审核" super.viewDidLoad() wireViewModel(viewModel) { } } /// 返回列表 section 数量。 override func numberOfTableSections() -> Int { 2 } /// 返回指定 section 行数。 override func tableRowCount(in section: Int) -> Int { section == 0 ? viewModel.scenicApplications.count : viewModel.roleApplications.count } /// section 标题。 override func tableSectionTitle(for section: Int) -> String? { section == 0 ? "景区申请" : "权限申请" } /// 提供自定义 Cell。 override func tableCell(for indexPath: IndexPath, row: ModuleTableRow, in tableView: UITableView) -> UITableViewCell { let cell = tableView.dequeueReusableCell( withIdentifier: TitleSubtitleTableViewCell.reuseIdentifier, for: indexPath ) as! TitleSubtitleTableViewCell if indexPath.section == 0 { let item = viewModel.scenicApplications[indexPath.row] cell.configure( title: item.scenicName, subtitle: viewModel.statusText(item.status), detail: item.createdAt ) } else { let item = viewModel.roleApplications[indexPath.row] cell.configure( title: item.roleName, subtitle: viewModel.statusText(item.status, fallback: item.statusLabel), detail: item.createdAt ) } return cell } /// 刷新Content。 override func reloadContent() async { await viewModel.load(api: services.scenicPermissionAPI) } } extension ScenicSettlementReviewViewModel: ViewModelBindable {}