进行优化

This commit is contained in:
zouzhibing 2022-08-24 16:48:03 +08:00
parent 5740774c2b
commit 5b9bd73340
6 changed files with 294 additions and 3 deletions

View File

@ -0,0 +1,49 @@
<template>
<component :is="type" v-bind="linkProps(to)">
<slot />
</component>
</template>
<script lang="ts">
import { isExternal } from '@/utils/validate.js'
export default {
props: {
to: {
type: String,
required: true,
},
},
computed: {
isExternal() {
return isExternal(this.to)
},
type() {
if (this.isExternal) {
return 'a'
}
return 'router-link'
},
},
methods: {
linkProps(to) {
if (this.isExternal) {
return {
href: to,
target: '_blank',
rel: 'noopener',
}
}
return {
to: to,
}
},
},
}
</script>
<style lang="scss" scoped>
a {
text-decoration: none;
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<div class="sidebar-logo-container" >
<router-link key="collapse" class="sidebar-logo-link" to="/">
<img :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title" v-if="!isCollapse">{{ title }} </h1>
</router-link>
</div>
</template>
<script lang="ts" setup>
import { computed, reactive, ref } from 'vue'
import { useStore } from 'vuex' // useStore ===vue2.0this.$store
import logo from '@/assets/logo.png'
const store = useStore()
const title = ref<string>('Vue Admin Perfect')
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
</script>
<style lang="scss" scoped>
//.sidebarLogoFade-enter-active {
// transition: opacity 1.5s;
//}
//
//.sidebarLogoFade-enter,
//.sidebarLogoFade-leave-to {
// opacity: 0;
//}
.sidebar-logo-container {
position: relative;
width: 100%;
height: 60px;
line-height: 60px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
height: 100%;
width: 100%;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>

View File

@ -0,0 +1,56 @@
<template>
<el-menu
:default-active="activeMenu"
active-text-color="#ffd04b"
background-color="#304156"
text-color="#fff"
:mode="mode"
:collapse-transition="false"
class="el-menu-vertical-demo"
:collapse="isCollapse"
>
<sidebar-item
v-for="route in permission_routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</template>
<script lang="ts" setup>
import SidebarItem from './SidebarItem.vue'
import logo from './Logo.vue'
import { useRoute } from 'vue-router'
import { useStore, mapGetters } from 'vuex' // useStore ===vue2.0this.$store
import { ref, computed } from 'vue'
// setupstore
const store = useStore()
const route = useRoute()
//
const permission_routes = computed(() => {
console.log('permission_routes', store.state.permission.routes)
return store.state.permission.routes
})
const activeMenu = computed(() => {
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
})
//
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
//
const mode = computed(() => {
return store.state.setting.mode
})
</script>

View File

@ -0,0 +1,79 @@
<template>
<template v-if="!item.hidden">
<template v-if="!item.alwaysShow && hasOneShowingChild(item.children, item)">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)">
<el-icon :size="20">
<component :is="onlyOneChild?.meta.icon"></component>
</el-icon>
<template #title>{{ onlyOneChild.meta && onlyOneChild.meta.title }}</template>
</el-menu-item>
</app-link>
</template>
<el-sub-menu :index="resolvePath(item.path)" v-else popper-append-to-body>
<template #title>
<el-icon :size="20"> <component :is="item.meta?.icon"></component></el-icon>
<span>{{ item.meta && item.meta.title }}</span>
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:item="child"
:base-path="resolvePath(child.path)"
/>
</el-sub-menu>
</template>
</template>
<script lang="ts" setup>
import { isExternal } from '@/utils/validate.js'
import AppLink from './Link.vue'
import path from 'path-browserify'
import { ref, computed } from 'vue'
const props = defineProps({
item: {
type: Object,
required: true,
},
basePath: {
type: String,
default: '',
},
})
const onlyOneChild = ref(null)
const hasOneShowingChild = (children = [], parent) => {
const showingChildren = children.filter((item) => {
//
if (item.hidden) {
return false
} else {
// 使
onlyOneChild.value = item
return true
}
})
//
if (showingChildren.length === 1) {
return true
}
//
if (showingChildren.length === 0) {
onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
return true
}
return false
}
const resolvePath = (routePath) => {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(props.basePath)) {
return props.basePath
}
return path.resolve(props.basePath, routePath)
}
</script>

View File

@ -0,0 +1,36 @@
<template>
<div :class="{ 'has-logo': isCollapse }">
<logo :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<menu/>
</el-scrollbar>
</div>
</template>
<script lang="ts" setup>
import Menu from './components/Menu.vue'
import logo from './components/Logo.vue'
import { useStore, mapGetters } from 'vuex' // useStore ===vue2.0this.$store
import { ref, computed } from 'vue'
// setupstore
const store = useStore()
//
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
</script>
<style lang="scss">
.el-menu-vertical-demo:not(.el-menu--collapse) {
//width: 200px;
height: 100%;
}
.crollbar-wrapper {
height: 100%;
.el-scrollbar__view {
height: 100%;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="g-container-layout" :class="classObj"> <div class="g-container-layout" :class="classObj">
<div v-if="device === 'mobile' && !isCollapse" class="drawer-bg" @click="handleClickOutside" /> <div v-if="device === 'mobile' && !isCollapse" class="drawer-bg" @click="handleClickOutside" />
<sidebar class="sidebar-container" v-if="mode === 'vertical'" /> <!-- <sidebar class="sidebar-container" v-if="mode === 'vertical'" />-->
<div <div
class="main-container" class="main-container"
:class="{ :class="{
@ -18,7 +18,7 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, ref } from 'vue' import { computed, defineComponent, ref } from 'vue'
import Sidebar from './Sidebar/index.vue' // import Sidebar from './Sidebar/index.vue'
import UHeader from './components/UHeader/index.vue' import UHeader from './components/UHeader/index.vue'
import AppMain from './components/AppMain.vue' import AppMain from './components/AppMain.vue'
import { useResizeHandler } from './hooks/useResizeHandler' import { useResizeHandler } from './hooks/useResizeHandler'
@ -28,7 +28,7 @@
export default defineComponent({ export default defineComponent({
name: 'layout', name: 'layout',
components: { components: {
Sidebar, // Sidebar,
UHeader, UHeader,
AppMain, AppMain,
}, },