添加夜间主题

This commit is contained in:
xugaoyi 2020-04-01 16:43:26 +08:00
parent 2aae9029a2
commit 3d97dc879a
49 changed files with 159 additions and 3124 deletions

View File

@ -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)'
},

View File

@ -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

View File

@ -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

View File

@ -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 //

View File

@ -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())}`
}
// 100
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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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; // vupressbeforeCreate(),created()访apiwindow
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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -1,3 +0,0 @@
module.exports = {
extend: '@vuepress/theme-default' // 继承到默认主题
}

File diff suppressed because one or more lines are too long

View File

@ -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>

View File

@ -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

View File

@ -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')
}

View File

@ -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
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
//

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -1,6 +1,6 @@
{$contentClass}
code
color lighten($textColor, 20%)
color var(--textLightenColor)
padding 0.25rem 0.5rem
margin 0
font-size 0.85em

View File

@ -1 +1 @@
$contentClass = '.theme-default-content'
$contentClass = '.theme-vdoing-content'

View File

@ -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)

View File

@ -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

View File

@ -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)