迁移合作订单完整能力,并统一 AppRoleCode 角色权限与首页菜单展示。
新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -157,6 +157,17 @@ struct V9AuthResponse: Decodable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
/// 当前账号的 app_role_code,用于登录后初始角色匹配。
|
||||
var currentAccountRoleCode: String? {
|
||||
if let storeUser = storeUsers.first(where: \.isCurrent) ?? storeUsers.first {
|
||||
return nonEmpty(storeUser.resolvedAppRoleCode)
|
||||
}
|
||||
if let scenicUser = scenicUsers.first(where: \.isCurrent) ?? scenicUsers.first {
|
||||
return nonEmpty(scenicUser.resolvedAppRoleCode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/// v9 登录响应的 JSON 字段映射。
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case token
|
||||
@ -178,6 +189,11 @@ struct V9AuthResponse: Decodable, Equatable {
|
||||
scenicUsers = (try? container.decodeIfPresent([V9ScenicUser].self, forKey: .scenicUsers)) ?? []
|
||||
storeUsers = (try? container.decodeIfPresent([V9StoreUser].self, forKey: .storeUsers)) ?? []
|
||||
}
|
||||
|
||||
private func nonEmpty(_ value: String) -> String? {
|
||||
let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return text.isEmpty ? nil : text
|
||||
}
|
||||
}
|
||||
|
||||
/// v9 景区账号实体,表示用户可进入的某个景区身份。
|
||||
@ -196,6 +212,13 @@ struct V9ScenicUser: Decodable, Equatable {
|
||||
let scenicId: Int
|
||||
let scenicName: String
|
||||
let isCurrent: Bool
|
||||
let appRoleCode: String
|
||||
let appRoleName: String
|
||||
|
||||
/// 解析后的 app_role_code,优先顶层字段。
|
||||
var resolvedAppRoleCode: String {
|
||||
appRoleCode.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
|
||||
/// set-user 使用的业务账号 ID,按后端可用字段优先级兜底。
|
||||
var businessUserId: Int {
|
||||
@ -240,6 +263,8 @@ struct V9ScenicUser: Decodable, Equatable {
|
||||
case scenicId = "scenic_id"
|
||||
case scenicName = "scenic_name"
|
||||
case isCurrent = "is_current"
|
||||
case appRoleCode = "app_role_code"
|
||||
case appRoleName = "app_role_name"
|
||||
}
|
||||
|
||||
/// 自定义解码,兼容 ID 字段类型不稳定和字段缺失。
|
||||
@ -257,6 +282,8 @@ struct V9ScenicUser: Decodable, Equatable {
|
||||
scenicId = try container.decodeLossyInt(forKey: .scenicId) ?? 0
|
||||
scenicName = try container.decodeLossyString(forKey: .scenicName)
|
||||
isCurrent = try container.decodeLossyBool(forKey: .isCurrent) ?? false
|
||||
appRoleCode = try container.decodeLossyString(forKey: .appRoleCode)
|
||||
appRoleName = try container.decodeLossyString(forKey: .appRoleName)
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,6 +305,13 @@ struct V9StoreUser: Decodable, Equatable {
|
||||
let storeId: Int
|
||||
let storeName: String
|
||||
let isCurrent: Bool
|
||||
let appRoleCode: String
|
||||
let appRoleName: String
|
||||
|
||||
/// 解析后的 app_role_code,优先顶层字段。
|
||||
var resolvedAppRoleCode: String {
|
||||
appRoleCode.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
|
||||
/// set-user 使用的业务账号 ID,按后端可用字段优先级兜底。
|
||||
var businessUserId: Int {
|
||||
@ -324,6 +358,8 @@ struct V9StoreUser: Decodable, Equatable {
|
||||
case storeId = "store_id"
|
||||
case storeName = "store_name"
|
||||
case isCurrent = "is_current"
|
||||
case appRoleCode = "app_role_code"
|
||||
case appRoleName = "app_role_name"
|
||||
}
|
||||
|
||||
/// 自定义解码,兼容 ID 字段类型不稳定和字段缺失。
|
||||
@ -343,6 +379,8 @@ struct V9StoreUser: Decodable, Equatable {
|
||||
storeId = try container.decodeLossyInt(forKey: .storeId) ?? 0
|
||||
storeName = try container.decodeLossyString(forKey: .storeName)
|
||||
isCurrent = try container.decodeLossyBool(forKey: .isCurrent) ?? false
|
||||
appRoleCode = try container.decodeLossyString(forKey: .appRoleCode)
|
||||
appRoleName = try container.decodeLossyString(forKey: .appRoleName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user