// // PermissionApplyStatusViewController.swift // suixinkan // import SnapKit import UIKit /// 权限申请审核状态页,严格对齐 Android `PermissionApplyStatusScreen`。 @MainActor final class PermissionApplyStatusViewController: BaseViewController { private let viewModel: PermissionApplyStatusViewModel private let homeAPI: HomeAPI private let scrollView = UIScrollView() private let contentStack = UIStackView() private let bannerView = PermissionApplyBannerView() private let existingRoleList = PermissionExistingRoleListView() private let loadingIndicator = UIActivityIndicatorView(style: .medium) /// 使用申请编号创建审核状态页。 init( applyCode: String, viewModel: PermissionApplyStatusViewModel? = nil, homeAPI: HomeAPI? = nil ) { self.viewModel = viewModel ?? PermissionApplyStatusViewModel(applyCode: applyCode) self.homeAPI = homeAPI ?? NetworkServices.shared.homeAPI super.init(nibName: nil, bundle: nil) } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func setupNavigationBar() { title = "权限申请" navigationItem.backButtonDisplayMode = .minimal } override func setupUI() { view.backgroundColor = PermissionApplyUITokens.pageBackground contentStack.axis = .vertical contentStack.spacing = 0 scrollView.addSubview(contentStack) view.addSubview(scrollView) view.addSubview(loadingIndicator) contentStack.snp.makeConstraints { make in make.edges.equalToSuperview() make.width.equalTo(scrollView) } scrollView.snp.makeConstraints { make in make.edges.equalTo(view.safeAreaLayoutGuide) } loadingIndicator.color = PermissionApplyUITokens.selectedBlue loadingIndicator.snp.makeConstraints { make in make.center.equalTo(view.safeAreaLayoutGuide) } } override func bindActions() { viewModel.onStateChange = { [weak self] in Task { @MainActor in self?.applyViewModel() } } viewModel.onNavigateToEdit = { [weak self] pending in Task { @MainActor in self?.navigateToEdit(pending: pending) } } bannerView.onApplyNewScenic = { [weak self] in self?.navigationController?.pushViewController(ScenicApplicationViewController(), animated: true) } existingRoleList.onShowAllScenics = { [weak self] roleName, scenics in self?.viewModel.showScenicList(roleName: roleName, scenics: scenics) } Task { await viewModel.loadPendingData(api: homeAPI) } } @MainActor private func applyViewModel() { if viewModel.isLoading { loadingIndicator.startAnimating() scrollView.isHidden = true return } loadingIndicator.stopAnimating() scrollView.isHidden = false navigationItem.rightBarButtonItem = nil contentStack.arrangedSubviews.forEach { $0.removeFromSuperview() } contentStack.addArrangedSubview(bannerView) guard let pending = viewModel.pendingData else { return } if pending.status == PermissionApplyPendingStatus.rejected { let editItem = UIBarButtonItem(title: "去编辑", style: .plain, target: self, action: #selector(editTapped)) editItem.tintColor = AppColor.primary editItem.setTitleTextAttributes([.font: UIFont.systemFont(ofSize: 14, weight: .medium)], for: .normal) navigationItem.rightBarButtonItem = editItem } contentStack.addArrangedSubview( insetContainer(makeStatusCard(pending: pending), insets: UIEdgeInsets(top: 16, left: 16, bottom: 8, right: 16)) ) let roleSection = PermissionStaticSectionView() roleSection.apply(title: "新增角色", names: [pending.roleName]) contentStack.addArrangedSubview( insetContainer(roleSection, insets: UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)) ) if !pending.scenicList.isEmpty { let scenicSection = PermissionStaticSectionView() scenicSection.apply(title: "新增景区", names: pending.scenicList.map(\.name)) contentStack.addArrangedSubview( insetContainer(scenicSection, insets: UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)) ) } if !viewModel.rolePermissionList.isEmpty { existingRoleList.apply(rolePermissions: viewModel.rolePermissionList) contentStack.addArrangedSubview( insetContainer(existingRoleList, insets: UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16)) ) } presentScenicListIfNeeded() } private func makeStatusCard(pending: RoleApplyPendingResponse) -> UIView { let card = UIView() card.backgroundColor = AppColor.warningBackground card.layer.cornerRadius = 12 card.layer.borderWidth = 1 card.layer.borderColor = AppColor.warning.cgColor let statusLabel = UILabel() statusLabel.text = pending.statusLabel statusLabel.font = .systemFont(ofSize: 18, weight: .medium) statusLabel.textColor = UIColor(hex: 0xFF6B00) let stack = UIStackView() stack.axis = .vertical stack.spacing = 8 stack.addArrangedSubview(statusLabel) stack.setCustomSpacing(12, after: statusLabel) [ ("提交时间:", pending.createdAt), ("审核时间:", pending.auditedAt ?? "--"), ("审核人:", pending.auditedBy ?? "--"), ("审核备注:", pending.auditNote.isEmpty ? "--" : pending.auditNote), ].forEach { stack.addArrangedSubview(makeInfoRow(label: $0.0, value: $0.1)) } card.addSubview(stack) stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(16) } return card } private func makeInfoRow(label: String, value: String) -> UIView { let row = UIStackView() row.axis = .horizontal row.alignment = .top row.spacing = 8 let left = UILabel() left.text = label left.font = .systemFont(ofSize: 14) left.textColor = UIColor(hex: 0x4B5563) left.setContentCompressionResistancePriority(.required, for: .horizontal) let right = UILabel() right.text = value.isEmpty ? "--" : value right.font = .systemFont(ofSize: 14) right.textColor = UIColor(hex: 0x4B5563) right.textAlignment = .right right.numberOfLines = 0 row.addArrangedSubview(left) row.addArrangedSubview(right) right.snp.makeConstraints { make in make.width.lessThanOrEqualTo(220) } return row } private func insetContainer(_ content: UIView, insets: UIEdgeInsets) -> UIView { let container = UIView() container.addSubview(content) content.snp.makeConstraints { make in make.edges.equalToSuperview().inset(insets) } return container } private func presentScenicListIfNeeded() { guard viewModel.showScenicListDialog, presentedViewController == nil else { return } present( PermissionScenicListDialogViewController( roleName: viewModel.dialogRoleName, scenics: viewModel.dialogScenicList, onDismiss: { [weak self] in self?.viewModel.hideScenicList() } ), animated: true ) } @objc private func editTapped() { viewModel.navigateToEditIfRejected() } private func navigateToEdit(pending: RoleApplyPendingResponse) { var controllers = navigationController?.viewControllers ?? [] controllers.removeAll { $0 is PermissionApplyStatusViewController } controllers.append(PermissionApplyViewController(pendingData: pending)) navigationController?.setViewControllers(controllers, animated: true) } }