初始提交
This commit is contained in:
116
suixinkan/Features/Home/ViewModels/HomeViewModel.swift
Normal file
116
suixinkan/Features/Home/ViewModels/HomeViewModel.swift
Normal file
@ -0,0 +1,116 @@
|
||||
//
|
||||
// HomeViewModel.swift
|
||||
// suixinkan
|
||||
//
|
||||
// Created by Codex on 2026/6/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
/// 首页 ViewModel,根据当前角色权限构建首页菜单列表。
|
||||
final class HomeViewModel {
|
||||
private(set) var menuItems: [HomeMenuItem] = []
|
||||
|
||||
/// 菜单排序权重,与旧工程和 Android 端保持一致。
|
||||
private let preferredOrder: [String] = [
|
||||
"space_settings",
|
||||
"album_list",
|
||||
"album_trailer",
|
||||
"wallet",
|
||||
"cloud_management",
|
||||
"cloud_storage_transit",
|
||||
"asset_management",
|
||||
"material_upload",
|
||||
"task_management",
|
||||
"schedule_management",
|
||||
"system_settings",
|
||||
"message_center",
|
||||
"checkin_points",
|
||||
"sample_management",
|
||||
"sample_upload",
|
||||
"live_stream_management",
|
||||
"scenicselection",
|
||||
"scenicapplication",
|
||||
"permission_apply",
|
||||
"permission_apply_status",
|
||||
"scenic_settlement",
|
||||
"scenic_settlement_review",
|
||||
"verification_order",
|
||||
"live_album",
|
||||
"pm",
|
||||
"location_report",
|
||||
"registration_invitation",
|
||||
"store",
|
||||
"fly",
|
||||
"pilot_cert",
|
||||
"task_management_editor",
|
||||
"deposit_order_detail",
|
||||
"deposit_order",
|
||||
"pm_manager",
|
||||
"pilot_controller",
|
||||
"/scenic-queue",
|
||||
"queue_management",
|
||||
"operating-area",
|
||||
"/scenic-order-manage",
|
||||
"photographer_orders"
|
||||
]
|
||||
|
||||
/// 从角色权限树扁平化出菜单项,按固定顺序排序并按 URI 别名去重。
|
||||
func buildMenus(from permissions: [RolePermissionResponse], currentRoleId: Int?) {
|
||||
let source: RolePermissionResponse?
|
||||
if let currentRoleId {
|
||||
source = permissions.first { $0.role.id == currentRoleId }
|
||||
} else {
|
||||
source = permissions.first
|
||||
}
|
||||
|
||||
guard let source else {
|
||||
menuItems = []
|
||||
return
|
||||
}
|
||||
|
||||
let permissionItems = flatten(source.role.permission)
|
||||
var seen = Set<String>()
|
||||
var deduplicated: [PermissionItem] = []
|
||||
for item in permissionItems where !item.uri.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
if seen.insert(HomeMenuRouter.menuAliasKey(for: item.uri)).inserted {
|
||||
deduplicated.append(item)
|
||||
}
|
||||
}
|
||||
|
||||
let preferredIndexMap = Dictionary(uniqueKeysWithValues: preferredOrder.enumerated().map { ($1, $0) })
|
||||
let sortedItems = deduplicated.sorted { lhs, rhs in
|
||||
let lhsRank = preferredIndexMap[lhs.uri] ?? Int.max
|
||||
let rhsRank = preferredIndexMap[rhs.uri] ?? Int.max
|
||||
if lhsRank != rhsRank {
|
||||
return lhsRank < rhsRank
|
||||
}
|
||||
let lhsIndex = deduplicated.firstIndex(where: { $0.id == lhs.id }) ?? Int.max
|
||||
let rhsIndex = deduplicated.firstIndex(where: { $0.id == rhs.id }) ?? Int.max
|
||||
return lhsIndex < rhsIndex
|
||||
}
|
||||
|
||||
menuItems = sortedItems.map { item in
|
||||
HomeMenuItem(
|
||||
title: item.name.isEmpty ? HomeMenuRouter.title(for: item.uri) : item.name,
|
||||
uri: item.uri,
|
||||
iconSrc: item.iconSrc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// 返回指定 URI 的展示标题。
|
||||
func title(for uri: String) -> String {
|
||||
HomeMenuRouter.title(for: uri)
|
||||
}
|
||||
|
||||
/// 递归展开权限树。
|
||||
private func flatten(_ items: [PermissionItem]) -> [PermissionItem] {
|
||||
items.flatMap { item in
|
||||
[item] + flatten(item.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user