新增门店订单与核销管理列表,对齐 Android 订单能力并完善账号级缓存。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -37,8 +37,8 @@ DEBUG 构建下,“我的”列表会额外展示“首页调试”入口,
|
||||
|
||||
## 加载流程
|
||||
|
||||
1. `ProfileView.task` 进入页面时调用 `reloadProfile(showToast: false)`。
|
||||
2. 下拉刷新时调用 `reloadProfile(showToast: true)`。
|
||||
1. `ProfileView.task` 进入页面时调用 `reloadProfile()`。
|
||||
2. 下拉刷新时同样调用 `reloadProfile()`,成功后不展示 Toast。
|
||||
3. `ProfileViewModel.reload` 并发请求:
|
||||
- `ProfileAPI.userInfo`
|
||||
- `ProfileAPI.realNameInfo`
|
||||
@ -111,6 +111,7 @@ DEBUG 构建下,“我的”列表会额外展示“首页调试”入口,
|
||||
|
||||
## 状态展示规则
|
||||
|
||||
- 进入个人信息页时,先用 `AccountContext` 中已恢复的本地缓存(`AccountSnapshot`)预填充昵称、手机号和头像;接口返回后再替换为最新数据。
|
||||
- 昵称为空时展示“未设置昵称”。
|
||||
- 真实姓名、手机号和账号状态为空时展示 `--`。
|
||||
- 实名认证状态:
|
||||
|
||||
@ -20,9 +20,13 @@ final class ProfileViewModel: ObservableObject {
|
||||
@Published private(set) var pendingAvatarData: Data?
|
||||
@Published private(set) var pendingAvatarFileName: String?
|
||||
@Published private(set) var avatarUploadProgress: Int?
|
||||
/// 接口返回前使用的本地账号资料缓存,来自 AccountContext / AccountSnapshot。
|
||||
private var cachedProfile: AccountProfile?
|
||||
|
||||
var displayNickname: String {
|
||||
nonEmpty(userInfo?.nickname) ?? "未设置昵称"
|
||||
nonEmpty(userInfo?.nickname)
|
||||
?? nonEmpty(cachedProfile?.displayName)
|
||||
?? "未设置昵称"
|
||||
}
|
||||
|
||||
var displayRealName: String {
|
||||
@ -30,11 +34,11 @@ final class ProfileViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
var displayPhone: String {
|
||||
nonEmpty(userInfo?.phone) ?? "--"
|
||||
nonEmpty(userInfo?.phone) ?? nonEmpty(cachedProfile?.phone) ?? "--"
|
||||
}
|
||||
|
||||
var displayAvatarURL: String {
|
||||
nonEmpty(userInfo?.avatar) ?? ""
|
||||
nonEmpty(userInfo?.avatar) ?? nonEmpty(cachedProfile?.avatarURL) ?? ""
|
||||
}
|
||||
|
||||
var accountStatusText: String {
|
||||
@ -53,6 +57,12 @@ final class ProfileViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
/// 用本地缓存的账号资料预填充展示字段,避免冷启动或重新进入页面时先显示占位文案。
|
||||
func applyCachedProfile(_ profile: AccountProfile?) {
|
||||
guard userInfo == nil else { return }
|
||||
cachedProfile = profile
|
||||
}
|
||||
|
||||
/// 重新加载用户资料和实名认证状态。
|
||||
func reload(api: ProfileAPI) async throws {
|
||||
guard !isLoading else { return }
|
||||
|
||||
@ -46,6 +46,9 @@ struct DebugHomeMenuPreviewView: View {
|
||||
appRouter.select(tab)
|
||||
case .orders(let entry):
|
||||
appRouter.selectOrders(entry: entry)
|
||||
case .orderPush(let route):
|
||||
appRouter.select(.orders)
|
||||
appRouter.router(for: .orders).navigate(to: .orders(route))
|
||||
case .destination(let homeRoute):
|
||||
router.navigate(to: .home(homeRoute))
|
||||
case .unsupported(_, let title, let reason):
|
||||
@ -102,6 +105,8 @@ private struct DebugHomeMenuRow: View {
|
||||
return "Tab"
|
||||
case .orders:
|
||||
return "订单"
|
||||
case .orderPush:
|
||||
return "订单页"
|
||||
case .destination(let homeRoute):
|
||||
if case .modulePlaceholder = homeRoute {
|
||||
return "占位"
|
||||
@ -119,7 +124,7 @@ private struct DebugHomeMenuRow: View {
|
||||
switch route {
|
||||
case .tab:
|
||||
return "rectangle.grid.1x2"
|
||||
case .orders:
|
||||
case .orders, .orderPush:
|
||||
return "doc.text"
|
||||
case .destination(let homeRoute):
|
||||
if case .modulePlaceholder = homeRoute {
|
||||
@ -136,7 +141,7 @@ private struct DebugHomeMenuRow: View {
|
||||
/// 返回当前路由类型颜色。
|
||||
private var iconColor: Color {
|
||||
switch route {
|
||||
case .tab, .orders, .destination:
|
||||
case .tab, .orders, .orderPush, .destination:
|
||||
AppDesign.primary
|
||||
case .unsupported:
|
||||
.red
|
||||
|
||||
@ -51,10 +51,11 @@ struct ProfileView: View {
|
||||
.navigationTitle("个人信息")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.task {
|
||||
await reloadProfile(showToast: false)
|
||||
viewModel.applyCachedProfile(accountContext.profile)
|
||||
await reloadProfile()
|
||||
}
|
||||
.refreshable {
|
||||
await reloadProfile(showToast: true)
|
||||
await reloadProfile()
|
||||
}
|
||||
.sheet(isPresented: $showsPasswordSheet) {
|
||||
PasswordUpdateSheet { password in
|
||||
@ -517,9 +518,9 @@ struct ProfileView: View {
|
||||
}
|
||||
|
||||
/// 重新拉取个人资料,并同步更新全局账号资料。
|
||||
private func reloadProfile(showToast: Bool) async {
|
||||
private func reloadProfile() async {
|
||||
do {
|
||||
try await globalLoading.withOptionalLoading(!showToast && viewModel.userInfo == nil, message: "加载中...") {
|
||||
try await globalLoading.withOptionalLoading(viewModel.userInfo == nil, message: "加载中...") {
|
||||
try await viewModel.reload(api: profileAPI)
|
||||
}
|
||||
if let userInfo = viewModel.userInfo {
|
||||
@ -527,9 +528,6 @@ struct ProfileView: View {
|
||||
} else {
|
||||
accountContext.replaceProfile(viewModel.accountProfileFallback(accountContext.profile))
|
||||
}
|
||||
if showToast {
|
||||
toastCenter.show("个人信息已刷新")
|
||||
}
|
||||
} catch is CancellationError {
|
||||
return
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user