/** * Admin 导航状态管理 * 管理路由切换、菜单选中、标签页等状态 */ import { ref, computed } from 'vue' import type { RouteRecord } from '@/layouts/admin/router/adminRoutes.uts' import { findRouteById, findRouteByPath, buildDefaultTabs, getTopMenus } from '@/layouts/admin/router/adminRoutes.uts' /** * 标签页类型 */ export type TabItem = { id: string title: string path: string isAffix: boolean // 是否固定(不可关闭) } // ============================================ // 状态定义 // ============================================ /** 当前选中的一级菜单ID */ export const activeTopMenuId = ref('home') /** 当前激活的路由ID */ export const activeRouteId = ref('home_index') /** 打开的标签页列表 */ export const tabs = ref([]) /** 是否折叠主侧边栏 */ export const isMainAsideCollapsed = ref(false) /** 是否显示二级侧边栏 */ export const showSubSider = computed(() => { const topMenus = getTopMenus() const activeMenu = topMenus.find(m => m.id === activeTopMenuId.value) return activeMenu ? activeMenu.groups.length > 0 : false }) // ============================================ // Actions // ============================================ /** * 打开路由(核心方法) * @param routeId 路由ID * @param addTab 是否添加到标签页 */ export function openRoute(routeId: string, addTab: boolean = true): void { const route = findRouteById(routeId) if (!route) { console.warn(`[AdminNav] Route not found: ${routeId}`) return } // 更新当前路由 activeRouteId.value = routeId // 更新一级菜单选中态 if (route.parentId) { activeTopMenuId.value = route.parentId } else { // 首页等顶级路由 activeTopMenuId.value = routeId.split('_')[0] } // 添加到标签页 if (addTab) { addTabItem(route) } } /** * 通过路径打开路由 */ export function openRouteByPath(path: string): void { const route = findRouteByPath(path) if (route) { openRoute(route.id) } } /** * 添加标签页 */ function addTabItem(route: RouteRecord): void { const existingTab = tabs.value.find(t => t.id === route.id) if (!existingTab) { tabs.value.push({ id: route.id, title: route.title, path: route.path, isAffix: route.isAffix || false }) } } /** * 关闭标签页 * @param tabId 标签ID */ export function closeTab(tabId: string): void { const index = tabs.value.findIndex(t => t.id === tabId) if (index === -1) return const tab = tabs.value[index] // 固定标签不可关闭 if (tab.isAffix) { console.warn(`[AdminNav] Cannot close fixed tab: ${tabId}`) return } // 如果关闭的是当前激活标签,需要切换到其他标签 if (activeRouteId.value === tabId) { // 优先切换到右侧标签,否则切换到左侧 const nextTab = tabs.value[index + 1] || tabs.value[index - 1] if (nextTab) { openRoute(nextTab.id, false) } } tabs.value.splice(index, 1) } /** * 关闭其他标签页 * @param keepTabId 保留的标签ID */ export function closeOtherTabs(keepTabId: string): void { tabs.value = tabs.value.filter(t => t.isAffix || t.id === keepTabId) // 如果当前激活的标签被关闭了,切换到保留的标签 const stillExists = tabs.value.find(t => t.id === activeRouteId.value) if (!stillExists) { openRoute(keepTabId, false) } } /** * 关闭所有标签页(保留固定标签) */ export function closeAllTabs(): void { tabs.value = tabs.value.filter(t => t.isAffix) // 切换到首页 const homeTab = tabs.value.find(t => t.isAffix) if (homeTab) { openRoute(homeTab.id, false) } } /** * 切换主侧边栏折叠状态 */ export function toggleMainAsideCollapse(): void { isMainAsideCollapsed.value = !isMainAsideCollapsed.value } /** * 初始化导航状态 * 在 AdminLayout 组件 onMounted 时调用 */ export function initNavState(): void { // 初始化默认标签页 const defaultTabs = buildDefaultTabs() tabs.value = defaultTabs.map(r => ({ id: r.id, title: r.title, path: r.path, isAffix: r.isAffix || false })) // 打开首页 openRoute('home_index', false) } /** * 根据 currentPage 同步状态 * 用于页面组件传入 currentPage prop 时的状态同步 */ export function syncFromCurrentPage(currentPage: string): void { if (!currentPage) return // 可能是路由ID或路径 const route = findRouteById(currentPage) || findRouteByPath(currentPage) if (route) { activeRouteId.value = route.id // 更新一级菜单 if (route.parentId) { activeTopMenuId.value = route.parentId } } }