// // HomeCommonMenuStore.swift // suixinkan // import Foundation /// 常用应用 URI 持久化,按账号与角色作用域存储。 final class HomeCommonMenuStore { private let defaults: UserDefaults init(defaults: UserDefaults = .standard) { self.defaults = defaults } /// 读取已保存的常用 URI;无记录时返回空数组。 func savedCommonURIs(accountScope: String, roleCode: String) -> [String] { guard let key = storageKey(accountScope: accountScope, roleCode: roleCode) else { return [] } let saved = defaults.stringArray(forKey: key) ?? [] let sanitized = saved.filter(HomeMenuCatalog.isCustomizable(uri:)) if sanitized != saved { defaults.set(sanitized, forKey: key) } return sanitized } /// 保存常用 URI 列表。 func saveCommonURIs(_ uris: [String], accountScope: String, roleCode: String) { guard let key = storageKey(accountScope: accountScope, roleCode: roleCode) else { return } defaults.set(uris.filter(HomeMenuCatalog.isCustomizable(uri:)), forKey: key) } /// 根据权限生成默认常用 URI(最多 4 个)。 static func defaultCommonURIs(from permissions: [HomePermissionItem]) -> [String] { let uris = permissions.map(\.uri).filter(HomeMenuCatalog.isCustomizable(uri:)) return uris.count > 4 ? Array(uris.prefix(4)) : uris } /// 构建常用菜单列表。 func commonMenus( from allMenus: [HomeMenuItem], permissions: [HomePermissionItem], accountScope: String, roleCode: String ) -> [HomeMenuItem] { let saved = savedCommonURIs(accountScope: accountScope, roleCode: roleCode) let defaultURIs = Self.defaultCommonURIs(from: permissions) let commonURIs = saved.isEmpty ? defaultURIs : saved return Self.splitMenus(from: allMenus, commonURIs: commonURIs).common } /// 按常用 URI 将菜单拆分为常用与更多两组。 static func splitMenus( from allMenus: [HomeMenuItem], commonURIs: [String] ) -> (common: [HomeMenuItem], more: [HomeMenuItem]) { let commonSet = Set(commonURIs) let customizableMenus = allMenus.filter { HomeMenuCatalog.isCustomizable(uri: $0.uri) } let common = customizableMenus.filter { commonSet.contains($0.uri) } let more = customizableMenus.filter { !commonSet.contains($0.uri) } return (common, more) } private func storageKey(accountScope: String, roleCode: String) -> String? { let normalizedScope = accountScope.trimmingCharacters(in: .whitespacesAndNewlines) let normalizedRoleCode = roleCode.trimmingCharacters(in: .whitespacesAndNewlines) guard !normalizedScope.isEmpty, !normalizedRoleCode.isEmpty else { return nil } return "\(normalizedScope)_role_\(normalizedRoleCode)_common_uris" } }