diff --git a/src/components/menu/menu.js b/src/components/menu/menu.js
index 15d18eb..49ef98f 100644
--- a/src/components/menu/menu.js
+++ b/src/components/menu/menu.js
@@ -77,7 +77,7 @@ export default {
   },
   created () {
     this.updateMenu()
-    if (!this.options[0].fullPath) {
+    if (this.options.length > 0 && !this.options[0].fullPath) {
       this.formatOptions(this.options, '')
     }
     // 自定义国际化配置
@@ -90,7 +90,7 @@ export default {
   },
   watch: {
     options(val) {
-      if (!val[0].fullPath) {
+      if (val.length > 0 && !val[0].fullPath) {
         this.formatOptions(this.options, '')
       }
     },
@@ -195,18 +195,14 @@ export default {
     },
     updateMenu () {
       const menuRoutes = this.$route.matched.filter(item => item.path !== '')
-      const route = menuRoutes.pop()
-      this.selectedKeys = [this.getSelectedKey(route)]
+      this.selectedKeys = this.getSelectedKey(this.$route)
       let openKeys = menuRoutes.map(item => item.path)
       if (!fastEqual(openKeys, this.sOpenKeys)) {
         this.collapsed || this.mode === 'horizontal' ? this.cachedOpenKeys = openKeys : this.sOpenKeys = openKeys
       }
     },
     getSelectedKey (route) {
-      if (route.meta.invisible && route.parent) {
-        return this.getSelectedKey(route.parent)
-      }
-      return route.path
+      return route.matched.map(item => item.path)
     }
   },
   render (h) {
diff --git a/src/components/setting/Setting.vue b/src/components/setting/Setting.vue
index 93ec7f1..d4bdd4d 100644
--- a/src/components/setting/Setting.vue
+++ b/src/components/setting/Setting.vue
@@ -26,6 +26,7 @@
       >
         <img-checkbox :title="$t('navigate.side')" img="https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg" value="side"/>
         <img-checkbox :title="$t('navigate.head')" img="https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg" value="head"/>
+        <img-checkbox :title="$t('navigate.mix')" img="https://gw.alipayobjects.com/zos/antfincdn/x8Ob%26B8cy8/LCkqqYNmvBEbokSDscrm.svg" value="mix"/>
       </img-checkbox-group>
     </setting-item>
     <setting-item>
diff --git a/src/components/setting/i18n.js b/src/components/setting/i18n.js
index 03873a7..85fb98d 100644
--- a/src/components/setting/i18n.js
+++ b/src/components/setting/i18n.js
@@ -12,6 +12,7 @@ module.exports = {
         title: '导航设置',
         side: '侧边导航',
         head: '顶部导航',
+        mix: '混合导航',
         content: {
           title: '内容区域宽度',
           fluid: '流式',
@@ -82,6 +83,7 @@ module.exports = {
         title: 'Navigation Mode',
         side: 'Side Menu Layout',
         head: 'Top Menu Layout',
+        mix: 'Mix Menu Layout',
         content: {
           title: 'Content Width',
           fluid: 'Fluid',
diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue
index 92a9075..dd197fe 100644
--- a/src/layouts/AdminLayout.vue
+++ b/src/layouts/AdminLayout.vue
@@ -3,7 +3,7 @@
     <drawer v-if="isMobile" v-model="collapsed">
       <side-menu :theme="theme.mode" :menuData="menuData" :collapsed="false" :collapsible="false" @menuSelect="onMenuSelect"/>
     </drawer>
-    <side-menu :class="[fixedSideBar ? 'fixed-side' : '']" :theme="theme.mode" v-else-if="layout === 'side'" :menuData="menuData" :collapsed="collapsed" :collapsible="true" />
+    <side-menu :class="[fixedSideBar ? 'fixed-side' : '']" :theme="theme.mode" v-else-if="layout === 'side' || layout === 'mix'" :menuData="sideMenuData" :collapsed="collapsed" :collapsible="true" />
     <div v-if="fixedSideBar && !isMobile" :style="`width: ${sideMenuWidth}; min-width: ${sideMenuWidth};max-width: ${sideMenuWidth};`" class="virtual-side"></div>
     <drawer v-if="!hideSetting" v-model="showSetting" placement="right">
       <div class="setting" slot="handler">
@@ -12,7 +12,7 @@
       <setting />
     </drawer>
     <a-layout class="admin-layout-main beauty-scroll">
-      <admin-header :style="headerStyle" :menuData="menuData" :collapsed="collapsed" @toggleCollapse="toggleCollapse"/>
+      <admin-header :style="headerStyle" :menuData="headMenuData" :collapsed="collapsed" @toggleCollapse="toggleCollapse"/>
       <a-layout-header v-if="fixedHeader"></a-layout-header>
       <a-layout-content class="admin-layout-content">
         <div :style="`min-height: ${minHeight}px; position: relative`">
@@ -32,7 +32,7 @@ import PageFooter from './footer/PageFooter'
 import Drawer from '../components/tool/Drawer'
 import SideMenu from '../components/menu/SideMenu'
 import Setting from '../components/setting/Setting'
-import {mapState, mapMutations} from 'vuex'
+import {mapState, mapMutations, mapGetters} from 'vuex'
 
 const minHeight = window.innerHeight - 64 - 24 - 122
 
@@ -46,30 +46,61 @@ export default {
       showSetting: false
     }
   },
+  watch: {
+    $route(val) {
+      this.setActivated(val)
+    },
+    layout() {
+      this.setActivated(this.$route)
+    }
+  },
   computed: {
     ...mapState('setting', ['isMobile', 'theme', 'layout', 'footerLinks', 'copyright', 'fixedHeader', 'fixedSideBar',
       'hideSetting', 'menuData']),
+    ...mapGetters('setting', ['firstMenu', 'subMenu']),
     sideMenuWidth() {
       return this.collapsed ? '80px' : '256px'
     },
     headerStyle() {
-      let width = (this.fixedHeader && this.layout == 'side' && !this.isMobile) ? `calc(100% - ${this.sideMenuWidth})` : '100%'
+      let width = (this.fixedHeader && this.layout !== 'head' && !this.isMobile) ? `calc(100% - ${this.sideMenuWidth})` : '100%'
       let position = this.fixedHeader ? 'fixed' : 'static'
       let transition = this.fixedHeader ? 'transition: width 0.2s' : ''
       return `width: ${width}; position: ${position}; ${transition}`
+    },
+    headMenuData() {
+      const {layout, menuData, firstMenu} = this
+      return layout === 'mix' ? firstMenu : menuData
+    },
+    sideMenuData() {
+      const {layout, menuData, subMenu} = this
+      return layout === 'mix' ? subMenu : menuData
     }
   },
   methods: {
-    ...mapMutations('setting', ['correctPageMinHeight']),
+    ...mapMutations('setting', ['correctPageMinHeight', 'setActivatedFirst']),
     toggleCollapse () {
       this.collapsed = !this.collapsed
     },
     onMenuSelect () {
       this.toggleCollapse()
     },
+    setActivated(route) {
+      if (this.layout === 'mix') {
+        let matched = route.matched
+        matched = matched.slice(0, matched.length - 1)
+        const {firstMenu} = this
+        for (let menu of firstMenu) {
+          if (matched.findIndex(item => item.path === menu.fullPath) !== -1) {
+            this.setActivatedFirst(menu.fullPath)
+            break
+          }
+        }
+      }
+    }
   },
   created() {
     this.correctPageMinHeight(minHeight - 1)
+    this.setActivated(this.$route)
   },
   beforeDestroy() {
     this.correctPageMinHeight(-minHeight + 1)
diff --git a/src/layouts/header/AdminHeader.vue b/src/layouts/header/AdminHeader.vue
index b320432..a65b0ad 100644
--- a/src/layouts/header/AdminHeader.vue
+++ b/src/layouts/header/AdminHeader.vue
@@ -6,12 +6,12 @@
         <h1 v-if="!isMobile">{{systemName}}</h1>
       </router-link>
       <a-divider v-if="isMobile" type="vertical" />
-      <a-icon v-if="layout === 'side'" class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="toggleCollapse"/>
-      <div v-if="layout == 'head' && !isMobile" class="admin-header-menu">
-        <i-menu class="head-menu" style="height: 64px; line-height: 64px;box-shadow: none" :theme="headerTheme" mode="horizontal" :options="menuData" @select="onSelect"/>
+      <a-icon v-if="layout !== 'head'" class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="toggleCollapse"/>
+      <div v-if="layout !== 'side' && !isMobile" class="admin-header-menu" :style="`width: ${menuWidth};`">
+        <i-menu class="head-menu" :theme="headerTheme" mode="horizontal" :options="menuData" @select="onSelect"/>
       </div>
       <div :class="['admin-header-right', headerTheme]">
-          <header-search class="header-item" />
+          <header-search class="header-item" @active="val => searchActive = val" />
           <a-tooltip class="header-item" title="帮助文档" placement="bottom" >
             <a href="https://iczer.github.io/vue-antd-admin/" target="_blank">
               <a-icon type="question-circle-o" />
@@ -49,7 +49,8 @@ export default {
         {key: 'CN', name: '简体中文', alias: '简体'},
         {key: 'HK', name: '繁體中文', alias: '繁體'},
         {key: 'US', name: 'English', alias: 'English'}
-      ]
+      ],
+      searchActive: false
     }
   },
   computed: {
@@ -63,6 +64,12 @@ export default {
     langAlias() {
       let lang = this.langList.find(item => item.key == this.lang)
       return lang.alias
+    },
+    menuWidth() {
+      const {layout, searchActive} = this
+      const headWidth = layout === 'head' ? '1236px' : '100%'
+      const extraWidth = searchActive ? '564px' : '364px'
+      return `calc(${headWidth} - ${extraWidth})`
     }
   },
   methods: {
diff --git a/src/layouts/header/HeaderSearch.vue b/src/layouts/header/HeaderSearch.vue
index bd408cc..ec4f116 100644
--- a/src/layouts/header/HeaderSearch.vue
+++ b/src/layouts/header/HeaderSearch.vue
@@ -24,10 +24,12 @@ export default {
   methods: {
     enterSearchMode () {
       this.searchMode = true
+      this.$emit('active', true)
       setTimeout(() => this.$refs.input.focus(), 300)
     },
     leaveSearchMode () {
       this.searchMode = false
+      setTimeout(() => this.$emit('active', false), 300)
     }
   }
 }
diff --git a/src/layouts/header/index.less b/src/layouts/header/index.less
index 443f030..ba90761 100644
--- a/src/layouts/header/index.less
+++ b/src/layouts/header/index.less
@@ -4,6 +4,12 @@
   box-shadow: @shadow-down;
   position: relative;
   background: @base-bg-color;
+  .head-menu{
+    height: 64px;
+    line-height: 64px;
+    vertical-align: middle;
+    box-shadow: none;
+  }
   &.dark{
     background: @header-bg-color-dark;
     color: white;
diff --git a/src/router/guards.js b/src/router/guards.js
index b8719f9..67de64c 100644
--- a/src/router/guards.js
+++ b/src/router/guards.js
@@ -38,7 +38,30 @@ const authorityGuard = (to, from, next, options) => {
   }
 }
 
+/**
+ * 混合导航模式下一级菜单跳转重定向
+ * @param to
+ * @param from
+ * @param next
+ * @param options
+ * @returns {*}
+ */
+const redirectGuard = (to, from, next, options) => {
+  const {store} = options
+  if (store.state.setting.layout === 'mix') {
+    const firstMenu = store.getters['setting/firstMenu']
+    if (firstMenu.find(item => item.fullPath === to.fullPath)) {
+      store.commit('setting/setActivatedFirst', to.fullPath)
+      const subMenu = store.getters['setting/subMenu']
+      if (subMenu.length > 0) {
+        return next({path: subMenu[0].fullPath})
+      }
+    }
+  }
+  next()
+}
+
 export default {
-  beforeEach: [loginGuard, authorityGuard],
+  beforeEach: [loginGuard, authorityGuard, redirectGuard],
   afterEach: []
 }
diff --git a/src/store/modules/setting.js b/src/store/modules/setting.js
index 7f0c22b..904c173 100644
--- a/src/store/modules/setting.js
+++ b/src/store/modules/setting.js
@@ -1,5 +1,6 @@
 import config from '@/config'
 import {ADMIN} from '@/config/default'
+import {formatFullPath} from '@/utils/i18n'
 export default {
   namespaced: true,
   state: {
@@ -8,8 +9,30 @@ export default {
     palettes: ADMIN.palettes,
     pageMinHeight: 0,
     menuData: [],
+    activatedFirst: undefined,
     ...config,
   },
+  getters: {
+    firstMenu(state) {
+      const {menuData} = state
+      if (!menuData[0].fullPath) {
+        formatFullPath(menuData)
+      }
+      return menuData.map(item => {
+        const menuItem = {...item}
+        delete menuItem.children
+        return menuItem
+      })
+    },
+    subMenu(state) {
+      const {menuData, activatedFirst} = state
+      if (!menuData[0].fullPath) {
+        formatFullPath(menuData)
+      }
+      const current = menuData.find(menu => menu.fullPath === activatedFirst)
+      return current ? current.children : []
+    }
+  },
   mutations: {
     setDevice (state, isMobile) {
       state.isMobile = isMobile
@@ -49,6 +72,9 @@ export default {
     },
     setAsyncRoutes(state, asyncRoutes) {
       state.asyncRoutes = asyncRoutes
+    },
+    setActivatedFirst(state, activatedFirst) {
+      state.activatedFirst = activatedFirst
     }
   }
 }
diff --git a/src/utils/i18n.js b/src/utils/i18n.js
index 50e3c36..ec64b9f 100644
--- a/src/utils/i18n.js
+++ b/src/utils/i18n.js
@@ -73,5 +73,6 @@ function mergeI18nFromRoutes(i18n, routes) {
 
 export {
   initI18n,
-  mergeI18nFromRoutes
+  mergeI18nFromRoutes,
+  formatFullPath
 }