import { defineStore } from 'pinia' import { type AuthState } from '@/stores/interface' import { getAuthButtonListApi, getAuthMenuListApi } from '@/api/user/login' import { getAllBreadcrumbList, getFlatMenuList, getShowMenuList } from '@/utils' import { AUTH_STORE_KEY } from '@/stores/constant' import { getLicense } from '@/api/activate' import type { Activate } from '@/api/activate/interface' export const useAuthStore = defineStore(AUTH_STORE_KEY, { state: (): AuthState => ({ authButtonList: {}, authMenuList: [], showMenuList: [], flatMenuList: [], breadcrumbList: {}, routeName: '', showMenuFlag: localStorage.getItem('showMenuFlag') === 'true', activateInfo: {} as Activate.ActivationCodePlaintext, activateInfoLoaded: false }), getters: { authButtonListGet: state => state.authButtonList, authMenuListGet: state => state.authMenuList, showMenuListGet: state => state.showMenuList, flatMenuListGet: state => state.flatMenuList, breadcrumbListGet: state => state.breadcrumbList, showMenuFlagGet: state => state.showMenuFlag, activateInfoGet: state => state.activateInfo, activateInfoLoadedGet: state => state.activateInfoLoaded }, actions: { async getAuthButtonList() { const { data } = await getAuthButtonListApi() this.authButtonList = data }, async getAuthMenuList() { const { data: menuData } = await getAuthMenuListApi() this.authMenuList = normalizeBusinessMenus(filterBusinessMenus(menuData)) // 菜单派生数据只在菜单源数据变化时重算,避免每次路由跳转都深拷贝整棵菜单。 this.refreshDerivedMenus() }, refreshDerivedMenus() { this.showMenuList = getShowMenuList(this.authMenuList) this.flatMenuList = getFlatMenuList(this.authMenuList) this.breadcrumbList = getAllBreadcrumbList(this.authMenuList) }, async setRouteName(name: string) { this.routeName = name }, async resetAuthStore() { this.authButtonList = {} this.authMenuList = [] this.showMenuList = [] this.flatMenuList = [] this.breadcrumbList = {} this.routeName = '' this.showMenuFlag = false this.activateInfo = {} this.activateInfoLoaded = false localStorage.removeItem('showMenuFlag') }, async setShowMenu() { this.showMenuFlag = true localStorage.setItem('showMenuFlag', 'true') }, changeModel() { this.showMenuFlag = false localStorage.removeItem('showMenuFlag') }, async setActivateInfo() { const license_result = await getLicense() this.activateInfo = normalizeActivateInfo(license_result.data) this.activateInfoLoaded = true } } }) function filterBusinessMenus(menuList: any[]): any[] { const excludedNames = new Set([ 'home', 'plan', 'singlePlanList', 'preTest', 'autoTest', 'machine', 'testSource', 'testScript', 'controlSource', 'standardDevice', 'device', 'devType', 'errorSystem', 'icd', 'template', 'dictPq', 'base' ]) const excludedComponentPatterns = [ '/home/', '/plan/', '/machine/', '/system/template/', '/system/dictionary/dictPq/', '/system/base/' ] const excludedPathPatterns = [ '/home', '/plan', '/machine', '/system/template', '/system/dictionary/dictPq', '/system/base' ] return menuList.filter(menu => { if (Array.isArray(menu.children) && menu.children.length > 0) { menu.children = filterBusinessMenus(menu.children) } const component = typeof menu.component === 'string' ? menu.component : '' const path = typeof menu.path === 'string' ? menu.path : '' const hasChildren = Array.isArray(menu.children) && menu.children.length > 0 const removedByName = excludedNames.has(menu.name) const removedByComponent = excludedComponentPatterns.some(pattern => component.includes(pattern)) const removedByPath = excludedPathPatterns.some(pattern => path.includes(pattern)) if (removedByName || removedByComponent || removedByPath) { return hasChildren } return true }) } function normalizeBusinessMenus(menuList: any[]): any[] { return menuList.map(menu => normalizeBusinessMenu(menu)) } function normalizeBusinessMenu(menu: any): any { if (Array.isArray(menu.children) && menu.children.length > 0) { menu.children = normalizeBusinessMenus(menu.children) } if (isEventListMenu(menu)) { // 后端菜单历史配置不统一,前端统一收敛到静态 eventList 页面入口。 menu.path = '/eventList/index' menu.name = 'eventList' menu.component = '@/views/event/eventList/index.vue' } if (isSteadyDataViewMenu(menu)) { // 后端菜单可能存在 steady-data-view 等历史写法,前端统一收敛到静态 steadyDataView 页面入口。 menu.path = '/steadyDataView/index' menu.name = 'steadyDataView' menu.component = '@/views/steady/steadyDataView/index.vue' } if (isSteadyTrendMenu(menu)) { menu.path = '/steadyTrend/index' menu.name = 'steadyTrend' menu.component = '@/views/steady/steadyTrend/index.vue' } if (isChecksquareMenu(menu)) { menu.path = '/checksquare/index' menu.name = 'checksquare' menu.component = '@/views/steady/checksquare/index.vue' } if (isDbmsMenu(menu)) { // 数据库运维菜单后端存在 systemMonitor/dbms 等历史路径,统一收敛到当前静态页面入口。 menu.path = '/system-ops/dbms' menu.name = 'systemOpsDbms' menu.component = '@/views/system-ops/dbms/index.vue' } return menu } function isEventListMenu(menu: any): boolean { const normalizedName = String(menu?.name ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedPath = String(menu?.path ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedComponent = String(menu?.component ?? '').toLowerCase().replace(/[-_]/g, '') const title = String(menu?.meta?.title ?? menu?.title ?? '') if (normalizedName === 'eventlist') return true if (normalizedPath.includes('eventlist')) return true if (normalizedComponent.includes('eventlist')) return true return title.includes('事件列表') && (title.includes('暂降') || title.includes('暂态')) } function isSteadyDataViewMenu(menu: any): boolean { const normalizedName = String(menu?.name ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedPath = String(menu?.path ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedComponent = String(menu?.component ?? '').toLowerCase().replace(/[-_]/g, '') const title = String(menu?.meta?.title ?? menu?.title ?? '') if (normalizedName === 'steadydataview') return true if (normalizedPath.includes('steadydataview')) return true if (normalizedComponent.includes('steadydataview')) return true return title.includes('稳态数据') } function isSteadyTrendMenu(menu: any): boolean { const normalizedName = String(menu?.name ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedPath = String(menu?.path ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedComponent = String(menu?.component ?? '').toLowerCase().replace(/[-_]/g, '') const title = String(menu?.meta?.title ?? menu?.title ?? '') if (normalizedName === 'steadytrend') return true if (normalizedPath.includes('steadytrend')) return true if (normalizedComponent.includes('steadytrend')) return true return title.includes('\u7a33\u6001\u8d8b\u52bf') } function isChecksquareMenu(menu: any): boolean { const normalizedName = String(menu?.name ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedPath = String(menu?.path ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedComponent = String(menu?.component ?? '').toLowerCase().replace(/[-_]/g, '') const title = String(menu?.meta?.title ?? menu?.title ?? '') if (normalizedName === 'checksquare') return true if (normalizedPath.includes('checksquare')) return true if (normalizedComponent.includes('checksquare')) return true return title.includes('数据验证') } function isDbmsMenu(menu: any): boolean { const normalizedName = String(menu?.name ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedPath = String(menu?.path ?? '').toLowerCase().replace(/[-_]/g, '') const normalizedComponent = String(menu?.component ?? '').toLowerCase().replace(/[-_]/g, '') const title = String(menu?.meta?.title ?? menu?.title ?? '') if (normalizedName === 'systemopsdbms' || normalizedName === 'dbms') return true if (normalizedPath.includes('systemmonitor/dbms') || normalizedPath.includes('systemops/dbms')) return true if (normalizedPath.includes('databasemonitor') || normalizedComponent.includes('databasemonitor')) return true if (normalizedComponent.includes('systemmonitor/dbms') || normalizedComponent.includes('systemops/dbms')) return true return title.includes('数据库') && (title.includes('运维') || title.includes('监控')) } export function resolveBusinessMenuPath(menu: Menu.MenuOptions): string { if (isEventListMenu(menu)) return '/eventList/index' if (isChecksquareMenu(menu)) return '/checksquare/index' if (isSteadyTrendMenu(menu)) return '/steadyTrend/index' if (isDbmsMenu(menu)) return '/system-ops/dbms' return isSteadyDataViewMenu(menu) ? '/steadyDataView/index' : menu.path } function normalizeActivateInfo(rawData: unknown): Activate.ActivationCodePlaintext { if (!rawData || typeof rawData !== 'object' || Array.isArray(rawData)) { return {} } return Object.entries(rawData as Record).reduce( (modules, [key, value]) => { if (!value || typeof value !== 'object' || Array.isArray(value)) { return modules } if (!Object.prototype.hasOwnProperty.call(value, 'permanently')) { return modules } const permanentlyValue = (value as { permanently?: unknown }).permanently modules[key] = { permanently: Number(permanentlyValue) === 1 ? 1 : 0 } return modules }, {} as Activate.ActivationCodePlaintext ) }