// // ScenicPermissionViewControllers.swift // suixinkan // // Created by Codex on 2026/6/26. // import UIKit /// 景区选择页。 final class ScenicSelectionViewController: ModuleTableViewController { private let viewModel = ScenicSelectionViewModel() private let searchBar = UISearchBar() override func viewDidLoad() { title = "选择景区" super.viewDidLoad() setupSearchBar() wireViewModel(viewModel) { } } private func setupSearchBar() { searchBar.placeholder = "搜索景区" searchBar.delegate = self searchBar.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 56) tableView.tableHeaderView = searchBar } override func tableRowCount() -> Int { viewModel.filteredItems.count } override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) { let item = viewModel.filteredItems[indexPath.row] cell.configure(title: item.name, subtitle: item.address, detail: item.distanceText) } override func didSelectTableRow(at indexPath: IndexPath) { let item = viewModel.filteredItems[indexPath.row] viewModel.select( scenicId: item.id, accountContext: services.accountContext, permissionContext: services.permissionContext, snapshotStore: AccountSnapshotStore() ) navigationController?.popViewController(animated: true) } override func reloadContent() async { viewModel.reload(from: services.accountContext) } } extension ScenicSelectionViewModel: ViewModelBindable {} extension ScenicSelectionViewController: UISearchBarDelegate { func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { viewModel.searchQuery = searchText } } /// 权限申请页。 final class PermissionApplyViewController: ModuleTableViewController { private let viewModel = PermissionApplyViewModel() override func viewDidLoad() { title = "权限申请" navigationItem.rightBarButtonItem = UIBarButtonItem( title: "提交", style: .done, target: self, action: #selector(submit) ) super.viewDidLoad() wireViewModel(viewModel) { } } override func numberOfSections(in tableView: UITableView) -> Int { 2 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { section == 0 ? viewModel.roleOptions.count : viewModel.scenicOptions.count } func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { section == 0 ? "选择角色" : "选择景区" } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell( withIdentifier: TitleSubtitleTableViewCell.reuseIdentifier, for: indexPath ) as! TitleSubtitleTableViewCell if indexPath.section == 0 { let role = viewModel.roleOptions[indexPath.row] cell.configure(title: role.name, subtitle: role.notes) cell.accessoryType = viewModel.selectedRoleId == role.id ? .checkmark : .none } else { let scenic = viewModel.scenicOptions[indexPath.row] cell.configure(title: scenic.name, subtitle: scenic.disabled ? "已有权限" : nil) cell.accessoryType = scenic.selected ? .checkmark : .none } return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) if indexPath.section == 0 { viewModel.selectRole(id: viewModel.roleOptions[indexPath.row].id) Task { await viewModel.loadScenicListIfNeeded(api: services.scenicPermissionAPI, force: true) } } else { viewModel.toggleScenic(id: viewModel.scenicOptions[indexPath.row].id) } } override func reloadContent() async { viewModel.bootstrap(rolePermissions: services.permissionContext.rolePermissions) if viewModel.selectedRoleId != nil { await viewModel.loadScenicListIfNeeded(api: services.scenicPermissionAPI, force: true) } } @objc private func submit() { Task { await viewModel.submit(api: services.scenicPermissionAPI) if viewModel.message == "提交成功,等待审核" { services.toastCenter.show(viewModel.message ?? "提交成功") navigationController?.popViewController(animated: true) } else if let message = viewModel.message { services.toastCenter.show(message) } } } } extension PermissionApplyViewModel: ViewModelBindable {} /// 权限申请状态页。 final class PermissionApplyStatusViewController: ModuleTableViewController { private let viewModel = PermissionApplyStatusViewModel() override func viewDidLoad() { title = "申请状态" super.viewDidLoad() viewModel.onChange = { [weak self] in self?.reloadTable() } } override func tableRowCount() -> Int { viewModel.pending == nil ? 0 : 4 } override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) { guard let pending = viewModel.pending else { return } switch indexPath.row { case 0: cell.configure(title: "申请编号", subtitle: pending.code) case 1: cell.configure(title: "角色", subtitle: pending.roleName) case 2: cell.configure(title: "状态", subtitle: pending.statusLabel) default: cell.configure(title: "申请时间", subtitle: pending.createdAt) } } override func reloadContent() async { await viewModel.load(api: services.scenicPermissionAPI, applyCode: nil) } } /// 景区申请页。 final class ScenicApplicationViewController: ModuleTableViewController { private let viewModel = ScenicApplicationViewModel() private let nameField = UITextField() override func viewDidLoad() { title = "景区申请" navigationItem.rightBarButtonItem = UIBarButtonItem( title: "提交", style: .done, target: self, action: #selector(submit) ) super.viewDidLoad() nameField.placeholder = "景区名称" nameField.borderStyle = .roundedRect nameField.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 52) tableView.tableHeaderView = nameField wireViewModel(viewModel) { [weak self] in if self?.nameField.text?.isEmpty != false { self?.nameField.text = self?.viewModel.scenicName } } } override func tableRowCount() -> Int { 3 } override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) { switch indexPath.row { case 0: cell.configure(title: "省份", subtitle: viewModel.selectedProvince) case 1: cell.configure(title: "城市", subtitle: viewModel.selectedCity) default: cell.configure(title: "合作类型", subtitle: viewModel.coopType == 1 ? "自营" : "合作") } } override func reloadContent() async { await viewModel.loadInitial(api: services.scenicPermissionAPI) } @objc private func submit() { viewModel.scenicName = nameField.text ?? "" Task { await viewModel.submit(api: services.scenicPermissionAPI, uploader: services.ossUploadService) if let message = viewModel.message { services.toastCenter.show(message) } } } } extension ScenicApplicationViewModel: ViewModelBindable {}