whj 7 tháng trước cách đây
mục cha
commit
318ad0262c

+ 130 - 0
src/components/GlobalHeader/MixGlobalHeader.vue

@@ -0,0 +1,130 @@
+<template>
+  <transition name="showHeader">
+    <div v-if="visible" class="header-animat">
+      <a-layout-header
+        v-if="visible"
+        :class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed', ]"
+        :style="{ padding: '0' }">
+        <div :class="['top-nav-header-index', theme]">
+          <div class="header-index-wide">
+            <div class="header-index-left">
+              <logo class="top-nav-header" :show-title="device !== 'mobile'"/>
+              <s-menu :class="theme === 'dark' ?'future-menu':''" v-if="device !== 'mobile'" mode="horizontal" :menu="headerMenus" :theme="theme" />
+            </div>
+            <user-menu class="header-index-right"></user-menu>
+          </div>
+        </div>
+      </a-layout-header>
+    </div>
+  </transition>
+</template>
+
+<script>
+import UserMenu from '../tools/UserMenu'
+import SMenu from '../Menu/mixMenu'
+import Logo from '../tools/Logo'
+import { mixin } from '@/utils/mixin'
+
+export default {
+  name: 'GlobalHeader',
+  components: {
+    UserMenu,
+    SMenu,
+    Logo
+  },
+  mixins: [mixin],
+  props: {
+    mode: {
+      type: String,
+      // sidemenu, topmenu
+      default: 'sidemenu'
+    },
+    menus: {
+      type: Array,
+      required: true
+    },
+    theme: {
+      type: String,
+      required: false,
+      default: 'dark'
+    },
+    collapsed: {
+      type: Boolean,
+      required: false,
+      default: false
+    },
+    device: {
+      type: String,
+      required: false,
+      default: 'desktop'
+    }
+  },
+  computed: {
+    headerMenus () {
+      // console.log(this.menus)
+      return this.menus.map(item => {
+        return item
+      })
+    }
+  },
+  data () {
+    return {
+      visible: true,
+      oldScrollTop: 0
+    }
+  },
+  mounted () {
+    document.addEventListener('scroll', this.handleScroll, { passive: true })
+  },
+  methods: {
+    handleScroll () {
+      if (!this.autoHideHeader) {
+        return
+      }
+
+      const scrollTop = document.body.scrollTop + document.documentElement.scrollTop
+      if (!this.ticking) {
+        this.ticking = true
+        requestAnimationFrame(() => {
+          if (this.oldScrollTop > scrollTop) {
+            this.visible = true
+          } else if (scrollTop > 300 && this.visible) {
+            this.visible = false
+          } else if (scrollTop < 300 && !this.visible) {
+            this.visible = true
+          }
+          this.oldScrollTop = scrollTop
+          this.ticking = false
+        })
+      }
+    },
+    toggle () {
+      this.$emit('toggle')
+    }
+  },
+  beforeDestroy () {
+    document.body.removeEventListener('scroll', this.handleScroll, true)
+  }
+}
+</script>
+
+<style lang="less">
+@import '../index.less';
+
+.header-animat{
+  position: relative;
+  z-index: @ant-global-header-zindex;
+}
+.showHeader-enter-active {
+  transition: all 0.25s ease;
+}
+.showHeader-leave-active {
+  transition: all 0.5s ease;
+}
+.showHeader-enter, .showHeader-leave-to {
+  opacity: 0;
+}
+  .future-menu>.ant-menu-item-selected>a{
+    color: #fff !important;
+  }
+</style>

+ 175 - 0
src/components/Menu/mixMenu.js

@@ -0,0 +1,175 @@
+import Menu from 'ant-design-vue/es/menu'
+import Icon from 'ant-design-vue/es/icon'
+
+const { Item, SubMenu } = Menu
+
+export default {
+  name: 'SMenu',
+  props: {
+    menu: {
+      type: Array,
+      required: true
+    },
+    theme: {
+      type: String,
+      required: false,
+      default: 'dark'
+    },
+    mode: {
+      type: String,
+      required: false,
+      default: 'inline'
+    },
+    collapsed: {
+      type: Boolean,
+      required: false,
+      default: false
+    }
+  },
+  data () {
+    return {
+      openKeys: [],
+      selectedKeys: [],
+      cachedOpenKeys: []
+    }
+  },
+  computed: {
+    rootSubmenuKeys: vm => {
+      const keys = []
+      vm.menu.forEach(item => keys.push(item.path))
+      return keys
+    }
+  },
+  mounted () {
+    this.updateMenu()
+  },
+  watch: {
+    collapsed (val) {
+      if (val) {
+        this.cachedOpenKeys = this.openKeys.concat()
+        this.openKeys = []
+      } else {
+        this.openKeys = this.cachedOpenKeys
+      }
+    },
+    $route: function () {
+      this.updateMenu()
+    }
+  },
+  methods: {
+    // select menu item
+    onOpenChange (openKeys) {
+      // 在水平模式下时执行,并且不再执行后续
+      if (this.mode === 'horizontal') {
+        this.openKeys = openKeys
+      }
+    },
+    updateMenu () {
+      const routes = this.$route.matched.concat()
+      const { hidden } = this.$route.meta
+      console.log(routes)
+      if (routes.length >= 3 && hidden) {
+        routes.pop()
+        this.selectedKeys = [routes[routes.length - 1].name]
+      } else {
+        this.selectedKeys = [routes[1].name]
+      }
+      this.$store.commit('SET_ACTIVE_MENU', this.selectedKeys[0])
+      const openKeys = []
+      if (this.mode === 'inline') {
+        routes.forEach(item => {
+          openKeys.push(item.path)
+        })
+      }
+
+      this.collapsed ? (this.cachedOpenKeys = openKeys) : (this.openKeys = openKeys)
+    },
+
+    // render
+    renderItem (menu) {
+      if (!menu.hidden) {
+        return this.renderMenuItem(menu)
+      }
+      return null
+    },
+    renderMenuItem (menu) {
+      const target = menu.meta.target || null
+      const tag = target && 'a' || 'router-link'
+      const props = { to: { name: menu.name } }
+      const attrs = { href: menu.path, target: menu.meta.target }
+
+      if (menu.children && menu.hideChildrenInMenu) {
+        // 把有子菜单的 并且 父菜单是要隐藏子菜单的
+        // 都给子菜单增加一个 hidden 属性
+        // 用来给刷新页面时, selectedKeys 做控制用
+        menu.children.forEach(item => {
+          item.meta = Object.assign(item.meta, { hidden: true })
+        })
+      }
+
+      return (
+        <Item {...{ key: menu.name }}>
+          <tag {...{ props, attrs }}>
+            {this.renderIcon(menu.meta.icon)}
+            <span>{menu.meta.title}</span>
+          </tag>
+        </Item>
+      )
+    },
+    renderSubMenu (menu) {
+      const itemArr = []
+      if (!menu.hideChildrenInMenu) {
+        menu.children.forEach(item => itemArr.push(this.renderItem(item)))
+      }
+      return (
+        <SubMenu {...{ key: menu.name }}>
+          <span slot="title">
+            {this.renderIcon(menu.meta.icon)}
+            <span>{menu.meta.title}</span>
+          </span>
+          {itemArr}
+        </SubMenu>
+      )
+    },
+    renderIcon (icon) {
+      if (icon === 'none' || icon === undefined) {
+        return null
+      }
+      const props = {}
+      typeof (icon) === 'object' ? props.component = icon : props.type = icon
+      return (
+        <Icon {... { props } }/>
+      )
+    }
+  },
+
+  render () {
+    const { mode, theme, menu } = this
+    const props = {
+      mode: mode,
+      theme: theme,
+      openKeys: this.openKeys
+    }
+    const on = {
+      select: obj => {
+        this.selectedKeys = obj.selectedKeys
+        this.$store.commit('SET_ACTIVE_MENU', this.selectedKeys[0])
+        this.$emit('select', obj)
+      },
+      openChange: this.onOpenChange
+    }
+
+    const menuTree = menu.map(item => {
+      if (item.hidden) {
+        return null
+      }
+      return this.renderItem(item)
+    })
+    // {...{ props, on: on }}
+    return (
+      <Menu vModel={this.selectedKeys} {...{ props, on: on }}>
+        {menuTree}
+      </Menu>
+    )
+  }
+}

+ 116 - 79
src/components/SettingDrawer/SettingDrawer.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="setting-drawer" ref="settingDrawer">
     <div class="setting-drawer-index-handle" @click="toggle">
-      <a-icon type="setting" v-if="!visible"/>
-      <a-icon type="close" v-else/>
+      <a-icon type="setting" v-if="!visible" />
+      <a-icon type="close" v-else />
     </div>
     <a-drawer
       width="300"
@@ -10,8 +10,7 @@
       @close="onClose"
       :closable="false"
       :visible="visible"
-      :handle="handle"
-    >
+      :handle="handle">
       <div class="setting-drawer-index-content">
 
         <div :style="{ marginBottom: '24px' }">
@@ -25,7 +24,7 @@
               <div class="setting-drawer-index-item" @click="handleMenuTheme('dark')">
                 <img src="https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg" alt="dark">
                 <div class="setting-drawer-index-selectIcon" v-if="navTheme === 'dark'">
-                  <a-icon type="check"/>
+                  <a-icon type="check" />
                 </div>
               </div>
             </a-tooltip>
@@ -37,7 +36,7 @@
               <div class="setting-drawer-index-item" @click="handleMenuTheme('light')">
                 <img src="https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg" alt="light">
                 <div class="setting-drawer-index-selectIcon" v-if="navTheme !== 'dark'">
-                  <a-icon type="check"/>
+                  <a-icon type="check" />
                 </div>
               </div>
             </a-tooltip>
@@ -72,19 +71,29 @@
               <div class="setting-drawer-index-item" @click="handleLayout('sidemenu')">
                 <img src="https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg" alt="sidemenu">
                 <div class="setting-drawer-index-selectIcon" v-if="layoutMode === 'sidemenu'">
-                  <a-icon type="check"/>
+                  <a-icon type="check" />
                 </div>
               </div>
             </a-tooltip>
-
             <a-tooltip>
               <template slot="title">
                 顶部栏导航
               </template>
               <div class="setting-drawer-index-item" @click="handleLayout('topmenu')">
                 <img src="https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg" alt="topmenu">
-                <div class="setting-drawer-index-selectIcon" v-if="layoutMode !== 'sidemenu'">
-                  <a-icon type="check"/>
+                <div class="setting-drawer-index-selectIcon" v-if="layoutMode === 'topmenu'">
+                  <a-icon type="check" />
+                </div>
+              </div>
+            </a-tooltip>
+            <a-tooltip>
+              <template slot="title">
+                混合栏导航
+              </template>
+              <div class="setting-drawer-index-item" @click="handleLayout('mixmenu')">
+                <div class="mix"></div>
+                <div class="setting-drawer-index-selectIcon " v-if="layoutMode === 'mixmenu'">
+                  <a-icon type="check" />
                 </div>
               </div>
             </a-tooltip>
@@ -120,7 +129,7 @@
                   </a-tooltip>
                 </a-list-item-meta>
               </a-list-item>
-              <a-list-item >
+              <a-list-item>
                 <a-switch slot="actions" size="small" :disabled="(layoutMode === 'topmenu')" :defaultChecked="fixSiderbar" @change="handleFixSiderbar" />
                 <a-list-item-meta>
                   <div slot="title" :style="{ textDecoration: layoutMode === 'topmenu' ? 'line-through' : 'unset' }">固定侧边菜单</div>
@@ -186,12 +195,10 @@ export default {
     return {
       visible: false,
       colorList,
-      handle: <div/>
+      handle: <div />
     }
   },
-  watch: {
-
-  },
+  watch: {},
   mounted () {
     updateTheme(this.primaryColor)
     if (this.colorWeak !== config.colorWeak) {
@@ -238,13 +245,15 @@ export default {
     storage: 'local',
   }
 }`
-      this.$copyText(text).then(message => {
-        console.log('copy', message)
-        this.$message.success('复制完毕')
-      }).catch(err => {
-        console.log('copy.err', err)
-        this.$message.error('复制失败')
-      })
+      this.$copyText(text)
+        .then((message) => {
+          console.log('copy', message)
+          this.$message.success('复制完毕')
+        })
+        .catch((err) => {
+          console.log('copy.err', err)
+          this.$message.error('复制失败')
+        })
     },
     handleLayout (mode) {
       this.$store.dispatch('ToggleLayoutMode', mode)
@@ -278,75 +287,103 @@ export default {
 </script>
 
 <style lang="less" scoped>
+.setting-drawer-index-content {
+  .setting-drawer-index-blockChecbox {
+    display: flex;
 
-  .setting-drawer-index-content {
-
-    .setting-drawer-index-blockChecbox {
-      display: flex;
-
-      .setting-drawer-index-item {
-        margin-right: 16px;
-        position: relative;
-        border-radius: 4px;
-        cursor: pointer;
-
-        img {
-          width: 48px;
-        }
+    .setting-drawer-index-item {
+      margin-right: 16px;
+      position: relative;
+      border-radius: 4px;
+      cursor: pointer;
 
-        .setting-drawer-index-selectIcon {
-          position: absolute;
-          top: 0;
-          right: 0;
-          width: 100%;
-          padding-top: 15px;
-          padding-left: 24px;
-          height: 100%;
-          color: #1890ff;
-          font-size: 14px;
-          font-weight: 700;
-        }
+      img {
+        width: 48px;
       }
-    }
-    .setting-drawer-theme-color-colorBlock {
-      width: 20px;
-      height: 20px;
-      border-radius: 2px;
-      float: left;
-      cursor: pointer;
-      margin-right: 8px;
-      padding-left: 0px;
-      padding-right: 0px;
-      text-align: center;
-      color: #fff;
-      font-weight: 700;
 
-      i {
+      .setting-drawer-index-selectIcon {
+        position: absolute;
+        top: 0;
+        right: 0;
+        width: 100%;
+        padding-top: 15px;
+        padding-left: 24px;
+        height: 100%;
+        color: #1890ff;
         font-size: 14px;
+        font-weight: 700;
       }
     }
   }
-
-  .setting-drawer-index-handle {
-    position: fixed;
-    top: 240px;
-    background: #1890ff;
-    width: 48px;
-    height: 48px;
-    right: 10px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
+  .setting-drawer-theme-color-colorBlock {
+    width: 20px;
+    height: 20px;
+    border-radius: 2px;
+    float: left;
     cursor: pointer;
-    pointer-events: auto;
-    z-index: 1001;
+    margin-right: 8px;
+    padding-left: 0px;
+    padding-right: 0px;
     text-align: center;
-    font-size: 16px;
-    border-radius: 4px 0 0 4px;
+    color: #fff;
+    font-weight: 700;
 
     i {
-      color: rgb(255, 255, 255);
-      font-size: 20px;
+      font-size: 14px;
     }
   }
+}
+
+.setting-drawer-index-handle {
+  position: fixed;
+  top: 240px;
+  background: #1890ff;
+  width: 48px;
+  height: 48px;
+  right: 10px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  pointer-events: auto;
+  z-index: 1001;
+  text-align: center;
+  font-size: 16px;
+  border-radius: 4px 0 0 4px;
+
+  i {
+    color: rgb(255, 255, 255);
+    font-size: 20px;
+  }
+}
+.mix {
+  position: relative;
+  width: 48px;
+  height: 38px;
+  margin-top: 1px;
+  margin-right: 16px;
+  overflow: hidden;
+  background-color: #f0f2f5;
+  border-radius: 4px;
+  box-shadow: 0 1px 2.5px #0000002e;
+  cursor: pointer;
+  &::before {
+    content: '';
+    background-color: #fff;
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 33%;
+    height: 100%;
+  }
+  &::after {
+    content: '';
+    background-color: #001529;
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 25%;
+  }
+}
 </style>

+ 1 - 1
src/components/tools/Logo.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="logo">
     <router-link :to="{name:'dashboard'}">
-      <img src="~@/assets/logo.png" style="width:50px;height:40px" class="logo" alt="logo">
+      <img src="~@/assets/logo.png" style="width:150px;height:40px" class="logo" alt="logo">
       <h1 v-if="showTitle">设备管理系统</h1>
     </router-link>
   </div>

+ 103 - 137
src/layouts/BasicLayout.vue

@@ -1,61 +1,92 @@
 <template>
   <a-layout :class="['layout', device]">
-    <!-- SideMenu -->
-    <a-drawer
-      v-if="isMobile()"
-      placement="left"
-      :wrapClassName="`drawer-sider ${navTheme}`"
-      :closable="false"
-      :visible="collapsed"
-      @close="drawerClose"
-    >
+    <template v-if="!isMixMenu()">
+      <!-- SideMenu -->
+      <a-drawer
+        v-if="isMobile()"
+        placement="left"
+        :wrapClassName="`drawer-sider ${navTheme}`"
+        :closable="false"
+        :visible="collapsed"
+        @close="drawerClose"
+      >
+        <side-menu
+          mode="inline"
+          :menus="menus"
+          :theme="navTheme"
+          :collapsed="false"
+          :collapsible="true"
+        ></side-menu>
+      </a-drawer>
+
       <side-menu
+        v-else-if="isSideMenu()"
         mode="inline"
-        :menus="mobileMenus"
+        :menus="menus"
         :theme="navTheme"
-        :collapsed="false"
+        :collapsed="collapsed"
         :collapsible="true"
-        @menuSelect="menuSelect"
       ></side-menu>
-    </a-drawer>
 
-    <side-menu
-      v-else-if="isSideMenu()"
-      mode="inline"
-      :menus="menus"
-      :theme="navTheme"
-      :collapsed="collapsed"
-      :collapsible="true"
-    ></side-menu>
-
-    <a-layout :class="[layoutMode, `content-width-${contentWidth}`]" :style="{ paddingLeft: contentPaddingLeft, minHeight: '100vh' }">
-      <!-- layout header -->
-      <global-header
-        :mode="layoutMode"
-        :menus="menus"
-        :theme="navTheme"
-        :collapsed="collapsed"
-        :device="device"
-        @toggle="toggle"
-      />
+      <a-layout :class="[layoutMode, `content-width-${contentWidth}`]" :style="{ paddingLeft: contentPaddingLeft, minHeight: '100vh' }">
+        <!-- layout header -->
+        <global-header
+          :mode="layoutMode"
+          :menus="menus"
+          :theme="navTheme"
+          :collapsed="collapsed"
+          :device="device"
+          @toggle="toggle"
+        />
 
-      <!-- layout content -->
-      <a-layout-content :style="{ height: '100%', margin: '24px 24px 0', paddingTop: fixedHeader ? '64px' : '0' }">
-        <multi-tab v-if="multiTab"></multi-tab>
-        <transition name="page-transition">
-          <route-view />
-        </transition>
-      </a-layout-content>
+        <!-- layout content -->
+        <a-layout-content :style="{ height: '100%', margin: '24px 24px 0', paddingTop: fixedHeader ? '64px' : '0' }">
+          <multi-tab v-if="multiTab"></multi-tab>
+          <transition name="page-transition">
+            <route-view />
+          </transition>
+        </a-layout-content>
 
-      <!-- layout footer -->
-      <a-layout-footer>
-        <global-footer />
-      </a-layout-footer>
+        <!-- layout footer -->
+        <a-layout-footer>
+          <global-footer />
+        </a-layout-footer>
 
-      <!-- Setting Drawer (show in development mode) -->
-      <!--      <setting-drawer v-if="!production"></setting-drawer>-->
-      <setting-drawer></setting-drawer>
-    </a-layout>
+        <!-- Setting Drawer (show in development mode) -->
+        <!--      <setting-drawer v-if="!production"></setting-drawer>-->
+        <setting-drawer></setting-drawer>
+      </a-layout>
+    </template>
+    <template v-else>
+      <a-layout :class="[layoutMode, `content-width-${contentWidth}`]" :style="{ paddingLeft: contentPaddingLeft, minHeight: '100vh' }">
+        <!-- layout header -->
+        <MixGlobalHeader
+          :mode="layoutMode"
+          :menus="mainMenu.find(item => item.path === '/').children"
+          :theme="navTheme"
+          :collapsed="collapsed"
+          :device="device"
+          @toggle="toggle"
+        />
+        <!-- layout content -->
+        <a-layout-content :style="{ height: '100%', margin: '24px 24px 0', paddingTop: fixedHeader ? '64px' : '0' }">
+          <multi-tab v-if="multiTab"></multi-tab>
+          <transition name="page-transition">
+            <SideMenuRouteView
+              :collapsed="collapsed"
+              :menus="mixMenu"
+              :theme="navTheme" />
+          </transition>
+        </a-layout-content>
+        <!-- layout footer -->
+        <a-layout-footer>
+          <global-footer />
+        </a-layout-footer>
+        <!-- Setting Drawer (show in development mode) -->
+        <!--      <setting-drawer v-if="!production"></setting-drawer>-->
+        <setting-drawer></setting-drawer>
+      </a-layout>
+    </template>
   </a-layout>
 
 </template>
@@ -67,8 +98,10 @@ import { mixin, mixinDevice } from '@/utils/mixin'
 import config from '@/config/defaultSettings'
 
 import RouteView from './RouteView'
+import SideMenuRouteView from './SideMenuRouteView'
 import SideMenu from '@/components/Menu/SideMenu'
 import GlobalHeader from '@/components/GlobalHeader'
+import MixGlobalHeader from '@/components/GlobalHeader/MixGlobalHeader.vue'
 import GlobalFooter from '@/components/GlobalFooter'
 import SettingDrawer from '@/components/SettingDrawer'
 
@@ -80,46 +113,14 @@ export default {
     SideMenu,
     GlobalHeader,
     GlobalFooter,
+    MixGlobalHeader,
+    SideMenuRouteView,
     SettingDrawer
   },
   data () {
     return {
       production: config.production,
       collapsed: false,
-      menus: [],
-      analysisFinance: {
-        'path': '/mobile/analysisFinance',
-        'name': 'MobileAnalysisFinance',
-        'meta': {
-          'title': '财务指标',
-          'keepAlive': false,
-          'hiddenHeaderContent': false,
-          'target': null,
-          'permission': null
-        }
-      },
-      analysisFinancing: {
-        'path': '/mobile/analysisFinancing',
-        'name': 'MobileAnalysisFinancing',
-        'meta': {
-          'title': '融资指标',
-          'keepAlive': false,
-          'hiddenHeaderContent': false,
-          'target': null,
-          'permission': null
-        }
-      },
-      analysisInvest: {
-        'path': '/mobile/analysisInvest',
-        'name': 'MobileAnalysisInvest',
-        'meta': {
-          'title': '投资指标',
-          'keepAlive': false,
-          'hiddenHeaderContent': false,
-          'target': null,
-          'permission': null
-        }
-      },
       analysisLiquidate: {
         'path': '/mobile/analysisLiquidate',
         'name': 'MobileAnalysisLiquidate',
@@ -131,38 +132,28 @@ export default {
           'permission': null
         }
       },
-      mobileMenus: [
-        {
-          'path': '/dashboard',
-          'name': 'dashboard',
-          'component': {
-            'name': 'RouteView',
-            'props': {
-              'keepAlive': {
-                'default': true
-              }
-            },
-            'beforeCreate': [
-              null
-            ],
-            'beforeDestroy': [
-              null
-            ],
-            '__file': 'src/layouts/RouteView.vue',
-            '_Ctor': {}
-          },
-          'meta': {
-            'title': '指标分析',
-            'icon': 'form',
-            'keepAlive': false,
-            'hiddenHeaderContent': false,
-            'target': null,
-            'permission': 'test:test'
-          },
-          'redirect': '/dashboard/workplace',
-          'children': []
+      menus: [],
+      mixMenu: {}
+    }
+  },
+  watch: {
+    mainMenu: {
+      deep: true,
+      handler (val) {
+        if (this.isMixMenu()) {
+          const that = this
+          const menus = this.mainMenu.find(item => item.path === '/').children
+          this.menus = menus.map(item => {
+            that.mixMenu[item.name] = item
+            return item
+          })
+        } else {
+          this.menus = this.mainMenu.find(item => item.path === '/').children
         }
-      ]
+      }
+    },
+    sidebarOpened (val) {
+      this.collapsed = !val
     }
   },
   computed: {
@@ -180,14 +171,7 @@ export default {
       return '80px'
     }
   },
-  watch: {
-    sidebarOpened (val) {
-      this.collapsed = !val
-    }
-  },
   created () {
-    this.menus = this.mainMenu.find(item => item.path === '/').children
-    this.setMobileMenus()
     this.collapsed = !this.sidebarOpened
   },
   mounted () {
@@ -202,24 +186,6 @@ export default {
     }
   },
   methods: {
-    setMobileMenus () {
-      if (this.BaseTool.Object.isBlank(this.menus)) {
-        return
-      }
-      const menuJson = JSON.stringify(this.menus)
-      if (menuJson.indexOf('财务指标') !== -1) {
-        this.mobileMenus[0].children.push(this.analysisFinance)
-      }
-      if (menuJson.indexOf('融资指标') !== -1) {
-        this.mobileMenus[0].children.push(this.analysisFinancing)
-      }
-      if (menuJson.indexOf('投资指标') !== -1) {
-        this.mobileMenus[0].children.push(this.analysisInvest)
-      }
-      if (menuJson.indexOf('清收指标') !== -1) {
-        this.mobileMenus[0].children.push(this.analysisLiquidate)
-      }
-    },
     ...mapActions(['setSidebar']),
     toggle () {
       this.collapsed = !this.collapsed

+ 78 - 0
src/layouts/SideMenuRouteView.vue

@@ -0,0 +1,78 @@
+<template>
+  <a-layout>
+    <a-layout-sider
+      v-if="menu&&menu.children!==null&&menu.children!==undefined"
+      width="190px"
+      v-model="collapsed"
+      :theme="theme"
+      :trigger="null">
+      <s-menu
+        :collapsed="collapsed"
+        :menu="menu.children"
+        :theme="theme"
+        style="padding: 16px 0px;"></s-menu>
+    </a-layout-sider>
+    <a-layout-content>
+      <transition name="page-transition">
+        <RouteView />
+      </transition>
+    </a-layout-content>
+  </a-layout>
+
+</template>
+
+<script>
+import RouteView from './RouteView'
+import SMenu from '@/components/Menu'
+import { mapState } from 'vuex'
+
+export default {
+  name: 'SideMenuRouteView',
+  components: {
+    RouteView,
+    SMenu
+  },
+  props: {
+    menus: {
+      type: Object,
+      required: true
+    },
+    theme: {
+      type: String,
+      required: false,
+      default: 'dark'
+    },
+    collapsed: {
+      type: Boolean,
+      required: false,
+      default: false
+    },
+    device: {
+      type: String,
+      required: false,
+      default: 'desktop'
+    }
+  },
+  data () {
+    return {
+    }
+  },
+  computed: {
+    ...mapState({
+      // 动态主路由
+      activeMenu: state => state.permission.activeMenu
+    }),
+    menu () {
+      console.log(this.menus[this.activeMenu])
+      return this.menus[this.activeMenu]
+    }
+  },
+  mounted () {
+
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 9 - 1
src/router/generator-platform-routers.js

@@ -709,7 +709,15 @@ export const generator = (routerMap, parent) => {
       currentRouter.path = currentRouter.path.replace('//', '/')
     }
     // 重定向
-    item.redirect && (currentRouter.redirect = item.redirect)
+    if (item.redirect) {
+      currentRouter.redirect = item.redirect
+    } else if (item.children && item.children.length > 0) {
+      // console.log('item.children', item.children)
+      const redirectChild = item.children.find(child => child.item.visible)
+      if (redirectChild) {
+        currentRouter.redirect = redirectChild.item.url
+      }
+    }
     // 是否有子菜单,并递归处理
     if (item.children && item.children.length > 0) {
       // Recursion

+ 7 - 1
src/store/modules/async-router.js

@@ -6,12 +6,18 @@ import { generatorDynamicRouter, constantRouterMap } from '@/router/generator-pl
 const permission = {
   state: {
     routers: constantRouterMap,
-    addRouters: []
+    addRouters: [],
+    activeMenu: null,
+    activeMenus: []
   },
   mutations: {
     SET_ROUTERS: (state, routers) => {
       state.addRouters = routers
       state.routers = constantRouterMap.concat(routers)
+    },
+    SET_ACTIVE_MENU: (state, menus) => {
+      // 设置当前激活的菜单
+      state.activeMenu = menus
     }
   },
   actions: {

+ 4 - 1
src/utils/mixin.js

@@ -26,7 +26,10 @@ const mixin = {
       return this.layoutMode === 'topmenu'
     },
     isSideMenu () {
-      return !this.isTopMenu()
+      return this.layoutMode === 'sidemenu'
+    },
+    isMixMenu () {
+      return this.layoutMode === 'mixmenu'
     }
   }
 }