新增景区权限模块,集成 AMap CocoaPods 并支持模拟器

将景区选择与权限申请流程接入首页路由,集成高德 SDK 用于真机构建,并通过 Podfile post_install 钩子保证 arm64 模拟器可编译。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-23 10:15:26 +08:00
parent 5d4613f317
commit b61bf0d070
416 changed files with 18641 additions and 38 deletions

View File

@ -0,0 +1,36 @@
//
// AMapBootstrap.swift
// suixinkan
//
// SDK AMAP_ENABLED AMap
//
import Foundation
#if AMAP_ENABLED
import AMapFoundationKit
import AMapLocationKit
import AMapSearchKit
import MAMapKit
enum AMapBootstrap {
/// App `apiKey` Key
static func configure(apiKey: String) {
guard !apiKey.isEmpty else { return }
AMapServices.shared().apiKey = apiKey
AMapServices.shared().enableHTTPS = true
AMapSearchAPI.updatePrivacyShow(.didShow, privacyInfo: .didContain)
AMapSearchAPI.updatePrivacyAgree(.didAgree)
MAMapView.updatePrivacyShow(.didShow, privacyInfo: .didContain)
MAMapView.updatePrivacyAgree(.didAgree)
AMapLocationManager.updatePrivacyShow(.didShow, privacyInfo: .didContain)
AMapLocationManager.updatePrivacyAgree(.didAgree)
}
}
#else
enum AMapBootstrap {
static func configure(apiKey: String) {}
}
#endif

View File

@ -15,6 +15,7 @@ struct RootView: View {
@State private var scenicSpotContext = ScenicSpotContext()
@State private var appRouter = AppRouter()
@State private var toastCenter = ToastCenter()
@State private var snapshotStore: AccountSnapshotStore
@State private var apiClient: APIClient
@State private var authAPI: AuthAPI
@State private var profileAPI: ProfileAPI
@ -25,6 +26,7 @@ struct RootView: View {
@State private var statisticsAPI: StatisticsAPI
@State private var paymentAPI: PaymentAPI
@State private var walletAPI: WalletAPI
@State private var scenicPermissionAPI: ScenicPermissionAPI
@State private var authSessionCoordinator: AuthSessionCoordinator
@State private var sessionBootstrapper: SessionBootstrapper
@ -33,6 +35,7 @@ struct RootView: View {
let apiClient = APIClient()
let tokenStore = SessionTokenStore()
let snapshotStore = AccountSnapshotStore()
_snapshotStore = State(initialValue: snapshotStore)
_apiClient = State(initialValue: apiClient)
_authAPI = State(initialValue: AuthAPI(client: apiClient))
_profileAPI = State(initialValue: ProfileAPI(client: apiClient))
@ -44,6 +47,7 @@ struct RootView: View {
_statisticsAPI = State(initialValue: StatisticsAPI(client: apiClient))
_paymentAPI = State(initialValue: PaymentAPI(client: apiClient))
_walletAPI = State(initialValue: WalletAPI(client: apiClient))
_scenicPermissionAPI = State(initialValue: ScenicPermissionAPI(client: apiClient))
_authSessionCoordinator = State(
initialValue: AuthSessionCoordinator(
tokenStore: tokenStore,
@ -68,6 +72,7 @@ struct RootView: View {
.environment(scenicSpotContext)
.environment(appRouter)
.environment(toastCenter)
.environment(snapshotStore)
.environment(apiClient)
.environment(authAPI)
.environment(profileAPI)
@ -78,6 +83,7 @@ struct RootView: View {
.environment(statisticsAPI)
.environment(paymentAPI)
.environment(walletAPI)
.environment(scenicPermissionAPI)
.environment(authSessionCoordinator)
.task {
apiClient.bindAuthTokenProvider { appSession.token }

View File

@ -27,13 +27,33 @@ struct BusinessScope: Codable, Equatable, Identifiable {
var name: String
var kind: Kind
var parentScenicId: Int?
var status: Int?
var address: String?
var latitude: Double?
var longitude: Double?
var coverURLString: String?
/// parentScenicId
init(id: Int, name: String, kind: Kind, parentScenicId: Int? = nil) {
init(
id: Int,
name: String,
kind: Kind,
parentScenicId: Int? = nil,
status: Int? = nil,
address: String? = nil,
latitude: Double? = nil,
longitude: Double? = nil,
coverURLString: String? = nil
) {
self.id = id
self.name = name
self.kind = kind
self.parentScenicId = parentScenicId
self.status = status
self.address = address
self.latitude = latitude
self.longitude = longitude
self.coverURLString = coverURLString
}
}

View File

@ -77,7 +77,16 @@ final class PermissionContext {
var seen = Set<Int>()
return scenics.compactMap { scenic in
guard seen.insert(scenic.id).inserted else { return nil }
return BusinessScope(id: scenic.id, name: scenic.name, kind: .scenic)
return BusinessScope(
id: scenic.id,
name: scenic.name,
kind: .scenic,
status: scenic.status,
address: scenic.location?.address,
latitude: scenic.location?.lat,
longitude: scenic.location?.lng,
coverURLString: scenic.coverImg
)
}
}
}