迁移合作订单完整能力,并统一 AppRoleCode 角色权限与首页菜单展示。
新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -18,7 +18,7 @@ Account 模块负责同步账号进入业务页前必须具备的上下文数据
|
||||
登录成功或冷启动恢复时,`AccountContextLoader` 会并行请求用户资料和角色权限。权限成功后继续读取景区和门店:
|
||||
|
||||
1. 用户资料刷新 `AccountContext.profile`。
|
||||
2. 角色权限刷新 `PermissionContext`,并计算当前角色的权限 URI 集合。
|
||||
2. 角色权限刷新 `PermissionContext`,按 `role_code` 优先匹配当前角色,并计算权限 URI 集合。
|
||||
3. 景区列表失败时,从角色权限里的景区数据去重兜底。
|
||||
4. 门店列表失败时不阻断登录,只写入空门店列表。
|
||||
5. 当前景区确定后,`ScenicSpotContext` 再按景区 ID 拉取景点/打卡点。
|
||||
@ -31,6 +31,8 @@ Account 模块负责同步账号进入业务页前必须具备的上下文数据
|
||||
|
||||
## 缓存规则
|
||||
|
||||
`AccountSnapshotStore` 只保存非敏感上下文快照,包括当前角色 ID、当前景区 ID、当前门店 ID 和基础账号展示信息。
|
||||
`AccountSnapshotStore` 只保存非敏感上下文快照,包括当前 `role_code`(`currentRoleCode`)、当前景区 ID、当前门店 ID 和基础账号展示信息。旧版快照中的 `currentRoleId` 会在读取时一次性迁移为 `role_code`。
|
||||
|
||||
角色匹配优先级:`role_code` → legacy `role_id` → 角色名 → 权限列表推断。登录时还会从 V9 响应的 `app_role_code` 写入初始角色 hint。
|
||||
|
||||
景点/打卡点列表只保存在内存中,不长期落盘。后续业务需要离线缓存时,需要按账号类型、业务账号 ID 和景区 ID 做隔离。
|
||||
|
||||
@ -17,6 +17,7 @@ struct RolePermissionResponse: Decodable, Equatable {
|
||||
struct RoleInfo: Decodable, Equatable, Identifiable {
|
||||
let id: Int
|
||||
let name: String
|
||||
let roleCode: String
|
||||
let notes: String?
|
||||
let permission: [PermissionItem]
|
||||
|
||||
@ -24,14 +25,16 @@ struct RoleInfo: Decodable, Equatable, Identifiable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case name
|
||||
case roleCode = "role_code"
|
||||
case notes
|
||||
case permission
|
||||
}
|
||||
|
||||
/// 创建角色实体,主要用于测试和本地状态恢复。
|
||||
init(id: Int, name: String, notes: String? = nil, permission: [PermissionItem] = []) {
|
||||
init(id: Int, name: String, roleCode: String = "", notes: String? = nil, permission: [PermissionItem] = []) {
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.roleCode = roleCode
|
||||
self.notes = notes
|
||||
self.permission = permission
|
||||
}
|
||||
@ -41,6 +44,7 @@ struct RoleInfo: Decodable, Equatable, Identifiable {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try container.decodeLossyInt(forKey: .id) ?? 0
|
||||
name = try container.decodeLossyString(forKey: .name)
|
||||
roleCode = try container.decodeLossyString(forKey: .roleCode)
|
||||
notes = try container.decodeIfPresent(String.self, forKey: .notes)
|
||||
permission = try container.decodeIfPresent([PermissionItem].self, forKey: .permission) ?? []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user