feat: 🎸 新增固定一级菜单配置
This commit is contained in:
parent
62eeb55330
commit
4c4903e806
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "vue-element-plus-admin",
|
"name": "vue-element-plus-admin",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
|
|
|
@ -36,23 +36,23 @@ export default defineComponent({
|
||||||
const levelList = ref<RouteRecordRaw[]>([])
|
const levelList = ref<RouteRecordRaw[]>([])
|
||||||
|
|
||||||
function getBreadcrumb() {
|
function getBreadcrumb() {
|
||||||
let matched: any[] = currentRoute.value.matched.filter((item: RouteLocationMatched) => item.meta && item.meta.title)
|
const matched: any[] = currentRoute.value.matched.filter((item: RouteLocationMatched) => item.meta && item.meta.title)
|
||||||
const first = matched[0]
|
// const first = matched[0]
|
||||||
|
|
||||||
if (!isDashboard(first)) {
|
// if (!isDashboard(first)) {
|
||||||
matched = [{ path: '/dashboard', meta: { title: '首页', icon: 'dashboard' }}].concat(matched)
|
// matched = [{ path: '/dashboard', meta: { title: '首页', icon: 'dashboard' }}].concat(matched)
|
||||||
}
|
// }
|
||||||
|
|
||||||
levelList.value = matched.filter((item: RouteLocationMatched) => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
levelList.value = matched.filter((item: RouteLocationMatched) => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDashboard(route: RouteLocationMatched) {
|
// function isDashboard(route: RouteLocationMatched) {
|
||||||
const name = route && route.name
|
// const name = route && route.name
|
||||||
if (!name) {
|
// if (!name) {
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
return (name as any).trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
|
// return (name as any).trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
|
||||||
}
|
// }
|
||||||
|
|
||||||
function pathCompile(path: string): string {
|
function pathCompile(path: string): string {
|
||||||
const { params } = currentRoute.value
|
const { params } = currentRoute.value
|
|
@ -0,0 +1,125 @@
|
||||||
|
<template>
|
||||||
|
<el-tabs
|
||||||
|
v-model="activeName"
|
||||||
|
:tab-position="tabPosition"
|
||||||
|
@tab-click="changeTab"
|
||||||
|
>
|
||||||
|
<el-tab-pane
|
||||||
|
v-for="(item, $index) in tabRouters"
|
||||||
|
:key="$index"
|
||||||
|
:name="item.path === '/' ? '/dashboard' : item.path"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<div class="label-item">
|
||||||
|
<svg-icon :icon-class="filterTab(item, 'icon')" />
|
||||||
|
<div class="title-item">{{ filterTab(item, 'title') }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, watch, onMounted, computed } from 'vue'
|
||||||
|
import { appStore } from '_@/store/modules/app'
|
||||||
|
import { permissionStore } from '_@/store/modules/permission'
|
||||||
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { findIndex } from '@/utils'
|
||||||
|
import { isExternal } from '@/utils/validate'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'MenuTab',
|
||||||
|
setup() {
|
||||||
|
const { currentRoute, push } = useRouter()
|
||||||
|
|
||||||
|
const activeName = ref<string>('')
|
||||||
|
|
||||||
|
const routers = computed((): RouteRecordRaw[] => permissionStore.routers)
|
||||||
|
const tabRouters = computed((): RouteRecordRaw[] => routers.value.filter(v => !v.meta?.hidden))
|
||||||
|
|
||||||
|
const layout = computed(() => appStore.layout)
|
||||||
|
const tabPosition = computed(() => layout.value === 'Classic' ? 'left' : 'top')
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
const currentPath = currentRoute.value.fullPath.split('/')
|
||||||
|
const index = findIndex(tabRouters.value, (v: RouteRecordRaw) => {
|
||||||
|
if (v.path === '/') {
|
||||||
|
return `/${currentPath[1]}` === '/dashboard'
|
||||||
|
} else {
|
||||||
|
return v.path === `/${currentPath[1]}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (index > -1) {
|
||||||
|
activeName.value = `/${currentPath[1]}`
|
||||||
|
setActive(index)
|
||||||
|
permissionStore.SetAcitveTab(activeName.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterTab(item: RouteRecordRaw | any, key: string): any {
|
||||||
|
return item.meta && item.meta[key] ? item.meta[key] : item.children[0].meta[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
function setActive(index: number): void {
|
||||||
|
const currRoute: any = tabRouters.value[index]
|
||||||
|
permissionStore.SetMenuTabRouters(currRoute.children)
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeTab(item: any) {
|
||||||
|
const currRoute: any = tabRouters.value[item.index]
|
||||||
|
permissionStore.SetMenuTabRouters(currRoute.children)
|
||||||
|
if (isExternal(currRoute.children[0].path)) {
|
||||||
|
window.open(currRoute.children[0].path)
|
||||||
|
} else {
|
||||||
|
push(`${activeName.value === '/dashboard' ? '' : activeName.value}/${currRoute.children[0].path}`)
|
||||||
|
permissionStore.SetAcitveTab(activeName.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => currentRoute.value,
|
||||||
|
() => {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => activeName.value,
|
||||||
|
(val) => {
|
||||||
|
permissionStore.SetAcitveTab(val)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
activeName,
|
||||||
|
tabRouters,
|
||||||
|
tabPosition,
|
||||||
|
filterTab,
|
||||||
|
setActive,
|
||||||
|
changeTab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.label-item {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
&>div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.title-item {
|
||||||
|
position: relative;
|
||||||
|
top: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -37,6 +37,11 @@
|
||||||
<!-- <div class="setting__title">界面功能</div> -->
|
<!-- <div class="setting__title">界面功能</div> -->
|
||||||
|
|
||||||
<div class="setting__title">界面显示</div>
|
<div class="setting__title">界面显示</div>
|
||||||
|
<div v-if="layout !== 'Top'" class="setting__item">
|
||||||
|
<span>固定一级菜单</span>
|
||||||
|
<el-switch v-model="showMenuTab" @change="setShowMenuTab" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="setting__item">
|
<div class="setting__item">
|
||||||
<span>固定Header</span>
|
<span>固定Header</span>
|
||||||
<el-switch v-model="fixedHeader" @change="setFixedHeader" />
|
<el-switch v-model="fixedHeader" @change="setFixedHeader" />
|
||||||
|
@ -117,6 +122,7 @@ export default defineComponent({
|
||||||
if (mode === layout.value) return
|
if (mode === layout.value) return
|
||||||
appStore.SetLayout(mode)
|
appStore.SetLayout(mode)
|
||||||
appStore.SetCollapsed(false)
|
appStore.SetCollapsed(false)
|
||||||
|
mode === 'Top' && appStore.SetShowMenuTab(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fixedHeader = ref<boolean>(appStore.fixedHeader)
|
const fixedHeader = ref<boolean>(appStore.fixedHeader)
|
||||||
|
@ -179,6 +185,11 @@ export default defineComponent({
|
||||||
appStore.SetShowBackTop(showBackTop)
|
appStore.SetShowBackTop(showBackTop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showMenuTab = ref<boolean>(appStore.showMenuTab)
|
||||||
|
function setShowMenuTab(showMenuTab: boolean) {
|
||||||
|
appStore.SetShowMenuTab(showMenuTab)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
drawer, toggleClick,
|
drawer, toggleClick,
|
||||||
layout, setLayout,
|
layout, setLayout,
|
||||||
|
@ -193,7 +204,8 @@ export default defineComponent({
|
||||||
title, setTitle,
|
title, setTitle,
|
||||||
logoTitle, setLogoTitle,
|
logoTitle, setLogoTitle,
|
||||||
greyMode, setGreyMode,
|
greyMode, setGreyMode,
|
||||||
showBackTop, setShowBackTop
|
showBackTop, setShowBackTop,
|
||||||
|
showMenuTab, setShowMenuTab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<template v-if="!item.meta?.hidden">
|
<template v-if="!item.meta?.hidden">
|
||||||
<template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.meta?.alwaysShow">
|
<template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.meta?.alwaysShow">
|
||||||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown': !isNest}">
|
<el-menu-item :index="resolvePath(onlyOneChild.path, showMenuTab ? `${activeTab === '/dashboard' ? '' : activeTab}/${basePath}` : '')" :class="{'submenu-title-noDropdown': !isNest}">
|
||||||
<item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" />
|
<item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" />
|
||||||
<template #title>
|
<template #title>
|
||||||
<span class="anticon-item">{{ onlyOneChild.meta.title }}</span>
|
<span class="anticon-item">{{ onlyOneChild.meta.title }}</span>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
:popper-class="layout !== 'Top'
|
:popper-class="layout !== 'Top'
|
||||||
? 'nest-popper-menu'
|
? 'nest-popper-menu'
|
||||||
: 'top-popper-menu'"
|
: 'top-popper-menu'"
|
||||||
:index="resolvePath(item.path)"
|
:index="resolvePath(item.path, showMenuTab ? `${activeTab === '/dashboard' ? '' : activeTab}/${basePath}` : '')"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
|
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
|
||||||
|
@ -32,11 +32,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType, ref } from 'vue'
|
import { defineComponent, PropType, ref, computed } from 'vue'
|
||||||
import type { RouteRecordRaw } from 'vue-router'
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { isExternal } from '@/utils/validate'
|
import { isExternal } from '@/utils/validate'
|
||||||
import Item from './Item.vue'
|
import Item from './Item.vue'
|
||||||
|
import { permissionStore } from '_@/store/modules/permission'
|
||||||
|
import { appStore } from '_@/store/modules/app'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SiderItem',
|
name: 'SiderItem',
|
||||||
components: { Item },
|
components: { Item },
|
||||||
|
@ -62,6 +64,9 @@ export default defineComponent({
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const onlyOneChild = ref<any>(null)
|
const onlyOneChild = ref<any>(null)
|
||||||
|
|
||||||
|
const activeTab = computed(() => permissionStore.activeTab)
|
||||||
|
const showMenuTab = computed(() => appStore.showMenuTab)
|
||||||
|
|
||||||
function hasOneShowingChild(children: RouteRecordRaw[] = [], parent: RouteRecordRaw): boolean {
|
function hasOneShowingChild(children: RouteRecordRaw[] = [], parent: RouteRecordRaw): boolean {
|
||||||
const showingChildren: RouteRecordRaw[] = children.filter((item: RouteRecordRaw) => {
|
const showingChildren: RouteRecordRaw[] = children.filter((item: RouteRecordRaw) => {
|
||||||
if (item.meta && item.meta.hidden) {
|
if (item.meta && item.meta.hidden) {
|
||||||
|
@ -87,14 +92,16 @@ export default defineComponent({
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolvePath(routePath: string): string {
|
function resolvePath(routePath: string, otherPath: string): string {
|
||||||
if (isExternal(routePath)) {
|
if (isExternal(routePath)) {
|
||||||
return routePath
|
return routePath
|
||||||
}
|
}
|
||||||
return path.resolve(props.basePath, routePath)
|
return path.resolve(otherPath || props.basePath, routePath)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
onlyOneChild,
|
onlyOneChild,
|
||||||
|
activeTab,
|
||||||
|
showMenuTab,
|
||||||
hasOneShowingChild,
|
hasOneShowingChild,
|
||||||
resolvePath
|
resolvePath
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
@select="selectMenu"
|
@select="selectMenu"
|
||||||
>
|
>
|
||||||
<sider-item
|
<sider-item
|
||||||
v-for="route in routers"
|
v-for="route in showMenuTab ? menuTabRouters : routers"
|
||||||
:key="route.path"
|
:key="route.path"
|
||||||
:item="route"
|
:item="route"
|
||||||
:layout="layout"
|
:layout="layout"
|
||||||
|
@ -62,7 +62,12 @@ export default defineComponent({
|
||||||
const collapsed = computed(() => appStore.collapsed)
|
const collapsed = computed(() => appStore.collapsed)
|
||||||
const showLogo = computed(() => appStore.showLogo)
|
const showLogo = computed(() => appStore.showLogo)
|
||||||
|
|
||||||
|
const showMenuTab = computed(() => appStore.showMenuTab)
|
||||||
|
const menuTabRouters = computed(() => permissionStore.menuTabRouters)
|
||||||
|
const activeTab = computed(() => permissionStore.activeTab)
|
||||||
|
|
||||||
function selectMenu(path: string) {
|
function selectMenu(path: string) {
|
||||||
|
if (currentRoute.value.fullPath === path) return
|
||||||
if (isExternal(path)) {
|
if (isExternal(path)) {
|
||||||
window.open(path)
|
window.open(path)
|
||||||
} else {
|
} else {
|
||||||
|
@ -75,6 +80,9 @@ export default defineComponent({
|
||||||
activeMenu,
|
activeMenu,
|
||||||
collapsed,
|
collapsed,
|
||||||
showLogo,
|
showLogo,
|
||||||
|
showMenuTab,
|
||||||
|
menuTabRouters,
|
||||||
|
activeTab,
|
||||||
variables,
|
variables,
|
||||||
selectMenu
|
selectMenu
|
||||||
}
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="classObj" class="app__wrap">
|
<div :class="classObj" class="app__wrap">
|
||||||
<!-- Classic -->
|
<!-- Classic -->
|
||||||
|
<div v-if="showMenuTab" class="menu__tab">
|
||||||
|
<menu-tab />
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
id="sidebar__wrap"
|
id="sidebar__wrap"
|
||||||
class="sidebar__wrap"
|
class="sidebar__wrap"
|
||||||
:class="{'sidebar__wrap--collapsed': collapsed}"
|
:class="{'sidebar__wrap--collapsed': collapsed, 'sidebar__wrap--tab': showMenuTab}"
|
||||||
>
|
>
|
||||||
<logo
|
<logo
|
||||||
v-if="showLogo && layout === 'Classic'"
|
v-if="showLogo && layout === 'Classic'"
|
||||||
|
@ -16,7 +19,9 @@
|
||||||
<div
|
<div
|
||||||
class="main__wrap"
|
class="main__wrap"
|
||||||
:class="{
|
:class="{
|
||||||
'main__wrap--collapsed': collapsed
|
'main__wrap--collapsed': collapsed,
|
||||||
|
'main__wrap--tab': showMenuTab,
|
||||||
|
'main__wrap--tab--collapsed': showMenuTab && collapsed
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<el-scrollbar
|
<el-scrollbar
|
||||||
|
@ -31,7 +36,10 @@
|
||||||
class="header__wrap"
|
class="header__wrap"
|
||||||
:class="{
|
:class="{
|
||||||
'header__wrap--fixed': fixedHeader,
|
'header__wrap--fixed': fixedHeader,
|
||||||
'header__wrap--collapsed': fixedHeader && collapsed
|
'header__wrap--tab--fixed': fixedHeader && showMenuTab,
|
||||||
|
'header__wrap--collapsed': fixedHeader && collapsed,
|
||||||
|
'header__wrap--tab': showMenuTab,
|
||||||
|
'header__wrap--tab--collapsed': showMenuTab && collapsed
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -75,17 +83,18 @@
|
||||||
import { defineComponent, computed } from 'vue'
|
import { defineComponent, computed } from 'vue'
|
||||||
import { appStore } from '_@/store/modules/app'
|
import { appStore } from '_@/store/modules/app'
|
||||||
|
|
||||||
import AppMain from '../components/AppMain.vue'
|
import AppMain from '../components/AppMain/index.vue'
|
||||||
import TagsView from '_c/TagsView/index.vue'
|
import TagsView from '../components/TagsView/index.vue'
|
||||||
import Logo from '_c/Logo/index.vue'
|
import Logo from '../components/Logo/index.vue'
|
||||||
import Sider from '_c/Sider/index.vue'
|
import Sider from '../components/Sider/index.vue'
|
||||||
import Hamburger from '_c/Hamburger/index.vue'
|
import Hamburger from '../components/Hamburger/index.vue'
|
||||||
import Breadcrumb from '_c/Breadcrumb/index.vue'
|
import Breadcrumb from '../components/Breadcrumb/index.vue'
|
||||||
import Screenfull from '_c/Screenfull/index.vue'
|
import Screenfull from '../components/Screenfull/index.vue'
|
||||||
import UserInfo from '_c/UserInfo/index.vue'
|
import UserInfo from '../components/UserInfo/index.vue'
|
||||||
|
import MenuTab from '../components/MenuTab/index.vue'
|
||||||
|
|
||||||
import Setting from '_c/Setting/index.vue'
|
import Setting from '../components/Setting/index.vue'
|
||||||
import Backtop from '_c/Backtop/index.vue'
|
import Backtop from '../components/Backtop/index.vue'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Classic',
|
name: 'Classic',
|
||||||
components: {
|
components: {
|
||||||
|
@ -98,7 +107,8 @@ export default defineComponent({
|
||||||
TagsView,
|
TagsView,
|
||||||
Logo,
|
Logo,
|
||||||
Setting,
|
Setting,
|
||||||
Backtop
|
Backtop,
|
||||||
|
MenuTab
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const layout = computed(() => appStore.layout)
|
const layout = computed(() => appStore.layout)
|
||||||
|
@ -114,6 +124,7 @@ export default defineComponent({
|
||||||
// const fixedTags = computed(() => appStore.fixedTags)
|
// const fixedTags = computed(() => appStore.fixedTags)
|
||||||
const fixedHeader = computed(() => appStore.fixedHeader)
|
const fixedHeader = computed(() => appStore.fixedHeader)
|
||||||
const showBackTop = computed(() => appStore.showBackTop)
|
const showBackTop = computed(() => appStore.showBackTop)
|
||||||
|
const showMenuTab = computed(() => appStore.showMenuTab)
|
||||||
|
|
||||||
const classObj = computed(() => {
|
const classObj = computed(() => {
|
||||||
const obj = {}
|
const obj = {}
|
||||||
|
@ -140,7 +151,8 @@ export default defineComponent({
|
||||||
// fixedNavbar,
|
// fixedNavbar,
|
||||||
// fixedTags,
|
// fixedTags,
|
||||||
setCollapsed,
|
setCollapsed,
|
||||||
showBackTop
|
showBackTop,
|
||||||
|
showMenuTab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
:collapsed="collapsed"
|
:collapsed="collapsed"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="layout === 'Top'" class="sidebar__item--Top">
|
<div v-if="showMenuTab" class="menu__tab--top sidebar__item--Top">
|
||||||
<sider :layout="layout" mode="horizontal" />
|
<menu-tab />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="showScreenfull || showUserInfo" class="navbar__wrap--right">
|
<div v-if="showScreenfull || showUserInfo" class="navbar__wrap--right">
|
||||||
|
@ -96,17 +96,18 @@
|
||||||
import { defineComponent, computed } from 'vue'
|
import { defineComponent, computed } from 'vue'
|
||||||
import { appStore } from '_@/store/modules/app'
|
import { appStore } from '_@/store/modules/app'
|
||||||
|
|
||||||
import AppMain from '../components/AppMain.vue'
|
import AppMain from '../components/AppMain/index.vue'
|
||||||
import TagsView from '_c/TagsView/index.vue'
|
import TagsView from '../components/TagsView/index.vue'
|
||||||
import Logo from '_c/Logo/index.vue'
|
import Logo from '../components/Logo/index.vue'
|
||||||
import Sider from '_c/Sider/index.vue'
|
import Sider from '../components/Sider/index.vue'
|
||||||
import Hamburger from '_c/Hamburger/index.vue'
|
import Hamburger from '../components/Hamburger/index.vue'
|
||||||
import Breadcrumb from '_c/Breadcrumb/index.vue'
|
import Breadcrumb from '../components/Breadcrumb/index.vue'
|
||||||
import Screenfull from '_c/Screenfull/index.vue'
|
import Screenfull from '../components/Screenfull/index.vue'
|
||||||
import UserInfo from '_c/UserInfo/index.vue'
|
import UserInfo from '../components/UserInfo/index.vue'
|
||||||
|
import MenuTab from '../components/MenuTab/index.vue'
|
||||||
|
|
||||||
import Setting from '_c/Setting/index.vue'
|
import Setting from '../components/Setting/index.vue'
|
||||||
import Backtop from '_c/Backtop/index.vue'
|
import Backtop from '../components/Backtop/index.vue'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LeftTop',
|
name: 'LeftTop',
|
||||||
components: {
|
components: {
|
||||||
|
@ -119,7 +120,8 @@ export default defineComponent({
|
||||||
TagsView,
|
TagsView,
|
||||||
Logo,
|
Logo,
|
||||||
Setting,
|
Setting,
|
||||||
Backtop
|
Backtop,
|
||||||
|
MenuTab
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const layout = computed(() => appStore.layout)
|
const layout = computed(() => appStore.layout)
|
||||||
|
@ -135,6 +137,7 @@ export default defineComponent({
|
||||||
// const fixedTags = computed(() => appStore.fixedTags)
|
// const fixedTags = computed(() => appStore.fixedTags)
|
||||||
const fixedHeader = computed(() => appStore.fixedHeader)
|
const fixedHeader = computed(() => appStore.fixedHeader)
|
||||||
const showBackTop = computed(() => appStore.showBackTop)
|
const showBackTop = computed(() => appStore.showBackTop)
|
||||||
|
const showMenuTab = computed(() => appStore.showMenuTab)
|
||||||
|
|
||||||
const classObj = computed(() => {
|
const classObj = computed(() => {
|
||||||
const obj = {}
|
const obj = {}
|
||||||
|
@ -161,7 +164,8 @@ export default defineComponent({
|
||||||
// fixedNavbar,
|
// fixedNavbar,
|
||||||
// fixedTags,
|
// fixedTags,
|
||||||
setCollapsed,
|
setCollapsed,
|
||||||
showBackTop
|
showBackTop,
|
||||||
|
showMenuTab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -81,17 +81,17 @@
|
||||||
import { defineComponent, computed } from 'vue'
|
import { defineComponent, computed } from 'vue'
|
||||||
import { appStore } from '_@/store/modules/app'
|
import { appStore } from '_@/store/modules/app'
|
||||||
|
|
||||||
import AppMain from '../components/AppMain.vue'
|
import AppMain from '../components/AppMain/index.vue'
|
||||||
import TagsView from '_c/TagsView/index.vue'
|
import TagsView from '../components/TagsView/index.vue'
|
||||||
import Logo from '_c/Logo/index.vue'
|
import Logo from '../components/Logo/index.vue'
|
||||||
import Sider from '_c/Sider/index.vue'
|
import Sider from '../components/Sider/index.vue'
|
||||||
// import Hamburger from '_c/Hamburger/index.vue'
|
// import Hamburger from '../components/Hamburger/index.vue'
|
||||||
// import Breadcrumb from '_c/Breadcrumb/index.vue'
|
// import Breadcrumb from '../components/Breadcrumb/index.vue'
|
||||||
import Screenfull from '_c/Screenfull/index.vue'
|
import Screenfull from '../components/Screenfull/index.vue'
|
||||||
import UserInfo from '_c/UserInfo/index.vue'
|
import UserInfo from '../components/UserInfo/index.vue'
|
||||||
|
|
||||||
import Setting from '_c/Setting/index.vue'
|
import Setting from '../components/Setting/index.vue'
|
||||||
import Backtop from '_c/Backtop/index.vue'
|
import Backtop from '../components/Backtop/index.vue'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Top',
|
name: 'Top',
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -2,6 +2,74 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
.menu__tab {
|
||||||
|
width: @menuTabWidth;
|
||||||
|
height: 100%;
|
||||||
|
background: @menuTabBg;
|
||||||
|
@{deep}(.is-left::after),
|
||||||
|
@{deep}(.el-tabs__active-bar) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@{deep}(.el-tabs) {
|
||||||
|
height: 100%;
|
||||||
|
.el-tabs__header {
|
||||||
|
height: 100%;
|
||||||
|
margin-right: 0;
|
||||||
|
width: @menuTabWidth;
|
||||||
|
.el-tabs__nav-wrap {
|
||||||
|
height: 100%;
|
||||||
|
.el-tabs__item {
|
||||||
|
padding: 0;
|
||||||
|
line-height: 0;
|
||||||
|
height: @menuTabItemHeight;
|
||||||
|
text-align: center;
|
||||||
|
color: @menuTabText;
|
||||||
|
transition: all .3s cubic-bezier(.645,.045,.355,1);
|
||||||
|
}
|
||||||
|
.el-tabs__item:hover {
|
||||||
|
color: @menuTabActiveText;
|
||||||
|
background: @menuTabActiveBg;
|
||||||
|
}
|
||||||
|
.is-active {
|
||||||
|
color: @menuTabActiveText;
|
||||||
|
background: @menuTabActiveBg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&--top {
|
||||||
|
width: auto;
|
||||||
|
@{deep}(.el-tabs),
|
||||||
|
@{deep}(.is-top),
|
||||||
|
@{deep}(.el-tabs__nav-scroll) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
@{deep}(.is-top::after),
|
||||||
|
@{deep}(.el-tabs__active-bar) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@{deep}(.is-top) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
@{deep}(.el-tabs__item) {
|
||||||
|
padding: 0;
|
||||||
|
width: @menuTopTabWidth;
|
||||||
|
text-align: center;
|
||||||
|
height: 100%;
|
||||||
|
padding-top: 10px;
|
||||||
|
color: @menuTabText;
|
||||||
|
transition: all .3s cubic-bezier(.645,.045,.355,1);
|
||||||
|
}
|
||||||
|
@{deep}(.el-tabs__item:hover) {
|
||||||
|
color: @menuTopTabActiveText;
|
||||||
|
background: @menuTopTabActiveBg;
|
||||||
|
}
|
||||||
|
@{deep}(.is-active) {
|
||||||
|
color: @menuTopTabActiveText;
|
||||||
|
background: @menuTopTabActiveBg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.sidebar__wrap {
|
.sidebar__wrap {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: @menuWidth;
|
width: @menuWidth;
|
||||||
|
@ -10,6 +78,9 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
transition: width 0.2s;
|
transition: width 0.2s;
|
||||||
}
|
}
|
||||||
|
.sidebar__wrap--tab {
|
||||||
|
left: @menuTabWidth;
|
||||||
|
}
|
||||||
.sidebar__wrap--collapsed {
|
.sidebar__wrap--collapsed {
|
||||||
width: @menuMinWidth;
|
width: @menuMinWidth;
|
||||||
@{deep}(.anticon-item) {
|
@{deep}(.anticon-item) {
|
||||||
|
@ -76,10 +147,18 @@
|
||||||
}
|
}
|
||||||
// content样式
|
// content样式
|
||||||
}
|
}
|
||||||
|
.main__wrap--tab {
|
||||||
|
width: calc(~"100% - @{menuWidth} - @{menuTabWidth}");
|
||||||
|
left: @menuWidth + @menuTabWidth;
|
||||||
|
}
|
||||||
.main__wrap--collapsed {
|
.main__wrap--collapsed {
|
||||||
width: calc(~"100% - @{menuMinWidth}");
|
width: calc(~"100% - @{menuMinWidth}");
|
||||||
left: @menuMinWidth;
|
left: @menuMinWidth;
|
||||||
}
|
}
|
||||||
|
.main__wrap--tab--collapsed {
|
||||||
|
width: calc(~"100% - @{menuMinWidth} - @{menuTabWidth}");
|
||||||
|
left: @menuMinWidth + @menuTabWidth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeftTop模式
|
// LeftTop模式
|
||||||
|
@ -105,10 +184,20 @@
|
||||||
left: @menuWidth !important;
|
left: @menuWidth !important;
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
}
|
}
|
||||||
|
.header__wrap--tab--fixed {
|
||||||
|
width: calc(~"100% - @{menuWidth} - @{menuTabWidth}") !important;
|
||||||
|
}
|
||||||
|
.header__wrap--tab {
|
||||||
|
left: @menuWidth + @menuTabWidth !important;
|
||||||
|
}
|
||||||
.header__wrap--collapsed {
|
.header__wrap--collapsed {
|
||||||
width: calc(~"100% - @{menuMinWidth}") !important;
|
width: calc(~"100% - @{menuMinWidth}") !important;
|
||||||
left: @menuMinWidth !important;
|
left: @menuMinWidth !important;
|
||||||
}
|
}
|
||||||
|
.header__wrap--tab--collapsed {
|
||||||
|
width: calc(~"100% - @{menuMinWidth} - @{menuTabWidth}") !important;
|
||||||
|
left: @menuMinWidth + @menuTabWidth !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.app__wrap--Classic {
|
.app__wrap--Classic {
|
||||||
.header__wrap--fixed {
|
.header__wrap--fixed {
|
||||||
|
|
|
@ -17,6 +17,7 @@ export interface AppState {
|
||||||
userInfo: String
|
userInfo: String
|
||||||
greyMode: Boolean
|
greyMode: Boolean
|
||||||
showBackTop: Boolean
|
showBackTop: Boolean
|
||||||
|
showMenuTab: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Module({ dynamic: true, namespaced: true, store, name: 'app' })
|
@Module({ dynamic: true, namespaced: true, store, name: 'app' })
|
||||||
|
@ -36,6 +37,7 @@ class App extends VuexModule implements AppState {
|
||||||
public userInfo = 'userInfo' // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突
|
public userInfo = 'userInfo' // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突
|
||||||
public greyMode = false // 是否开始灰色模式,用于特殊悼念日
|
public greyMode = false // 是否开始灰色模式,用于特殊悼念日
|
||||||
public showBackTop = true // 是否显示回到顶部
|
public showBackTop = true // 是否显示回到顶部
|
||||||
|
public showMenuTab = false // 是否固定一级菜单
|
||||||
|
|
||||||
@Mutation
|
@Mutation
|
||||||
private SET_COLLAPSED(collapsed: boolean): void {
|
private SET_COLLAPSED(collapsed: boolean): void {
|
||||||
|
@ -93,6 +95,10 @@ class App extends VuexModule implements AppState {
|
||||||
private SET_SHOWBACKTOP(showBackTop: boolean): void {
|
private SET_SHOWBACKTOP(showBackTop: boolean): void {
|
||||||
this.showBackTop = showBackTop
|
this.showBackTop = showBackTop
|
||||||
}
|
}
|
||||||
|
@Mutation
|
||||||
|
private SET_SHOWMENUTAB(showMenuTab: boolean): void {
|
||||||
|
this.showMenuTab = showMenuTab
|
||||||
|
}
|
||||||
|
|
||||||
@Action
|
@Action
|
||||||
public SetCollapsed(collapsed: boolean): void {
|
public SetCollapsed(collapsed: boolean): void {
|
||||||
|
@ -150,6 +156,10 @@ class App extends VuexModule implements AppState {
|
||||||
public SetShowBackTop(showBackTop: boolean): void {
|
public SetShowBackTop(showBackTop: boolean): void {
|
||||||
this.SET_SHOWBACKTOP(showBackTop)
|
this.SET_SHOWBACKTOP(showBackTop)
|
||||||
}
|
}
|
||||||
|
@Action
|
||||||
|
public SetShowMenuTab(showMenuTab: boolean): void {
|
||||||
|
this.SET_SHOWMENUTAB(showMenuTab)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const appStore = getModule<App>(App)
|
export const appStore = getModule<App>(App)
|
||||||
|
|
|
@ -17,6 +17,8 @@ export interface PermissionState {
|
||||||
routers: AppRouteRecordRaw[]
|
routers: AppRouteRecordRaw[]
|
||||||
addRouters: AppRouteRecordRaw[]
|
addRouters: AppRouteRecordRaw[]
|
||||||
isAddRouters: boolean
|
isAddRouters: boolean
|
||||||
|
activeTab: string
|
||||||
|
menuTabRouters: AppRouteRecordRaw[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@Module({ dynamic: true, namespaced: true, store, name: 'permission' })
|
@Module({ dynamic: true, namespaced: true, store, name: 'permission' })
|
||||||
|
@ -24,6 +26,8 @@ class Permission extends VuexModule implements PermissionState {
|
||||||
public routers = [] as any[]
|
public routers = [] as any[]
|
||||||
public addRouters = [] as any[]
|
public addRouters = [] as any[]
|
||||||
public isAddRouters = false
|
public isAddRouters = false
|
||||||
|
public menuTabRouters = [] as any[]
|
||||||
|
public activeTab = ''
|
||||||
|
|
||||||
@Mutation
|
@Mutation
|
||||||
private SET_ROUTERS(routers: AppRouteRecordRaw[]): void {
|
private SET_ROUTERS(routers: AppRouteRecordRaw[]): void {
|
||||||
|
@ -44,6 +48,14 @@ class Permission extends VuexModule implements PermissionState {
|
||||||
private SET_ISADDROUTERS(state: boolean): void {
|
private SET_ISADDROUTERS(state: boolean): void {
|
||||||
this.isAddRouters = state
|
this.isAddRouters = state
|
||||||
}
|
}
|
||||||
|
@Mutation
|
||||||
|
private SET_MENUTABROUTERS(routers: AppRouteRecordRaw[]): void {
|
||||||
|
this.menuTabRouters = routers
|
||||||
|
}
|
||||||
|
@Mutation
|
||||||
|
private SET_ACTIVETAB(activeTab: string): void {
|
||||||
|
this.activeTab = activeTab
|
||||||
|
}
|
||||||
|
|
||||||
@Action
|
@Action
|
||||||
public GenerateRoutes(): Promise<unknown> {
|
public GenerateRoutes(): Promise<unknown> {
|
||||||
|
@ -66,6 +78,14 @@ class Permission extends VuexModule implements PermissionState {
|
||||||
public SetIsAddRouters(state: boolean): void {
|
public SetIsAddRouters(state: boolean): void {
|
||||||
this.SET_ISADDROUTERS(state)
|
this.SET_ISADDROUTERS(state)
|
||||||
}
|
}
|
||||||
|
@Action
|
||||||
|
public SetMenuTabRouters(routers: AppRouteRecordRaw[]): void {
|
||||||
|
this.SET_MENUTABROUTERS(routers)
|
||||||
|
}
|
||||||
|
@Action
|
||||||
|
public SetAcitveTab(activeTab: string): void {
|
||||||
|
this.SET_ACTIVETAB(activeTab)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 路由过滤,主要用于权限控制
|
// 路由过滤,主要用于权限控制
|
||||||
|
|
|
@ -25,6 +25,21 @@
|
||||||
@topSMenuHover: #2d8cf0;
|
@topSMenuHover: #2d8cf0;
|
||||||
@topSMenuActiveText: #2d8cf0;
|
@topSMenuActiveText: #2d8cf0;
|
||||||
|
|
||||||
|
// meunTab
|
||||||
|
@menuTabWidth: 90px;
|
||||||
|
@menuTabItemHeight: 70px;
|
||||||
|
@menuTabBg: #fff;
|
||||||
|
@menuTabText: black;
|
||||||
|
@menuTabActiveBg: #2d8cf0;
|
||||||
|
@menuTabActiveText: #fff;
|
||||||
|
|
||||||
|
// menuTopTab
|
||||||
|
@menuTopTabWidth: 120px;
|
||||||
|
@menuTopTabBg: #fff;
|
||||||
|
@menuTopTabText: black;
|
||||||
|
@menuTopTabActiveBg: #2d8cf0;
|
||||||
|
@menuTopTabActiveText: #fff;
|
||||||
|
|
||||||
// navbar
|
// navbar
|
||||||
@navbarHeight: 40px;
|
@navbarHeight: 40px;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ export interface IScssVariables {
|
||||||
subMenuHover: string
|
subMenuHover: string
|
||||||
menuWidth: string
|
menuWidth: string
|
||||||
menuMinWidth: string
|
menuMinWidth: string
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const variables: IScssVariables
|
export const variables: IScssVariables
|
||||||
|
|
Loading…
Reference in New Issue