从 iOS 17 Observation 迁移至 iOS 16 兼容的 Combine 架构

将最低部署版本降至 iOS 16,以 ObservableObject 替换 @Observable,新增导航与 UI 兼容层,并补充登录冒烟 UI 测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 10:16:35 +08:00
parent 0314033a7f
commit 703078352c
127 changed files with 2320 additions and 1465 deletions

View File

@ -11,12 +11,12 @@ import SwiftUI
///
struct WalletView: View {
@Environment(AccountContext.self) private var accountContext
@Environment(WalletAPI.self) private var walletAPI
@Environment(ProfileAPI.self) private var profileAPI
@Environment(ToastCenter.self) private var toastCenter
@EnvironmentObject private var accountContext: AccountContext
@Environment(\.walletAPI) private var walletAPI
@Environment(\.profileAPI) private var profileAPI
@EnvironmentObject private var toastCenter: ToastCenter
@State private var viewModel = WalletViewModel()
@StateObject private var viewModel = WalletViewModel()
@State private var route: WalletRoute?
var body: some View {
@ -33,7 +33,7 @@ struct WalletView: View {
.background(Color(hex: 0xF5F7FA))
.navigationTitle("我的钱包")
.navigationBarTitleDisplayMode(.inline)
.navigationDestination(item: $route) { route in
.appNavigationDestination(item: $route) { route in
switch route {
case .withdrawApply:
WithdrawApplyView()
@ -51,7 +51,7 @@ struct WalletView: View {
.refreshable {
await viewModel.loadInitial(api: walletAPI, staffId: staffId)
}
.onChange(of: viewModel.errorMessage) { _, message in
.onChange(of: viewModel.errorMessage) { message in
if let message {
toastCenter.show(message)
}
@ -256,10 +256,10 @@ struct WalletView: View {
///
struct WithdrawApplyView: View {
@Environment(WalletAPI.self) private var walletAPI
@Environment(ToastCenter.self) private var toastCenter
@Environment(\.walletAPI) private var walletAPI
@EnvironmentObject private var toastCenter: ToastCenter
@Environment(\.dismiss) private var dismiss
@State private var viewModel = WithdrawApplyViewModel()
@StateObject private var viewModel = WithdrawApplyViewModel()
var body: some View {
Form {
@ -301,7 +301,7 @@ struct WithdrawApplyView: View {
viewModel.smsCountdown -= 1
}
}
.onChange(of: viewModel.errorMessage) { _, message in
.onChange(of: viewModel.errorMessage) { message in
if let message {
toastCenter.show(message)
}
@ -311,13 +311,13 @@ struct WithdrawApplyView: View {
/// 使 OSS
struct WithdrawalSettingsView: View {
@Environment(AccountContext.self) private var accountContext
@Environment(WalletAPI.self) private var walletAPI
@Environment(OSSUploadService.self) private var ossUploadService
@Environment(ToastCenter.self) private var toastCenter
@EnvironmentObject private var accountContext: AccountContext
@Environment(\.walletAPI) private var walletAPI
@Environment(\.ossUploadService) private var ossUploadService
@EnvironmentObject private var toastCenter: ToastCenter
@Environment(\.dismiss) private var dismiss
@State private var viewModel = WithdrawalSettingsViewModel()
@StateObject private var viewModel = WithdrawalSettingsViewModel()
@State private var frontItem: PhotosPickerItem?
@State private var backItem: PhotosPickerItem?
@ -389,10 +389,10 @@ struct WithdrawalSettingsView: View {
.navigationTitle("银行卡设置")
.navigationBarTitleDisplayMode(.inline)
.task { await viewModel.load(api: walletAPI) }
.onChange(of: frontItem) { _, item in
.onChange(of: frontItem) { item in
Task { viewModel.frontImageData = try? await item?.loadTransferable(type: Data.self) }
}
.onChange(of: backItem) { _, item in
.onChange(of: backItem) { item in
Task { viewModel.backImageData = try? await item?.loadTransferable(type: Data.self) }
}
.onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { _ in
@ -400,7 +400,7 @@ struct WithdrawalSettingsView: View {
viewModel.smsCountdown -= 1
}
}
.onChange(of: viewModel.errorMessage) { _, message in
.onChange(of: viewModel.errorMessage) { message in
if let message {
toastCenter.show(message)
}
@ -449,10 +449,10 @@ struct WithdrawalSettingsView: View {
///
struct PointsRedemptionView: View {
@Environment(AccountContext.self) private var accountContext
@Environment(WalletAPI.self) private var walletAPI
@Environment(ToastCenter.self) private var toastCenter
@State private var viewModel = PointsRedemptionViewModel()
@EnvironmentObject private var accountContext: AccountContext
@Environment(\.walletAPI) private var walletAPI
@EnvironmentObject private var toastCenter: ToastCenter
@StateObject private var viewModel = PointsRedemptionViewModel()
var body: some View {
ScrollView {
@ -517,7 +517,7 @@ struct PointsRedemptionView: View {
.navigationTitle("积分兑换")
.navigationBarTitleDisplayMode(.inline)
.task { await viewModel.load(api: walletAPI, staffId: staffId) }
.onChange(of: viewModel.errorMessage) { _, message in
.onChange(of: viewModel.errorMessage) { message in
if let message {
toastCenter.show(message)
}