// // AppRoleCode.swift // suixinkan // // Created by Codex on 2026/6/29. // import Foundation /// App 业务角色枚举,与后端 `app_role_code` / `role_code` 字符串一一对应。 enum AppRoleCode: String, CaseIterable, Hashable { 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 isStoreAdmin: Bool { self == .storeAdmin } var isScenicAdmin: Bool { self == .scenicAdmin } var isPhotographer: Bool { self == .photographer } /// 从后端 role_code 字符串解析角色。 static func fromCode(_ code: String?) -> AppRoleCode? { guard let trimmed = code?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { return nil } return AppRoleCode(rawValue: trimmed) } /// 从旧版 numeric 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_code 缺失时的兜底。 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) } } /// 首页隐藏顶部在线/计时/位置/快捷操作的角色(原 46/47/52/53/54)。 static let homeMinimalTopRoles: Set = [ .storeAdmin, .editor, .scenicCS, .scenicAdmin, .scenicOperation, ] }