Add ScenicPermission module and AMap CocoaPods with simulator support.
Integrate scenic selection and permission flows into home routing, add AMap SDK for device builds while keeping arm64 simulators compilable via Podfile post_install hooks. 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