迁移合作订单完整能力,并统一 AppRoleCode 角色权限与首页菜单展示。
新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -13,6 +13,8 @@ struct AccountSnapshot: Codable, Equatable {
|
||||
var profile: AccountProfile?
|
||||
var accountType: String?
|
||||
var businessUserId: Int?
|
||||
var currentRoleCode: String?
|
||||
/// 旧版快照字段,仅用于解码与一次性迁移。
|
||||
var currentRoleId: Int?
|
||||
var scenicScopes: [BusinessScope]
|
||||
var storeScopes: [BusinessScope]
|
||||
@ -24,6 +26,7 @@ struct AccountSnapshot: Codable, Equatable {
|
||||
profile: AccountProfile? = nil,
|
||||
accountType: String? = nil,
|
||||
businessUserId: Int? = nil,
|
||||
currentRoleCode: String? = nil,
|
||||
currentRoleId: Int? = nil,
|
||||
scenicScopes: [BusinessScope] = [],
|
||||
storeScopes: [BusinessScope] = [],
|
||||
@ -33,12 +36,25 @@ struct AccountSnapshot: Codable, Equatable {
|
||||
self.profile = profile
|
||||
self.accountType = accountType
|
||||
self.businessUserId = businessUserId
|
||||
self.currentRoleCode = currentRoleCode
|
||||
self.currentRoleId = currentRoleId
|
||||
self.scenicScopes = scenicScopes
|
||||
self.storeScopes = storeScopes
|
||||
self.currentScenicId = currentScenicId
|
||||
self.currentStoreId = currentStoreId
|
||||
}
|
||||
|
||||
/// 若快照仅有 legacy role id,则迁移为 role_code 并清除 id。
|
||||
mutating func migrateLegacyRoleIfNeeded() {
|
||||
guard AppRoleCode.fromCode(currentRoleCode) == nil,
|
||||
let legacyId = currentRoleId,
|
||||
legacyId > 0,
|
||||
let migrated = AppRoleCode.fromLegacyRoleId(legacyId) else {
|
||||
return
|
||||
}
|
||||
currentRoleCode = migrated.rawValue
|
||||
currentRoleId = nil
|
||||
}
|
||||
}
|
||||
|
||||
/// 账号快照存储服务,使用 UserDefaults 保存非敏感登录上下文。
|
||||
@ -67,11 +83,17 @@ final class AccountSnapshotStore {
|
||||
defaults.set(data, forKey: key)
|
||||
}
|
||||
|
||||
/// 读取账号快照,解码失败时清空损坏数据。
|
||||
/// 读取账号快照,解码失败时清空损坏数据;读取后自动尝试 legacy 角色迁移。
|
||||
func load() -> AccountSnapshot? {
|
||||
guard let data = defaults.data(forKey: key) else { return nil }
|
||||
do {
|
||||
return try decoder.decode(AccountSnapshot.self, from: data)
|
||||
var snapshot = try decoder.decode(AccountSnapshot.self, from: data)
|
||||
let beforeCode = snapshot.currentRoleCode
|
||||
snapshot.migrateLegacyRoleIfNeeded()
|
||||
if snapshot.currentRoleCode != beforeCode {
|
||||
save(snapshot)
|
||||
}
|
||||
return snapshot
|
||||
} catch {
|
||||
clear()
|
||||
return nil
|
||||
@ -87,7 +109,7 @@ final class AccountSnapshotStore {
|
||||
@MainActor
|
||||
func saveCurrentSelection(
|
||||
accountContext: AccountContext,
|
||||
currentRoleId: Int?
|
||||
currentRoleCode: String?
|
||||
) {
|
||||
let existing = load()
|
||||
save(
|
||||
@ -95,7 +117,7 @@ final class AccountSnapshotStore {
|
||||
profile: accountContext.profile ?? existing?.profile,
|
||||
accountType: existing?.accountType,
|
||||
businessUserId: existing?.businessUserId,
|
||||
currentRoleId: currentRoleId ?? existing?.currentRoleId,
|
||||
currentRoleCode: currentRoleCode ?? existing?.currentRoleCode,
|
||||
scenicScopes: accountContext.scenicScopes,
|
||||
storeScopes: accountContext.storeScopes,
|
||||
currentScenicId: accountContext.currentScenic?.id,
|
||||
|
||||
Reference in New Issue
Block a user