314 lines
6.3 KiB
Vue
314 lines
6.3 KiB
Vue
<template>
|
|
<aside class="one-nav">
|
|
<nav class="secondary">
|
|
<h2><span>VEUI<small>beta</small></span></h2>
|
|
<section class="desc">
|
|
<a href="https://github.com/ecomfe/veui">
|
|
<img
|
|
alt="VEUI on GitHub"
|
|
src="https://badgen.net/badge/-/GitHub?icon=github&label"
|
|
width="69.2"
|
|
height="20"
|
|
>
|
|
</a>
|
|
<nuxt-link
|
|
:class="{
|
|
'locale-swith': true,
|
|
disabled: altLocale.disabled
|
|
}"
|
|
:to="altLocale.disabled ? '' : altLocale.to"
|
|
>
|
|
{{ altLocale.label }}
|
|
</nuxt-link>
|
|
</section>
|
|
<section class="filter">
|
|
<input
|
|
type="text"
|
|
placeholder="Search…"
|
|
class="search"
|
|
>
|
|
</section>
|
|
<menu class="menu">
|
|
<template v-for="(item, i) in nav">
|
|
<li
|
|
:key="`menu-${i}`"
|
|
class="menu-item"
|
|
>
|
|
<nuxt-link
|
|
v-if="item.link !== false"
|
|
class="menu-link"
|
|
:exact="item.exact"
|
|
:to="getLocalePath(`/${item.slug}`)"
|
|
>
|
|
{{ item.title }}
|
|
</nuxt-link>
|
|
<span
|
|
v-else
|
|
class="menu-link"
|
|
>{{ item.title }}</span>
|
|
<menu
|
|
v-if="item.children && item.children.length"
|
|
class="menu"
|
|
>
|
|
<template
|
|
v-for="(subItem, j) in item.children"
|
|
>
|
|
<li
|
|
v-if="!subItem.hidden"
|
|
:key="`sub-${j}`"
|
|
class="menu-item"
|
|
>
|
|
<nuxt-link
|
|
:class="{
|
|
'menu-link': true,
|
|
'menu-link-disabled': subItem.disabled,
|
|
'menu-link-sub': subItem.sub,
|
|
'menu-link-active': isActive(`/${item.slug}/${subItem.slug}`)
|
|
}"
|
|
:exact="subItem.exact"
|
|
:to="subItem.disabled ? '/' : getLocalePath(`/${item.slug}/${subItem.slug}`)"
|
|
v-html="getTitleHTML(subItem.title)"
|
|
/>
|
|
</li>
|
|
</template>
|
|
</menu>
|
|
</li>
|
|
</template>
|
|
</menu>
|
|
</nav>
|
|
</aside>
|
|
</template>
|
|
|
|
<script>
|
|
import { escape } from 'lodash'
|
|
import i18n from '../common/i18n'
|
|
|
|
export default {
|
|
name: 'one-menu',
|
|
mixins: [i18n],
|
|
props: {
|
|
nav: {
|
|
type: Array,
|
|
default () {
|
|
return []
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
altLocale () {
|
|
let { canonicalPath, locale, getLocalePath, isPathDisabled } = this
|
|
let altLocale = locale === 'zh-Hans' ? 'en-US' : 'zh-Hans'
|
|
let label = locale === 'zh-Hans' ? 'English' : '中文'
|
|
let disabled = isPathDisabled(canonicalPath, altLocale)
|
|
return {
|
|
to: disabled ? '' : getLocalePath(canonicalPath, altLocale),
|
|
disabled,
|
|
label
|
|
}
|
|
}
|
|
},
|
|
watch: {
|
|
$route: 'scrollActiveIntoView'
|
|
},
|
|
mounted () {
|
|
this.scrollActiveIntoView()
|
|
},
|
|
beforeDestroy () {
|
|
clearTimeout(this.timer)
|
|
},
|
|
methods: {
|
|
getTitleHTML (title) {
|
|
let [main, sub] = title.split(' - ')
|
|
return escape(main) + (sub ? `<small>${escape(sub)}</small>` : '')
|
|
},
|
|
isActive (path) {
|
|
let { route = {} } = this.$router.resolve(path) || {}
|
|
return route.name === this.$route.name
|
|
},
|
|
scrollActiveIntoView () {
|
|
this.timer = setTimeout(() => {
|
|
if (!this.$el) {
|
|
return
|
|
}
|
|
let active =
|
|
this.$el.querySelector('.nuxt-link-exact-active') ||
|
|
this.$el.querySelector('.menu-link-active')
|
|
if (!active) {
|
|
return
|
|
}
|
|
|
|
let menu = active.offsetParent
|
|
if (!menu) {
|
|
return
|
|
}
|
|
if (
|
|
active.offsetTop < menu.scrollTop ||
|
|
active.offsetTop + active.offsetHeight > menu.scrollTop
|
|
) {
|
|
active.scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'nearest'
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="stylus" scoped>
|
|
.one-nav
|
|
position fixed
|
|
top 60px
|
|
bottom 0
|
|
left 0
|
|
z-index 1
|
|
padding-top 30px
|
|
border-right 1px solid #e5e5e5
|
|
|
|
.primary
|
|
margin-left -250px
|
|
|
|
.secondary
|
|
height 100%
|
|
position relative
|
|
display flex
|
|
justify-content stretch
|
|
flex-direction column
|
|
float left
|
|
width 240px
|
|
|
|
h2
|
|
display flex
|
|
align-items center
|
|
margin 0 0 0 20px
|
|
font-size 20px
|
|
font-weight 500
|
|
|
|
span
|
|
position relative
|
|
|
|
small
|
|
position absolute
|
|
font-size 16px
|
|
font-weight 400
|
|
transform scale(0.75) translateY(-3px)
|
|
margin-left 3px
|
|
opacity 0.7
|
|
|
|
a
|
|
display block
|
|
|
|
& + .desc
|
|
display flex
|
|
align-items center
|
|
margin-top 15px
|
|
margin-left 20px
|
|
|
|
img
|
|
display block
|
|
|
|
.locale-swith
|
|
display block
|
|
margin-left 12px
|
|
padding 0 6px
|
|
border 1px solid #dbdbdb
|
|
border-radius 3px
|
|
line-height 18px
|
|
font-size 12px
|
|
text-align center
|
|
text-decoration none
|
|
transition all 0.2s
|
|
|
|
&:hover
|
|
border-color #999
|
|
|
|
.filter
|
|
margin-top 20px
|
|
margin-left 20px
|
|
|
|
.search
|
|
display block
|
|
width 180px
|
|
height 32px
|
|
padding 0 7px
|
|
border 1px solid #dbdbdb
|
|
border-radius 4px
|
|
outline none
|
|
font-size 13px
|
|
transition all 0.2s
|
|
|
|
&.focus-visible
|
|
border-color #999
|
|
box-shadow 0 0 0 2px rgba(0, 0, 0, 0.15)
|
|
|
|
& > .menu
|
|
position relative
|
|
width 100%
|
|
flex 1 1 auto
|
|
margin-top 25px
|
|
padding-left 20px
|
|
overflow auto
|
|
|
|
.menu
|
|
.menu-item
|
|
.menu-link
|
|
float left
|
|
clear left
|
|
|
|
.menu .menu
|
|
margin 3.5px 0
|
|
|
|
.menu-item
|
|
margin 3.5px 0
|
|
font-size 16px
|
|
|
|
.menu-item
|
|
font-size 13px
|
|
|
|
.menu-link
|
|
color #333
|
|
font-weight 400
|
|
|
|
& >>> small
|
|
color #999
|
|
font-size 13px
|
|
margin-left 10px
|
|
white-space nowrap
|
|
|
|
&::after
|
|
display block
|
|
|
|
.menu-link
|
|
float left
|
|
clear left
|
|
color #333
|
|
font-weight 500
|
|
padding 9px 0
|
|
text-decoration none
|
|
|
|
&-disabled
|
|
opacity 0.3
|
|
pointer-events none
|
|
|
|
// &-sub
|
|
// margin-left 10px
|
|
&::after
|
|
background-color #999
|
|
|
|
.nuxt-link-exact-active::after
|
|
.menu-link-active::after
|
|
width 100%
|
|
left 0
|
|
background-color #333
|
|
|
|
.toggle
|
|
margin-right 15px
|
|
font-size 13px
|
|
vertical-align middle
|
|
|
|
.disabled
|
|
opacity 0.3
|
|
pointer-events none
|
|
</style>
|