模块化 AppStore 并完善素材管理与个人空间设置。

将会话、权限、位置、收款与排队存储拆分为独立模块,同步更新各 ViewModel 与单元测试,并补充素材管理 UI 与个人空间设置交互。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-13 11:01:08 +08:00
parent ceca780ab3
commit 005349f8e6
128 changed files with 2953 additions and 1123 deletions

View File

@ -0,0 +1,91 @@
//
// AppPermissionStore.swift
// suixinkan
//
import Foundation
///
final class AppPermissionStore {
private enum Key: String, CaseIterable {
case legacyRoleId = "key_in_role_id"
case rolePermissionList = "key_role_permission_list"
case permissionItems = "key_in_permission"
case roleScenicList = "key_current_role_scenic_list"
}
private let defaults: UserDefaults
private let session: AppSessionStore
/// 使
init(defaults: UserDefaults, session: AppSessionStore) {
self.defaults = defaults
self.session = session
}
/// role_id
var legacyRoleId: Int {
get { defaults.integer(forKey: scopedKey(.legacyRoleId)) }
set { defaults.set(newValue, forKey: scopedKey(.legacyRoleId)) }
}
/// role-permission
func saveRolePermissionList(_ list: [RolePermissionResponse]) {
save(list, for: .rolePermissionList)
}
/// role-permission
func rolePermissionList() -> [RolePermissionResponse] {
load([RolePermissionResponse].self, for: .rolePermissionList) ?? []
}
///
func savePermissionItems(_ items: [HomePermissionItem]) {
save(items, for: .permissionItems)
}
///
func permissionItems() -> [HomePermissionItem] {
load([HomePermissionItem].self, for: .permissionItems) ?? []
}
///
func saveRoleScenicList(_ scenicList: [ScenicInfo]) {
save(scenicList, for: .roleScenicList)
}
///
func roleScenicList() -> [ScenicInfo] {
load([ScenicInfo].self, for: .roleScenicList) ?? []
}
/// role-permission
func matchRolePermissionItem(in list: [RolePermissionResponse]) -> RolePermissionResponse? {
RolePermissionMatcher.match(
in: list,
roleCode: session.roleCode,
roleName: session.roleName,
legacyRoleId: legacyRoleId
)
}
///
func clear() {
Key.allCases.forEach { defaults.removeObject(forKey: scopedKey($0)) }
}
private func save<Value: Encodable>(_ value: Value, for key: Key) {
guard let data = try? JSONEncoder().encode(value) else { return }
defaults.set(data, forKey: scopedKey(key))
}
private func load<Value: Decodable>(_ type: Value.Type, for key: Key) -> Value? {
guard let data = defaults.data(forKey: scopedKey(key)) else { return nil }
return try? JSONDecoder().decode(type, from: data)
}
private func scopedKey(_ key: Key) -> String {
"\(session.accountCachePrefix)_\(key.rawValue)"
}
}