实现我的 Tab、对齐 Android 流程并接入 OSS 上传
This commit is contained in:
88
suixinkan/Features/Auth/Models/AppRoleCode.swift
Normal file
88
suixinkan/Features/Auth/Models/AppRoleCode.swift
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// AppRoleCode.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// 业务角色编码,与 Android `AppRoleCode` 对齐。
|
||||
enum AppRoleCode: String, CaseIterable, Equatable {
|
||||
case driver = "driver"
|
||||
case floristBuilder = "florist_builder"
|
||||
case clerk = "clerk"
|
||||
case liveStream = "live_stream"
|
||||
case frontDesk = "front_desk"
|
||||
case makeupArtist = "makeup_artist"
|
||||
case photographerAssistant = "photographer_assistant"
|
||||
case assistantManager = "assistant_manager"
|
||||
case scenicOperation = "scenic_operation"
|
||||
case scenicAdmin = "scenic_admin"
|
||||
case scenicCS = "scenic_cs"
|
||||
case editor = "editor"
|
||||
case storeAdmin = "store_admin"
|
||||
case photographer = "photographer"
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .driver: "司机"
|
||||
case .floristBuilder: "搭建花艺师"
|
||||
case .clerk: "店员"
|
||||
case .liveStream: "直播"
|
||||
case .frontDesk: "前台"
|
||||
case .makeupArtist: "化妆师"
|
||||
case .photographerAssistant: "摄影师助理"
|
||||
case .assistantManager: "副店长"
|
||||
case .scenicOperation: "景区运营"
|
||||
case .scenicAdmin: "景区管理员"
|
||||
case .scenicCS: "飞手"
|
||||
case .editor: "剪辑师"
|
||||
case .storeAdmin: "店铺管理员"
|
||||
case .photographer: "摄影师"
|
||||
}
|
||||
}
|
||||
|
||||
var isPhotographer: Bool {
|
||||
self == .photographer
|
||||
}
|
||||
|
||||
/// 从后端 role_code 解析角色。
|
||||
static func fromCode(_ code: String?) -> AppRoleCode? {
|
||||
let normalized = code?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
guard !normalized.isEmpty else { return nil }
|
||||
return AppRoleCode(rawValue: normalized)
|
||||
}
|
||||
|
||||
/// 从旧版 role_id 推断角色。
|
||||
static func fromLegacyRoleId(_ roleId: Int) -> AppRoleCode? {
|
||||
switch roleId {
|
||||
case 41: .photographer
|
||||
case 46: .storeAdmin
|
||||
case 47: .editor
|
||||
case 52: .scenicCS
|
||||
case 53: .scenicAdmin
|
||||
case 54: .scenicOperation
|
||||
default: nil
|
||||
}
|
||||
}
|
||||
|
||||
/// 从 role_name 文本推断角色,避免「摄影师助理」误判为摄影师。
|
||||
static func fromRoleName(_ roleName: String?) -> AppRoleCode? {
|
||||
let name = roleName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
guard !name.isEmpty else { return nil }
|
||||
if name.contains("摄影师助理") { return .photographerAssistant }
|
||||
if name.contains("副店长") { return .assistantManager }
|
||||
if name.contains("搭建花艺") || name.contains("花艺师") { return .floristBuilder }
|
||||
if name.contains("店铺管理") || name.contains("店长") { return .storeAdmin }
|
||||
if name.contains("景区管理") { return .scenicAdmin }
|
||||
if name.contains("景区运营") { return .scenicOperation }
|
||||
if name.contains("景区客服") || name.contains("飞手") { return .scenicCS }
|
||||
if name.contains("剪辑") { return .editor }
|
||||
if name.contains("化妆师") { return .makeupArtist }
|
||||
if name.contains("摄影师") { return .photographer }
|
||||
if name.contains("司机") { return .driver }
|
||||
if name.contains("店员") { return .clerk }
|
||||
if name.contains("直播") { return .liveStream }
|
||||
if name.contains("前台") { return .frontDesk }
|
||||
return AppRoleCode.allCases.first { name.contains($0.displayName) }
|
||||
}
|
||||
}
|
||||
@ -55,7 +55,7 @@ enum LoginValidationError: Equatable {
|
||||
|
||||
/// 登录结果实体,区分已完成登录和需要用户选择账号两种情况。
|
||||
enum LoginResolution {
|
||||
case completed(V9AuthResponse)
|
||||
case completed(V9AuthResponse, AccountSwitchAccount)
|
||||
case needsAccountSelection(AccountSelectionPayload)
|
||||
}
|
||||
|
||||
@ -201,6 +201,8 @@ struct V9ScenicUser: Decodable, Equatable {
|
||||
let phone: String
|
||||
let scenicId: Int
|
||||
let scenicName: String
|
||||
let appRoleCode: String
|
||||
let appRoleName: String
|
||||
let isCurrent: Bool
|
||||
|
||||
var businessUserId: Int {
|
||||
@ -241,6 +243,8 @@ struct V9ScenicUser: Decodable, Equatable {
|
||||
case phone
|
||||
case scenicId = "scenic_id"
|
||||
case scenicName = "scenic_name"
|
||||
case appRoleCode = "app_role_code"
|
||||
case appRoleName = "app_role_name"
|
||||
case isCurrent = "is_current"
|
||||
}
|
||||
|
||||
@ -257,6 +261,8 @@ struct V9ScenicUser: Decodable, Equatable {
|
||||
phone = try container.decodeLossyString(forKey: .phone)
|
||||
scenicId = try container.decodeLossyInt(forKey: .scenicId) ?? 0
|
||||
scenicName = try container.decodeLossyString(forKey: .scenicName)
|
||||
appRoleCode = try container.decodeLossyString(forKey: .appRoleCode)
|
||||
appRoleName = try container.decodeLossyString(forKey: .appRoleName)
|
||||
isCurrent = try container.decodeLossyBool(forKey: .isCurrent) ?? false
|
||||
}
|
||||
}
|
||||
@ -278,6 +284,8 @@ struct V9StoreUser: Decodable, Equatable {
|
||||
let scenicName: String
|
||||
let storeId: Int
|
||||
let storeName: String
|
||||
let appRoleCode: String
|
||||
let appRoleName: String
|
||||
let isCurrent: Bool
|
||||
|
||||
var businessUserId: Int {
|
||||
@ -320,6 +328,8 @@ struct V9StoreUser: Decodable, Equatable {
|
||||
case scenicName = "scenic_name"
|
||||
case storeId = "store_id"
|
||||
case storeName = "store_name"
|
||||
case appRoleCode = "app_role_code"
|
||||
case appRoleName = "app_role_name"
|
||||
case isCurrent = "is_current"
|
||||
}
|
||||
|
||||
@ -338,6 +348,8 @@ struct V9StoreUser: Decodable, Equatable {
|
||||
scenicName = try container.decodeLossyString(forKey: .scenicName)
|
||||
storeId = try container.decodeLossyInt(forKey: .storeId) ?? 0
|
||||
storeName = try container.decodeLossyString(forKey: .storeName)
|
||||
appRoleCode = try container.decodeLossyString(forKey: .appRoleCode)
|
||||
appRoleName = try container.decodeLossyString(forKey: .appRoleName)
|
||||
isCurrent = try container.decodeLossyBool(forKey: .isCurrent) ?? false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user