添加夜间主题
This commit is contained in:
parent
2aae9029a2
commit
3d97dc879a
|
|
@ -74,7 +74,7 @@ module.exports = {
|
|||
plugins: [ // 插件
|
||||
// [require('./plugins/love-me'), { // 鼠标点击爱心特效
|
||||
// color: '#11a8cd', // 爱心颜色,默认随机色
|
||||
// excludeClassName: 'theme-default-content' // 要排除元素的class, 默认空''
|
||||
// excludeClassName: 'theme-vdoing-content' // 要排除元素的class, 默认空''
|
||||
// }],
|
||||
[require('./plugins/title-badge'), { // h1标题徽章
|
||||
// badges: [ // 替换默认的徽章图标
|
||||
|
|
@ -122,7 +122,7 @@ module.exports = {
|
|||
[
|
||||
'vuepress-plugin-zooming', // 放大图片
|
||||
{
|
||||
selector:'.theme-default-content img:not(.no-zoom)',
|
||||
selector:'.theme-vdoing-content img:not(.no-zoom)',
|
||||
options: {
|
||||
bgColor: 'rgba(0,0,0,0.6)'
|
||||
},
|
||||
|
|
|
|||
|
|
@ -228,9 +228,9 @@ export default {
|
|||
cursor text
|
||||
width 10rem
|
||||
height: 2rem
|
||||
color lighten($textColor, 25%)
|
||||
color var(--textColor)
|
||||
display inline-block
|
||||
border 1px solid darken($borderColor, 10%)
|
||||
border 1px solid var(--borderColor, #ccc)
|
||||
border-radius 2rem
|
||||
font-size 0.9rem
|
||||
line-height 2rem
|
||||
|
|
@ -243,11 +243,11 @@ export default {
|
|||
cursor auto
|
||||
border-color $accentColor
|
||||
.suggestions
|
||||
background #fff
|
||||
background var(--bg, #fff)
|
||||
width 20rem
|
||||
position absolute
|
||||
top 1.5rem
|
||||
border 1px solid darken($borderColor, 10%)
|
||||
border 1px solid var(--borderColor, #ccc)
|
||||
border-radius 6px
|
||||
padding 0.4rem
|
||||
list-style-type none
|
||||
|
|
@ -260,7 +260,8 @@ export default {
|
|||
cursor pointer
|
||||
a
|
||||
white-space normal
|
||||
color lighten($textColor, 35%)
|
||||
color var(--textColor)
|
||||
opacity .75
|
||||
.page-title
|
||||
font-weight 600
|
||||
.header
|
||||
|
|
|
|||
|
|
@ -1,17 +1,9 @@
|
|||
|
||||
// h1标签徽章图标
|
||||
h1
|
||||
img
|
||||
width 1.6rem
|
||||
|
||||
// 强制换行(如链接文本太长换行)
|
||||
.theme-default-content:not(.custom)
|
||||
word-wrap break-word
|
||||
|
||||
// 表格宽度
|
||||
table
|
||||
width: 100%;
|
||||
display: inline-table;
|
||||
|
||||
// 评论区样式
|
||||
#vuepress-plugin-comment
|
||||
max-width $contentWidth
|
||||
|
|
@ -24,6 +16,8 @@ table
|
|||
|
||||
// 评论区颜色重置
|
||||
.gt-container
|
||||
.gt-meta
|
||||
border-color var(--borderColor)!important
|
||||
.gt-comments-null
|
||||
color #999
|
||||
.gt-header-textarea
|
||||
|
|
@ -39,7 +33,11 @@ table
|
|||
.gt-svg svg
|
||||
fill $accentColor!important
|
||||
.gt-comment-admin .gt-comment-content
|
||||
background-color lighten($readModeColor, 50%)!important
|
||||
background-color rgba(150,150,150,0.1)!important
|
||||
&:hover
|
||||
box-shadow 0 0 25px rgba(150,150,150,.5)
|
||||
.gt-comment-body
|
||||
color var(--textColor)!important
|
||||
|
||||
|
||||
// qq徽章
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
// 主题调色板
|
||||
|
||||
// 默认 颜色
|
||||
$accentColor = #3eaf7c
|
||||
$textColor = #2c3e50
|
||||
$borderColor = #eaecef
|
||||
$codeBgColor = #282c34
|
||||
$arrowBgColor = #ccc
|
||||
$badgeTipColor = #42b983
|
||||
$badgeWarningColor = darken(#ffe564, 35%)
|
||||
$badgeErrorColor = #DA5961
|
||||
$accentColor = #3eaf7c // 强调色
|
||||
$textColor = #2c3e50 // 文本色
|
||||
$borderColor = #eaecef // 边框色
|
||||
$codeBgColor = #282c34 // 代码块背景色
|
||||
$arrowBgColor = #ccc // 箭头背景色?
|
||||
$badgeTipColor = #42b983 // 提示框
|
||||
$badgeWarningColor = darken(#ffe564, 35%) // 警告框
|
||||
$badgeErrorColor = #DA5961 // 错误框
|
||||
|
||||
// 默认 布局
|
||||
// $navbarHeight = 3.6rem
|
||||
|
|
@ -20,23 +20,10 @@ $badgeErrorColor = #DA5961
|
|||
// 自定义 蓝色主题
|
||||
$accentColor = #11A8CD
|
||||
$textColor = #004050
|
||||
$borderColor = rgba(80,80,80,.1)
|
||||
$borderColor = rgba(0,0,0,.1)
|
||||
$badgeTipColor = #11A8CD
|
||||
|
||||
|
||||
|
||||
// 阅读模式
|
||||
$readModeColor = #f5f5d5 // 杏仁黄
|
||||
// $readModeColor = #c7edcc // 绿豆色
|
||||
// $readModeColor = #FFF2E2 // 秋叶褐
|
||||
|
||||
// 布局
|
||||
$sidebarWidth = 18rem
|
||||
$contentWidth = 850px
|
||||
$rightMenuWidth = 280px // 右侧菜单
|
||||
|
||||
|
||||
|
||||
// 深色主题
|
||||
// $textColor = #686880
|
||||
// $readModeColor = #191828 // 深蓝
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
<template>
|
||||
<div class="articleInfo-wrap">
|
||||
<div class="articleInfo">
|
||||
<ul class="breadcrumbs">
|
||||
<li>
|
||||
<router-link to="/" class="iconfont icon-home" title="首页" />
|
||||
</li>
|
||||
<li v-if="articleInfo.classify1">
|
||||
<router-link v-if="articleInfo.cataloguePermalink" :to="articleInfo.cataloguePermalink" :title="articleInfo.classify1+'-目录页'">{{articleInfo.classify1}}</router-link>
|
||||
<span v-else>{{articleInfo.classify1}}</span>
|
||||
</li>
|
||||
<li v-if="articleInfo.classify2">
|
||||
<span>{{articleInfo.classify2}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="info">
|
||||
<div class="author iconfont icon-touxiang" v-if="articleInfo.author">
|
||||
<a :href="articleInfo.author.href" v-if="articleInfo.author.href" target="_blank" class="beLink" title="作者">{{articleInfo.author.name}}</a>
|
||||
<a v-else href="javascript:;" title="作者">{{articleInfo.author.name}}</a>
|
||||
</div>
|
||||
<div class="date iconfont icon-riqi" v-if="articleInfo.date">
|
||||
<a href="javascript:;" title="创建时间">{{articleInfo.date}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
articleInfo: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.articleInfo = this.getPageInfo()
|
||||
},
|
||||
watch: {
|
||||
$route: {
|
||||
handler:function(){
|
||||
this.articleInfo = this.getPageInfo()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getPageInfo() {
|
||||
const pageInfo = this.$page
|
||||
const { relativePath } = pageInfo
|
||||
const { catalogue } = this.$themeConfig.sidebar
|
||||
const relativePathArr = relativePath.split('/')
|
||||
const classifyArr = relativePathArr[0].split('.')
|
||||
const classify1 = classifyArr.length > 1 ? classifyArr[1] : classifyArr[0] // 文章一级分类名称
|
||||
const classify2 = relativePathArr.length > 2 ? relativePathArr[1].split('.')[1] : undefined// 文章二级分类名称
|
||||
const cataloguePermalink = catalogue ? catalogue[classify1] : undefined// 目录页永久链接
|
||||
const author = this.$frontmatter.author || this.$themeConfig.author // 作者
|
||||
let date = pageInfo.frontmatter.date || pageInfo.lastUpdated // 文章创建时间
|
||||
date = Date.parse(date) ? dateFormat(new Date(date)) : undefined
|
||||
return {
|
||||
date,
|
||||
classify1,
|
||||
classify2,
|
||||
cataloguePermalink,
|
||||
author
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 日期格式化
|
||||
function dateFormat(date) {
|
||||
if (!(date instanceof Date)) {
|
||||
date = new Date(date)
|
||||
}
|
||||
return `${date.getFullYear()}-${zero(date.getMonth()+1)}-${zero(date.getDate())}`
|
||||
}
|
||||
|
||||
// 小于10补0
|
||||
function zero(d){
|
||||
return d.toString().padStart(2,'0')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus' scoped>
|
||||
|
||||
.articleInfo-wrap
|
||||
// margin-bottom -3.6rem!important
|
||||
margin: 2.6rem 0 -3.1rem 0
|
||||
// padding-top 0!important
|
||||
color #888
|
||||
.articleInfo
|
||||
overflow hidden
|
||||
font-size .95rem
|
||||
.breadcrumbs
|
||||
margin 0
|
||||
padding 0
|
||||
overflow hidden
|
||||
display inline-block
|
||||
line-height 2rem
|
||||
@media (max-width: 960px)
|
||||
width 100%
|
||||
li
|
||||
list-style-type none
|
||||
float left
|
||||
padding-right 5px
|
||||
&:after
|
||||
content '-'
|
||||
margin-left 5px
|
||||
color #999
|
||||
&:last-child
|
||||
&:after
|
||||
content ''
|
||||
a
|
||||
color #888
|
||||
&:before
|
||||
font-size .95rem
|
||||
&:hover
|
||||
color $accentColor
|
||||
.icon-home
|
||||
text-decoration none
|
||||
.info
|
||||
float right
|
||||
line-height 32px
|
||||
@media (max-width: 960px)
|
||||
float left
|
||||
div
|
||||
float left
|
||||
margin-left 20px
|
||||
font-size .8rem
|
||||
@media (max-width: 960px)
|
||||
margin 0 20px 0 0
|
||||
&:before
|
||||
margin-right 3px
|
||||
a
|
||||
color #888
|
||||
&:hover
|
||||
text-decoration none
|
||||
a.beLink
|
||||
&:hover
|
||||
color $accentColor
|
||||
text-decoration underline
|
||||
</style>
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
<template>
|
||||
<div class="buttons">
|
||||
<transition name="fade">
|
||||
<div
|
||||
title="返回顶部"
|
||||
class="button go-to-top iconfont icon-fanhuidingbu"
|
||||
v-show="showToTop"
|
||||
@click="scrollToTop"
|
||||
/>
|
||||
</transition>
|
||||
<div
|
||||
title="去评论"
|
||||
class="button go-to-comment iconfont icon-pinglun"
|
||||
v-show="showCommentBut"
|
||||
@click="scrollToComment"
|
||||
/>
|
||||
<div
|
||||
title="阅读模式"
|
||||
class="button read-mode iconfont icon-yuedu"
|
||||
@click="$emit('toggle-read-mode')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash.debounce'
|
||||
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
threshold: 300,
|
||||
scrollTop: null,
|
||||
showCommentBut: false,
|
||||
commentTop: null,
|
||||
_scrollTimer: null,
|
||||
_textareaEl: null,
|
||||
_recordScrollTop: null,
|
||||
COMMENT_SELECTOR: '#vuepress-plugin-comment' // 评论区元素的选择器
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.scrollTop = this.getScrollTop()
|
||||
window.addEventListener('scroll', debounce(() => {
|
||||
this.scrollTop = this.getScrollTop()
|
||||
}, 100))
|
||||
|
||||
this.handleShowCommentBut()
|
||||
window.addEventListener('load', () => {
|
||||
this.getCommentTop()
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
showToTop () {
|
||||
return this.scrollTop > this.threshold
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getScrollTop () {
|
||||
return window.pageYOffset
|
||||
|| document.documentElement.scrollTop
|
||||
|| document.body.scrollTop || 0
|
||||
},
|
||||
|
||||
scrollToTop () {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
this.scrollTop = 0
|
||||
},
|
||||
|
||||
getCommentTop () {
|
||||
setTimeout(() => {
|
||||
const commentEl = document.querySelector(this.COMMENT_SELECTOR)
|
||||
if (commentEl) {
|
||||
this.commentTop = commentEl.offsetTop
|
||||
} else {
|
||||
this.showCommentBut = false
|
||||
}
|
||||
},500)
|
||||
},
|
||||
|
||||
handleShowCommentBut() {
|
||||
this.showCommentBut = this.$frontmatter.comment !== false && this.$frontmatter.home !== true
|
||||
},
|
||||
|
||||
scrollToComment() {
|
||||
window.scrollTo({ top: this.commentTop, behavior: 'smooth' })
|
||||
this._textareaEl = document.querySelector(this.COMMENT_SELECTOR + ' textarea')
|
||||
if( this._textareaEl && this.getScrollTop() !== this._recordScrollTop) {
|
||||
document.addEventListener("scroll", this._handleListener)
|
||||
} else if (this._textareaEl && this.getScrollTop() === this._recordScrollTop) {
|
||||
this._handleFocus()
|
||||
}
|
||||
},
|
||||
|
||||
_handleListener() {
|
||||
clearTimeout(this._scrollTimer)
|
||||
this._scrollTimer = setTimeout(() => {
|
||||
document.removeEventListener('scroll', this._handleListener)
|
||||
this._recordScrollTop = this.getScrollTop()
|
||||
this._handleFocus()
|
||||
}, 30)
|
||||
},
|
||||
|
||||
_handleFocus() {
|
||||
this._textareaEl.focus()
|
||||
this._textareaEl.classList.add('yellowBorder')
|
||||
setTimeout(() => {
|
||||
this._textareaEl.classList.remove('yellowBorder')
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.handleShowCommentBut()
|
||||
this.getCommentTop()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus'>
|
||||
.yellowBorder
|
||||
border: #FFE089 1px solid!important
|
||||
box-shadow 0 0 10px #FFE089!important
|
||||
.buttons
|
||||
position fixed
|
||||
right 2rem
|
||||
bottom 2.5rem
|
||||
@media (max-width: $MQNarrow)
|
||||
right 1rem
|
||||
bottom 1.5rem
|
||||
z-index 1
|
||||
.button
|
||||
width 40px
|
||||
height 40px
|
||||
line-height 40px
|
||||
border-radius 50%
|
||||
box-shadow 0 2px 6px rgba(0,0,0,.15)
|
||||
margin-top .9rem
|
||||
text-align center
|
||||
cursor pointer
|
||||
background rgba(255,255,255,0.6)
|
||||
// color #666
|
||||
&:hover
|
||||
color $accentColor
|
||||
|
||||
.fade-enter-active, .fade-leave-active
|
||||
transition opacity .2s
|
||||
.fade-enter, .fade-leave-to
|
||||
opacity 0
|
||||
</style>
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
<template>
|
||||
<div class="theme-default-content">
|
||||
<div class="column-wrapper">
|
||||
<img :src="getPageData().imgUrl" />
|
||||
<dl class="column-info">
|
||||
<dt class="title">{{getPageData().title}}</dt>
|
||||
<dd class="description" v-html="getPageData().description"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="catalogue-wrapper">
|
||||
<div class="catalogue-title">目录</div>
|
||||
<div class="catalogue-content">
|
||||
<template v-for="(item, index) in getCatalogueList()">
|
||||
<dl v-if="type(item) === 'array'" :key="index" class="inline">
|
||||
<dt>
|
||||
<router-link :to="item[2]">{{`${index+1}. ${item[1]}`}}</router-link>
|
||||
</dt>
|
||||
</dl>
|
||||
<dl v-else-if="type(item) === 'object'" :key="index">
|
||||
<dt>{{`${index+1}. ${item.title}`}}</dt>
|
||||
<dd>
|
||||
<router-link :to="s[2]" v-for="(s, i) in item.children" :key="i">
|
||||
{{`${index+1}-${i+1}. ${s[1]}`}}
|
||||
</router-link>
|
||||
</dd>
|
||||
</dl>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
getPageData() {
|
||||
const pageData = this.$frontmatter.pageComponent.data
|
||||
pageData.title = this.$frontmatter.title
|
||||
return pageData
|
||||
},
|
||||
getCatalogueList() {
|
||||
const { sidebar } = this.$site.themeConfig
|
||||
const key = this.$frontmatter.pageComponent.data.key
|
||||
const catalogueList = sidebar[`/${key}/`]
|
||||
|
||||
if(!catalogueList) {
|
||||
console.error('未获取到目录数据,请查看front matter中设置的key是否正确。')
|
||||
}
|
||||
|
||||
return catalogueList
|
||||
},
|
||||
type(o) { // 数据类型检查
|
||||
return Object.prototype.toString.call(o).match(/\[object (.*?)\]/)[1].toLowerCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="stylus" rel="stylesheet/stylus">
|
||||
dl,dd
|
||||
margin 0
|
||||
.column-wrapper
|
||||
display flex
|
||||
margin-top 4.6rem!important
|
||||
padding-bottom 2rem
|
||||
border-bottom 1px solid #eaecef
|
||||
img
|
||||
width 80px
|
||||
height 80px
|
||||
border-radius 2px
|
||||
margin-right 1rem
|
||||
.column-info
|
||||
.title
|
||||
font-size 1.6rem
|
||||
.description
|
||||
color #666
|
||||
margin .5rem 0
|
||||
.catalogue-wrapper
|
||||
.catalogue-title
|
||||
font-size 1.5rem
|
||||
margin 2rem 0
|
||||
.catalogue-content
|
||||
dl
|
||||
margin-bottom 1.8rem
|
||||
&.inline
|
||||
display inline-block
|
||||
width 50%
|
||||
margin-bottom 1rem
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
width 100%
|
||||
a
|
||||
width 100%
|
||||
dt
|
||||
font-size 1.1rem
|
||||
dd
|
||||
margin-top .7rem
|
||||
a
|
||||
margin-bottom .5rem
|
||||
display inline-block
|
||||
width 50%
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
width 100%
|
||||
</style>
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
class="dropdown-wrapper"
|
||||
:class="{ open }"
|
||||
>
|
||||
<button
|
||||
class="dropdown-title"
|
||||
type="button"
|
||||
:aria-label="dropdownAriaLabel"
|
||||
@click="toggle"
|
||||
>
|
||||
<router-link v-if="item.link" :to="item.link" class="link-title">{{ item.text }}</router-link>
|
||||
<span class="title" v-show="!item.link">{{ item.text }}</span>
|
||||
<span
|
||||
class="arrow"
|
||||
:class="open ? 'down' : 'right'"
|
||||
></span>
|
||||
</button>
|
||||
|
||||
<DropdownTransition>
|
||||
<ul
|
||||
class="nav-dropdown"
|
||||
v-show="open"
|
||||
>
|
||||
<li
|
||||
class="dropdown-item"
|
||||
:key="subItem.link || index"
|
||||
v-for="(subItem, index) in item.items"
|
||||
>
|
||||
<h4 v-if="subItem.type === 'links'">{{ subItem.text }}</h4>
|
||||
|
||||
<ul
|
||||
class="dropdown-subitem-wrapper"
|
||||
v-if="subItem.type === 'links'"
|
||||
>
|
||||
<li
|
||||
class="dropdown-subitem"
|
||||
:key="childSubItem.link"
|
||||
v-for="childSubItem in subItem.items"
|
||||
>
|
||||
<NavLink
|
||||
@focusout="
|
||||
isLastItemOfArray(childSubItem, subItem.items) &&
|
||||
isLastItemOfArray(subItem, item.items) &&
|
||||
toggle()
|
||||
"
|
||||
:item="childSubItem"/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<NavLink
|
||||
v-else
|
||||
@focusout="isLastItemOfArray(subItem, item.items) && toggle()"
|
||||
:item="subItem"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</DropdownTransition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavLink from '@theme/components/NavLink.vue'
|
||||
import DropdownTransition from '@theme/components/DropdownTransition.vue'
|
||||
import last from 'lodash/last'
|
||||
|
||||
export default {
|
||||
components: { NavLink, DropdownTransition },
|
||||
|
||||
data () {
|
||||
return {
|
||||
open: false,
|
||||
isMQMobile: false
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
item: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
dropdownAriaLabel () {
|
||||
return this.item.ariaLabel || this.item.text
|
||||
}
|
||||
},
|
||||
beforeMount(){
|
||||
this.isMQMobile = window.innerWidth < 720 ? true : false;
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
this.isMQMobile = window.innerWidth < 720 ? true : false;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
toggle () {
|
||||
if(this.isMQMobile){
|
||||
this.open = !this.open
|
||||
}
|
||||
},
|
||||
|
||||
isLastItemOfArray (item, array) {
|
||||
return last(array) === item
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
$route () {
|
||||
this.open = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.dropdown-wrapper
|
||||
cursor pointer
|
||||
.dropdown-title
|
||||
display block
|
||||
font-size 0.9rem
|
||||
font-family inherit
|
||||
cursor inherit
|
||||
padding inherit
|
||||
line-height 1.4rem
|
||||
background transparent
|
||||
border none
|
||||
font-weight 500
|
||||
color $textColor
|
||||
&:hover
|
||||
border-color transparent
|
||||
.arrow
|
||||
vertical-align middle
|
||||
margin-top -1px
|
||||
margin-left 0.4rem
|
||||
.nav-dropdown
|
||||
.dropdown-item
|
||||
color inherit
|
||||
line-height 1.7rem
|
||||
h4
|
||||
margin 0.45rem 0 0
|
||||
border-top 1px solid #eee
|
||||
padding 0.45rem 1.5rem 0 1.25rem
|
||||
.dropdown-subitem-wrapper
|
||||
padding 0
|
||||
list-style none
|
||||
.dropdown-subitem
|
||||
font-size 0.9em
|
||||
a
|
||||
display block
|
||||
line-height 1.7rem
|
||||
position relative
|
||||
border-bottom none
|
||||
font-weight 400
|
||||
margin-bottom 0
|
||||
padding 0 1.5rem 0 1.25rem
|
||||
&:hover
|
||||
color $accentColor
|
||||
&.router-link-active
|
||||
color $accentColor
|
||||
&::after
|
||||
content ""
|
||||
width 0
|
||||
height 0
|
||||
border-left 5px solid $accentColor
|
||||
border-top 3px solid transparent
|
||||
border-bottom 3px solid transparent
|
||||
position absolute
|
||||
top calc(50% - 2px)
|
||||
left 9px
|
||||
&:first-child h4
|
||||
margin-top 0
|
||||
padding-top 0
|
||||
border-top 0
|
||||
|
||||
@media (max-width: $MQMobile)
|
||||
.dropdown-wrapper
|
||||
&.open .dropdown-title
|
||||
margin-bottom 0.5rem
|
||||
.dropdown-title
|
||||
font-weight 600
|
||||
font-size inherit
|
||||
&:hover
|
||||
color $accentColor
|
||||
.link-title
|
||||
display none
|
||||
.title
|
||||
display inline-block!important
|
||||
.nav-dropdown
|
||||
transition height .1s ease-out
|
||||
overflow hidden
|
||||
.dropdown-item
|
||||
h4
|
||||
border-top 0
|
||||
margin-top 0
|
||||
padding-top 0
|
||||
h4, & > a
|
||||
font-size 15px
|
||||
line-height 2rem
|
||||
.dropdown-subitem
|
||||
font-size 14px
|
||||
padding-left 1rem
|
||||
|
||||
@media (min-width: $MQMobile)
|
||||
.dropdown-wrapper
|
||||
height 1.8rem
|
||||
&:hover .nav-dropdown,
|
||||
&.open .nav-dropdown
|
||||
// override the inline style.
|
||||
display block !important
|
||||
&.open:blur
|
||||
display none
|
||||
.dropdown-title .arrow
|
||||
// make the arrow always down at desktop
|
||||
border-left 4px solid transparent
|
||||
border-right 4px solid transparent
|
||||
border-top 6px solid $arrowBgColor
|
||||
border-bottom 0
|
||||
.nav-dropdown
|
||||
display none
|
||||
// Avoid height shaked by clicking
|
||||
height auto !important
|
||||
box-sizing border-box;
|
||||
max-height calc(100vh - 2.7rem)
|
||||
overflow-y auto
|
||||
position absolute
|
||||
top 100%
|
||||
right 0
|
||||
background-color #fff
|
||||
padding 0.6rem 0
|
||||
border 1px solid #ddd
|
||||
border-bottom-color #ccc
|
||||
text-align left
|
||||
border-radius 0.25rem
|
||||
white-space nowrap
|
||||
margin 0
|
||||
.nav-item .dropdown-title a
|
||||
&:hover, &.router-link-active
|
||||
margin-bottom -2px
|
||||
border-bottom 2px solid lighten($accentColor, 8%)
|
||||
</style>
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
<template>
|
||||
<div class="footer">
|
||||
<div class="icons" v-if="social && social.icons">
|
||||
<a
|
||||
:href="item.link"
|
||||
:title="item.title"
|
||||
:class="['iconfont', item.iconClass]"
|
||||
v-for="(item, index) in social.icons"
|
||||
:key="index"
|
||||
target="_blank"
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
<template v-if="footer">
|
||||
<a href="https://github.com/xugaoyi/vuepress-theme-vdoing-blog" target="_blank" title="本站主题">♔♕Vdoing | </a>
|
||||
Copyright © {{ footer.createYear }}-{{ new Date().getFullYear() }}
|
||||
<span v-html="footer.copyrightInfo"></span>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
social() {
|
||||
return this.$themeConfig.blogger && this.$themeConfig.blogger.social
|
||||
},
|
||||
footer() {
|
||||
return this.$themeConfig.footer
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus' scoped>
|
||||
$mobileSidebarWidth = $sidebarWidth * 0.82
|
||||
|
||||
.icons
|
||||
margin-bottom 12px
|
||||
.iconfont
|
||||
padding 0 10px
|
||||
font-size 19px
|
||||
.footer
|
||||
padding 2.5rem 2.5rem 3rem
|
||||
text-align center
|
||||
color #999
|
||||
box-sizing border-box
|
||||
font-size .85rem
|
||||
transition all .2s ease
|
||||
a
|
||||
color #999
|
||||
@media (min-width: ($MQMobile + 1px))
|
||||
.sidebar-open .footer
|
||||
width auto
|
||||
margin-left $sidebarWidth
|
||||
|
||||
.no-sidebar .footer
|
||||
width auto
|
||||
margin-left 0
|
||||
|
||||
</style>
|
||||
|
|
@ -1,558 +0,0 @@
|
|||
<template>
|
||||
<div class="i-body" :style="'background-image: url('+ footerBgImg || '' +')'">
|
||||
<div class="banner">
|
||||
<main class="home">
|
||||
<header class="hero">
|
||||
<img v-if="data.heroImage" :src="$withBase(data.heroImage)" :alt="data.heroAlt || 'hero'" />
|
||||
<h1 v-if="data.heroText !== null" id="main-title">{{ data.heroText || $title || 'Hello' }}</h1>
|
||||
<p class="description">{{ data.tagline || $description || 'Welcome to your VuePress site' }}</p>
|
||||
<p class="action" v-if="data.actionText && data.actionLink">
|
||||
<NavLink class="action-button" :item="actionLink" />
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<!-- PC端features块 s -->
|
||||
<div class="features" v-if="data.features && data.features.length && !isMQMobile">
|
||||
<div class="feature" v-for="(feature, index) in data.features" :key="index">
|
||||
<router-link :to="$withBase(feature.link)">
|
||||
<img class="image_title" :src="$withBase(feature.imgUrl)" :alt="feature.title" />
|
||||
<h2>{{ feature.title }}</h2>
|
||||
<p>{{ feature.details }}</p>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<!-- PC端features块 e -->
|
||||
</main>
|
||||
|
||||
<!-- 移动端slide s -->
|
||||
<div class="slide-banner" v-if="data.features && data.features.length" v-show="isMQMobile">
|
||||
<div class="banner-wrapper">
|
||||
<div class="slide-banner-scroll" ref="slide">
|
||||
<div class="slide-banner-wrapper">
|
||||
<div class="slide-item" v-for="(feature, index) in data.features" :key="index">
|
||||
<router-link :to="$withBase(feature.link)">
|
||||
<img class="image_title" :src="$withBase(feature.imgUrl)" :alt="feature.title" />
|
||||
<h2>{{ feature.title }}</h2>
|
||||
<p>{{ feature.details }}</p>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="docs-wrapper">
|
||||
<span
|
||||
class="doc"
|
||||
v-for="(item, index) in data.features.length"
|
||||
:key="index"
|
||||
:class="{'active': currentPageIndex === index}"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 移动端slide e -->
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="main-wrapper">
|
||||
<main class="home home-content" aria-labelledby="main-title">
|
||||
<UpdateArticle pageMark="home" />
|
||||
<Content class="theme-default-content custom" />
|
||||
</main>
|
||||
|
||||
<aside class="info-wrapper" v-if="blogger">
|
||||
<div class="avatar">
|
||||
<img :src="blogger.avatar" alt="头像">
|
||||
</div>
|
||||
<div class="icons" v-if="blogger.social">
|
||||
<a
|
||||
:href="item.link"
|
||||
:title="item.title"
|
||||
:class="['iconfont', item.iconClass]"
|
||||
v-for="(item, index) in blogger.social.icons"
|
||||
:key="index"
|
||||
:style="{width: 100/blogger.social.icons.length + '%'}"
|
||||
target="_blank"
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
<div class="blogger">
|
||||
<span class="name">{{blogger.name}}</span>
|
||||
<span class="slogan">
|
||||
{{blogger.slogan}}
|
||||
</span>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavLink from "@theme/components/NavLink.vue";
|
||||
import BScroll from "@better-scroll/core"
|
||||
import Slide from "@better-scroll/slide"
|
||||
import UpdateArticle from './UpdateArticle.vue'
|
||||
import Footer from './Footer.vue'
|
||||
|
||||
BScroll.use(Slide)
|
||||
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
isMQMobile: false,
|
||||
slide: null,
|
||||
currentPageIndex: 0,
|
||||
playTimer: 0,
|
||||
mark: 0
|
||||
}
|
||||
},
|
||||
beforeMount(){
|
||||
this.isMQMobile = window.innerWidth < 720 ? true : false; // vupress在打包时不能在beforeCreate(),created()访问浏览器api(如window)
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
this.isMQMobile = window.innerWidth < 720 ? true : false;
|
||||
if(this.isMQMobile && !this.slide && !this.mark){
|
||||
this.mark++
|
||||
setTimeout(() => {
|
||||
this.init()
|
||||
},60)
|
||||
}
|
||||
})
|
||||
|
||||
// 引入图标库
|
||||
if(this.blogger && this.blogger.social && this.blogger.social.iconfontCssFile ) {
|
||||
let linkElm = document.createElement("link")
|
||||
linkElm.setAttribute('rel', 'stylesheet');
|
||||
linkElm.setAttribute("type", "text/css")
|
||||
linkElm.setAttribute("href", this.blogger.social.iconfontCssFile)
|
||||
document.head.appendChild(linkElm)
|
||||
}
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.isMQMobile && this.init()
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearTimeout(this.playTimer)
|
||||
this.slide && this.slide.destroy()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
clearTimeout(this.playTimer)
|
||||
this.slide = new BScroll(this.$refs.slide, {
|
||||
scrollX: true, // x轴滚动
|
||||
scrollY: false, // y轴滚动
|
||||
slide: {
|
||||
loop: true,
|
||||
threshold: 100
|
||||
},
|
||||
useTransition: true, // 使用css3 transition动画
|
||||
momentum: false,
|
||||
bounce: false, // 回弹
|
||||
stopPropagation: false, // 是否阻止事件冒泡
|
||||
probeType: 2,
|
||||
preventDefault: false
|
||||
})
|
||||
|
||||
// user touches the slide area
|
||||
this.slide.on('beforeScrollStart', () => {
|
||||
clearTimeout(this.playTimer)
|
||||
})
|
||||
// user touched the slide done
|
||||
this.slide.on('scrollEnd', () => {
|
||||
this.autoGoNext()
|
||||
})
|
||||
this.slide.on('slideWillChange', (page) => {
|
||||
this.currentPageIndex = page.pageX
|
||||
})
|
||||
this.autoGoNext()
|
||||
},
|
||||
autoGoNext() {
|
||||
clearTimeout(this.playTimer)
|
||||
this.playTimer = setTimeout(() => {
|
||||
this.slide.next()
|
||||
}, 4000)
|
||||
}
|
||||
},
|
||||
|
||||
components: { NavLink, UpdateArticle, Footer },
|
||||
|
||||
computed: {
|
||||
data() {
|
||||
return this.$page.frontmatter;
|
||||
},
|
||||
blogger() {
|
||||
return this.$themeConfig.blogger
|
||||
},
|
||||
footerBgImg() {
|
||||
return this.$themeConfig.footer && this.$themeConfig.footer.footerBgImg
|
||||
},
|
||||
actionLink() {
|
||||
return {
|
||||
link: this.data.actionLink,
|
||||
text: this.data.actionText
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.slide-banner
|
||||
margin-top: 2rem;
|
||||
.banner-wrapper
|
||||
position relative
|
||||
.slide-banner-scroll
|
||||
min-height 1px
|
||||
overflow hidden
|
||||
.slide-banner-wrapper
|
||||
height 300px
|
||||
.slide-item
|
||||
display inline-block
|
||||
height 300px
|
||||
width 100%
|
||||
text-align center
|
||||
.image_title
|
||||
width: 10rem;
|
||||
height: 10rem;
|
||||
h2
|
||||
font-size: 1.1rem;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
p
|
||||
color: #b0b6be;
|
||||
|
||||
.docs-wrapper
|
||||
position absolute
|
||||
bottom 25px
|
||||
left 50%
|
||||
transform translateX(-50%)
|
||||
.doc
|
||||
display inline-block
|
||||
margin 0 4px
|
||||
width 8px
|
||||
height 8px
|
||||
border-radius 50%
|
||||
background #2F455A
|
||||
&.active
|
||||
background #517EA9
|
||||
|
||||
.i-body{
|
||||
background #fafafa bottom no-repeat
|
||||
overflow hidden
|
||||
}
|
||||
.banner{
|
||||
width 100%
|
||||
background #1F2837
|
||||
color #fff
|
||||
position relative
|
||||
overflow hidden
|
||||
background-image url(../../public/img/bg-line.png);
|
||||
background-size: 35px 35px;
|
||||
.home{
|
||||
background none
|
||||
position relative
|
||||
z-index 1
|
||||
.hero{
|
||||
h1{
|
||||
font-size 3.5rem
|
||||
margin: 3.5rem auto 1.8rem auto;
|
||||
}
|
||||
.description{
|
||||
font-size 1.2rem
|
||||
color #fff
|
||||
}
|
||||
}
|
||||
.features{
|
||||
border-top none
|
||||
}
|
||||
.feature {
|
||||
h2{
|
||||
font-size 1.3rem
|
||||
color #fff
|
||||
}
|
||||
p{
|
||||
color #B0B6BE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
body .main-wrapper{
|
||||
margin 2rem auto;
|
||||
max-width 1080px;
|
||||
position relative
|
||||
display flex
|
||||
>*{
|
||||
border-radius 5px;
|
||||
background #fff;
|
||||
box-shadow: 0 1px 2px 0 rgba(0,0,0,.1), 0 2px 4px 0 rgba(0,0,0,.1);
|
||||
}
|
||||
.home-content{
|
||||
padding 1rem 1.5rem 0;
|
||||
// max-width 730px;
|
||||
flex 1
|
||||
}
|
||||
.info-wrapper{
|
||||
width 260px;
|
||||
padding: 15px;
|
||||
height: auto;
|
||||
margin-left: 10px;
|
||||
display: inline-table;
|
||||
.avatar {
|
||||
width 260px
|
||||
height 260px
|
||||
overflow: hidden;
|
||||
img{
|
||||
width 100%
|
||||
height 100%
|
||||
border-radius 3px
|
||||
}
|
||||
}
|
||||
.icons {
|
||||
border 1px solid #e1e4e8;
|
||||
height 40px
|
||||
line-height 40px
|
||||
a{
|
||||
font-size 20px
|
||||
width 33%
|
||||
color #666
|
||||
display block
|
||||
float left
|
||||
text-align center
|
||||
&:hover{
|
||||
color $accentColor
|
||||
}
|
||||
}
|
||||
}
|
||||
.blogger{
|
||||
margin: 15px 0 10px 0;
|
||||
.name{
|
||||
font-size 24px
|
||||
display: block
|
||||
margin-bottom 10px
|
||||
}
|
||||
.slogan{
|
||||
color #777
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.home {
|
||||
padding: $navbarHeight 2rem 0;
|
||||
max-width: 1080px;
|
||||
margin: 0px auto;
|
||||
display: block;
|
||||
|
||||
.hero {
|
||||
text-align: center;
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 192px;
|
||||
display: block;
|
||||
margin: 2rem auto 1.5rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
h1, .description, .action {
|
||||
margin: 1.8rem auto;
|
||||
}
|
||||
|
||||
.description {
|
||||
max-width: 40rem;
|
||||
font-size: 1.4rem;
|
||||
line-height: 1.3;
|
||||
// color: lighten($textColor, 40%);
|
||||
color: lighten($textColor, 20%);
|
||||
}
|
||||
|
||||
.action-button {
|
||||
display: inline-block;
|
||||
font-size: 1.2rem;
|
||||
color: #fff;
|
||||
background-color: $accentColor;
|
||||
padding: 0.8rem 1.6rem;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.1s ease;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid darken($accentColor, 10%);
|
||||
|
||||
&:hover {
|
||||
background-color: lighten($accentColor, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.features {
|
||||
border-top: 1px solid $borderColor;
|
||||
padding: 2rem 0;
|
||||
margin-top: 2.5rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
align-content: stretch;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.feature {
|
||||
flex-grow: 1;
|
||||
flex-basis: 30%;
|
||||
max-width: 30%;
|
||||
text-align: center;
|
||||
|
||||
.image_title {
|
||||
width: 11rem;
|
||||
height: 11rem;
|
||||
animation: heart 1.2s ease-in-out 0s infinite alternate;
|
||||
animation-play-state: paused
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 500;
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.feature:hover {
|
||||
.image_title {
|
||||
animation-play-state: running;
|
||||
}
|
||||
h2{
|
||||
color: lighten($textColor, 80%);
|
||||
}
|
||||
p{
|
||||
color: lighten($textColor, 25%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes heart{
|
||||
from{transform:translate(0,0)}
|
||||
to{transform:translate(0,8px)}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1025px){
|
||||
.i-body{
|
||||
background-color: #fff;
|
||||
}
|
||||
body .home-content{
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
body .main-wrapper >*{
|
||||
box-shadow: none;
|
||||
}
|
||||
.banner .home{
|
||||
.hero h1{
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
.feature h2{
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.hero .description{
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
.home .feature .image_title{
|
||||
width: 10rem;
|
||||
height: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 765px){
|
||||
body .main-wrapper .info-wrapper{
|
||||
width: 200px
|
||||
.avatar{
|
||||
width: 200px
|
||||
height: 200px
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $MQMobile) {
|
||||
body .main-wrapper{
|
||||
margin 0
|
||||
display: block;
|
||||
.info-wrapper{
|
||||
display: none;
|
||||
}
|
||||
.home-content{
|
||||
padding-top 1.5rem
|
||||
}
|
||||
}
|
||||
// 719px
|
||||
.banner{
|
||||
min-height 517px
|
||||
.home .hero h1{
|
||||
margin: 1.8rem auto;
|
||||
}
|
||||
}
|
||||
.home {
|
||||
.features {
|
||||
display none
|
||||
flex-direction: column;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.feature {
|
||||
max-width: 100%;
|
||||
padding: 0 2.5rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $MQMobileNarrow) {
|
||||
// 419px
|
||||
.home {
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
|
||||
.hero {
|
||||
img {
|
||||
max-height: 210px;
|
||||
margin: 2rem auto 1.2rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h1, .description, .action {
|
||||
margin: 1.2rem auto;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
font-size: 1rem;
|
||||
padding: 0.6rem 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.feature {
|
||||
h2 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
<template>
|
||||
<header class="navbar">
|
||||
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')"/>
|
||||
|
||||
<router-link
|
||||
:to="$localePath"
|
||||
class="home-link"
|
||||
>
|
||||
<img
|
||||
class="logo"
|
||||
v-if="$site.themeConfig.logo"
|
||||
:src="$withBase($site.themeConfig.logo)"
|
||||
:alt="$siteTitle"
|
||||
>
|
||||
<span
|
||||
ref="siteName"
|
||||
class="site-name"
|
||||
v-if="$siteTitle"
|
||||
:class="{ 'can-hide': $site.themeConfig.logo }"
|
||||
>{{ $siteTitle }}</span>
|
||||
</router-link>
|
||||
|
||||
<div
|
||||
class="links"
|
||||
:style="linksWrapMaxWidth ? {
|
||||
'max-width': linksWrapMaxWidth + 'px'
|
||||
} : {}"
|
||||
>
|
||||
<AlgoliaSearchBox
|
||||
v-if="isAlgoliaSearch"
|
||||
:options="algolia"
|
||||
/>
|
||||
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false"/>
|
||||
<NavLinks class="can-hide"/>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AlgoliaSearchBox from '@AlgoliaSearchBox'
|
||||
import SearchBox from '@SearchBox'
|
||||
import SidebarButton from '@theme/components/SidebarButton.vue'
|
||||
import NavLinks from '@theme/components/NavLinks.vue'
|
||||
|
||||
export default {
|
||||
components: { SidebarButton, NavLinks, SearchBox, AlgoliaSearchBox },
|
||||
|
||||
data () {
|
||||
return {
|
||||
linksWrapMaxWidth: null
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
|
||||
const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
|
||||
const handleLinksWrapWidth = () => {
|
||||
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
|
||||
this.linksWrapMaxWidth = null
|
||||
} else {
|
||||
this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
|
||||
- (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
|
||||
}
|
||||
}
|
||||
handleLinksWrapWidth()
|
||||
window.addEventListener('resize', handleLinksWrapWidth, false)
|
||||
},
|
||||
|
||||
computed: {
|
||||
algolia () {
|
||||
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
|
||||
},
|
||||
|
||||
isAlgoliaSearch () {
|
||||
return this.algolia && this.algolia.apiKey && this.algolia.indexName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function css (el, property) {
|
||||
// NOTE: Known bug, will return 'auto' if style value is 'auto'
|
||||
const win = el.ownerDocument.defaultView
|
||||
// null means not to return pseudo styles
|
||||
return win.getComputedStyle(el, null)[property]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
$navbar-vertical-padding = 0.7rem
|
||||
$navbar-horizontal-padding = 1.5rem
|
||||
|
||||
.navbar
|
||||
padding $navbar-vertical-padding $navbar-horizontal-padding
|
||||
line-height $navbarHeight - 1.4rem
|
||||
a, span, img
|
||||
display inline-block
|
||||
.logo
|
||||
height $navbarHeight - 1.4rem
|
||||
min-width $navbarHeight - 1.4rem
|
||||
margin-right 0.8rem
|
||||
vertical-align top
|
||||
.site-name
|
||||
font-size 1.3rem
|
||||
font-weight 600
|
||||
color $textColor
|
||||
position relative
|
||||
.links
|
||||
padding-left 1.5rem
|
||||
box-sizing border-box
|
||||
// background-color white
|
||||
white-space nowrap
|
||||
font-size 0.9rem
|
||||
position absolute
|
||||
right $navbar-horizontal-padding
|
||||
top $navbar-vertical-padding
|
||||
display flex
|
||||
.search-box
|
||||
flex: 0 0 auto
|
||||
vertical-align top
|
||||
|
||||
@media (max-width: $MQMobile)
|
||||
.navbar
|
||||
padding-left 4rem
|
||||
.can-hide
|
||||
display none
|
||||
.links
|
||||
padding-left 1.5rem
|
||||
.site-name
|
||||
width calc(100vw - 9.4rem)
|
||||
overflow hidden
|
||||
white-space nowrap
|
||||
text-overflow ellipsis
|
||||
</style>
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<main class="page">
|
||||
<slot name="top" />
|
||||
|
||||
<div class="theme-vdoing-wrapper">
|
||||
<RightMenu v-if="showRightMenu !== false"/>
|
||||
<ArticleInfo v-if="isArticle()" />
|
||||
<component class="theme-default-content" v-if="pageComponent" :is="pageComponent" />
|
||||
<Content class="theme-default-content" />
|
||||
|
||||
</div>
|
||||
|
||||
<PageEdit />
|
||||
<PageNav v-bind="{ sidebarItems }" />
|
||||
|
||||
<UpdateArticle />
|
||||
|
||||
<slot name="bottom" />
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageEdit from '@theme/components/PageEdit.vue'
|
||||
import PageNav from '@theme/components/PageNav.vue'
|
||||
import ArticleInfo from './ArticleInfo.vue'
|
||||
import Catalogue from './Catalogue.vue'
|
||||
import UpdateArticle from './UpdateArticle.vue'
|
||||
import Timeline from './Timeline.vue'
|
||||
import Footer from './Footer.vue'
|
||||
import RightMenu from './RightMenu.vue'
|
||||
|
||||
export default {
|
||||
components: { PageEdit, PageNav, ArticleInfo, Catalogue, UpdateArticle, Timeline, Footer, RightMenu},
|
||||
props: ['sidebarItems'],
|
||||
computed: {
|
||||
showRightMenu(){
|
||||
return this.$frontmatter && this.$frontmatter.sidebar && this.$frontmatter.sidebar !== false
|
||||
},
|
||||
pageComponent () {
|
||||
return this.$frontmatter.pageComponent ? this.$frontmatter.pageComponent.name : false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isArticle() {
|
||||
return this.$frontmatter.article !== false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
@require '../styles/wrapper.styl'
|
||||
.page
|
||||
padding-bottom 2rem
|
||||
display block
|
||||
|
||||
.theme-vdoing-wrapper
|
||||
max-width $contentWidth
|
||||
margin 0 auto
|
||||
padding 2rem 2.5rem
|
||||
position relative
|
||||
@media (max-width: $MQNarrow)
|
||||
padding 2rem
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
padding 1.5rem
|
||||
.theme-default-content
|
||||
padding 0!important
|
||||
&>.theme-default-content
|
||||
margin 0
|
||||
|
||||
// 右侧菜单的自适应
|
||||
@media (min-width: 1680px) // 在大屏时
|
||||
.theme-vdoing-wrapper,.page-edit,.page-nav,#vuepress-plugin-comment,.article:not(.article-home)
|
||||
transition: all .2s!important
|
||||
.have-rightmenu // 有右侧菜单时
|
||||
.theme-vdoing-wrapper,.page-edit,.page-nav,#vuepress-plugin-comment,.article:not(.article-home)
|
||||
transform translateX(-($rightMenuWidth / 2.5))
|
||||
|
||||
@media (min-width: 1360px) and (max-width: 1679px)
|
||||
.have-rightmenu
|
||||
.page
|
||||
transition: all 0s!important
|
||||
&.sidebar-open
|
||||
.theme-vdoing-wrapper,.page-edit,.page-nav,#vuepress-plugin-comment
|
||||
margin 0 0 0 2rem
|
||||
.article:not(.article-home)
|
||||
margin 0 0 0 4rem
|
||||
@media (min-width: 1360px) and (max-width: 1519px)
|
||||
.have-rightmenu
|
||||
.theme-vdoing-wrapper,.page-edit,.page-nav,#vuepress-plugin-comment,.article:not(.article-home)
|
||||
max-width ($contentWidth - 200px)
|
||||
.right-menu-wrapper
|
||||
margin-left ($contentWidth - 180px)
|
||||
|
||||
@media (max-width: 1359px) // 小于等于1359时隐藏右侧锚点菜单
|
||||
.right-menu-wrapper
|
||||
display none
|
||||
@media (min-width: 1360px) // 大于等于1360时隐藏左侧锚点菜单
|
||||
.sidebar .sidebar-sub-headers
|
||||
display none
|
||||
</style>
|
||||
|
|
@ -1,232 +0,0 @@
|
|||
<template>
|
||||
<div class="page-nav-wapper">
|
||||
<!-- 页面中间左右翻页 -->
|
||||
<div class="page-nav-centre-wrap" v-if="prev || next">
|
||||
<router-link
|
||||
class="page-nav-centre page-nav-centre-prev"
|
||||
v-if="prev"
|
||||
:to="prev.path"
|
||||
@mouseenter.native="showTooltip($event)"
|
||||
@mousemove.native="showTooltip($event)"
|
||||
@mouseleave.native="hideTooltip()"
|
||||
@click.native="hideTooltip()"
|
||||
:data-tooltip="prev.title || prev.path"
|
||||
/>
|
||||
|
||||
<router-link
|
||||
class="page-nav-centre page-nav-centre-next"
|
||||
v-if="next"
|
||||
:to="next.path"
|
||||
@mouseenter.native="showTooltip($event)"
|
||||
@mousemove.native="showTooltip($event)"
|
||||
@mouseleave.native="hideTooltip()"
|
||||
@click.native="hideTooltip()"
|
||||
:data-tooltip="next.title || next.path"
|
||||
/>
|
||||
<div class="tooltip" ref="tooltip" v-show="isShowTooltip">提高学习效率的策略</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部翻页按钮 -->
|
||||
<div class="page-nav" v-if="prev || next">
|
||||
<p class="inner">
|
||||
<span v-if="prev" class="prev">
|
||||
←
|
||||
<router-link v-if="prev" class="prev" :to="prev.path">{{ prev.title || prev.path }}</router-link>
|
||||
</span>
|
||||
|
||||
<span v-if="next" class="next">
|
||||
<router-link v-if="next" :to="next.path">{{ next.title || next.path }}</router-link>
|
||||
→
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { resolvePage } from '../util'
|
||||
import isString from 'lodash/isString'
|
||||
import isNil from 'lodash/isNil'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isShowTooltip: false
|
||||
}
|
||||
},
|
||||
name: 'PageNav',
|
||||
props: ['sidebarItems'],
|
||||
computed: {
|
||||
prev () {
|
||||
return resolvePageLink(LINK_TYPES.PREV, this)
|
||||
},
|
||||
|
||||
next () {
|
||||
return resolvePageLink(LINK_TYPES.NEXT, this)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showTooltip(e) {
|
||||
this.isShowTooltip = true
|
||||
const tooltipEle = this.$refs.tooltip
|
||||
|
||||
const tooltipText = e.target.dataset.tooltip
|
||||
if (tooltipEle.textContent !== tooltipText) {
|
||||
tooltipEle.textContent = tooltipText
|
||||
}
|
||||
|
||||
const clientW = document.body.clientWidth
|
||||
const X = e.clientX
|
||||
const tooltipEleStyle = tooltipEle.style
|
||||
|
||||
if (X < clientW/2) {
|
||||
tooltipEleStyle.right = null
|
||||
tooltipEleStyle.left = X + 10 + 'px'
|
||||
} else {
|
||||
tooltipEleStyle.left = null
|
||||
tooltipEleStyle.right = clientW - X + 10 + 'px'
|
||||
}
|
||||
tooltipEleStyle.top = e.clientY + 10 + 'px'
|
||||
},
|
||||
|
||||
hideTooltip() {
|
||||
this.isShowTooltip = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePrev (page, items) {
|
||||
return find(page, items, -1)
|
||||
}
|
||||
|
||||
function resolveNext (page, items) {
|
||||
return find(page, items, 1)
|
||||
}
|
||||
|
||||
const LINK_TYPES = {
|
||||
NEXT: {
|
||||
resolveLink: resolveNext,
|
||||
getThemeLinkConfig: ({ nextLinks }) => nextLinks,
|
||||
getPageLinkConfig: ({ frontmatter }) => frontmatter.next
|
||||
},
|
||||
PREV: {
|
||||
resolveLink: resolvePrev,
|
||||
getThemeLinkConfig: ({ prevLinks }) => prevLinks,
|
||||
getPageLinkConfig: ({ frontmatter }) => frontmatter.prev
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePageLink (
|
||||
linkType,
|
||||
{ $themeConfig, $page, $route, $site, sidebarItems }
|
||||
) {
|
||||
const { resolveLink, getThemeLinkConfig, getPageLinkConfig } = linkType
|
||||
|
||||
// Get link config from theme
|
||||
const themeLinkConfig = getThemeLinkConfig($themeConfig)
|
||||
|
||||
// Get link config from current page
|
||||
const pageLinkConfig = getPageLinkConfig($page)
|
||||
|
||||
// Page link config will overwrite global theme link config if defined
|
||||
const link = isNil(pageLinkConfig) ? themeLinkConfig : pageLinkConfig
|
||||
|
||||
if (link === false) {
|
||||
return
|
||||
} else if (isString(link)) {
|
||||
return resolvePage($site.pages, link, $route.path)
|
||||
} else {
|
||||
return resolveLink($page, sidebarItems)
|
||||
}
|
||||
}
|
||||
|
||||
function find (page, items, offset) {
|
||||
const res = []
|
||||
flatten(items, res)
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const cur = res[i]
|
||||
if (cur.type === 'page' && cur.path === decodeURIComponent(page.path)) {
|
||||
return res[i + offset]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function flatten (items, res) {
|
||||
for (let i = 0, l = items.length; i < l; i++) {
|
||||
if (items[i].type === 'group') {
|
||||
flatten(items[i].children || [], res)
|
||||
} else {
|
||||
res.push(items[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus">
|
||||
@require '../styles/wrapper.styl'
|
||||
|
||||
.page-nav
|
||||
@extend $wrapper
|
||||
padding-top 1rem
|
||||
padding-bottom 0
|
||||
.inner
|
||||
min-height 2rem
|
||||
margin-top 0
|
||||
border-top 1px solid $borderColor
|
||||
padding-top 1rem
|
||||
overflow auto // clear float
|
||||
.next
|
||||
float right
|
||||
|
||||
|
||||
.page-nav-centre-wrap
|
||||
.page-nav-centre
|
||||
position fixed
|
||||
top 50%
|
||||
width 80px
|
||||
height 70px
|
||||
margin-top -35px
|
||||
outline 0
|
||||
transition all .2s
|
||||
@media (max-width: 1340px)
|
||||
width 50px
|
||||
@media (max-width: 960px)
|
||||
display none
|
||||
&:hover
|
||||
background rgba(153, 153, 153, .15)
|
||||
&:before
|
||||
content: ""
|
||||
display block
|
||||
width 12px
|
||||
height 12px
|
||||
border-top 2px solid #999
|
||||
border-right 2px solid #999
|
||||
position absolute
|
||||
top 0
|
||||
right 0
|
||||
bottom 0
|
||||
left 0
|
||||
margin auto
|
||||
.tooltip
|
||||
background rgba(0, 0, 0, .5)
|
||||
color #fff
|
||||
padding 4px 8px
|
||||
font-size 13px
|
||||
border-radius 3px
|
||||
position fixed
|
||||
max-width 200px
|
||||
.page-nav-centre-prev
|
||||
left 0
|
||||
&:before
|
||||
transform rotate(-135deg)
|
||||
.page-nav-centre-next
|
||||
right: 0
|
||||
&:before
|
||||
transform rotate(45deg)
|
||||
|
||||
.sidebar-open .page-nav-centre-wrap .page-nav-centre-prev
|
||||
-webkit-transform translateX($sidebarWidth)
|
||||
transform translateX($sidebarWidth)
|
||||
.no-sidebar .page-nav-centre-wrap .page-nav-centre-prev
|
||||
-webkit-transform translateX(0)
|
||||
transform translateX(0)
|
||||
|
||||
</style>
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
<template>
|
||||
<div class="right-menu-wrapper">
|
||||
<div class="right-menu-padding">
|
||||
<div class="right-menu-content">
|
||||
<div
|
||||
:class="['right-menu-item', 'level'+item.level, { active: item.slug === hashText }]"
|
||||
v-for="(item, i) in headers"
|
||||
:key="i"
|
||||
>
|
||||
<a :href="'#'+item.slug">{{item.title}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
headers: [],
|
||||
hashText: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getHeadersData()
|
||||
this.getHashText()
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.headers = this.$page.headers
|
||||
this.getHashText()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getHeadersData() {
|
||||
this.headers = this.$page.headers
|
||||
},
|
||||
getHashText() {
|
||||
this.hashText = decodeURIComponent(window.location.hash.slice(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus'>
|
||||
.right-menu-wrapper
|
||||
width $rightMenuWidth
|
||||
height 0
|
||||
margin 0 0 0 ($contentWidth + 20px)
|
||||
position sticky
|
||||
top 0
|
||||
font-size .9rem
|
||||
.right-menu-padding
|
||||
padding-top ($navbarHeight + 3rem)
|
||||
.right-menu-content
|
||||
max-height 80vh
|
||||
position relative
|
||||
overflow hidden
|
||||
&::-webkit-scrollbar-track-piece
|
||||
background none
|
||||
&::-webkit-scrollbar-thumb:vertical
|
||||
background-color hsla(0,0%,49%,.3)
|
||||
&:hover
|
||||
overflow-y auto
|
||||
.right-menu-item
|
||||
padding 4px 15px
|
||||
border-left .2rem solid #E4E4E4
|
||||
&.level3
|
||||
padding-left 28px
|
||||
&.active
|
||||
border-color $accentColor
|
||||
a
|
||||
color $accentColor
|
||||
opacity 1
|
||||
a
|
||||
color $textColor
|
||||
opacity 0.75
|
||||
display block
|
||||
width ($rightMenuWidth - 30px)
|
||||
&:hover
|
||||
color $accentColor
|
||||
</style>
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
<template>
|
||||
<aside class="sidebar">
|
||||
<div class="blogger" v-if="blogger">
|
||||
<img :src="blogger.avatar">
|
||||
<div class="blogger-info">
|
||||
<h3>{{blogger.name}}</h3>
|
||||
|
||||
<div class="icons" v-if="blogger.social">
|
||||
<a
|
||||
:href="item.link"
|
||||
:title="item.title"
|
||||
:class="['iconfont', item.iconClass]"
|
||||
v-for="(item, index) in blogger.social.icons"
|
||||
:key="index"
|
||||
target="_blank"
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
<span v-else>
|
||||
{{blogger.slogan}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<NavLinks/>
|
||||
<slot name="top"/>
|
||||
<SidebarLinks :depth="0" :items="items"/>
|
||||
<slot name="bottom"/>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SidebarLinks from '@theme/components/SidebarLinks.vue'
|
||||
import NavLinks from '@theme/components/NavLinks.vue'
|
||||
|
||||
export default {
|
||||
name: 'Sidebar',
|
||||
|
||||
components: { SidebarLinks, NavLinks },
|
||||
|
||||
props: ['items'],
|
||||
|
||||
computed: {
|
||||
blogger() {
|
||||
return this.$themeConfig.blogger
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.sidebar
|
||||
ul
|
||||
padding 0
|
||||
margin 0
|
||||
list-style-type none
|
||||
a
|
||||
display inline-block
|
||||
.nav-links
|
||||
display none
|
||||
border-bottom 1px solid $borderColor
|
||||
padding 0.5rem 0 0.75rem 0
|
||||
a
|
||||
font-weight 600
|
||||
.nav-item, .repo-link
|
||||
display block
|
||||
line-height 1.25rem
|
||||
font-size 1.1em
|
||||
padding 0.5rem 0 0.5rem 1.5rem
|
||||
& > .sidebar-links
|
||||
padding 1.5rem 0
|
||||
& > li > a.sidebar-link
|
||||
font-size 1.1em
|
||||
line-height 1.7
|
||||
font-weight bold
|
||||
& > li:not(:first-child)
|
||||
margin-top .75rem
|
||||
.blogger
|
||||
display none
|
||||
border-bottom 1px solid $borderColor
|
||||
img
|
||||
width 60px
|
||||
height 60px
|
||||
border-radius 5px
|
||||
margin .75rem 1rem
|
||||
.blogger-info
|
||||
flex 1
|
||||
h3
|
||||
margin .95rem 0 .7rem
|
||||
font-size 1.1rem
|
||||
.icons .iconfont
|
||||
font-size 1.2rem
|
||||
padding-right .6rem
|
||||
color #777
|
||||
@media (max-width: $MQMobile)
|
||||
.sidebar
|
||||
.blogger
|
||||
display flex
|
||||
.nav-links
|
||||
display block
|
||||
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
|
||||
top calc(1rem - 2px)
|
||||
& > .sidebar-links
|
||||
padding 1rem 0
|
||||
</style>
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<template>
|
||||
<div class="sidebar-button" @click="$emit('toggle-sidebar')" title="目录">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512">
|
||||
<path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="stylus">
|
||||
.sidebar-button
|
||||
cursor pointer
|
||||
display none
|
||||
width 1.25rem
|
||||
height 1.25rem
|
||||
position absolute
|
||||
padding 0.6rem
|
||||
top 0.6rem
|
||||
left 1rem
|
||||
@media (max-width: $MQMobile)
|
||||
display block
|
||||
.icon
|
||||
display block
|
||||
width 1.25rem
|
||||
height 1.25rem
|
||||
|
||||
@media (min-width: ($MQMobile + 1px))
|
||||
$mobileSidebarWidth = $sidebarWidth * 0.82
|
||||
.sidebar-button
|
||||
width 40px
|
||||
height 40px
|
||||
display inline-block
|
||||
position fixed
|
||||
left 0
|
||||
top $navbarHeight
|
||||
text-align center
|
||||
line-height 44px
|
||||
margin 5px 8px
|
||||
color #888
|
||||
border-radius 50%
|
||||
padding 0
|
||||
transition all .2s ease
|
||||
&:hover
|
||||
box-shadow 0 2px 6px rgba(0,0,0,.15)
|
||||
.icon
|
||||
display inline
|
||||
width 1rem
|
||||
height 1rem
|
||||
</style>
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
<template>
|
||||
<div class="timeline-wrapper theme-default-content">
|
||||
<div class="tags">
|
||||
<a href="#全部" :class="{active: currentTag === '全部'}" :style="randomBgcolor()" @click="toggleTag('全部')">全部</a>
|
||||
<a
|
||||
:class="{active: currentTag === key}"
|
||||
v-for="(item, key) of getPages.tagGroup"
|
||||
:style="randomBgcolor()"
|
||||
@click="toggleTag(key)"
|
||||
:key="key"
|
||||
:href="'#'+key"
|
||||
>
|
||||
{{key}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="timeline">
|
||||
<transition-group tag="ul">
|
||||
<li class="desc" key="0">{{pageData.slogan}}</li>
|
||||
<template v-for="yearItem in tagPages()">
|
||||
<li :key="yearItem.year">
|
||||
<h3 class="year">{{yearItem.year}}</h3>
|
||||
<div class="year-wrapper">
|
||||
<transition-group tag="span">
|
||||
<router-link :to="item.path" v-for="item in yearItem.pageList" :key="item.path.slice(-6)">
|
||||
<span class="date">{{item.formatDay}}</span>
|
||||
<span class="title">{{item.title}}</span>
|
||||
</router-link>
|
||||
</transition-group>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</transition-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getPagesList } from '../util/getArticleDate'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pageData: {
|
||||
tagBgColor: ['#11a8cd', '#F8B26A', '#67CC86', '#E15B64', '#F47E60', '#849B87'],
|
||||
slogan: '只争朝夕,不负韶华!( •̀ ω •́ )✧'
|
||||
},
|
||||
currentTag: "",
|
||||
posts: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const fmData = this.$frontmatter.pageComponent.data
|
||||
if(fmData && fmData.tagBgColor) {
|
||||
this.pageData.tagBgColor = fmData.tagBgColor
|
||||
}
|
||||
if(fmData && fmData.slogan) {
|
||||
this.pageData.slogan = fmData.slogan
|
||||
}
|
||||
|
||||
this.posts = this.$site.pages
|
||||
document.body.style="overflow-y: scroll;" // 解决切换tag页面高度不满屏出现跳动的问题
|
||||
|
||||
this.handleHashTag()
|
||||
|
||||
window.onhashchange = () => {
|
||||
this.handleHashTag()
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
getPages() {
|
||||
return getPagesList(this.posts)
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentTag(tag) {
|
||||
document.body.setAttribute('id', tag); // 用于解决vue-router在处理描点元素定位时的报错
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleHashTag() {
|
||||
const hashTag = decodeURIComponent(window.location.hash.slice(1))
|
||||
this.currentTag = hashTag ? hashTag : '全部'
|
||||
},
|
||||
// 根据标签获取数据
|
||||
tagPages() {
|
||||
if (this.currentTag === "全部") {
|
||||
return this.getPages.allPage
|
||||
} else {
|
||||
return this.getPages.tagGroup[this.currentTag]
|
||||
}
|
||||
},
|
||||
// 切换标签
|
||||
toggleTag(tag) {
|
||||
this.currentTag = tag
|
||||
},
|
||||
|
||||
// 随机背景色
|
||||
randomBgcolor() {
|
||||
const tagBgColor = this.pageData.tagBgColor
|
||||
return { background: `${tagBgColor[Math.floor(Math.random() * tagBgColor.length)]}`}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="stylus" rel="stylesheet/stylus">
|
||||
.timeline-wrapper
|
||||
.tags
|
||||
margin-bottom 30px
|
||||
a
|
||||
vertical-align: middle;
|
||||
margin: 4px 4px 10px;
|
||||
padding: 5px 8px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
border-radius: .25rem;
|
||||
background: #E15B64;
|
||||
color: #fff;
|
||||
line-height: 13px;
|
||||
font-size: 13px;
|
||||
transition: all .5s;
|
||||
opacity: 0.9;
|
||||
box-shadow: 2px 2px 5px #ccc;
|
||||
&.active
|
||||
transform: scale(1.2);
|
||||
opacity: 1;
|
||||
&:hover
|
||||
text-decoration: none!important;
|
||||
&:not(.active):hover
|
||||
transform: scale(1.05);
|
||||
|
||||
|
||||
.v-enter{
|
||||
opacity: 0;
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
.v-leave-active{
|
||||
display:none;
|
||||
}
|
||||
.v-leave{
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
ul
|
||||
list-style: none;
|
||||
.timeline ul
|
||||
box-sizing: border-box;
|
||||
margin: 4rem auto;
|
||||
position: relative;
|
||||
&:after
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: 0;
|
||||
// z-index: -1;
|
||||
margin-left: -2px;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: $borderColor;
|
||||
>li
|
||||
transition: all .25s ease-in-out;
|
||||
margin-bottom: 55px;
|
||||
.year
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
font-size: 26px;
|
||||
.desc,.year
|
||||
position: relative;
|
||||
.desc:before,.year:before
|
||||
content: " ";
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
left: -20px;
|
||||
top: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #fff;
|
||||
border: 1px solid $borderColor;
|
||||
border-radius: 50%;
|
||||
.year-wrapper
|
||||
padding-left: 0!important;
|
||||
a
|
||||
display: flex;
|
||||
padding: 30px 0 10px;
|
||||
list-style: none;
|
||||
border-bottom: 1px dashed $borderColor;
|
||||
position: relative;
|
||||
color: #666;
|
||||
transition: all 0.25s ease-in-out;
|
||||
.date
|
||||
min-width: 40px;
|
||||
line-height: 30px;
|
||||
font-size: 13px;
|
||||
margin-right: 5px;
|
||||
color: #999;
|
||||
&:before
|
||||
content: " ";
|
||||
position: absolute;
|
||||
left: -19px;
|
||||
top: 41px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-left: -4px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
border: 1px solid $borderColor;
|
||||
z-index: 2;
|
||||
&:hover
|
||||
text-decoration:none
|
||||
color: $accentColor
|
||||
.date
|
||||
color: $accentColor
|
||||
.date:before
|
||||
background: $accentColor
|
||||
</style>
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
<template>
|
||||
<div :class="['article',{ 'article-home': pageMark === 'home', 'no-article': isShowArticle}]">
|
||||
<div class="article-title">
|
||||
<h1 v-if="pageMark === 'home'">
|
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAABKFJREFUSA3tVl1oFVcQnrMbrak3QUgkya1akpJYcrUtIqW1JvFBE9LiQ5v6JmJpolbMg32rVrhgoYK0QiMY6i9Y6EMaW5D+xFJaTYItIuK2Kr3+BJNwkxBj05sQY3b3nM6cs2dv9t7NT/vQJw/sndk5M/PNzJkzewGerP+pAmy+ON8lLzUJgA8ZYxYIYZmGYRnctDaWvJJAmTtfP1pvXsBCCPP8QFcCaRkZYACgDZFO4stNIcBCajEOlmmC9XpJ9bAGCaPaPmzPl32dvLSVu3BWCTQs0XQQ6g0DYgwLIoAZbBCdW/i+781o1VVlm/410mw4h06Y7bIPHNyWDyL4FHkX03Q8SrzNhZTZriieckWt7cL6MM85YcLpsi/7O9/iXFT6MswI0DmmpkSaJ0qLxFIm3+i1THHB3zmBH3PYx9CcykcLOeQVVa7QtdxTgQgEleX2AjHYfwA+2ddV77ruGoJUbhGDI09YSNXyMpUt5ylOzxgbUmtOp7NmbNt8v3arjTBfYELmLUV+M+nSawNNAUqpT3ClJWg5I3BLT+cGW/DXNGCa6tx1aakCGEigArTn4TDIPdrXXYKCZNrHLMCOEPvHBlLQ99s9eHB7EB6NTki73CVPQ2F5MSx/uRQixfmq7rK0wYD8w8E905bnPDfwoWs/rfv93NWN/ZfvwsLIU7A09gxECyISeGJkHAau98L97tuw7NXnoPyNF8FcYGLGKsOs0mN3OEyec9esGW/ZEl945dTP34wlR2FZVQWU1q0Cw8Tr7p+hgLLNL0FPxx/Q35mA8aEUrH6nCgwEl0tn7wUiZYJnNRh6DK4UH/k0lfyrsBKdPVv/AriGIQcEDQZ65LBAGe2Rzui9Ybjz7XUppz1/uKBbyVPGkN3ZAeC6hr0x7Nr38N5+EqkoOm17xpoqR9ohQF55ERSvr4Dkr3chNfC3DMzGJlNBElW8w9nsGQvhNGIzDkXzCg8cLK951xHsFBlTJspJNi3ZFIMF2AeDV3q8DNOB+YHi6QTrChDIWDBRi5U5f+ZMfJLu3ccrqxtdxk4SKH336LFxSmkqefwU5T8fhdSdQf9IVKD6aNiwI/hnmcAZ91isYMJIaCUCx9W098+LgruikeTqzqqxKPUwqJyCPJiyemVVZBOijDGjD38Os0jOiSPL1z3SPjXNANbiNPXAdzTfukjjuknNBbyz3nwgTd3AVFqUJ5hpHlq9MveLnWwttUfoygBmvVjuikxND3znrhsELnZk7k+OjIGxeNEkomyLVta0xxn+HZhjBc4YZ/AFjHjz9u3xRZl2BN4aq9nFwWh16IrQ1aHHEd3j1+4/dB9OtH4e29A2H1DyHQRmOSfQZ1Fy7MHBTGB6J/Djq6p3OxyO2cB+4Car7v/o3GXgfAkj23+x9ID1Teoamo/SXcbvSf2PX7Vc8DdCmE1vN9di+32P9/5YR3vLnhCVGUWBjEkr3yh4H8v9CzmsbdhzOKzsJKM90iFdaTMjRPhGVsakRvOaRidljo6H6G7j+ctrJpsP+4COhDIl0La2+FS4+5mlocBaXY5QnGZysIBYoeSsl5qQzrSj/cgNrfuEzlWBfwA+EjrZyWUvpAAAAABJRU5ErkJggg==">
|
||||
最近更新
|
||||
</h1>
|
||||
<span v-else>最近更新</span>
|
||||
</div>
|
||||
<div class="article-wrapper">
|
||||
<dl v-for="(item, index) in topPublishPosts" :key="index">
|
||||
<dd>{{'0' + (index + 1)}}</dd>
|
||||
<dt>
|
||||
<router-link :to="item.path"><div>{{item.title}}</div></router-link>
|
||||
<span>{{item.formatDay}}</span>
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dd></dd>
|
||||
<dt>
|
||||
<router-link to="/timeline/" class="more">更多文章></router-link>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getTopKPosts } from '../util/getArticleDate'
|
||||
|
||||
export default {
|
||||
props: ['pageMark'],
|
||||
data() {
|
||||
return {
|
||||
posts: [],
|
||||
currentPath: ''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.posts = this.$site.pages
|
||||
this.currentPath = this.$page.path
|
||||
},
|
||||
computed: {
|
||||
topPublishPosts() {
|
||||
const count = this.pageMark === 'home' ? 5 : 3
|
||||
return getTopKPosts(this.posts, count, this.currentPath)
|
||||
},
|
||||
isShowArticle () {
|
||||
const { frontmatter } = this.$page
|
||||
return !(frontmatter.article !== false)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.currentPath = this.$page.path
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus'>
|
||||
.article
|
||||
max-width $contentWidth
|
||||
margin 0 auto
|
||||
padding 2rem 2.5rem 0 2.5rem
|
||||
&:not(.article-home)
|
||||
margin 2rem auto 0 auto
|
||||
border 8px solid rgba(160,160,160,.1)
|
||||
box-sizing border-box
|
||||
@media (max-width: $MQNarrow)
|
||||
padding 2rem 2rem 0rem 2rem
|
||||
&:not(.article-home)
|
||||
border-width 10px
|
||||
border-left none
|
||||
border-right none
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
padding 1.5rem 1.5rem 0rem 1.5rem
|
||||
&.article-home
|
||||
max-width: 100%
|
||||
padding 0 0 2rem 0
|
||||
&.no-article
|
||||
display none
|
||||
.article-title
|
||||
border-bottom 1px solid #eaecef
|
||||
font-size 1.3rem
|
||||
font-weight bold
|
||||
padding 0 0 .5rem 1rem
|
||||
h1
|
||||
font-size 1.6rem
|
||||
img
|
||||
width 1.6rem
|
||||
margin-bottom: -4px;
|
||||
.article-wrapper
|
||||
overflow hidden
|
||||
dl
|
||||
border-bottom 1px dotted #eaecef
|
||||
float left
|
||||
display flex
|
||||
padding 8px 0
|
||||
margin 0
|
||||
height 55px
|
||||
width 100%
|
||||
// width 50%
|
||||
// @media (max-width: $MQNarrow)
|
||||
// width 100%
|
||||
&:last-child
|
||||
border-bottom none
|
||||
dd
|
||||
font-size 1.1rem
|
||||
color #F17229
|
||||
width 50px
|
||||
margin-left 22px
|
||||
font-weight bold
|
||||
line-height: 55px;
|
||||
@media (max-width: $MQNarrow)
|
||||
width 45px
|
||||
dt
|
||||
flex 1
|
||||
display flex
|
||||
a
|
||||
color $textColor
|
||||
flex 1
|
||||
display: flex;
|
||||
height: 55px;
|
||||
align-items: center;
|
||||
div
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
&:hover
|
||||
text-decoration underline
|
||||
&.more
|
||||
color $accentColor
|
||||
span
|
||||
width 100px
|
||||
margin-right 15px
|
||||
color #999
|
||||
text-align right
|
||||
font-size .9rem
|
||||
line-height: 55px;
|
||||
@media (max-width: $MQNarrow)
|
||||
width 95px
|
||||
</style>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = {
|
||||
extend: '@vuepress/theme-default' // 继承到默认主题
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,224 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
class="theme-container"
|
||||
:class="pageClasses"
|
||||
@touchstart="onTouchStart"
|
||||
@touchend="onTouchEnd"
|
||||
>
|
||||
<Navbar
|
||||
v-if="shouldShowNavbar"
|
||||
@toggle-sidebar="toggleSidebar"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="sidebar-mask"
|
||||
@click="toggleSidebar(false)"
|
||||
></div>
|
||||
|
||||
<Sidebar
|
||||
:items="sidebarItems"
|
||||
@toggle-sidebar="toggleSidebar"
|
||||
v-show="showSidebar"
|
||||
>
|
||||
<slot
|
||||
name="sidebar-top"
|
||||
#top
|
||||
/>
|
||||
<slot
|
||||
name="sidebar-bottom"
|
||||
#bottom
|
||||
/>
|
||||
</Sidebar>
|
||||
|
||||
<Home v-if="$page.frontmatter.home"/>
|
||||
|
||||
<Page
|
||||
v-else
|
||||
:sidebar-items="sidebarItems"
|
||||
>
|
||||
<slot
|
||||
name="page-top"
|
||||
#top
|
||||
/>
|
||||
<slot
|
||||
name="page-bottom"
|
||||
#bottom
|
||||
/>
|
||||
</Page>
|
||||
|
||||
<Buttons
|
||||
@toggle-read-mode="toggleReadMode"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Home from '@theme/components/Home.vue'
|
||||
import Navbar from '@theme/components/Navbar.vue'
|
||||
import Page from '@theme/components/Page.vue'
|
||||
import Sidebar from '@theme/components/Sidebar.vue'
|
||||
import Buttons from '@theme/components/Buttons.vue'
|
||||
import { resolveSidebarItems } from '../util'
|
||||
import storage from 'good-storage' // 本地存储
|
||||
|
||||
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
|
||||
|
||||
export default {
|
||||
components: { Home, Page, Sidebar, Navbar, Buttons },
|
||||
|
||||
data () {
|
||||
return {
|
||||
isSidebarOpen: true,
|
||||
showSidebar: false,
|
||||
readMode: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showRightMenu() {
|
||||
const { headers } = this.$page
|
||||
return (
|
||||
!this.$frontmatter.home
|
||||
&& headers
|
||||
&& headers.length
|
||||
&& this.$frontmatter.sidebar !== false
|
||||
)
|
||||
},
|
||||
shouldShowNavbar () {
|
||||
const { themeConfig } = this.$site
|
||||
const { frontmatter } = this.$page
|
||||
if (
|
||||
frontmatter.navbar === false
|
||||
|| themeConfig.navbar === false) {
|
||||
return false
|
||||
}
|
||||
return (
|
||||
this.$title
|
||||
|| themeConfig.logo
|
||||
|| themeConfig.repo
|
||||
|| themeConfig.nav
|
||||
|| this.$themeLocaleConfig.nav
|
||||
)
|
||||
},
|
||||
|
||||
shouldShowSidebar () {
|
||||
const { frontmatter } = this.$page
|
||||
return (
|
||||
!frontmatter.home
|
||||
&& frontmatter.sidebar !== false
|
||||
&& this.sidebarItems.length
|
||||
)
|
||||
},
|
||||
|
||||
sidebarItems () {
|
||||
return resolveSidebarItems(
|
||||
this.$page,
|
||||
this.$page.regularPath,
|
||||
this.$site,
|
||||
this.$localePath
|
||||
)
|
||||
},
|
||||
|
||||
pageClasses () {
|
||||
const userPageClass = this.$page.frontmatter.pageClass
|
||||
return [
|
||||
{
|
||||
'no-navbar': !this.shouldShowNavbar,
|
||||
'sidebar-open': this.isSidebarOpen,
|
||||
'no-sidebar': !this.shouldShowSidebar,
|
||||
'have-rightmenu': this.showRightMenu,
|
||||
'theme-read-mode': this.readMode
|
||||
},
|
||||
userPageClass
|
||||
]
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.isSidebarOpenOfclientWidth()
|
||||
if(storage.get('mode')) {
|
||||
this.readMode = true
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.showSidebar = true // 解决移动端初始化页面时侧边栏闪现的问题
|
||||
this.$router.afterEach(() => {
|
||||
this.isSidebarOpenOfclientWidth()
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
isSidebarOpenOfclientWidth() {
|
||||
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
|
||||
this.isSidebarOpen = false
|
||||
}
|
||||
},
|
||||
toggleSidebar (to) {
|
||||
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
|
||||
this.$emit('toggle-sidebar', this.isSidebarOpen)
|
||||
},
|
||||
toggleReadMode (){
|
||||
this.readMode = !this.readMode
|
||||
storage.set('mode', this.readMode)
|
||||
// if (document.documentElement.clientWidth > MOBILE_DESKTOP_BREAKPOINT) {
|
||||
// this.isSidebarOpen = !this.readMode
|
||||
// }
|
||||
},
|
||||
// side swipe
|
||||
onTouchStart (e) {
|
||||
this.touchStart = {
|
||||
x: e.changedTouches[0].clientX,
|
||||
y: e.changedTouches[0].clientY
|
||||
}
|
||||
},
|
||||
|
||||
onTouchEnd (e) {
|
||||
const dx = e.changedTouches[0].clientX - this.touchStart.x
|
||||
const dy = e.changedTouches[0].clientY - this.touchStart.y
|
||||
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
|
||||
if (dx > 0 && this.touchStart.x <= 80) {
|
||||
this.toggleSidebar(true)
|
||||
} else {
|
||||
this.toggleSidebar(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
// 阅读模式样式
|
||||
.theme-read-mode
|
||||
min-height 100vh
|
||||
background $readModeColor
|
||||
.i-body // 首页
|
||||
background-color $readModeColor
|
||||
.banner,.home .hero .description,.home .feature h2,.slide-banner .slide-banner-wrapper .slide-item h2 // banner栏
|
||||
color lighten($readModeColor, 50%)
|
||||
.main-wrapper >*
|
||||
background-color lighten($readModeColor, 50%)!important
|
||||
.sidebar // 侧边栏
|
||||
@media (max-width: $MQNarrow)
|
||||
background-color lighten($readModeColor, 30%)!important
|
||||
.navbar // 导航栏
|
||||
background $readModeColor
|
||||
.dropdown-wrapper .nav-dropdown
|
||||
background lighten($readModeColor, 50%)
|
||||
.suggestions // 搜索结果
|
||||
background lighten($readModeColor, 50%)
|
||||
.buttons // 右下角按钮
|
||||
.button
|
||||
background lighten($readModeColor, 50%)
|
||||
.read-mode // 阅读模式按钮
|
||||
background lighten($accentColor, 30%)
|
||||
opacity .85
|
||||
color #fff
|
||||
&:hover
|
||||
opacity 1
|
||||
color #fff
|
||||
tr // 表格
|
||||
&:nth-child(2n)
|
||||
background-color lighten($readModeColor, 50%)
|
||||
// 时间轴页面
|
||||
.timeline-wrapper .timeline ul .desc:before, .timeline-wrapper .timeline ul .year:before,.timeline-wrapper .timeline ul .year-wrapper a .date:before
|
||||
background-color $readModeColor!important
|
||||
</style>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
$wrapper
|
||||
max-width $contentWidth
|
||||
margin 0 auto
|
||||
padding 2rem 2.5rem
|
||||
@media (max-width: $MQNarrow)
|
||||
padding 2rem
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
padding 1.5rem
|
||||
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
const re = /.*\/(.*?)\.(html|md)/
|
||||
|
||||
export function getPagesList(posts) {
|
||||
let pagesList = {}
|
||||
let tagGroup = {}
|
||||
|
||||
// 过滤非文章页
|
||||
posts = filterNotArticle(posts)
|
||||
|
||||
// 对页面数据二次处理和排序
|
||||
const pages = posts.map(post => {
|
||||
// const execs = re.exec(post.relativePath)
|
||||
const date = new Date(post.frontmatter.date || post.lastUpdated)
|
||||
const pathArr = post.relativePath.split('/')
|
||||
|
||||
return {
|
||||
// ...post,
|
||||
title: post.title,
|
||||
path: post.path,
|
||||
// lastUpdated: post.lastUpdated,
|
||||
updateTimestamp: date.getTime(), // 更新日期的时间戳
|
||||
// filename: execs ? execs['1'] : '',
|
||||
formatDay: formatDate(date),
|
||||
year: date.getFullYear(),
|
||||
tag: /\./g.test(pathArr[0]) ? pathArr[1].split('.')[1] : pathArr[0] // 区分是单独合集的笔记还是文章
|
||||
}
|
||||
}).sort((a, b) => b.updateTimestamp - a.updateTimestamp)
|
||||
|
||||
|
||||
// 根据年份对数据分组
|
||||
let pageYearArr = []
|
||||
let pageYearObj = {}
|
||||
pages.forEach( page => {
|
||||
// 全部
|
||||
if (!pageYearObj[page.year]){
|
||||
pageYearArr.push({
|
||||
year: page.year,
|
||||
pageList: [page]
|
||||
})
|
||||
pageYearObj[page.year] = page
|
||||
} else {
|
||||
pageYearArr.forEach(ele => {
|
||||
if (ele.year == page.year){
|
||||
ele.pageList.push(page)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 加入标签属性
|
||||
if (!tagGroup[page.tag]) {
|
||||
tagGroup[page.tag] = []
|
||||
}
|
||||
})
|
||||
|
||||
// 根据标签分组
|
||||
for (let item in tagGroup) { // 循环标签
|
||||
|
||||
for(let i in pageYearArr) { // 循环全部
|
||||
const filterTag = pageYearArr[i].pageList.filter(page => { // 按标签过滤
|
||||
return page.tag === item
|
||||
})
|
||||
if (filterTag.length) { // 该年份中有数据才加入
|
||||
tagGroup[item].push({
|
||||
year: pageYearArr[i].year,
|
||||
pageList: filterTag
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
pagesList.tagGroup = tagGroup
|
||||
pagesList.allPage = pageYearArr // 加入全部
|
||||
|
||||
return pagesList
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function getTopKPosts(posts, len, currentPath) {
|
||||
return filterNotArticle(posts, currentPath)
|
||||
.map(post => {
|
||||
const execs = re.exec(post.relativePath)
|
||||
return {
|
||||
...post,
|
||||
updateTimestamp: (new Date(post.frontmatter.date || post.lastUpdated)).getTime(), // 更新日期的时间戳
|
||||
filename: execs ? execs['1'] : '',
|
||||
formatDay: formatDate(new Date(post.frontmatter.date || post.lastUpdated))
|
||||
}
|
||||
})
|
||||
.sort((a, b) => b.updateTimestamp - a.updateTimestamp)
|
||||
.slice(0,len)
|
||||
}
|
||||
|
||||
// 过滤没有frontmatter数据的 和 非文章页面的,
|
||||
function filterNotArticle(posts, currentPath){
|
||||
return posts.filter(post => {
|
||||
const { frontmatter, path } = post;
|
||||
if (currentPath) { // 过滤是当前页面的
|
||||
return frontmatter && frontmatter.permalink && frontmatter.title && frontmatter.article !== false && path !== currentPath;
|
||||
} else {
|
||||
return frontmatter && frontmatter.permalink && frontmatter.title && frontmatter.article !== false;
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 日期格式化
|
||||
function formatDate(date) {
|
||||
if (!(date instanceof Date)) {
|
||||
return
|
||||
}
|
||||
// return `${date.getFullYear()}/${zero(date.getMonth() + 1)}/${zero(date.getDate())}`
|
||||
return `${zero(date.getMonth() + 1)}-${zero(date.getDate())}`
|
||||
}
|
||||
|
||||
// 补0
|
||||
function zero(d) {
|
||||
return d.toString().padStart(2,'0')
|
||||
}
|
||||
|
|
@ -1,245 +0,0 @@
|
|||
export const hashRE = /#.*$/
|
||||
export const extRE = /\.(md|html)$/
|
||||
export const endingSlashRE = /\/$/
|
||||
export const outboundRE = /^[a-z]+:/i
|
||||
|
||||
export function normalize (path) {
|
||||
return decodeURI(path)
|
||||
.replace(hashRE, '')
|
||||
.replace(extRE, '')
|
||||
}
|
||||
|
||||
export function getHash (path) {
|
||||
const match = path.match(hashRE)
|
||||
if (match) {
|
||||
return match[0]
|
||||
}
|
||||
}
|
||||
|
||||
export function isExternal (path) {
|
||||
return outboundRE.test(path)
|
||||
}
|
||||
|
||||
export function isMailto (path) {
|
||||
return /^mailto:/.test(path)
|
||||
}
|
||||
|
||||
export function isTel (path) {
|
||||
return /^tel:/.test(path)
|
||||
}
|
||||
|
||||
export function ensureExt (path) {
|
||||
if (isExternal(path)) {
|
||||
return path
|
||||
}
|
||||
const hashMatch = path.match(hashRE)
|
||||
const hash = hashMatch ? hashMatch[0] : ''
|
||||
const normalized = normalize(path)
|
||||
|
||||
if (endingSlashRE.test(normalized)) {
|
||||
return path
|
||||
}
|
||||
return normalized + '.html' + hash
|
||||
}
|
||||
|
||||
export function isActive (route, path) {
|
||||
const routeHash = route.hash
|
||||
const linkHash = getHash(path)
|
||||
if (linkHash && routeHash !== linkHash) {
|
||||
return false
|
||||
}
|
||||
const routePath = normalize(route.path)
|
||||
const pagePath = normalize(path)
|
||||
return routePath === pagePath
|
||||
}
|
||||
|
||||
export function resolvePage (pages, rawPath, base) {
|
||||
if (isExternal(rawPath)) {
|
||||
return {
|
||||
type: 'external',
|
||||
path: rawPath
|
||||
}
|
||||
}
|
||||
if (base) {
|
||||
rawPath = resolvePath(rawPath, base)
|
||||
}
|
||||
const path = normalize(rawPath)
|
||||
for (let i = 0; i < pages.length; i++) {
|
||||
if (normalize(pages[i].regularPath) === path) {
|
||||
return Object.assign({}, pages[i], {
|
||||
type: 'page',
|
||||
path: ensureExt(pages[i].path)
|
||||
})
|
||||
}
|
||||
}
|
||||
console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
|
||||
return {}
|
||||
}
|
||||
|
||||
function resolvePath (relative, base, append) {
|
||||
const firstChar = relative.charAt(0)
|
||||
if (firstChar === '/') {
|
||||
return relative
|
||||
}
|
||||
|
||||
if (firstChar === '?' || firstChar === '#') {
|
||||
return base + relative
|
||||
}
|
||||
|
||||
const stack = base.split('/')
|
||||
|
||||
// remove trailing segment if:
|
||||
// - not appending
|
||||
// - appending to trailing slash (last segment is empty)
|
||||
if (!append || !stack[stack.length - 1]) {
|
||||
stack.pop()
|
||||
}
|
||||
|
||||
// resolve relative path
|
||||
const segments = relative.replace(/^\//, '').split('/')
|
||||
for (let i = 0; i < segments.length; i++) {
|
||||
const segment = segments[i]
|
||||
if (segment === '..') {
|
||||
stack.pop()
|
||||
} else if (segment !== '.') {
|
||||
stack.push(segment)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure leading slash
|
||||
if (stack[0] !== '') {
|
||||
stack.unshift('')
|
||||
}
|
||||
|
||||
return stack.join('/')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param { Page } page
|
||||
* @param { string } regularPath
|
||||
* @param { SiteData } site
|
||||
* @param { string } localePath
|
||||
* @returns { SidebarGroup }
|
||||
*/
|
||||
export function resolveSidebarItems (page, regularPath, site, localePath) {
|
||||
const { pages, themeConfig } = site
|
||||
|
||||
const localeConfig = localePath && themeConfig.locales
|
||||
? themeConfig.locales[localePath] || themeConfig
|
||||
: themeConfig
|
||||
|
||||
const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
|
||||
if (pageSidebarConfig === 'auto') {
|
||||
return resolveHeaders(page)
|
||||
}
|
||||
|
||||
const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
|
||||
if (!sidebarConfig) {
|
||||
return []
|
||||
} else {
|
||||
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
|
||||
return config
|
||||
? config.map(item => resolveItem(item, pages, base))
|
||||
: []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param { Page } page
|
||||
* @returns { SidebarGroup }
|
||||
*/
|
||||
function resolveHeaders (page) {
|
||||
const headers = groupHeaders(page.headers || [])
|
||||
return [{
|
||||
type: 'group',
|
||||
collapsable: false,
|
||||
title: page.title,
|
||||
path: null,
|
||||
children: headers.map(h => ({
|
||||
type: 'auto',
|
||||
title: h.title,
|
||||
basePath: page.path,
|
||||
path: page.path + '#' + h.slug,
|
||||
children: h.children || []
|
||||
}))
|
||||
}]
|
||||
}
|
||||
|
||||
export function groupHeaders (headers) {
|
||||
// group h3s under h2
|
||||
headers = headers.map(h => Object.assign({}, h))
|
||||
let lastH2
|
||||
headers.forEach(h => {
|
||||
if (h.level === 2) {
|
||||
lastH2 = h
|
||||
} else if (lastH2) {
|
||||
(lastH2.children || (lastH2.children = [])).push(h)
|
||||
}
|
||||
})
|
||||
return headers.filter(h => h.level === 2)
|
||||
}
|
||||
|
||||
export function resolveNavLinkItem (linkItem) {
|
||||
return Object.assign(linkItem, {
|
||||
type: linkItem.items && linkItem.items.length ? 'links' : 'link'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param { Route } route
|
||||
* @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
|
||||
* @returns { base: string, config: SidebarConfig }
|
||||
*/
|
||||
export function resolveMatchingConfig (regularPath, config) {
|
||||
if (Array.isArray(config)) {
|
||||
return {
|
||||
base: '/',
|
||||
config: config
|
||||
}
|
||||
}
|
||||
for (const base in config) {
|
||||
if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
|
||||
return {
|
||||
base,
|
||||
config: config[base]
|
||||
}
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
function ensureEndingSlash (path) {
|
||||
return /(\.html|\/)$/.test(path)
|
||||
? path
|
||||
: path + '/'
|
||||
}
|
||||
|
||||
function resolveItem (item, pages, base, groupDepth = 1) {
|
||||
if (typeof item === 'string') {
|
||||
return resolvePage(pages, item, base)
|
||||
} else if (Array.isArray(item)) {
|
||||
return Object.assign(resolvePage(pages, item[0], base), {
|
||||
title: item[1]
|
||||
})
|
||||
} else {
|
||||
if (groupDepth > 3) {
|
||||
console.error(
|
||||
'[vuepress] detected a too deep nested sidebar group.'
|
||||
)
|
||||
}
|
||||
const children = item.children || []
|
||||
if (children.length === 0 && item.path) {
|
||||
return Object.assign(resolvePage(pages, item.path, base), {
|
||||
title: item.title
|
||||
})
|
||||
}
|
||||
return {
|
||||
type: 'group',
|
||||
path: item.path,
|
||||
title: item.title,
|
||||
sidebarDepth: item.sidebarDepth,
|
||||
children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
|
||||
collapsable: item.collapsable !== false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,11 +93,11 @@ export default {
|
|||
.ds-suggestions
|
||||
margin-top 0
|
||||
.ds-suggestion
|
||||
border-bottom 1px solid $borderColor
|
||||
border-bottom 1px solid var(--borderColor)
|
||||
.algolia-docsearch-suggestion--highlight
|
||||
color #2c815b
|
||||
.algolia-docsearch-suggestion
|
||||
border-color $borderColor
|
||||
border-color var(--borderColor)
|
||||
padding 0
|
||||
.algolia-docsearch-suggestion--category-header
|
||||
padding 5px 10px
|
||||
|
|
@ -112,21 +112,21 @@ export default {
|
|||
.algolia-docsearch-suggestion--title
|
||||
font-weight 600
|
||||
margin-bottom 0
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
.algolia-docsearch-suggestion--subcategory-column
|
||||
vertical-align top
|
||||
padding 5px 7px 5px 5px
|
||||
border-color $borderColor
|
||||
border-color var(--borderColor)
|
||||
background #f1f3f5
|
||||
&:after
|
||||
display none
|
||||
.algolia-docsearch-suggestion--subcategory-column-text
|
||||
color #555
|
||||
.algolia-docsearch-footer
|
||||
border-color $borderColor
|
||||
border-color var(--borderColor)
|
||||
.ds-cursor .algolia-docsearch-suggestion--content
|
||||
background-color #e7edf3 !important
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
|
||||
@media (min-width: $MQMobile)
|
||||
.algolia-search-wrapper
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ function zero(d){
|
|||
color #888
|
||||
.articleInfo
|
||||
overflow hidden
|
||||
font-size .95rem
|
||||
font-size .92rem
|
||||
.breadcrumbs
|
||||
margin 0
|
||||
padding 0
|
||||
|
|
@ -113,7 +113,7 @@ function zero(d){
|
|||
a
|
||||
color #888
|
||||
&:before
|
||||
font-size .95rem
|
||||
font-size .92rem
|
||||
&:hover
|
||||
color $accentColor
|
||||
.icon-home
|
||||
|
|
|
|||
|
|
@ -15,9 +15,10 @@
|
|||
@click="scrollToComment"
|
||||
/>
|
||||
<div
|
||||
title="阅读模式"
|
||||
class="button read-mode iconfont icon-yuedu"
|
||||
@click="$emit('toggle-read-mode')"
|
||||
title="主题模式"
|
||||
class="button theme-mode-but iconfont"
|
||||
:class="themeIconClass"
|
||||
@click="$emit('toggle-theme-mode')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -25,7 +26,6 @@
|
|||
<script>
|
||||
import debounce from 'lodash.debounce'
|
||||
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -33,6 +33,7 @@ export default {
|
|||
scrollTop: null,
|
||||
showCommentBut: false,
|
||||
commentTop: null,
|
||||
themeIconClass: 'icon-rijianmoshi',
|
||||
_scrollTimer: null,
|
||||
_textareaEl: null,
|
||||
_recordScrollTop: null,
|
||||
|
|
@ -56,6 +57,10 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIconClass(mode) {
|
||||
this.themeIconClass = mode == 1 ? 'icon-rijianmoshi' : mode == 2 ? 'icon-yejianmoshi' : 'icon-yuedu'
|
||||
},
|
||||
|
||||
getScrollTop () {
|
||||
return window.pageYOffset
|
||||
|| document.documentElement.scrollTop
|
||||
|
|
@ -135,12 +140,12 @@ export default {
|
|||
height 40px
|
||||
line-height 40px
|
||||
border-radius 50%
|
||||
box-shadow 0 2px 6px rgba(0,0,0,.15)
|
||||
box-shadow 0 2px 6px rgba(0,0,0,.25)
|
||||
margin-top .9rem
|
||||
text-align center
|
||||
cursor pointer
|
||||
background rgba(255,255,255,0.6)
|
||||
// color #666
|
||||
color var(--textLightenColor)
|
||||
background rgba(255,255,255,.1)
|
||||
&:hover
|
||||
color $accentColor
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="theme-default-content">
|
||||
<div class="theme-vdoing-content">
|
||||
<div class="column-wrapper">
|
||||
<img :src="getPageData().imgUrl" />
|
||||
<dl class="column-info">
|
||||
|
|
@ -63,7 +63,7 @@ dl,dd
|
|||
display flex
|
||||
margin-top 4.6rem!important
|
||||
padding-bottom 2rem
|
||||
border-bottom 1px solid #eaecef
|
||||
border-bottom 1px solid var(--borderColor)
|
||||
img
|
||||
width 80px
|
||||
height 80px
|
||||
|
|
@ -73,11 +73,12 @@ dl,dd
|
|||
.title
|
||||
font-size 1.6rem
|
||||
.description
|
||||
color #666
|
||||
color var(--textColor)
|
||||
opacity .8
|
||||
margin .5rem 0
|
||||
.catalogue-wrapper
|
||||
.catalogue-title
|
||||
font-size 1.5rem
|
||||
font-size 1.45rem
|
||||
margin 2rem 0
|
||||
.catalogue-content
|
||||
dl
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export default {
|
|||
background transparent
|
||||
border none
|
||||
font-weight 500
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
&:hover
|
||||
border-color transparent
|
||||
.arrow
|
||||
|
|
@ -138,7 +138,7 @@ export default {
|
|||
line-height 1.7rem
|
||||
h4
|
||||
margin 0.45rem 0 0
|
||||
border-top 1px solid #eee
|
||||
border-top 1px solid var(--borderColor)
|
||||
padding 0.45rem 1.5rem 0 1.25rem
|
||||
.dropdown-subitem-wrapper
|
||||
padding 0
|
||||
|
|
@ -225,10 +225,10 @@ export default {
|
|||
position absolute
|
||||
top 100%
|
||||
right 0
|
||||
background-color #fff
|
||||
background-color var(--bg)
|
||||
padding 0.6rem 0
|
||||
border 1px solid #ddd
|
||||
border-bottom-color #ccc
|
||||
border 1px solid var(--borderColor)
|
||||
border-bottom-color var(--borderColor)
|
||||
text-align left
|
||||
border-radius 0.25rem
|
||||
white-space nowrap
|
||||
|
|
|
|||
|
|
@ -43,12 +43,13 @@ $mobileSidebarWidth = $sidebarWidth * 0.82
|
|||
.footer
|
||||
padding 2.5rem 2.5rem 3rem
|
||||
text-align center
|
||||
color #999
|
||||
color var(--textColor)
|
||||
opacity .6
|
||||
box-sizing border-box
|
||||
font-size .85rem
|
||||
transition all .2s ease
|
||||
a
|
||||
color #999
|
||||
color var(--textColor)
|
||||
@media (min-width: ($MQMobile + 1px))
|
||||
.sidebar-open .footer
|
||||
width auto
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
<div class="main-wrapper">
|
||||
<main class="home home-content" aria-labelledby="main-title">
|
||||
<UpdateArticle pageMark="home" />
|
||||
<Content class="theme-default-content custom" />
|
||||
<Content class="theme-vdoing-content custom" />
|
||||
</main>
|
||||
|
||||
<aside class="info-wrapper" v-if="blogger">
|
||||
|
|
@ -241,7 +241,9 @@ export default {
|
|||
background #517EA9
|
||||
|
||||
.i-body
|
||||
background #fafafa bottom no-repeat
|
||||
background bottom no-repeat
|
||||
// background-color var(--homeBg)
|
||||
background-color rgba(220,220,220,0.1)
|
||||
overflow hidden
|
||||
.banner
|
||||
width 100%
|
||||
|
|
@ -278,8 +280,8 @@ body .main-wrapper
|
|||
display flex
|
||||
>*
|
||||
border-radius 5px
|
||||
background #fff
|
||||
box-shadow 0 1px 2px 0 rgba(0,0,0,.1), 0 2px 4px 0 rgba(0,0,0,.1)
|
||||
background var(--bg)
|
||||
box-shadow 0 1px 2px 0 rgba(0,0,30,.1), 0 2px 4px 0 rgba(0,0,0,.1)
|
||||
|
||||
.home-content
|
||||
padding 1rem 1.5rem 0
|
||||
|
|
@ -299,13 +301,13 @@ body .main-wrapper
|
|||
height 100%
|
||||
border-radius 3px
|
||||
.icons
|
||||
border 1px solid #e1e4e8
|
||||
border 1px solid var(--borderColor)
|
||||
height 40px
|
||||
line-height 40px
|
||||
a
|
||||
font-size 20px
|
||||
width 33%
|
||||
color #666
|
||||
color var(--textColor)
|
||||
display block
|
||||
float left
|
||||
text-align center
|
||||
|
|
@ -318,7 +320,7 @@ body .main-wrapper
|
|||
display: block
|
||||
margin-bottom 10px
|
||||
.slogan
|
||||
color #777
|
||||
color var(--textColor)
|
||||
|
||||
|
||||
.home
|
||||
|
|
@ -343,7 +345,7 @@ body .main-wrapper
|
|||
max-width 40rem
|
||||
font-size 1.4rem
|
||||
line-height 1.3
|
||||
color lighten($textColor, 20%)
|
||||
color var(--textLightenColor)
|
||||
.action-button
|
||||
display inline-block
|
||||
font-size 1.2rem
|
||||
|
|
@ -358,7 +360,7 @@ body .main-wrapper
|
|||
background-color lighten($accentColor, 10%)
|
||||
|
||||
.features
|
||||
border-top 1px solid $borderColor
|
||||
border-top 1px solid var(--borderColor)
|
||||
padding 2rem 0
|
||||
margin-top 2.5rem
|
||||
display flex
|
||||
|
|
@ -384,9 +386,9 @@ body .main-wrapper
|
|||
.image_title
|
||||
animation-play-state: running
|
||||
h2
|
||||
color lighten($textColor, 80%)
|
||||
color var(--textColor)
|
||||
p
|
||||
color lighten($textColor, 25%)
|
||||
color var(--textLightenColor)
|
||||
|
||||
@keyframes heart
|
||||
from{transform:translate(0,0)}
|
||||
|
|
@ -395,7 +397,7 @@ body .main-wrapper
|
|||
|
||||
@media (max-width: 1025px)
|
||||
.i-body
|
||||
background-color #fff
|
||||
background-color var(--bg)
|
||||
|
||||
body .home-content
|
||||
margin 0
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ export default {
|
|||
@media (min-width: $MQMobile)
|
||||
.nav-links a
|
||||
&:hover, &.router-link-active
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
.nav-item > a:not(.external)
|
||||
&:hover, &.router-link-active
|
||||
margin-bottom -2px
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ $navbar-horizontal-padding = 1.5rem
|
|||
.site-name
|
||||
font-size 1.3rem
|
||||
font-weight 600
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
position relative
|
||||
.links
|
||||
padding-left 1.5rem
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<div class="theme-vdoing-wrapper">
|
||||
<RightMenu v-if="showRightMenu !== false"/>
|
||||
<ArticleInfo v-if="isArticle()" />
|
||||
<component class="theme-default-content" v-if="pageComponent" :is="pageComponent" />
|
||||
<Content class="theme-default-content" />
|
||||
<component class="theme-vdoing-content" v-if="pageComponent" :is="pageComponent" />
|
||||
<Content class="theme-vdoing-content" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -67,9 +67,9 @@ export default {
|
|||
padding 2rem
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
padding 1.5rem
|
||||
.theme-default-content
|
||||
.theme-vdoing-content
|
||||
padding 0!important
|
||||
&>.theme-default-content
|
||||
&>.theme-vdoing-content
|
||||
margin 0
|
||||
|
||||
// 右侧菜单的自适应
|
||||
|
|
|
|||
|
|
@ -106,14 +106,14 @@ export default {
|
|||
.edit-link
|
||||
display inline-block
|
||||
a
|
||||
color lighten($textColor, 25%)
|
||||
margin-right 0.25rem
|
||||
.last-updated
|
||||
float right
|
||||
font-size 0.9em
|
||||
.prefix
|
||||
font-weight 500
|
||||
color lighten($textColor, 25%)
|
||||
color var(--textColor)
|
||||
opacity .8
|
||||
.time
|
||||
font-weight 400
|
||||
color #aaa
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ function flatten (items, res) {
|
|||
.inner
|
||||
min-height 2rem
|
||||
margin-top 0
|
||||
border-top 1px solid $borderColor
|
||||
border-top 1px solid var(--borderColor)
|
||||
padding-top 1rem
|
||||
overflow auto // clear float
|
||||
.next
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export default {
|
|||
overflow-y auto
|
||||
.right-menu-item
|
||||
padding 4px 15px
|
||||
border-left .2rem solid #E4E4E4
|
||||
border-left .2rem solid var(--borderColor)
|
||||
&.level3
|
||||
padding-left 28px
|
||||
&.active
|
||||
|
|
@ -74,7 +74,7 @@ export default {
|
|||
color $accentColor
|
||||
opacity 1
|
||||
a
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
opacity 0.75
|
||||
display block
|
||||
width ($rightMenuWidth - 30px)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export default {
|
|||
display inline-block
|
||||
.nav-links
|
||||
display none
|
||||
border-bottom 1px solid $borderColor
|
||||
border-bottom 1px solid var(--borderColor)
|
||||
padding 0.5rem 0 0.75rem 0
|
||||
a
|
||||
font-weight 600
|
||||
|
|
@ -76,7 +76,7 @@ export default {
|
|||
margin-top .75rem
|
||||
.blogger
|
||||
display none
|
||||
border-bottom 1px solid $borderColor
|
||||
border-bottom 1px solid var(--borderColor)
|
||||
img
|
||||
width 60px
|
||||
height 60px
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ export default {
|
|||
border-left none
|
||||
|
||||
.sidebar-heading
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
transition color .15s ease
|
||||
cursor pointer
|
||||
font-size 1.1em
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ a.sidebar-link
|
|||
font-size 1em
|
||||
font-weight 400
|
||||
display inline-block
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
border-left 0.25rem solid transparent
|
||||
padding 0.35rem 1rem 0.35rem 1.25rem
|
||||
line-height 1.4
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="timeline-wrapper theme-default-content">
|
||||
<div class="timeline-wrapper theme-vdoing-content">
|
||||
<div class="tags">
|
||||
<a href="#全部" :class="{active: currentTag === '全部'}" :style="randomBgcolor()" @click="toggleTag('全部')">全部</a>
|
||||
<a
|
||||
|
|
@ -125,7 +125,7 @@ export default {
|
|||
font-size: 13px;
|
||||
transition: all .5s;
|
||||
opacity: 0.9;
|
||||
box-shadow: 2px 2px 5px #ccc;
|
||||
box-shadow: 0px 0px 8px rgba(80,80,80,.3);
|
||||
&.active
|
||||
transform: scale(1.2);
|
||||
opacity: 1;
|
||||
|
|
@ -162,7 +162,7 @@ export default {
|
|||
margin-left: -2px;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: $borderColor;
|
||||
background: var(--borderColor);
|
||||
>li
|
||||
transition: all .25s ease-in-out;
|
||||
margin-bottom: 55px;
|
||||
|
|
@ -183,7 +183,7 @@ export default {
|
|||
width: 8px;
|
||||
height: 8px;
|
||||
background: #fff;
|
||||
border: 1px solid $borderColor;
|
||||
border: 1px solid var(--borderColor);
|
||||
border-radius: 50%;
|
||||
.year-wrapper
|
||||
padding-left: 0!important;
|
||||
|
|
@ -191,10 +191,12 @@ export default {
|
|||
display: flex;
|
||||
padding: 30px 0 10px;
|
||||
list-style: none;
|
||||
border-bottom: 1px dashed $borderColor;
|
||||
border-bottom: 1px dashed var(--borderColor);
|
||||
position: relative;
|
||||
color: #666;
|
||||
color: var(--textColor)
|
||||
transition: all 0.25s ease-in-out;
|
||||
.title
|
||||
opacity .9
|
||||
.date
|
||||
min-width: 40px;
|
||||
line-height: 30px;
|
||||
|
|
@ -211,7 +213,7 @@ export default {
|
|||
margin-left: -4px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
border: 1px solid $borderColor;
|
||||
border: 1px solid var(--borderColor);
|
||||
z-index: 2;
|
||||
&:hover
|
||||
text-decoration:none
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export default {
|
|||
&.no-article
|
||||
display none
|
||||
.article-title
|
||||
border-bottom 1px solid #eaecef
|
||||
border-bottom 1px solid var(--borderColor)
|
||||
font-size 1.3rem
|
||||
font-weight bold
|
||||
padding 0 0 .5rem 1rem
|
||||
|
|
@ -95,7 +95,7 @@ export default {
|
|||
.article-wrapper
|
||||
overflow hidden
|
||||
dl
|
||||
border-bottom 1px dotted #eaecef
|
||||
border-bottom 1px dotted var(--borderColor)
|
||||
float left
|
||||
display flex
|
||||
padding 8px 0
|
||||
|
|
@ -120,7 +120,7 @@ export default {
|
|||
flex 1
|
||||
display flex
|
||||
a
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
flex 1
|
||||
display: flex;
|
||||
height: 55px;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -47,7 +47,8 @@
|
|||
</Page>
|
||||
|
||||
<Buttons
|
||||
@toggle-read-mode="toggleReadMode"
|
||||
ref="buttons"
|
||||
@toggle-theme-mode="toggleThemeMode"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -70,7 +71,8 @@ export default {
|
|||
return {
|
||||
isSidebarOpen: true,
|
||||
showSidebar: false,
|
||||
readMode: false
|
||||
themeMode: 1, // 1 => 日间模式, 2=> 夜间模式, 3=> 阅读模式
|
||||
THEMEMODE_COUNT: 3 // 主题模式的数量
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -126,23 +128,25 @@ export default {
|
|||
'sidebar-open': this.isSidebarOpen,
|
||||
'no-sidebar': !this.shouldShowSidebar,
|
||||
'have-rightmenu': this.showRightMenu,
|
||||
'theme-read-mode': this.readMode
|
||||
},
|
||||
'theme-mode-' + (this.themeMode == 1 ? 'daytime' : this.themeMode == 2 ? 'night' : 'read'),
|
||||
userPageClass
|
||||
]
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.isSidebarOpenOfclientWidth()
|
||||
if(storage.get('mode')) {
|
||||
this.readMode = true
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.showSidebar = true // 解决移动端初始化页面时侧边栏闪现的问题
|
||||
this.$router.afterEach(() => {
|
||||
this.isSidebarOpenOfclientWidth()
|
||||
})
|
||||
|
||||
if(storage.get('mode')) {
|
||||
this.themeMode = storage.get('mode')
|
||||
this.toggleThemeIcon()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -155,13 +159,17 @@ export default {
|
|||
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
|
||||
this.$emit('toggle-sidebar', this.isSidebarOpen)
|
||||
},
|
||||
toggleReadMode (){
|
||||
this.readMode = !this.readMode
|
||||
storage.set('mode', this.readMode)
|
||||
toggleThemeMode (){
|
||||
this.themeMode = this.themeMode+1 > this.THEMEMODE_COUNT ? 1 : this.themeMode+1
|
||||
storage.set('mode', this.themeMode)
|
||||
this.toggleThemeIcon()
|
||||
// if (document.documentElement.clientWidth > MOBILE_DESKTOP_BREAKPOINT) {
|
||||
// this.isSidebarOpen = !this.readMode
|
||||
// }
|
||||
},
|
||||
toggleThemeIcon() {
|
||||
this.$refs.buttons.toggleIconClass(this.themeMode)
|
||||
},
|
||||
// side swipe
|
||||
onTouchStart (e) {
|
||||
this.touchStart = {
|
||||
|
|
@ -184,41 +192,3 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
// 阅读模式样式
|
||||
.theme-read-mode
|
||||
min-height 100vh
|
||||
background $readModeColor
|
||||
.i-body // 首页
|
||||
background-color $readModeColor
|
||||
.banner,.home .hero .description,.home .feature h2,.slide-banner .slide-banner-wrapper .slide-item h2 // banner栏
|
||||
color lighten($readModeColor, 50%)
|
||||
.main-wrapper >*
|
||||
background-color lighten($readModeColor, 50%)!important
|
||||
.sidebar // 侧边栏
|
||||
@media (max-width: $MQNarrow)
|
||||
background-color lighten($readModeColor, 30%)!important
|
||||
.navbar // 导航栏
|
||||
background $readModeColor
|
||||
.dropdown-wrapper .nav-dropdown
|
||||
background lighten($readModeColor, 50%)
|
||||
.suggestions // 搜索结果
|
||||
background lighten($readModeColor, 50%)
|
||||
.buttons // 右下角按钮
|
||||
.button
|
||||
background lighten($readModeColor, 50%)
|
||||
.read-mode // 阅读模式按钮
|
||||
background lighten($accentColor, 30%)
|
||||
opacity .85
|
||||
color #fff
|
||||
&:hover
|
||||
opacity 1
|
||||
color #fff
|
||||
tr // 表格
|
||||
&:nth-child(2n)
|
||||
background-color lighten($readModeColor, 50%)
|
||||
// 时间轴页面
|
||||
.timeline-wrapper .timeline ul .desc:before, .timeline-wrapper .timeline ul .year:before,.timeline-wrapper .timeline ul .year-wrapper a .date:before
|
||||
background-color $readModeColor!important
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{$contentClass}
|
||||
code
|
||||
color lighten($textColor, 20%)
|
||||
color var(--textLightenColor)
|
||||
padding 0.25rem 0.5rem
|
||||
margin 0
|
||||
font-size 0.85em
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
$contentClass = '.theme-default-content'
|
||||
$contentClass = '.theme-vdoing-content'
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
.custom-block-title
|
||||
color darken(#ffe564, 50%)
|
||||
a
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
&.danger
|
||||
background-color #ffe6e6
|
||||
border-color darken(red, 20%)
|
||||
|
|
@ -25,6 +25,6 @@
|
|||
.custom-block-title
|
||||
color darken(red, 40%)
|
||||
a
|
||||
color $textColor
|
||||
color var(--textColor)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@
|
|||
@require './arrow'
|
||||
@require './wrapper'
|
||||
@require './toc'
|
||||
@require './theme-mode'
|
||||
|
||||
// 引入字体图标
|
||||
@import '//at.alicdn.com/t/font_1678482_aerreja5rn7.css'
|
||||
@import '//at.alicdn.com/t/font_1678482_q8amu5272z.css'
|
||||
// 去掉黄色边框
|
||||
a,input,button
|
||||
outline: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); -webkit-focus-ring-color: rgba(0, 0, 0, 0);
|
||||
|
|
@ -52,9 +53,9 @@ body
|
|||
left 0
|
||||
right 0
|
||||
height $navbarHeight
|
||||
background-color #fff
|
||||
background-color var(--bg)
|
||||
box-sizing border-box
|
||||
border-bottom 1px solid $borderColor
|
||||
border-bottom 1px solid var(--borderColor)
|
||||
box-shadow 0 2px 5px rgba(0,0,0,.06)
|
||||
|
||||
.sidebar-mask
|
||||
|
|
@ -78,14 +79,15 @@ body
|
|||
left 0
|
||||
bottom 0
|
||||
box-sizing border-box
|
||||
border-right 1px solid $borderColor
|
||||
border-right 1px solid var(--borderColor)
|
||||
overflow-y auto
|
||||
transform translateX(-100%)
|
||||
transition transform .2s ease
|
||||
@media (max-width: $MQNarrow)
|
||||
background-color #fbfbfb
|
||||
background-color var(--bg)
|
||||
|
||||
{$contentClass}:not(.custom)
|
||||
word-wrap break-word
|
||||
@extend $wrapper
|
||||
> *:first-child
|
||||
margin-top $navbarHeight
|
||||
|
|
@ -165,7 +167,7 @@ h1
|
|||
h2
|
||||
font-size 1.5rem
|
||||
padding-bottom .3rem
|
||||
border-bottom 1px solid $borderColor
|
||||
border-bottom 1px solid var(--borderColor)
|
||||
|
||||
h3
|
||||
font-size 1.35rem
|
||||
|
|
@ -189,25 +191,30 @@ p, ul, ol
|
|||
|
||||
hr
|
||||
border 0
|
||||
border-top 1px solid $borderColor
|
||||
border-top 1px solid var(--borderColor)
|
||||
|
||||
table
|
||||
border-collapse collapse
|
||||
margin 1rem 0
|
||||
display: block
|
||||
// display: block
|
||||
overflow-x: auto
|
||||
width 100%
|
||||
display inline-table
|
||||
|
||||
tr
|
||||
border-top 1px solid #dfe2e5
|
||||
border-top 1px solid var(--borderColor)
|
||||
|
||||
&:nth-child(2n)
|
||||
background-color #f6f8fa
|
||||
background-color rgba(150,150,150,0.1)
|
||||
|
||||
th, td
|
||||
border 1px solid #dfe2e5
|
||||
border 1px solid var(--borderColor)
|
||||
padding .6em 1em
|
||||
|
||||
.theme-container
|
||||
background var(--bg)
|
||||
color var(--textColor)
|
||||
min-height 100vh
|
||||
&.sidebar-open
|
||||
.sidebar-mask
|
||||
display: block
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// 日间模式变量
|
||||
.theme-mode-daytime
|
||||
--bg: #fff
|
||||
--textColor: #004050
|
||||
--textLightenColor: #0085AD
|
||||
--borderColor: rgba(0,0,0,.15)
|
||||
|
||||
// 夜间模式变量
|
||||
.theme-mode-night
|
||||
--bg: #191828
|
||||
--textColor: #686880
|
||||
--textLightenColor: #0085AD
|
||||
--borderColor: #2C2C3A
|
||||
|
||||
// 阅读模式变量
|
||||
.theme-mode-read
|
||||
--bg: #f5f5d5 // 杏仁黄
|
||||
--textColor: #004050
|
||||
--textLightenColor: #0085AD
|
||||
--borderColor: rgba(0,0,0,.15)
|
||||
Loading…
Reference in New Issue