添加文章页的 面包屑 和 文章信息栏
This commit is contained in:
parent
3048471c8b
commit
8c31d98cb5
|
|
@ -11,6 +11,9 @@ module.exports = {
|
|||
['meta', { name: 'baidu-site-verification', content: '7F55weZDDc'}],
|
||||
['meta', { name: 'theme-color', content: '#11a8cd'}], // 移动浏览器主题颜色
|
||||
|
||||
// 不蒜子访问量统计
|
||||
// ['script', { src: '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js', async: 'async'}]
|
||||
|
||||
// 以下是vuepress-plugin-demo-block插件所需依赖
|
||||
// ['script', { src: 'https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js' }], // 此文件会影响导航router-link-active样式的切换
|
||||
// ['script', { src: 'https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js' }],
|
||||
|
|
@ -21,6 +24,10 @@ module.exports = {
|
|||
themeConfig: { // 主题配置
|
||||
nav,
|
||||
sidebar, // 侧边栏 'auto' | 自定义
|
||||
author: { // 文章默认的作者信息(此项非官方配置,是新增的一项配置),可在md文件中另外指定此项配置
|
||||
name: 'Evan xu', // 必需
|
||||
href: 'https://github.com/xugaoyi' // 非必需
|
||||
},
|
||||
sidebarDepth: 2, // 侧边栏显示深度,默认1,最大2(显示到h3标题)
|
||||
logo: '/img/EB-logo.png', // 导航栏logo
|
||||
repo: 'xugaoyi/vuepress-theme-vdoing-blog', // 导航栏右侧生成Github链接
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,3 +1,5 @@
|
|||
// 引入字体图标
|
||||
@import '//at.alicdn.com/t/font_1678482_m18ipwgi2da.css'
|
||||
|
||||
// 样式重置
|
||||
body
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
<template>
|
||||
<div class="articleInfo-wrap">
|
||||
<div class="articleInfo">
|
||||
<ul class="breadcrumbs">
|
||||
<li>
|
||||
<router-link to="/" class="iconfont icon-ai-home icon-home" />
|
||||
</li>
|
||||
<li v-if="articleInfo.classify1">
|
||||
<router-link v-if="articleInfo.cataloguePermalink" :to="articleInfo.cataloguePermalink">{{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" title="作者">{{articleInfo.author.name}}</a>
|
||||
</div>
|
||||
<div class="date iconfont icon-ic_calendar" 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
|
||||
padding-bottom 0
|
||||
color gray
|
||||
.articleInfo
|
||||
overflow hidden
|
||||
.breadcrumbs
|
||||
margin 0
|
||||
padding 0
|
||||
overflow hidden
|
||||
display inline-block
|
||||
@media (max-width: 960px)
|
||||
width 100%
|
||||
li
|
||||
list-style-type none
|
||||
float left
|
||||
padding-right 5px
|
||||
&:after
|
||||
content '→'
|
||||
margin-left: 5px;
|
||||
&:last-child
|
||||
&:after
|
||||
content ''
|
||||
.icon-home
|
||||
color gray
|
||||
text-decoration none
|
||||
&:hover
|
||||
color $accentColor
|
||||
.info
|
||||
float right
|
||||
line-height 32px
|
||||
@media (max-width: 960px)
|
||||
float left
|
||||
div
|
||||
float left
|
||||
margin-left 20px
|
||||
font-size .9rem
|
||||
@media (max-width: 960px)
|
||||
margin 0 20px 0 0
|
||||
&:before
|
||||
margin-right 3px
|
||||
a
|
||||
color gray
|
||||
&.date
|
||||
a
|
||||
text-decoration none
|
||||
</style>
|
||||
|
|
@ -106,7 +106,9 @@
|
|||
</aside>
|
||||
</div>
|
||||
|
||||
<div class="footer" v-if="data.footer">Copyright © {{ data.footer.year }}-{{ new Date().getFullYear() }} {{ data.footer.content }}</div>
|
||||
<div class="footer" v-if="data.footer">
|
||||
Copyright © {{ data.footer.year }}-{{ new Date().getFullYear() }} {{ data.footer.content }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -218,8 +220,6 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
// @import '//at.alicdn.com/t/font_1678482_k8ld4et1y2f.css'
|
||||
|
||||
.slide-banner
|
||||
margin-top: 2rem;
|
||||
.banner-wrapper
|
||||
|
|
@ -438,7 +438,9 @@ body .main-wrapper{
|
|||
.image_title {
|
||||
width: 11rem;
|
||||
height: 11rem;
|
||||
transition: all .3s;
|
||||
// transition: all .3s;
|
||||
animation: heart 1.2s ease-in-out 0s infinite alternate;
|
||||
animation-play-state: paused
|
||||
}
|
||||
|
||||
h2 {
|
||||
|
|
@ -447,20 +449,34 @@ body .main-wrapper{
|
|||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
color: lighten($textColor, 10%);
|
||||
transition: all 1.2s;
|
||||
}
|
||||
|
||||
p {
|
||||
color: lighten($textColor, 25%);
|
||||
transition: all 1.2s;
|
||||
}
|
||||
}
|
||||
|
||||
.feature:hover {
|
||||
.image_title {
|
||||
transform:scale(1.1,1.1)
|
||||
// transform:scale(1.1,1.1);
|
||||
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)}
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 2.5rem;
|
||||
margin-bottom 2rem;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
<main class="page">
|
||||
<slot name="top" />
|
||||
|
||||
<component v-if="pageComponent" :is="pageComponent" />
|
||||
<ArticleInfo class="theme-default-content" v-if="isArticle()" />
|
||||
|
||||
<component class="theme-default-content" v-if="pageComponent" :is="pageComponent" />
|
||||
|
||||
<Content class="theme-default-content" />
|
||||
<PageEdit />
|
||||
|
|
@ -18,17 +20,23 @@
|
|||
<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 Article from './Article.vue'
|
||||
import Timeline from './Timeline.vue'
|
||||
|
||||
export default {
|
||||
components: { PageEdit, PageNav, Catalogue, Article, Timeline},
|
||||
components: { PageEdit, PageNav, ArticleInfo, Catalogue, Article, Timeline},
|
||||
props: ['sidebarItems'],
|
||||
computed: {
|
||||
pageComponent () {
|
||||
return this.$frontmatter.pageComponent ? this.$frontmatter.pageComponent.name : false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isArticle() {
|
||||
return this.$frontmatter.article !== false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
pageComponent:
|
||||
name: Catalogue
|
||||
data:
|
||||
key: 04.更多
|
||||
imgUrl: /img/other.png
|
||||
description: 学习、面试、在线工具等更多文章和页面
|
||||
|
||||
title: 更多
|
||||
date: 2020-03-11 21:50:56
|
||||
permalink: /more
|
||||
sidebar: false
|
||||
article: false
|
||||
comment: false
|
||||
editLink: false
|
||||
---
|
||||
|
|
@ -2,6 +2,9 @@
|
|||
title: new命令原理
|
||||
date: 2019-12-25 14:27:01
|
||||
permalink: /pages/8143cc480faf9a11
|
||||
author:
|
||||
name: '阮一峰'
|
||||
href: 'https://github.com/xugaoyi'
|
||||
---
|
||||
# new命令原理
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: 关于
|
||||
date: 2019-12-25 14:27:01
|
||||
date: 2019-12-25 14:27:01
|
||||
permalink: /about
|
||||
sidebar: false
|
||||
article: false
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ features:
|
|||
imgname: /img/other.png
|
||||
aside:
|
||||
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg
|
||||
iconfontCssFile: //at.alicdn.com/t/font_1678482_u4nrnp8xp6g.css # 阿里矢量图标库在线css文件地址
|
||||
# iconfontCssFile: //at.alicdn.com/t/font_1678482_u4nrnp8xp6g.css # 阿里图标库在线css文件地址,对于原本没有的图标可以另外添加
|
||||
icons:
|
||||
# - iconClass: icon-QQ
|
||||
# title: QQ
|
||||
|
|
@ -33,7 +33,7 @@ aside:
|
|||
title: 听音乐
|
||||
link: https://music.163.com/#/playlist?id=755597173
|
||||
blogger:
|
||||
name: Evan Xu
|
||||
name: Evan xu
|
||||
slogan: 前端界的小学生
|
||||
footer:
|
||||
year: 2019
|
||||
|
|
|
|||
|
|
@ -10,15 +10,21 @@ const matter = require('gray-matter'); // FrontMatter解析器
|
|||
|
||||
const docsRoot = path.join(__dirname, '..', 'docs'); // docs文件路径
|
||||
const sidebarPath = path.join(__dirname, '..', 'docs', '.vuepress', 'config', 'sidebar-auto.js'); // 侧边栏js文件要保存的路径
|
||||
|
||||
const catalogueData = {}; // 目录页数据
|
||||
|
||||
// sidebar-auto.js代码模板
|
||||
const sidebarTemplate = `
|
||||
// 侧边栏自动生成 // 最里面的数组,格式:[<path>, <title>, <permalink>],其中permalink并非侧边栏所需,而是提供给其他页面使用
|
||||
/**
|
||||
* 自动生成的侧边栏
|
||||
* 说明:
|
||||
* 1. 最里边的数组,格式:[<path>, <title>, <permalink>],其中permalink并非侧边栏所需,而是提供给其他页面(目录页)使用
|
||||
* 2. catalogue属性是提供给面包屑所需的目录页数据
|
||||
*/
|
||||
module.exports = {
|
||||
<% for (let item of sidebarData) { %>
|
||||
"<%- item.path %>": <%- JSON.stringify(item.sidebarArr) %>,
|
||||
"<%- item.path %>": <%- JSON.stringify(item.sidebarArr) %>,
|
||||
<% } %>
|
||||
"catalogue": <%- JSON.stringify(catalogueData) %>
|
||||
}`;
|
||||
|
||||
main();
|
||||
|
|
@ -43,7 +49,7 @@ function main() {
|
|||
})
|
||||
})
|
||||
|
||||
const sidebarDataTem = ejs.render(sidebarTemplate, { sidebarData });
|
||||
const sidebarDataTem = ejs.render(sidebarTemplate, { sidebarData, catalogueData });
|
||||
fs.writeFileSync(sidebarPath, sidebarDataTem); // 同步写入文件, 参数一:写入到的文件, 参数二:写入的数据
|
||||
logger.info('侧边栏生成成功!')
|
||||
}
|
||||
|
|
@ -103,6 +109,12 @@ function mapTocToSidebar(root, prefix){
|
|||
const { data } = matter(contentStr) // 解析出front matter数据
|
||||
const permalink = data.permalink || ''
|
||||
sidebar[order] = [prefix + filename, title, permalink ]; // [<路径>, <文件标题>, <永久链接>]
|
||||
|
||||
// 目录页和永久链接,用于给面包屑提供数据
|
||||
const pageComponent = data.pageComponent
|
||||
if (pageComponent && pageComponent.name && pageComponent.name === "Catalogue") {
|
||||
catalogueData[title] = permalink
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue