Refactor AppServices into assembly, feature facades, and lifecycle coordinator.

Extract dependency wiring and session lifecycle from the container and RootViewController, split NetworkBundle by domain, and add module-level feature services while keeping flat accessors for compatibility.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-29 09:32:44 +08:00
parent 1a6d4a1791
commit 0d8f97417b
11 changed files with 686 additions and 197 deletions

View File

@ -17,132 +17,39 @@ final class AppServices {
let network: NetworkBundle
let ui: UIFeedbackBundle
let runtime: AppRuntimeBundle
let appNavigator = AppNavigator()
private let tokenStore: SessionTokenStore
private let snapshotStore: AccountSnapshotStore
// MARK: - 访
var appSession: AppSession { session.appSession }
var accountContext: AccountContext { context.accountContext }
var permissionContext: PermissionContext { context.permissionContext }
var scenicSpotContext: ScenicSpotContext { context.scenicSpotContext }
var toastCenter: ToastCenter { ui.toastCenter }
var globalLoading: GlobalLoadingCenter { ui.globalLoading }
var scenicQueueRuntime: ScenicQueueRuntime { runtime.scenicQueueRuntime }
var apiClient: APIClient { network.apiClient }
var authAPI: AuthAPI { network.authAPI }
var profileAPI: ProfileAPI { network.profileAPI }
var uploadAPI: UploadAPI { network.uploadAPI }
var ossUploadService: OSSUploadService { network.ossUploadService }
var accountContextAPI: AccountContextAPI { network.accountContextAPI }
var ordersAPI: OrdersAPI { network.ordersAPI }
var statisticsAPI: StatisticsAPI { network.statisticsAPI }
var paymentAPI: PaymentAPI { network.paymentAPI }
var walletAPI: WalletAPI { network.walletAPI }
var pushAPI: PushAPI { network.pushAPI }
var scenicPermissionAPI: ScenicPermissionAPI { network.scenicPermissionAPI }
var scenicSettlementAPI: ScenicSettlementAPI { network.scenicSettlementAPI }
var messageCenterAPI: MessageCenterAPI { network.messageCenterAPI }
var scenicQueueAPI: ScenicQueueAPI { network.scenicQueueAPI }
var liveAPI: LiveAPI { network.liveAPI }
var operatingAreaAPI: OperatingAreaAPI { network.operatingAreaAPI }
var pilotCertificationAPI: PilotCertificationAPI { network.pilotCertificationAPI }
var taskAPI: TaskAPI { network.taskAPI }
var projectAPI: ProjectAPI { network.projectAPI }
var scheduleAPI: ScheduleAPI { network.scheduleAPI }
var inviteAPI: InviteAPI { network.inviteAPI }
var assetsAPI: AssetsAPI { network.assetsAPI }
var punchPointAPI: PunchPointAPI { network.punchPointAPI }
var locationReportAPI: LocationReportAPI { network.locationReportAPI }
var authSessionCoordinator: AuthSessionCoordinator { session.authSessionCoordinator }
var sessionBootstrapper: SessionBootstrapper { session.sessionBootstrapper }
/// ID
var currentScenicId: Int? {
accountContext.currentScenic?.id
}
/// staffId
var staffId: Int? {
Int(accountContext.profile?.userId ?? "")
}
/// ID
var userId: String? {
accountContext.profile?.userId
}
let appNavigator: AppNavigator
///
private init() {
let tokenStore = SessionTokenStore()
let snapshotStore = AccountSnapshotStore()
let preferencesStore = AppPreferencesStore()
let apiClient = APIClient()
self.tokenStore = tokenStore
self.snapshotStore = snapshotStore
context = AppContextBundle(
accountContext: AccountContext(),
permissionContext: PermissionContext(),
scenicSpotContext: ScenicSpotContext()
)
network = NetworkBundle(apiClient: apiClient)
ui = UIFeedbackBundle(
toastCenter: ToastCenter(),
globalLoading: GlobalLoadingCenter()
)
runtime = AppRuntimeBundle(scenicQueueRuntime: ScenicQueueRuntime())
session = SessionBundle(
appSession: AppSession(),
authSessionCoordinator: AuthSessionCoordinator(
tokenStore: tokenStore,
snapshotStore: snapshotStore,
preferencesStore: preferencesStore
),
sessionBootstrapper: SessionBootstrapper(
tokenStore: tokenStore,
snapshotStore: snapshotStore
)
)
bindAuthTokenProvider()
private convenience init() {
self.init(assembly: AppServicesAssembly())
}
/// mock `APIClient`
init(
convenience init(
apiClient: APIClient,
tokenStore: SessionTokenStore = SessionTokenStore(),
snapshotStore: AccountSnapshotStore = AccountSnapshotStore(),
preferencesStore: AppPreferencesStore = AppPreferencesStore()
) {
self.tokenStore = tokenStore
self.snapshotStore = snapshotStore
context = AppContextBundle(
accountContext: AccountContext(),
permissionContext: PermissionContext(),
scenicSpotContext: ScenicSpotContext()
)
network = NetworkBundle(apiClient: apiClient)
ui = UIFeedbackBundle(
toastCenter: ToastCenter(),
globalLoading: GlobalLoadingCenter()
)
runtime = AppRuntimeBundle(scenicQueueRuntime: ScenicQueueRuntime())
session = SessionBundle(
appSession: AppSession(),
authSessionCoordinator: AuthSessionCoordinator(
self.init(
assembly: AppServicesAssembly(
apiClient: apiClient,
tokenStore: tokenStore,
snapshotStore: snapshotStore,
preferencesStore: preferencesStore
),
sessionBootstrapper: SessionBootstrapper(
tokenStore: tokenStore,
snapshotStore: snapshotStore
)
)
}
/// 使 bundle
private init(assembly: AppServicesAssembly) {
let dependencies = assembly.makeDependencies()
session = dependencies.session
context = dependencies.context
network = dependencies.network
ui = dependencies.ui
runtime = dependencies.runtime
appNavigator = dependencies.appNavigator
bindAuthTokenProvider()
}