refactor: 修改 Menu.recordRaw 和 Menu.recordMainRaw 类型里的 meta 为可选参数

This commit is contained in:
hooray
2022-11-27 23:40:16 +08:00
parent 5c6494931b
commit ca1ea48dc6
7 changed files with 137 additions and 141 deletions
+2 -2
View File
@@ -244,7 +244,7 @@ declare namespace Menu {
/** 原始 */
interface recordRaw {
path?: string
meta: {
meta?: {
title?: string
icon?: string
defaultOpened?: boolean
@@ -255,7 +255,7 @@ declare namespace Menu {
}
/** 主导航 */
interface recordMainRaw {
meta: {
meta?: {
title?: string
icon?: string
auth?: string | string[]
+3 -3
View File
@@ -30,10 +30,10 @@ function handlerMouserScroll(event: WheelEvent) {
<template v-for="(item, index) in menuStore.allMenus" :key="index">
<div v-if="item.children && item.children.length !== 0" class="item-container" :class="{ active: index === menuStore.actived }">
<div class="item" @click="switchTo(index)">
<el-icon>
<svg-icon v-if="item.meta.icon" :name="item.meta.icon" />
<el-icon v-if="item.meta?.icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span v-if="item.meta.title">{{ item.meta.title }}</span>
<span v-if="item.meta?.title">{{ item.meta.title }}</span>
</div>
</div>
</template>
+113 -113
View File
@@ -1,113 +1,113 @@
<script lang="ts" setup name="MainSidebar">
import Logo from '../Logo/index.vue'
import useSettingsStore from '@/store/modules/settings'
import useMenuStore from '@/store/modules/menu'
const settingsStore = useSettingsStore()
const menuStore = useMenuStore()
const { switchTo } = useMenu()
</script>
<template>
<transition name="main-sidebar">
<div v-if="settingsStore.menu.menuMode === 'side' || (settingsStore.mode === 'mobile' && settingsStore.menu.menuMode !== 'single')" class="main-sidebar-container">
<Logo :show-title="false" class="sidebar-logo" />
<!-- 侧边栏模式(含主导航) -->
<div class="nav">
<template v-for="(item, index) in menuStore.allMenus">
<div
v-if="item.children && item.children.length !== 0" :key="index" class="item" :class="{
active: index === menuStore.actived,
}" :title="item.meta.title ?? '[ 无标题 ]'" @click="switchTo(index)"
>
<el-icon>
<svg-icon v-if="item.meta.icon" :name="item.meta.icon" />
</el-icon>
<span>{{ item.meta.title ?? '[ 无标题 ]' }}</span>
</div>
</template>
</div>
</div>
</transition>
</template>
<style lang="scss" scoped>
.main-sidebar-container {
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
// firefox隐藏滚动条
scrollbar-width: none;
// chrome隐藏滚动条
&::-webkit-scrollbar {
display: none;
}
position: relative;
z-index: 1;
width: var(--g-main-sidebar-width);
color: var(--g-main-sidebar-menu-color);
background-color: var(--g-main-sidebar-bg);
transition: background-color 0.3s, var(--el-transition-color);
.sidebar-logo {
transition: 0.3s;
background-color: var(--g-main-sidebar-bg);
}
.nav {
width: inherit;
padding-top: var(--g-sidebar-logo-height);
.item {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
text-align: center;
height: 60px;
padding: 0 5px;
cursor: pointer;
color: var(--g-main-sidebar-menu-color);
background-color: var(--g-main-sidebar-bg);
transition: background-color 0.3s, var(--el-transition-color);
&:hover {
color: var(--g-main-sidebar-menu-hover-color);
background-color: var(--g-main-sidebar-menu-hover-bg);
}
&.active {
color: var(--g-main-sidebar-menu-active-color);
background-color: var(--g-main-sidebar-menu-active-bg);
}
.el-icon {
margin: 0 auto;
font-size: 24px;
}
span {
text-align: center;
font-size: 14px;
@include text-overflow(1, false);
}
}
}
}
// 主侧边栏动画
.main-sidebar-enter-active,
.main-sidebar-leave-active {
transition: transform 0.3s;
}
.main-sidebar-enter-from,
.main-sidebar-leave-to {
transform: translateX(calc(var(--g-main-sidebar-width) * -1));
}
</style>
<script lang="ts" setup name="MainSidebar">
import Logo from '../Logo/index.vue'
import useSettingsStore from '@/store/modules/settings'
import useMenuStore from '@/store/modules/menu'
const settingsStore = useSettingsStore()
const menuStore = useMenuStore()
const { switchTo } = useMenu()
</script>
<template>
<transition name="main-sidebar">
<div v-if="settingsStore.menu.menuMode === 'side' || (settingsStore.mode === 'mobile' && settingsStore.menu.menuMode !== 'single')" class="main-sidebar-container">
<Logo :show-title="false" class="sidebar-logo" />
<!-- 侧边栏模式(含主导航) -->
<div class="nav">
<template v-for="(item, index) in menuStore.allMenus">
<div
v-if="item.children && item.children.length !== 0" :key="index" class="item" :class="{
active: index === menuStore.actived,
}" :title="item.meta?.title ?? '[ 无标题 ]'" @click="switchTo(index)"
>
<el-icon v-if="item.meta?.icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span>{{ item.meta?.title ?? '[ 无标题 ]' }}</span>
</div>
</template>
</div>
</div>
</transition>
</template>
<style lang="scss" scoped>
.main-sidebar-container {
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
// firefox隐藏滚动条
scrollbar-width: none;
// chrome隐藏滚动条
&::-webkit-scrollbar {
display: none;
}
position: relative;
z-index: 1;
width: var(--g-main-sidebar-width);
color: var(--g-main-sidebar-menu-color);
background-color: var(--g-main-sidebar-bg);
transition: background-color 0.3s, var(--el-transition-color);
.sidebar-logo {
transition: 0.3s;
background-color: var(--g-main-sidebar-bg);
}
.nav {
width: inherit;
padding-top: var(--g-sidebar-logo-height);
.item {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
text-align: center;
height: 60px;
padding: 0 5px;
cursor: pointer;
color: var(--g-main-sidebar-menu-color);
background-color: var(--g-main-sidebar-bg);
transition: background-color 0.3s, var(--el-transition-color);
&:hover {
color: var(--g-main-sidebar-menu-hover-color);
background-color: var(--g-main-sidebar-menu-hover-bg);
}
&.active {
color: var(--g-main-sidebar-menu-active-color);
background-color: var(--g-main-sidebar-menu-active-bg);
}
.el-icon {
margin: 0 auto;
font-size: 24px;
}
span {
text-align: center;
font-size: 14px;
@include text-overflow(1, false);
}
}
}
}
// 主侧边栏动画
.main-sidebar-enter-active,
.main-sidebar-leave-active {
transition: transform 0.3s;
}
.main-sidebar-enter-from,
.main-sidebar-leave-to {
transform: translateX(calc(var(--g-main-sidebar-width) * -1));
}
</style>
+5 -5
View File
@@ -172,14 +172,14 @@ function getSourceListByMenus(arr: Menu.recordRaw[], icon?: string, breadcrumb?:
arr.forEach((item) => {
const breadcrumbTemp = cloneDeep(breadcrumb) || []
if (item.children && item.children.length > 0) {
breadcrumbTemp.push(item.meta.title)
getSourceListByMenus(item.children, item.meta.icon ?? icon, breadcrumbTemp)
breadcrumbTemp.push(item.meta?.title)
getSourceListByMenus(item.children, item.meta?.icon ?? icon, breadcrumbTemp)
}
else {
breadcrumbTemp.push(item.meta.title)
breadcrumbTemp.push(item.meta?.title)
sourceList.value.push({
icon: item.meta.icon ?? icon,
title: item.meta.title,
icon: item.meta?.icon ?? icon,
title: item.meta?.title,
path: item.path as string,
breadcrumb: breadcrumbTemp,
})
+8 -8
View File
@@ -20,7 +20,7 @@ const settingsStore = useSettingsStore()
const hasChildren = computed(() => {
let flag = true
if (props.item.children) {
if (props.item.children.every(item => item.meta.sidebar === false)) {
if (props.item.children.every(item => item.meta?.sidebar === false)) {
flag = false
}
}
@@ -35,23 +35,23 @@ const hasChildren = computed(() => {
<div class="sidebar-item">
<router-link v-if="!hasChildren" v-slot="{ href, navigate, isActive, isExactActive }" custom :to="resolveRoutePath(basePath, item.path || '')">
<a :href="isExternalLink(resolveRoutePath(basePath, item.path || '')) ? resolveRoutePath(basePath, item.path || '') : href" :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']" :target="isExternalLink(resolveRoutePath(basePath, item.path || '')) ? '_blank' : '_self'" @click="navigate">
<el-menu-item :title="item.meta.title ?? '[ 无标题 ]'" :index="resolveRoutePath(basePath, item.path || '')">
<el-icon v-if="item.meta.icon" class="title-icon">
<el-menu-item :title="item.meta?.title ?? '[ 无标题 ]'" :index="resolveRoutePath(basePath, item.path || '')">
<el-icon v-if="item.meta?.icon" class="title-icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span class="title">{{ item.meta.title ?? '[ 无标题 ]' }}</span>
<span class="title">{{ item.meta?.title ?? '[ 无标题 ]' }}</span>
</el-menu-item>
</a>
</router-link>
<el-sub-menu v-else :title="item.meta.title ?? '[ 无标题 ]'" :index="settingsStore.app.routeBaseOn !== 'filesystem' ? resolveRoutePath(basePath, item.path || '') : JSON.stringify(item)">
<el-sub-menu v-else :title="item.meta?.title ?? '[ 无标题 ]'" :index="settingsStore.app.routeBaseOn !== 'filesystem' ? resolveRoutePath(basePath, item.path || '') : JSON.stringify(item)">
<template #title>
<el-icon v-if="item.meta.icon" class="title-icon">
<el-icon v-if="item.meta?.icon" class="title-icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span class="title">{{ item.meta.title ?? '[ 无标题 ]' }}</span>
<span class="title">{{ item.meta?.title ?? '[ 无标题 ]' }}</span>
</template>
<template v-for="route in item.children">
<SidebarItem v-if="route.meta.sidebar !== false" :key="route.path" :item="route" :base-path="resolveRoutePath(basePath, item.path || '')" />
<SidebarItem v-if="route.meta?.sidebar !== false" :key="route.path" :item="route" :base-path="resolveRoutePath(basePath, item.path || '')" />
</template>
</el-sub-menu>
</div>
+1 -1
View File
@@ -30,7 +30,7 @@ function onSidebarScroll(e: Event) {
>
<transition-group name="sub-sidebar">
<template v-for="(route, index) in menuStore.sidebarMenus">
<SidebarItem v-if="route.meta.sidebar !== false" :key="route.path || index" :item="route" :base-path="route.path" />
<SidebarItem v-if="route.meta?.sidebar !== false" :key="route.path || index" :item="route" :base-path="route.path" />
</template>
</transition-group>
</el-menu>
+5 -9
View File
@@ -12,13 +12,9 @@ function getDeepestPath(menu: Menu.recordRaw, rootPath = '') {
let retnPath = ''
if (menu.path !== undefined) {
if (menu.children) {
if (
menu.children.some((item) => {
return item.meta.sidebar !== false
})
) {
if (menu.children.some(item => item.meta?.sidebar !== false)) {
for (let i = 0; i < menu.children.length; i++) {
if (menu.children[i].meta.sidebar !== false) {
if (menu.children[i].meta?.sidebar !== false) {
retnPath = getDeepestPath(menu.children[i], resolveRoutePath(rootPath, menu.path))
break
}
@@ -39,9 +35,9 @@ function hasPermission(permissions: string[], menu: Menu.recordMainRaw | Menu.re
let isAuth = false
if (menu.meta && menu.meta.auth) {
isAuth = permissions.some((auth) => {
return typeof menu.meta.auth === 'string'
return typeof menu.meta?.auth === 'string'
? menu.meta.auth === auth
: typeof menu.meta.auth === 'object'
: typeof menu.meta?.auth === 'object'
? menu.meta.auth.includes(auth)
: false
})
@@ -72,7 +68,7 @@ function filterAsyncMenus<T extends Menu.recordMainRaw[] | Menu.recordRaw[]>(men
function getDefaultOpenedPaths(menus: Menu.recordRaw[], rootPath = '') {
const defaultOpenedPaths: string[] = []
menus.forEach((item) => {
if (item.path && item.meta.defaultOpened && item.children) {
if (item.path && item.meta?.defaultOpened && item.children) {
defaultOpenedPaths.push(resolveRoutePath(rootPath, item.path))
const childrenDefaultOpenedPaths = getDefaultOpenedPaths(item.children, resolveRoutePath(rootPath, item.path))
if (childrenDefaultOpenedPaths.length > 0) {