|
|
@@ -1,13 +1,277 @@
|
|
|
<template>
|
|
|
- <span>123</span>
|
|
|
+ <div class="layout">
|
|
|
+ <div class="layout-left">
|
|
|
+ <div class="layout-logo">
|
|
|
+ <img src="" alt="">
|
|
|
+ </div>
|
|
|
+ <div class="layout-menu">
|
|
|
+ <el-menu class="layout-menu-inner" :collapse="isCollapse" :default-active="menuActive+''">
|
|
|
+ <template v-for="(route,index) in menuRouter">
|
|
|
+ <el-menu-item :index="index+''" @click="goto(route.path)" :key="route.path">
|
|
|
+ <i :class="[route.meta.icon,'icon']"></i>
|
|
|
+ <span slot="title">{{ route.meta.title }}</span>
|
|
|
+ </el-menu-item>
|
|
|
+ </template>
|
|
|
+ </el-menu>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="layout-right">
|
|
|
+ <div class="layout-breadcrumb">
|
|
|
+ <div :class="['icon',isCollapse?'collapse':'']" @click="changeCollapse">
|
|
|
+ <div class="icon-1"></div>
|
|
|
+ <div class="icon-2"></div>
|
|
|
+ <div class="icon-3"></div>
|
|
|
+ </div>
|
|
|
+ <el-breadcrumb separator="/">
|
|
|
+ <el-breadcrumb-item v-for="item in breadcrumb" :key="item.path">
|
|
|
+ <router-link :to="item.path||'/'">{{ item.meta.title }}</router-link>
|
|
|
+ </el-breadcrumb-item>
|
|
|
+ </el-breadcrumb>
|
|
|
+ </div>
|
|
|
+ <div class="layout-body">
|
|
|
+ <div class="body-inner" :class="{'animation':isAnimation}">
|
|
|
+ <router-view class="view-inner" />
|
|
|
+ </div>
|
|
|
+ <div class="body-inner trans" :class="{'animation':isAnimation}" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { isCoordSupported } from 'echarts/lib/component/dataZoom/helper'
|
|
|
+
|
|
|
export default {
|
|
|
- name: "layout"
|
|
|
+ name: 'Layout',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ isCollapse: false,
|
|
|
+ collapse: {
|
|
|
+ minWidth: 0,
|
|
|
+ maxWidth: 0,
|
|
|
+ currentWidth: 0
|
|
|
+ },
|
|
|
+ menuRouter: [],
|
|
|
+ menuActive: 0,
|
|
|
+ breadcrumb: [],
|
|
|
+ isAnimation: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.refreshRoute()
|
|
|
+ this.initGuards()
|
|
|
+ window.addEventListener('resize', () => {
|
|
|
+ this.collapse.maxWidth = 0
|
|
|
+ this.collapse.minWidth = 0
|
|
|
+ this.changeCollapse()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ changeCollapse() {
|
|
|
+ this.isCollapse = !this.isCollapse
|
|
|
+ let layoutBody = document.getElementsByClassName('el-table')[0]
|
|
|
+ layoutBody.style.transitionDuration = '360ms'
|
|
|
+ layoutBody.style.transitionTimingFunction = 'linear'
|
|
|
+ if (this.isCollapse) {
|
|
|
+ if (this.collapse.minWidth === 0) {
|
|
|
+ this.collapse.minWidth = layoutBody.offsetWidth
|
|
|
+ }
|
|
|
+ if (this.collapse.maxWidth) {
|
|
|
+ layoutBody.style.width = this.collapse.maxWidth + 'px'
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (this.collapse.maxWidth === 0) {
|
|
|
+ this.collapse.maxWidth = layoutBody.offsetWidth
|
|
|
+ }
|
|
|
+ if (this.collapse.minWidth) {
|
|
|
+ layoutBody.style.width = this.collapse.minWidth + 'px'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ goto(path) {
|
|
|
+ if ('/' + path === this.$route.path) { return }
|
|
|
+ this.$router.push(path)
|
|
|
+ this.refreshRoute()
|
|
|
+ },
|
|
|
+ initGuards() {
|
|
|
+ this.$router.afterEach((to, from, next) => {
|
|
|
+ this.refreshRoute()
|
|
|
+ })
|
|
|
+ this.$router.beforeEach((to, from, next) => {
|
|
|
+ this.isAnimation = true
|
|
|
+ setTimeout(() => {
|
|
|
+ this.isAnimation = false
|
|
|
+ next()
|
|
|
+ }, 400)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ refreshRoute() {
|
|
|
+ this.menuRouter = this.$router.options.routes[0].children
|
|
|
+ this.breadcrumb = this.$route.matched
|
|
|
+ this.menuRouter.forEach((item, index) => {
|
|
|
+ if ('/' + item.path === this.$route.path) {
|
|
|
+ this.menuActive = index
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
-<style scoped>
|
|
|
-
|
|
|
+<style scoped lang="scss">
|
|
|
+@use '@/styles/variables.scss' as *;
|
|
|
+.layout{
|
|
|
+ background: #F9FAFB;
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: auto 1fr;
|
|
|
+ .layout-left,.layout-right{
|
|
|
+ display: grid;
|
|
|
+ grid-template-rows: 80px 1fr;
|
|
|
+ }
|
|
|
+ .layout-left{
|
|
|
+ position: relative;
|
|
|
+ z-index: 1;
|
|
|
+ box-shadow: 0 4px 6px -4px #00000022,0 10px 15px -3px #00000022;
|
|
|
+ background: white;
|
|
|
+ .layout-logo{
|
|
|
+ border-bottom: 1px solid #E5E7EB;
|
|
|
+ height: 80px;
|
|
|
+ }
|
|
|
+ .layout-menu{
|
|
|
+ .layout-menu-inner{
|
|
|
+ border-right: unset;
|
|
|
+ .el-menu-item{
|
|
|
+ transition-duration: 300ms;
|
|
|
+ color: $menuText;
|
|
|
+ position: relative;
|
|
|
+ border-right: 0px solid transparent;
|
|
|
+ .icon{
|
|
|
+ color: inherit;
|
|
|
+ font-size: 22px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ &.is-active{
|
|
|
+ color: $menuActiveText;
|
|
|
+ background: $menuActiveBg;
|
|
|
+ border-right: 4px solid $menuActive;
|
|
|
+ }
|
|
|
+ &.hover{
|
|
|
+ background: $menuHover;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &:not(.el-menu--collapse) {
|
|
|
+ width: 300px;
|
|
|
+ min-height: 400px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .layout-right{
|
|
|
+ .layout-breadcrumb{
|
|
|
+ grid-gap: 24px;
|
|
|
+ padding: 0 24px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background: white;
|
|
|
+ border-bottom: 1px solid #E5E7EB;
|
|
|
+ height: 80px;
|
|
|
+ .icon{
|
|
|
+ transition-duration: 300ms;
|
|
|
+ cursor: pointer;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 10px 8px;
|
|
|
+ width: 36px;
|
|
|
+ height: 36px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ grid-gap: 3px;
|
|
|
+ border-radius: 6px;
|
|
|
+ .icon-1,.icon-2,.icon-3{
|
|
|
+ transition-duration: 300ms;
|
|
|
+ width: 20px;
|
|
|
+ height: 3px;
|
|
|
+ background: $menuText;
|
|
|
+ border-radius: 1.5px;
|
|
|
+ }
|
|
|
+ &:hover{
|
|
|
+ grid-gap: 0;
|
|
|
+ .icon-1,.icon-2,.icon-3{
|
|
|
+ transform-origin: 1.5px 50%;
|
|
|
+ }
|
|
|
+ .icon-1{
|
|
|
+ margin-bottom: -3px;
|
|
|
+ transform: rotate(45deg);
|
|
|
+ width: 16px;
|
|
|
+ }
|
|
|
+ .icon-2{
|
|
|
+ transform: scaleX(0);
|
|
|
+ }
|
|
|
+ .icon-3{
|
|
|
+ width: 16px;
|
|
|
+ margin-top: -3px;
|
|
|
+ transform: rotate(-45deg);
|
|
|
+ }
|
|
|
+ &.collapse{
|
|
|
+ .icon-1,.icon-2,.icon-3{
|
|
|
+ transform-origin: calc(100% - 1.5px) 50%;
|
|
|
+ }
|
|
|
+ .icon-1{
|
|
|
+ transform: rotate(-45deg);
|
|
|
+ }
|
|
|
+ .icon-3{
|
|
|
+ transform: rotate(45deg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .layout-body{
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ padding: 24px;
|
|
|
+ .body-inner{
|
|
|
+ position: relative;
|
|
|
+ border-radius: 16px;
|
|
|
+ width: 100%;
|
|
|
+ background: white;
|
|
|
+ height: 100%;
|
|
|
+ box-shadow: 0 1px 4px 0 #00000022;
|
|
|
+ transition-duration: 0ms;
|
|
|
+ opacity: 1;
|
|
|
+ transform: scale(1);
|
|
|
+ .view-inner{
|
|
|
+ padding: 16px;
|
|
|
+ animation: viewIn 200ms;
|
|
|
+ }
|
|
|
+ &.animation{
|
|
|
+ transition-duration: 400ms;
|
|
|
+ opacity: 0;
|
|
|
+ transform: scale(0.9);
|
|
|
+ }
|
|
|
+ &.trans{
|
|
|
+ pointer-events: none;
|
|
|
+ position: absolute;
|
|
|
+ top: 24px;
|
|
|
+ left: 24px;
|
|
|
+ width: calc(100% - 48px);
|
|
|
+ height: calc(100% - 48px);
|
|
|
+ transform: translateY(820px) scale(1);
|
|
|
+ opacity: 0;
|
|
|
+ &.animation{
|
|
|
+ opacity: 1;
|
|
|
+ transform: translateY(0) scale(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @keyframes viewIn {
|
|
|
+ from{opacity: 0}
|
|
|
+ to{opacity: 1}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
</style>
|