| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- <template>
- <a-menu v-model:selected-keys="selectedKey"
- :default-open-keys="selectedKey">
- <template v-for="menu in menuData" :key="menu.key">
- <a-sub-menu v-if="menu.children" :key="menu.key">
- <template #icon>
- <component :is="menu.icon"></component>
- </template>
- <template #title>{{ menu.label }}</template>
- <a-menu-item v-for="child in menu.children" :key="child.key" :disabled="child.disabled"
- @click="$router.push(child.key)">
- {{ child.label }}
- </a-menu-item>
- </a-sub-menu>
- <a-menu-item v-else :key="menu.key" :disabled="menu.disabled" @click="$router.push(menu.key)">
- <template #icon>
- <component :is="menu.icon"></component>
- </template>
- {{ menu.label }}
- </a-menu-item>
- </template>
- </a-menu>
- </template>
- <script setup>
- import { onMounted, ref, watch } from 'vue'
- import { routes } from '@/router'
- import { useUserStore } from '@/store/modules/user'
- import { useRouteListener } from '@/utils/route-listener'
- import { isElectron } from '../../utils/electron'
- import { canShowInMenu } from '@/utils/permission'
- const userStore = useUserStore()
- const user = ref({})
- const electron = ref(false)
- const menuData = ref([])
- const { selectedKey } = useRouteListener()
- const checkEnv = (route) => {
- if (!route.meta) return true
- if (route.meta.onlyWeb) return !electron.value
- if (route.meta.onlyElectron) return !!electron.value
- return true
- }
- const joinRoutePath = (parentPath, routePath) => {
- const base = parentPath.endsWith('/') ? parentPath.slice(0, -1) : parentPath
- const segment = routePath.startsWith('/') ? routePath : `/${routePath}`
- return `${base}${segment}`.replace(/\/+/g, '/')
- }
- const generateMenu = (routeList, parentPath = '') => {
- return routeList
- .filter((route) => canShowInMenu(route, user.value) && checkEnv(route))
- .map((route) => {
- const fullPath = joinRoutePath(parentPath, route.path)
- const menu = {
- key: fullPath,
- label: route.meta?.title || route.name,
- icon: route.meta?.icon || '',
- disabled: route.meta?.disabled || false
- }
- if (route.children && route.children.length > 0) {
- const childPrefix = fullPath.endsWith('/') ? fullPath : `${fullPath}/`
- menu.children = generateMenu(route.children, childPrefix)
- if (menu.children.length === 0) return null
- if (route.meta?.flatMenu && menu.children.length === 1) {
- const only = menu.children[0]
- return {
- ...only,
- icon: menu.icon || only.icon,
- label: menu.label || only.label
- }
- }
- }
- return menu
- })
- .filter(Boolean)
- }
- const refreshMenu = async () => {
- user.value = await userStore.getInfo()
- if ((!user.value.permissionCodes || user.value.permissionCodes.length === 0) && userStore.refreshPermissions) {
- await userStore.refreshPermissions()
- user.value = userStore.$state
- }
- electron.value = isElectron()
- menuData.value = generateMenu(routes)
- }
- onMounted(refreshMenu)
- watch(
- () => [userStore.uuid, userStore.session],
- () => {
- refreshMenu()
- }
- )
- </script>
|