@@@@@@
This commit is contained in:
87
library/components/VabMenu/components/VabMenuItem.vue
Normal file
87
library/components/VabMenu/components/VabMenuItem.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<el-menu-item :index="itemOrMenu.path" @click="handleLink">
|
||||
<vab-icon
|
||||
v-if="itemOrMenu.meta && itemOrMenu.meta.icon"
|
||||
:icon="itemOrMenu.meta.icon"
|
||||
:is-custom-svg="itemOrMenu.meta.isCustomSvg"
|
||||
:title="translate(itemOrMenu.meta.title)"
|
||||
/>
|
||||
<span :title="translate(itemOrMenu.meta.title)">
|
||||
{{ translate(itemOrMenu.meta.title) }}
|
||||
</span>
|
||||
<el-tag v-if="itemOrMenu.meta && itemOrMenu.meta.badge" effect="dark" type="danger">
|
||||
{{ translate(itemOrMenu.meta.badge) }}
|
||||
</el-tag>
|
||||
<vab-dot v-if="itemOrMenu.meta && itemOrMenu.meta.dot" type="danger" />
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { isHashRouterMode } from '/@/config'
|
||||
import { translate } from '/@/i18n'
|
||||
import { useSettingsStore } from '/@/store/modules/settings'
|
||||
import { isExternal } from '/@/utils/validate'
|
||||
|
||||
defineOptions({
|
||||
name: 'VabMenuItem',
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
itemOrMenu: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const settingsStore = useSettingsStore()
|
||||
const { device } = storeToRefs(settingsStore)
|
||||
const { foldSideBar } = settingsStore
|
||||
const { enter, exit } = useFullscreen()
|
||||
|
||||
const handleLink = () => {
|
||||
nextTick(() => {
|
||||
const routePath = props.itemOrMenu.path
|
||||
const target = props.itemOrMenu.meta.target
|
||||
const fullscreen = props.itemOrMenu.meta.fullscreen
|
||||
|
||||
if (target === '_blank') {
|
||||
if (isExternal(routePath)) {
|
||||
window.open(routePath)
|
||||
router.push('/redirect')
|
||||
} else if (route.path !== routePath) isHashRouterMode ? window.open(`#${routePath}`) : window.open(routePath)
|
||||
router.push('/redirect')
|
||||
} else {
|
||||
if (isExternal(routePath)) window.location.href = routePath
|
||||
else if (route.path !== routePath) {
|
||||
if (device.value === 'mobile') foldSideBar()
|
||||
router.push(props.itemOrMenu.path)
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (fullscreen) enter()
|
||||
else exit()
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-tag) {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
height: 18px;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
font-size: var(--el-font-size-extra-small);
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.vab-dot {
|
||||
position: absolute !important;
|
||||
right: 20px;
|
||||
}
|
||||
</style>
|
||||
36
library/components/VabMenu/components/VabSubMenu.vue
Normal file
36
library/components/VabMenu/components/VabSubMenu.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<template v-if="itemOrMenu.meta && itemOrMenu.meta.levelHidden">
|
||||
<template v-for="route in itemOrMenu.children" :key="route.path">
|
||||
<vab-menu :item="route" />
|
||||
</template>
|
||||
</template>
|
||||
<el-sub-menu v-else :index="itemOrMenu.path">
|
||||
<template #title>
|
||||
<vab-icon
|
||||
v-if="itemOrMenu.meta && itemOrMenu.meta.icon"
|
||||
:icon="itemOrMenu.meta.icon"
|
||||
:is-custom-svg="itemOrMenu.meta.isCustomSvg"
|
||||
:title="translate(itemOrMenu.meta.title)"
|
||||
/>
|
||||
<span :title="translate(itemOrMenu.meta.title)">
|
||||
{{ translate(itemOrMenu.meta.title) }}
|
||||
</span>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</el-sub-menu>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { translate } from '/@/i18n'
|
||||
|
||||
defineOptions({
|
||||
name: 'VabSubMenu',
|
||||
})
|
||||
|
||||
defineProps({
|
||||
itemOrMenu: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
39
library/components/VabMenu/index.vue
Normal file
39
library/components/VabMenu/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<component :is="menuComponent" :item-or-menu="item">
|
||||
<template v-if="item.children && item.children.length > 0">
|
||||
<vab-menu v-for="route in item.children" :key="route.path" :item="route" />
|
||||
</template>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineOptions({
|
||||
name: 'VabMenu',
|
||||
})
|
||||
|
||||
const imports = import.meta.glob('./**/*.vue', { eager: true })
|
||||
const Components = {}
|
||||
Object.getOwnPropertyNames(imports).forEach((key) => {
|
||||
Components[key.replaceAll(/(\/|components|\.|vue)/g, '')] = imports[key].default
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const menuComponent = computed(() =>
|
||||
props.item.children &&
|
||||
props.item.children.some((route) => {
|
||||
return route.meta && route.meta.hidden !== true
|
||||
})
|
||||
? Components['VabSubMenu']
|
||||
: Components['VabMenuItem']
|
||||
)
|
||||
</script>
|
||||
Reference in New Issue
Block a user