新增景区权限模块,集成 AMap CocoaPods 并支持模拟器
将景区选择与权限申请流程接入首页路由,集成高德 SDK 用于真机构建,并通过 Podfile post_install 钩子保证 arm64 模拟器可编译。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -0,0 +1,532 @@
|
||||
//
|
||||
// ScenicApplicationView.swift
|
||||
// suixinkan
|
||||
//
|
||||
// Created by Codex on 2026/6/23.
|
||||
//
|
||||
|
||||
import PhotosUI
|
||||
import SwiftUI
|
||||
|
||||
/// 景区申请页面,支持新增景区入驻资料、图片上传和审核状态回填。
|
||||
struct ScenicApplicationView: View {
|
||||
@Environment(ScenicPermissionAPI.self) private var scenicPermissionAPI
|
||||
@Environment(OSSUploadService.self) private var ossUploadService
|
||||
@State private var viewModel = ScenicApplicationViewModel()
|
||||
@State private var pickedImageItems: [PhotosPickerItem] = []
|
||||
@State private var activeLocationPicker: ScenicLocationPicker?
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
ScrollView {
|
||||
VStack(spacing: AppMetrics.Spacing.medium) {
|
||||
if viewModel.loadFailed {
|
||||
ContentUnavailableView(
|
||||
"景区申请初始化失败",
|
||||
systemImage: "exclamationmark.triangle",
|
||||
description: Text(viewModel.loadFailureReason ?? "请检查网络后重试")
|
||||
)
|
||||
Button("重新加载") {
|
||||
Task { await viewModel.loadInitial(api: scenicPermissionAPI) }
|
||||
}
|
||||
.font(.system(size: AppMetrics.FontSize.footnote, weight: .semibold))
|
||||
.buttonStyle(.plain)
|
||||
} else {
|
||||
warmTip
|
||||
formSection
|
||||
}
|
||||
}
|
||||
.padding(AppMetrics.Spacing.medium)
|
||||
}
|
||||
if !viewModel.loadFailed {
|
||||
agreementSection
|
||||
}
|
||||
}
|
||||
.background(Color(hex: 0xF4F4F4).ignoresSafeArea())
|
||||
.navigationTitle("景区申请")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.task {
|
||||
await viewModel.loadInitial(api: scenicPermissionAPI)
|
||||
}
|
||||
.onChange(of: pickedImageItems) { _, items in
|
||||
guard !items.isEmpty else { return }
|
||||
Task {
|
||||
await importPickedImages(items)
|
||||
pickedImageItems = []
|
||||
}
|
||||
}
|
||||
.sheet(item: $activeLocationPicker) { picker in
|
||||
ScenicLocationSelectionSheet(
|
||||
picker: picker,
|
||||
provinces: viewModel.provinces,
|
||||
cities: viewModel.cities,
|
||||
selectedProvince: viewModel.selectedProvince,
|
||||
selectedCity: viewModel.selectedCity,
|
||||
onSelectProvince: { item in
|
||||
viewModel.selectedProvince = item.name
|
||||
viewModel.onProvinceChange()
|
||||
activeLocationPicker = nil
|
||||
},
|
||||
onSelectCity: { item in
|
||||
viewModel.selectedCity = item.name
|
||||
activeLocationPicker = nil
|
||||
}
|
||||
)
|
||||
.presentationDetents([.medium, .large])
|
||||
}
|
||||
.alert("提示", isPresented: Binding(
|
||||
get: { viewModel.message != nil },
|
||||
set: { if !$0 { viewModel.message = nil } }
|
||||
)) {
|
||||
Button("知道了", role: .cancel) {}
|
||||
} message: {
|
||||
Text(viewModel.message ?? "")
|
||||
}
|
||||
}
|
||||
|
||||
private var warmTip: some View {
|
||||
VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
|
||||
Text("温馨提示")
|
||||
.font(.system(size: AppMetrics.FontSize.body, weight: .bold))
|
||||
Text("如果你想入驻更多的景区,平台可以帮你跟景区官方谈合作;如果已经有的景区,只要符合入驻条件即可申请。")
|
||||
.font(.system(size: AppMetrics.FontSize.subheadline))
|
||||
.lineSpacing(AppMetrics.LineSpacing.title)
|
||||
}
|
||||
.foregroundStyle(.white)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(AppMetrics.Spacing.medium)
|
||||
.background(AppDesign.primary, in: RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
|
||||
private var formSection: some View {
|
||||
VStack(alignment: .leading, spacing: AppMetrics.Spacing.large) {
|
||||
if let pending = viewModel.pending {
|
||||
pendingStatusCard(pending)
|
||||
}
|
||||
if viewModel.pendingLoadFailed && viewModel.pending == nil {
|
||||
pendingFailureRow
|
||||
}
|
||||
inputField("景区名称", text: $viewModel.scenicName, disabled: viewModel.isReadOnly)
|
||||
uploadSection
|
||||
locationSection
|
||||
coopTypeSection
|
||||
inputField("备注信息 (\(viewModel.remark.count)/50)", text: $viewModel.remark, axis: .vertical, disabled: viewModel.isReadOnly)
|
||||
.onChange(of: viewModel.remark) { _, value in
|
||||
if value.count > 50 {
|
||||
viewModel.remark = String(value.prefix(50))
|
||||
}
|
||||
}
|
||||
if let pending = viewModel.pending, pending.status == 3 {
|
||||
Text("驳回原因:\(pending.auditNote ?? pending.rejectReason ?? "--")")
|
||||
.font(.system(size: AppMetrics.FontSize.caption))
|
||||
.foregroundStyle(Color(hex: 0xDC2626))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(AppMetrics.Spacing.small)
|
||||
.background(Color(hex: 0xFEF2F2), in: RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
}
|
||||
.padding(AppMetrics.Spacing.medium)
|
||||
.background(.white, in: RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
|
||||
private var pendingFailureRow: some View {
|
||||
HStack(spacing: AppMetrics.Spacing.xSmall) {
|
||||
Image(systemName: "exclamationmark.triangle")
|
||||
.foregroundStyle(AppDesign.warning)
|
||||
Text("待审核记录加载失败,暂未展示历史申请状态")
|
||||
.font(.system(size: AppMetrics.FontSize.caption))
|
||||
.foregroundStyle(AppDesign.textSecondary)
|
||||
Spacer()
|
||||
Button("重试") {
|
||||
Task { await viewModel.reloadPending(api: scenicPermissionAPI) }
|
||||
}
|
||||
.font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
.padding(AppMetrics.Spacing.small)
|
||||
.background(Color(hex: 0xFFF7ED), in: RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
|
||||
private var uploadSection: some View {
|
||||
VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
|
||||
HStack {
|
||||
Text("景区图片")
|
||||
.font(.system(size: AppMetrics.FontSize.body, weight: .medium))
|
||||
Spacer()
|
||||
Text("\(viewModel.uploadPlaceholderCount)/20")
|
||||
.font(.system(size: AppMetrics.FontSize.caption, weight: .medium))
|
||||
.foregroundStyle(AppDesign.textSecondary)
|
||||
}
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 92), spacing: AppMetrics.Spacing.xSmall)], spacing: AppMetrics.Spacing.xSmall) {
|
||||
ForEach(viewModel.remoteImageURLs, id: \.self) { url in
|
||||
scenicImageCell(url: url, local: nil, progress: nil) {
|
||||
viewModel.removeRemoteImage(url)
|
||||
}
|
||||
}
|
||||
ForEach(viewModel.localImages) { image in
|
||||
scenicImageCell(url: image.uploadedURL, local: image.data, progress: image.uploading ? image.progress : nil) {
|
||||
viewModel.removeLocalImage(id: image.id)
|
||||
}
|
||||
}
|
||||
if viewModel.uploadPlaceholderCount < 20 && !viewModel.isReadOnly {
|
||||
PhotosPicker(
|
||||
selection: $pickedImageItems,
|
||||
maxSelectionCount: max(0, 20 - viewModel.uploadPlaceholderCount),
|
||||
matching: .images
|
||||
) {
|
||||
VStack(spacing: AppMetrics.Spacing.xSmall) {
|
||||
Image(systemName: "plus")
|
||||
.font(.system(size: AppMetrics.FontSize.title, weight: .semibold))
|
||||
Text("上传图片")
|
||||
.font(.system(size: AppMetrics.FontSize.caption, weight: .medium))
|
||||
}
|
||||
.foregroundStyle(AppDesign.primary)
|
||||
.frame(height: 92)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(AppDesign.primarySoft, in: RoundedRectangle(cornerRadius: 10))
|
||||
.overlay {
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.stroke(AppDesign.primary.opacity(0.25), style: StrokeStyle(lineWidth: 1, dash: [5, 4]))
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var locationSection: some View {
|
||||
VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
|
||||
Text("景区位置")
|
||||
.font(.system(size: AppMetrics.FontSize.body, weight: .medium))
|
||||
HStack(spacing: AppMetrics.Spacing.small) {
|
||||
Button {
|
||||
activeLocationPicker = .province
|
||||
} label: {
|
||||
pickerBox(title: viewModel.selectedProvince.isEmpty ? "省份" : viewModel.selectedProvince)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(viewModel.isReadOnly)
|
||||
|
||||
Button {
|
||||
guard !viewModel.selectedProvince.isEmpty else {
|
||||
viewModel.message = "请先选择省份"
|
||||
return
|
||||
}
|
||||
activeLocationPicker = .city
|
||||
} label: {
|
||||
pickerBox(title: viewModel.selectedCity.isEmpty ? "城市" : viewModel.selectedCity)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(viewModel.isReadOnly)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var coopTypeSection: some View {
|
||||
VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
|
||||
Text("合作类型")
|
||||
.font(.system(size: AppMetrics.FontSize.body, weight: .medium))
|
||||
VStack(spacing: AppMetrics.Spacing.xSmall) {
|
||||
coopButton(title: "我是摄影师,我想入驻", tag: 1)
|
||||
coopButton(title: "我是景区资源方,可以合作", tag: 2)
|
||||
coopButton(title: "我有摄影师团队,带队入驻", tag: 3)
|
||||
coopButton(title: "我是旅拍店,想合作", tag: 4)
|
||||
coopButton(title: "我已经在景区运营旅拍了,想使用软件,提高效率", tag: 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var agreementSection: some View {
|
||||
VStack(spacing: AppMetrics.Spacing.small) {
|
||||
HStack(spacing: AppMetrics.Spacing.small) {
|
||||
Button {
|
||||
viewModel.agreed.toggle()
|
||||
} label: {
|
||||
Image(systemName: viewModel.agreed ? "checkmark.square.fill" : "square")
|
||||
.font(.system(size: AppMetrics.ControlSize.passwordIcon))
|
||||
.foregroundStyle(viewModel.agreed ? AppDesign.primary : AppDesign.textSecondary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(viewModel.isReadOnly)
|
||||
Text("已阅读并同意《用户须知》与《隐私政策》")
|
||||
.font(.system(size: AppMetrics.FontSize.subheadline))
|
||||
.foregroundStyle(AppDesign.textPrimary)
|
||||
.lineLimit(2)
|
||||
Spacer()
|
||||
}
|
||||
Button(viewModel.submitting ? "提交中..." : "确认提交") {
|
||||
Task { await viewModel.submit(api: scenicPermissionAPI, uploader: ossUploadService) }
|
||||
}
|
||||
.disabled(viewModel.isSubmitLocked)
|
||||
.font(.system(size: AppMetrics.FontSize.body, weight: .medium))
|
||||
.foregroundStyle(.white)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 46)
|
||||
.background(viewModel.canSubmit ? AppDesign.primary : Color(hex: 0xD8D8D8), in: RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
.padding(AppMetrics.Spacing.medium)
|
||||
.background(.white)
|
||||
}
|
||||
|
||||
/// 构建输入区。
|
||||
private func inputField(_ title: String, text: Binding<String>, axis: Axis = .horizontal, disabled: Bool = false) -> some View {
|
||||
VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
|
||||
Text(title)
|
||||
.font(.system(size: AppMetrics.FontSize.body, weight: .medium))
|
||||
TextField("", text: text, prompt: Text("请输入\(title)").foregroundColor(AppDesign.placeholder), axis: axis)
|
||||
.disabled(disabled)
|
||||
.font(.system(size: AppMetrics.FontSize.subheadline))
|
||||
.lineLimit(axis == .vertical ? 3...5 : 1...1)
|
||||
.appInputFieldStyle(cornerRadius: 8, minHeight: axis == .vertical ? 100 : 50)
|
||||
}
|
||||
}
|
||||
|
||||
/// 构建地区选择框。
|
||||
private func pickerBox(title: String) -> some View {
|
||||
HStack {
|
||||
Text(title)
|
||||
.font(.system(size: AppMetrics.FontSize.subheadline))
|
||||
.foregroundStyle(title == "省份" || title == "城市" ? AppDesign.placeholder : AppDesign.textPrimary)
|
||||
.lineLimit(1)
|
||||
Spacer()
|
||||
Image(systemName: "chevron.down")
|
||||
.foregroundStyle(AppDesign.textSecondary)
|
||||
}
|
||||
.padding(.horizontal, AppMetrics.Spacing.substantial)
|
||||
.frame(height: 50)
|
||||
.background(Color(hex: 0xFBFCFE), in: RoundedRectangle(cornerRadius: 10))
|
||||
.overlay {
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.stroke(Color(hex: 0xE2E8F0), lineWidth: 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// 构建合作类型按钮。
|
||||
private func coopButton(title: String, tag: Int) -> some View {
|
||||
Button {
|
||||
viewModel.coopType = tag
|
||||
} label: {
|
||||
Text(title)
|
||||
.font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
|
||||
.foregroundStyle(viewModel.coopType == tag ? .white : AppDesign.textSecondary)
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.leading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, AppMetrics.Spacing.medium)
|
||||
.frame(minHeight: tag == 5 ? 70 : 48)
|
||||
.background(viewModel.coopType == tag ? AppDesign.primary : .white, in: RoundedRectangle(cornerRadius: 8))
|
||||
.overlay {
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.stroke(viewModel.coopType == tag ? AppDesign.primary : Color(hex: 0xE2E8F0), lineWidth: 1)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(viewModel.isReadOnly)
|
||||
}
|
||||
|
||||
/// 构建待审核状态卡片。
|
||||
private func pendingStatusCard(_ pending: ScenicApplicationPendingResponse) -> some View {
|
||||
VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
|
||||
Label(statusText(pending.status), systemImage: statusIcon(pending.status))
|
||||
.font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
|
||||
.foregroundStyle(statusColor(pending.status))
|
||||
.padding(.horizontal, AppMetrics.Spacing.small)
|
||||
.frame(height: 28)
|
||||
.background(statusColor(pending.status).opacity(0.12), in: Capsule())
|
||||
metaRow("申请编号", pending.code.isEmpty ? "--" : pending.code)
|
||||
metaRow("提交时间", pending.createdAt.isEmpty ? "--" : pending.createdAt)
|
||||
}
|
||||
.padding(AppMetrics.Spacing.small)
|
||||
.background(Color(hex: 0xF8FAFC), in: RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
|
||||
/// 构建图片格。
|
||||
private func scenicImageCell(url: String?, local data: Data?, progress: Int?, onDelete: @escaping () -> Void) -> some View {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
ZStack {
|
||||
if let data, let image = UIImage(data: data) {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
} else if let url, !url.isEmpty {
|
||||
RemoteImage(urlString: url) {
|
||||
imagePlaceholder
|
||||
}
|
||||
} else {
|
||||
imagePlaceholder
|
||||
}
|
||||
if let progress {
|
||||
Color.black.opacity(0.38)
|
||||
ProgressView(value: Double(progress), total: 100)
|
||||
.tint(.white)
|
||||
.padding(AppMetrics.Spacing.xSmall)
|
||||
}
|
||||
}
|
||||
.frame(height: 92)
|
||||
.frame(maxWidth: .infinity)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
|
||||
if !viewModel.isReadOnly {
|
||||
Button(action: onDelete) {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.font(.system(size: AppMetrics.FontSize.title2, weight: .semibold))
|
||||
.foregroundStyle(.white, Color.black.opacity(0.55))
|
||||
.padding(AppMetrics.Spacing.xxSmall)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var imagePlaceholder: some View {
|
||||
ZStack {
|
||||
Color(hex: 0xF1F5F9)
|
||||
Image(systemName: "photo.fill")
|
||||
.font(.system(size: AppMetrics.FontSize.title, weight: .semibold))
|
||||
.foregroundStyle(Color(hex: 0x94A3B8))
|
||||
}
|
||||
}
|
||||
|
||||
/// 导入用户从系统相册选择的图片数据。
|
||||
private func importPickedImages(_ items: [PhotosPickerItem]) async {
|
||||
for item in items {
|
||||
guard viewModel.uploadPlaceholderCount < 20 else { return }
|
||||
do {
|
||||
guard let data = try await item.loadTransferable(type: Data.self) else { continue }
|
||||
viewModel.addLocalImage(data: data, fileName: "scenic_\(UUID().uuidString).jpg")
|
||||
} catch {
|
||||
viewModel.message = error.localizedDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func metaRow(_ title: String, _ value: String) -> some View {
|
||||
HStack {
|
||||
Text("\(title):")
|
||||
.foregroundStyle(AppDesign.textSecondary)
|
||||
Text(value)
|
||||
.foregroundStyle(AppDesign.textPrimary)
|
||||
Spacer()
|
||||
}
|
||||
.font(.system(size: AppMetrics.FontSize.caption))
|
||||
}
|
||||
|
||||
private func statusText(_ status: Int) -> String {
|
||||
switch status {
|
||||
case 1: return "待审核"
|
||||
case 2: return "已通过"
|
||||
case 3: return "已驳回"
|
||||
case 9: return "已取消"
|
||||
default: return "未提交"
|
||||
}
|
||||
}
|
||||
|
||||
private func statusIcon(_ status: Int) -> String {
|
||||
switch status {
|
||||
case 2: return "checkmark.circle.fill"
|
||||
case 3: return "xmark.octagon.fill"
|
||||
case 1: return "clock.badge.exclamationmark.fill"
|
||||
default: return "questionmark.circle.fill"
|
||||
}
|
||||
}
|
||||
|
||||
private func statusColor(_ status: Int) -> Color {
|
||||
switch status {
|
||||
case 2: return AppDesign.success
|
||||
case 3: return Color(hex: 0xDC2626)
|
||||
case 1: return AppDesign.warning
|
||||
default: return AppDesign.textSecondary
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 景区申请地区选择器类型。
|
||||
private enum ScenicLocationPicker: Identifiable {
|
||||
case province
|
||||
case city
|
||||
|
||||
var id: String {
|
||||
switch self {
|
||||
case .province: "province"
|
||||
case .city: "city"
|
||||
}
|
||||
}
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .province: "选择省份"
|
||||
case .city: "选择城市"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 景区申请省市选择弹层。
|
||||
private struct ScenicLocationSelectionSheet: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
let picker: ScenicLocationPicker
|
||||
let provinces: [ScenicAreaNode]
|
||||
let cities: [ScenicAreaNode]
|
||||
let selectedProvince: String
|
||||
let selectedCity: String
|
||||
let onSelectProvince: (ScenicAreaNode) -> Void
|
||||
let onSelectCity: (ScenicAreaNode) -> Void
|
||||
|
||||
private var items: [ScenicAreaNode] {
|
||||
picker == .province ? provinces : cities
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: AppMetrics.Spacing.xSmall) {
|
||||
ForEach(items) { item in
|
||||
Button {
|
||||
switch picker {
|
||||
case .province:
|
||||
onSelectProvince(item)
|
||||
case .city:
|
||||
onSelectCity(item)
|
||||
}
|
||||
dismiss()
|
||||
} label: {
|
||||
HStack(spacing: AppMetrics.Spacing.small) {
|
||||
Text(item.name)
|
||||
.font(.system(size: AppMetrics.FontSize.subheadline, weight: isSelected(item) ? .semibold : .regular))
|
||||
.foregroundStyle(AppDesign.textPrimary)
|
||||
Spacer()
|
||||
if isSelected(item) {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.foregroundStyle(AppDesign.primary)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, AppMetrics.Spacing.substantial)
|
||||
.frame(height: 48)
|
||||
.background(.white, in: RoundedRectangle(cornerRadius: 12))
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
.padding(AppMetrics.Spacing.medium)
|
||||
}
|
||||
.background(Color(hex: 0xF5F7FA).ignoresSafeArea())
|
||||
.navigationTitle(picker.title)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("关闭") { dismiss() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 判断地区节点是否已选中。
|
||||
private func isSelected(_ item: ScenicAreaNode) -> Bool {
|
||||
switch picker {
|
||||
case .province:
|
||||
item.name == selectedProvince
|
||||
case .city:
|
||||
item.name == selectedCity
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user