267 lines
9.7 KiB
Vue
267 lines
9.7 KiB
Vue
<template>
|
|
<div v-wechat-title="pageTitle">
|
|
<transition name="fade">
|
|
<al-loading v-if="isLoading"></al-loading>
|
|
</transition>
|
|
<al-back-top></al-back-top>
|
|
|
|
<!--SideBar menu-->
|
|
<SidebarNav/>
|
|
|
|
<div id="body">
|
|
<div id="top" class="animateIn">
|
|
<ArticleTop :setting="userSetting"/>
|
|
<div class="scrollbar gradient-bg-rev" style="width: 0;"></div>
|
|
</div>
|
|
<div class="article-header">
|
|
<div class="article-background" :style="{backgroundImage: `url(${file.cover})`}"></div>
|
|
<div class="inner">
|
|
<div class="blog-title"><span id="article-title">{{pageTitle}}</span><span class="typed-cursor">_</span></div>
|
|
<div class="blog-description font-mono">
|
|
<a itemprop="name" href="https://www.jmal.top/author/1/" rel="author">{{file.username}}</a>
|
|
· {{file.uploadDate}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="body-wrapper">
|
|
<el-main id="main_body" :content="titleList.length > 0?'show':'hide'" class="l_main article_l_main">
|
|
<mavon-editor
|
|
ref="md"
|
|
v-if="!showList"
|
|
v-model="content"
|
|
:subfield="false"
|
|
:boxShadow="true"
|
|
:toolbarsFlag="false"
|
|
codeStyle="atom-one-dark"
|
|
defaultOpen="preview"
|
|
/>
|
|
</el-main>
|
|
<div v-show="titleList.length > 0" class="right-bj">
|
|
<a-affix>
|
|
<div class="slimScrollDiv">
|
|
<div class="right-menu" :style="{maxHeight:maxMenuHeight+'px'}">
|
|
<div class="toc-content">
|
|
<header class="toc-header"><svg-icon icon-class="contents"></svg-icon><span>目录</span></header>
|
|
</div>
|
|
<div class="j-titleList titleList">
|
|
<div class="j-bj" style="height: 30px; top: 0;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</a-affix>
|
|
</div>
|
|
</div>
|
|
<footer class="clearfix">
|
|
<div class="copyright"><p><a href="/articles">Copyright © 2020 jmal</a></p></div>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import AlLoading from "@/components/loading/AlLoading";
|
|
import AlBackTop from "@/components/backtop/AlBackTop";
|
|
import markdownApi from '@/api/markdown-api'
|
|
import {addCodeBtn} from '@/assets/js/mavon-line'
|
|
import $ from 'jquery'
|
|
import ArticleTop from "@/views/public/article/ArticleTop";
|
|
import {getSetting} from '@/api/user'
|
|
import SidebarNav from "@/views/public/article/SidebarNav";
|
|
|
|
export default {
|
|
components: {SidebarNav, ArticleTop, AlBackTop, AlLoading },
|
|
data() {
|
|
return {
|
|
file: {},
|
|
isLoading: true,
|
|
pageTitle: "文章",
|
|
showList: true,
|
|
toolbars: null,
|
|
toolbarsFlag: true,
|
|
content:'',
|
|
html:'',
|
|
userSetting: {},
|
|
titleList: [],
|
|
tocMaxHeight: 500,
|
|
befterScrollTop: 0,
|
|
maxMenuHeight: document.documentElement.clientHeight - 155,
|
|
top: 70
|
|
}
|
|
},
|
|
mounted() {
|
|
this.getSetting()
|
|
if(this.$route.query.mark){
|
|
this.getMarkDown()
|
|
this.showList = false
|
|
}
|
|
let that = this
|
|
window.onresize = function temp() {
|
|
that.maxMenuHeight= document.documentElement.clientHeight - 155
|
|
}
|
|
},
|
|
methods: {
|
|
getSetting() {
|
|
getSetting({userId: this.$store.state.user.userId}).then((res) => {
|
|
this.userSetting = res.data;
|
|
this.$nextTick(()=>{
|
|
this.dynamicTyping()
|
|
})
|
|
})
|
|
},
|
|
onScroll() {
|
|
// let befterScrollTop = document.documentElement.scrollTop;
|
|
},
|
|
dynamicTyping() {
|
|
let divTyping = document.getElementById('article-title')
|
|
let i = 0,timer = 0,str = this.pageTitle
|
|
function typing () {
|
|
if (i <= str.length) {
|
|
divTyping.innerHTML = str.slice(0, i++)
|
|
timer = setTimeout(typing, 100)
|
|
} else {
|
|
// 结束打字
|
|
clearTimeout(timer)
|
|
}
|
|
}
|
|
typing()
|
|
},
|
|
getMarkDown() {
|
|
markdownApi.getMarkdown({
|
|
mark: this.$route.query.mark
|
|
}).then((res) => {
|
|
this.file = res.data
|
|
const filename = res.data.name
|
|
this.pageTitle = filename.substring(0,filename.length - res.data.suffix.length-1)
|
|
this.content = res.data.contentText
|
|
this.$nextTick(()=>{ // DOM更新之后获取子元素
|
|
// 在文章最前面添加更新时间
|
|
let main = document.querySelector('.v-show-content.scroll-style.scroll-style-border-radius')
|
|
let p = document.createElement("p")
|
|
p.className = "note-update-date"
|
|
p.innerText = `本文最后更新于:${this.file.updateDate}`
|
|
main.insertBefore(p , main.childNodes[0])
|
|
|
|
// 动态打字效果
|
|
this.dynamicTyping()
|
|
|
|
const hTag = document.querySelector("h1");
|
|
if(hTag){
|
|
this.pageTitle = hTag.innerText
|
|
}
|
|
|
|
let a = $('.el-main').html().match(/<h1.*?<\/h1>|<h2.*?<\/h2>|<h3.*?<\/h3>|<h4.*?<\/h4>|<h5.*?<\/h5>|<h6.*?<\/h6>/g);
|
|
if(a && a.length >0 ){
|
|
a = a.splice(a.length/2,a.length)
|
|
for (let i = 0; i < a.length; i++) {
|
|
a[i] = a[i].replace(/id="/g, 'href="#')
|
|
if (i ===0 && a[i].indexOf('h1') !== -1) {
|
|
a[i] = '<li first class="h-1">' + a[i].replace(/<h1>|<\/h1>/g, '') + '</li>'
|
|
}else if (a[i].indexOf('h2') !== -1) {
|
|
a[i] = '<li class="pl h-2">' + a[i].replace(/<h2>|<\/h2>/g, '') + '</li>'
|
|
}else if (a[i].indexOf('h3') !== -1) {
|
|
a[i] = '<li class="pl h-3">' + a[i].replace(/<h3>|<\/h3>/g, '') + '</li>'
|
|
}else if (a[i].indexOf('h4') !== -1) {
|
|
a[i] = '<li class="pl h-4">' + a[i].replace(/<h4>|<\/h4>/g, '') + '</li>'
|
|
}else if (a[i].indexOf('h5') !== -1) {
|
|
a[i] = '<li class="pl h-5">' + a[i].replace(/<h5>|<\/h5>/g, '') + '</li>'
|
|
}else if (a[i].indexOf('h6') !== -1) {
|
|
a[i] = '<li class="pl h-6">' + a[i].replace(/<h6>|<\/h6>/g, '') + '</li>'
|
|
} else {
|
|
a[i] = '<li>' + a[i].replace(/<h1>|<\/h1>/g, '') + '</li>'
|
|
}
|
|
this.titleList.push(i)
|
|
}
|
|
$('.j-titleList').prepend(a)
|
|
|
|
//获取id数组
|
|
for (let i = 0; i < a.length; i++) {
|
|
a[i] = a[i].replace(/.*?#(.*)".*/g, '$1')
|
|
}
|
|
|
|
let beforeScrollTop = document.documentElement.scrollTop;
|
|
let fn = fn || function (direction) {
|
|
// 判断是上滑显示,下滑隐藏
|
|
if(direction === 'down'){
|
|
$('#top').removeClass('animateIn')
|
|
$('#top').addClass('animateOut')
|
|
}
|
|
if(direction === 'up'){
|
|
$('#top').removeClass('animateOut')
|
|
$('#top').addClass('animateIn')
|
|
}
|
|
};
|
|
|
|
$(window).on("scroll",function (event) {
|
|
for (let i = 0; i < a.length; i++) {
|
|
if ($(window).scrollTop() > $('#' + a[i]).offset().top - 100 || $(this).scrollTop() + $(this).height() == $(document).height()) {
|
|
$('.j-titleList').find('li').eq(i).addClass('active').siblings('li').removeClass('active');
|
|
$('.j-bj').css('top', i * 34)
|
|
}
|
|
}
|
|
|
|
// 判断是上滑还是下滑
|
|
var afterScrollTop = document.documentElement.scrollTop;
|
|
let delta = afterScrollTop - beforeScrollTop;
|
|
beforeScrollTop = afterScrollTop;
|
|
var scrollTop = $(this).scrollTop();
|
|
var scrollHeight = $(document).height();
|
|
var windowHeight = $(this).height();
|
|
var progress = ((afterScrollTop + document.body.clientHeight)/scrollHeight) * 100
|
|
// 改变top bar 进度条
|
|
document.querySelector(".scrollbar").style.width = progress +'%'
|
|
|
|
if (scrollTop + windowHeight > scrollHeight - 10) { //滚动到底部执行事件
|
|
fn('bottom');
|
|
return;
|
|
}
|
|
if (afterScrollTop < 10 || afterScrollTop > $(document.body).height - 10) {
|
|
fn('up');
|
|
} else {
|
|
if (Math.abs(delta) < 10) {
|
|
return false;
|
|
}
|
|
fn(delta > 0 ? "down" : "up");
|
|
}
|
|
})
|
|
|
|
let $root = $('html, body');
|
|
$('.j-titleList li').on("click", function () {
|
|
let top = 70
|
|
if (typeof($(this).attr("first"))!=="undefined") {
|
|
// 点击第一个目录
|
|
top = 100
|
|
}
|
|
$root.animate({
|
|
scrollTop: $($.attr(this.querySelector("a"), 'href')).offset().top - top
|
|
}, 400)
|
|
return false
|
|
});
|
|
}
|
|
|
|
const _this = this
|
|
setTimeout(function () {
|
|
// 添加行数
|
|
const clientWidth = document.documentElement.clientWidth;
|
|
if(clientWidth > 425){
|
|
addCodeBtn();
|
|
}
|
|
_this.isLoading = false
|
|
},150)
|
|
})
|
|
})
|
|
}
|
|
},
|
|
destroyed() {
|
|
$(window).unbind("scroll")
|
|
$('.j-titleList li').unbind("click");
|
|
}
|
|
}
|
|
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
@import "src/styles/index";
|
|
@import "src/styles/markdown";
|
|
@import "src/styles/articles";
|
|
@import "src/styles/article";
|
|
</style>
|