<template>
|
<div class="article-meta">
|
|
<div class="headertop filter-dot headertop-bar " v-if="coverURL.length>0">
|
<figure class="centerbg" v-bind:style="{'background-image':'url('+this.coverURL+')'}">
|
</figure>
|
<div class="countMeta"
|
v-if="articleFileType==fileType.fileTypeMarkDown_1|| articleFileType==fileType.fileTypeHtml_2">
|
<div style="display: flex;justify-content: space-between;padding: 0px 10px;">
|
<div style="display: flex;align-items: center;"> <span>发布时间:{{articelMeta.publishDate}}</span></div>
|
<div style="display: inline-grid;">
|
<span style="text-align: end;">字数:{{wordCount}}</span>
|
<span>预计耗时:{{Math.floor(wordCount/500)}}~{{Math.ceil(wordCount/300)}}分钟</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<div class="mySecret" v-if="myLock">
|
<h1>越不正经的人越深情..</h1>
|
<h3>受庇护的文字..输入神秘代码以解除封印</h3>
|
|
<a-auto-complete v-model="secret" ref="mySearch" v-bind="search" @blur="pressEnter">
|
<a-input-password @pressEnter="pressEnter">
|
<a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />
|
</a-input-password>
|
</a-auto-complete>
|
<span class="myTip">{{errorMsg}}</span>
|
</div>
|
|
<div v-else-if="showMsg">
|
<div class="mySecret">
|
<h1>怎样才能让你看到我呢</h1>
|
<h1>只要你要,只要我有...</h1>
|
<span class="myTip">{{errorMsg}}</span>
|
</div>
|
</div>
|
|
<div v-else>
|
|
<div v-if="articleFileType==fileType.fileTypeTalking_9">
|
<div class="markdown-body articleTitle">
|
<h4>{{articelMeta.title}}</h4>
|
|
<div class="introduceSamll" v-if="introduce==null||introduce.length==0">
|
<p>空荡荡的..我好像忘记写点什么了OωO</p>
|
</div>
|
<div class="introduce" v-else>
|
<pre style="white-space: pre-line;padding: 10px;max-width: 100%;">
|
{{introduce}}
|
</pre>
|
</div>
|
</div>
|
</div>
|
|
<div class="introduce"
|
v-else-if="articleFileType==fileType.fileTypeVideo_3 || articleFileType==fileType.fileTypeMp3_4">
|
<div class="markdown-body articleTitle">
|
<h4>{{articelMeta.title}}</h4>
|
</div>
|
<div class="playBox"
|
v-bind:class="{disabledPointer:articelMeta.videoUrlList==null||articelMeta.videoUrlList==0}">
|
<videoPlayBox ref="videoPlayBox" :showTar="true"></videoPlayBox>
|
</div>
|
<div class="introduceSamll" v-if="articelMeta.videoUrlList==null||articelMeta.videoUrlList==0">
|
<p>该视频资源仍未上传</p>
|
</div>
|
<div class="introduce">
|
<pre style="white-space: pre-line;padding: 10px;max-width: 100%;">
|
{{introduce}}
|
</pre>
|
</div>
|
|
</div>
|
|
<div class="introduce" v-else-if="articleFileType==fileType.fileTypePictures_5">
|
<div class="markdown-body articleTitle">
|
<h4>{{articelMeta.title}}</h4>
|
</div>
|
|
<div>
|
<div class="introduceSamll"
|
v-if="articelMeta.pictureUrlList==null ||articelMeta.pictureUrlList.length==0">
|
<p>空荡荡的..好像忘记传图了</p>
|
</div>
|
<div class="myPicture" @click="showPicture(articelMeta.pictureUrlList)" v-else>
|
<div>
|
<img :src="articelMeta.pictureUrlList[0]" :key="articelMeta.id" alt="" loading="lazy"
|
:onerror="img404">
|
</div>
|
<div style="text-align: center;">图组数量:{{articelMeta.pictureUrlList.length}}</div>
|
</div>
|
</div>
|
<div class="introduce" v-if="introduce!=null && introduce.length>0">
|
<pre style="white-space: pre-line;padding: 10px;max-width: 100%;">
|
{{introduce}}
|
</pre>
|
</div>
|
</div>
|
|
<div v-viewer.static="options" class="markdown-body " v-else>
|
<div class="articleTitle">
|
<h4>{{articelMeta.title}}</h4>
|
</div>
|
<vue-markdown :source="source" v-if="source== null || source.length>0"></vue-markdown>
|
|
<div class="introduceSamll" v-else-if="introduce==null || introduce.length==0">
|
<p>空荡荡的..我好像忘记写点什么了OωO</p>
|
</div>
|
|
<div class="introduce" v-else>
|
<pre style="white-space: pre-line;padding: 10px;max-width: 100%;">
|
{{introduce}}
|
</pre>
|
</div>
|
</div>
|
</div>
|
|
<!-- <div class="articleInfoMiniData">
|
<div>
|
<a-icon type="calendar" class="samllPadding" />
|
<span>{{articelMeta.publishDate==null?'--':articelMeta.publishDate}}</span>
|
</div>
|
<div class="smallOption" @click="articleOptionHandle('dislike')">
|
<a-icon type="dislike" style="margin-top: 2px;" />
|
</div>
|
<div>
|
<a-icon type="read" class="samllPadding" />
|
<span>{{articelMeta.readCount==null?'--':articelMeta.readCount}}</span>
|
</div>
|
<div class="smallOption" @click="articleOptionHandle('like')">
|
<a-icon type="like" class="samllPadding" />
|
<span>{{articelMeta.likeCount==null?'0':articelMeta.likeCount}}</span>
|
</div>
|
<div>
|
<a-icon type="book" class="samllPadding" />
|
<span>{{articelMeta.articleTypeName==null?'--':articelMeta.articleTypeName}}</span>
|
</div>
|
<a-icon type="folder-open" class="samllPadding" />
|
</div> -->
|
|
<div class="jumpURL" v-if="articelMeta.jumpURL">
|
外链:<a target="_blank" :href="articelMeta.jumpURL" :title="articelMeta.jumpURL">{{articelMeta.jumpURL}}</a>
|
</div>
|
|
<div class="articleInfoMiniData">
|
|
<div class="myTitleDeal">
|
<a-icon type="left" />
|
<a-tooltip placement="bottomLeft" :title="'上一篇: '+articelMeta.previousRecord.title"
|
v-if="articelMeta.previousRecord !=null">
|
<router-link
|
:to="{path:'/mdDetail',query:{id:articelMeta.previousRecord.id,articleFileType:articleFileType,typeId:typeId}}"
|
class="article-title">
|
{{articelMeta.previousRecord.title}}
|
</router-link>
|
</a-tooltip>
|
<span v-else class="myTip">到顶啦..</span>
|
</div>
|
|
<div style="display: -webkit-box;">
|
<div class="myTitleDeal">
|
<a-tooltip placement="bottomLeft" :title="'下一篇: '+articelMeta.nextRecord.title"
|
v-if="articelMeta.nextRecord !=null">
|
<router-link
|
:to="{path:'/mdDetail',query:{id:articelMeta.nextRecord.id,articleFileType:articleFileType,typeId:typeId}}"
|
class="article-title">
|
{{articelMeta.nextRecord.title}}
|
</router-link>
|
</a-tooltip>
|
<span v-else class="myTip">到底啦..</span>
|
</div>
|
<a-icon type="right" />
|
</div>
|
</div>
|
|
<div class="articleComment">
|
<comment ref="myComment" :articleId="articleId" :isAllowedComment="isAllowedComment" />
|
</div>
|
|
</div>
|
</template>
|
|
<script>
|
import VueMarkdown from 'vue-markdown'
|
import md5 from 'js-md5';
|
|
import {
|
queryBlogArticleDetail
|
} from '../../api/blogArticle.js'
|
|
import comment from "../mini/box12-comment.vue"
|
|
import axios from 'axios'
|
import myConstant from "../../config/myConstant.js"
|
import optionsConfig from "../../config/v-viewer-Config.js"
|
import videoPlayBox from "../mini/box15-videoPlayBox.vue"
|
import {
|
api as viewerApi
|
} from "v-viewer"
|
|
|
export default {
|
components: {
|
VueMarkdown,
|
comment,
|
videoPlayBox
|
},
|
data() {
|
return {
|
articleId: "",
|
articleFileType: myConstant.fileType.fileTypeMarkDown_1,
|
typeId: null,
|
|
fileType: myConstant.fileType,
|
articelMeta: '',
|
isAllowedComment: 1,
|
coverURL: "",
|
introduce: "",
|
source: "",
|
|
showMsg: false,
|
myLock: false,
|
errorMsg: '',
|
secret: '',
|
search: {
|
placeholder: "",
|
autoFocus: false,
|
backfill: true,
|
value: '',
|
disabled: false
|
},
|
videoData: {
|
pic: "",
|
url: "",
|
type: "normal",
|
title: "",
|
introduce: "",
|
id: ""
|
},
|
options: optionsConfig,
|
img404: myConstant.img404,
|
|
wordCount: 0
|
}
|
},
|
created() {
|
this.articleId = this.$route.query.id;
|
this.articleFileType = this.$route.query.articleFileType;
|
this.typeId = this.$route.query.typeId;
|
},
|
watch: {
|
'$route'(to, from) {
|
if ("mdDetail" === to.name) {
|
if (this.articleId != this.$route.query.id) {
|
this.articleId = this.$route.query.id;
|
this.articleFileType = this.$route.query.articleFileType;
|
this.typeId = this.$route.query.typeId;
|
}
|
}
|
},
|
articleId: function(newValue, oldValue) {
|
if (newValue == undefined || newValue == null || newValue == "") {
|
this.showMsg = true;
|
this.errorMsg = "日志id参数缺失";
|
} else {
|
this.queryDetail();
|
this.$refs.myComment.updateCommentList(this.articleId);
|
}
|
},
|
},
|
methods: {
|
getWordCount() {
|
var iTotal = 0;
|
var c;
|
for (var i = 0; i < this.source.length; i++) {
|
c = this.source.charAt(i);
|
//基本汉字
|
if (c.match(/[\u4e00-\u9fa5]/)) {
|
iTotal++;
|
}
|
//基本汉字补充
|
else if (c.match(/[\u9FA6-\u9fcb]/)) {
|
iTotal++;
|
}
|
}
|
this.wordCount = iTotal;
|
},
|
articleOptionHandle(type) {
|
this.$message.info(type)
|
},
|
showPicture(param) {
|
viewerApi({
|
options: this.options,
|
images: param
|
})
|
},
|
queryDetail() {
|
this.showMsg = true;
|
this.errorMsg = "加载中..";
|
let _this = this;
|
|
queryBlogArticleDetail({
|
id: this.articleId,
|
authWord: this.secret == "" ? null : md5(this.secret),
|
typeId: this.typeId,
|
fileType: this.articleFileType
|
}).then((res) => {
|
this.myLock = false;
|
this.errorMsg = res.message;
|
this.source = "";
|
if (res.code != 200) {
|
|
if (res.code == 1019001) {
|
//日志需要授权
|
this.errorMsg = "";
|
this.myLock = true;
|
} else if (res.code == 1019002) {
|
//授权码错误
|
this.errorMsg = "口令错误..神秘力量依然阻止了你的前进";
|
this.myLock = true;
|
} else {
|
this.$notification.error({
|
message: '好像哪里不对劲..',
|
description: res.message,
|
placement: 'bottomRight'
|
});
|
}
|
return
|
}
|
// this.test = res.data.isAllowedComment == 1 ? true : false;
|
|
this.isAllowedComment = res.data.isAllowedComment;
|
this.introduce = res.data.introduce;
|
this.articleFileType = res.data.articleFileType;
|
if (res.data.coverFileURL != null && res.data.coverFileURL != '') {
|
this.coverURL = res.data.coverFileURL;
|
} else {
|
this.coverURL = myConstant.defaultBG;
|
}
|
|
this.articelMeta = res.data;
|
|
if (res.data.articleFileType == this.fileType.fileTypeMarkDown_1 ||
|
res.data.articleFileType == this.fileType.fileTypeHtml_2) {
|
if (res.data.articleFileURL != null && res.data.articleFileURL != '') {
|
this.$axios
|
.get(res.data.articleFileURL)
|
.then((res) => {
|
this.source = res.data;
|
}).catch(() => [
|
this.$message.error("获取文件好像失败了..", 3)
|
]).finally(() => {
|
setTimeout(() => {
|
_this.getWordCount();
|
}, 500);
|
})
|
}
|
} else if (res.data.articleFileType == this.fileType.fileTypeVideo_3) {
|
if (res.data.videoUrlList == null || res.data.videoUrlList.length < 1) {
|
this.$notification.error({
|
message: '该日志还没有上传视频资源..',
|
placement: 'bottomRight'
|
});
|
} else {
|
this.videoData.url = res.data.videoUrlList[0];
|
|
this.videoData.pic = res.data.coverFileURL;
|
this.videoData.title = res.data.title;
|
this.videoData.introduce = res.data.introduce;
|
this.videoData.id = res.data.id;
|
if (this.lastArticleId != this.articleId) {
|
let tempParam = JSON.parse(JSON.stringify(this.videoData))
|
|
_this.$nextTick(function() {
|
_this.$refs.videoPlayBox.startPlay(tempParam)
|
})
|
}
|
}
|
|
|
}
|
|
//获取日志资源文件
|
this.showMsg = false;
|
this.errorMsg = "";
|
})
|
},
|
pressEnter() {
|
if (this.secret == "") {
|
return
|
}
|
this.search.disabled = true
|
this.source = "";
|
this.$message
|
.loading('卍解..', 1)
|
.then(() => {
|
this.queryDetail();
|
this.search.disabled = false;
|
})
|
|
}
|
},
|
|
}
|
</script>
|
|
<style lang="less">
|
@import '../../assets/md.less';
|
|
.disabledPointer {
|
position: relative;
|
pointer-events: none;
|
filter: blur(0.9px) brightness(.8);
|
}
|
|
.disabledPointer:before {
|
content: "\ec2a";
|
z-index: 2;
|
font-size: 4rem;
|
font-family: 'iconfont';
|
position: absolute;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
}
|
|
.articleTitle {
|
h4 {
|
margin: 0px 0px 10px 0px;
|
-webkit-line-clamp: 1;
|
}
|
|
text-align: center;
|
width: 100%;
|
}
|
|
.myPicture {
|
max-width: 70%;
|
margin: 0px auto;
|
padding: 20px 0px 0px 0px;
|
|
img {
|
display: block;
|
width: 100%;
|
transition: all 0.5s cubic-bezier(0.25, 0.1, 0.25, 1);
|
border-radius: 16px;
|
}
|
}
|
|
.countMeta {
|
position: absolute;
|
bottom: 0px;
|
width: 100%;
|
background: #f0f2f5;
|
opacity: 0.6;
|
}
|
|
.headertop {
|
position: relative;
|
overflow: hidden;
|
border-radius: 14px;
|
}
|
|
.centerbg {
|
width: 100%;
|
margin: 0;
|
padding: 0;
|
background-repeat: no-repeat;
|
// background-attachment: fixed;
|
background-size: cover;
|
z-index: -1;
|
// background-image: url("http://t.inleft.com/blog//cover/这世界那么多人.jpg");
|
height: 222px;
|
background-size: 100% auto;
|
background-position: center;
|
}
|
|
|
.headertop::before {
|
content: '';
|
position: absolute;
|
top: 0;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
z-index: 3;
|
background-attachment: fixed;
|
}
|
|
.headertop.filter-dot::before {
|
// background-image: url("https://blog-img-1258635493.cos.ap-chengdu.myqcloud.com/cdn/img/other/dot.gif");
|
// background-image: url("http://blog.inleft.com/photo/dot.gif");
|
}
|
|
// .headertop-bar::after {
|
// content: '';
|
// width: 150%;
|
// height: 4.375rem;
|
// background: linear-gradient(0deg, #fff, 84%, #ffffff4f);
|
// left: -25%;
|
// bottom: -2.875rem;
|
// border-radius: 100%;
|
// position: absolute;
|
// z-index: 4;
|
// }
|
|
.smallOption {
|
transition-function: ease-out;
|
transition-duration: 200ms;
|
-webkit-transition-function: ease-out;
|
-webkit-transition-duration: 200ms;
|
-moztransition-function: ease-out;
|
-moztransition-duration: 200ms;
|
-o-transition-function: ease-out;
|
-o-transition-duration: 200ms;
|
}
|
|
.smallOption:hover {
|
transform: scale(1.55, 1.55);
|
-webkit-transform: scale(1.55, 1.55);
|
-moz-transform: scale(1.55, 1.55);
|
-o-transform: scale(1.55, 1.55);
|
}
|
|
.jumpURL {
|
box-shadow: 8px 8px 18px rgba(0, 0, 0, 0.1), -8px -8px 18px #ffffff;
|
padding: 10px 23px;
|
margin: 20px 0px;
|
|
a {
|
color: black;
|
}
|
}
|
|
.articleInfoMiniData {
|
user-select: none;
|
box-shadow: 8px 8px 18px rgba(0, 0, 0, 0.1), -8px -8px 18px #ffffff;
|
padding: 10px 23px;
|
margin: 20px 0px;
|
display: flex;
|
justify-content: space-between;
|
flex-wrap: wrap;
|
|
|
a {
|
color: black;
|
}
|
|
.myTitleDeal {
|
max-width: 300px;
|
-webkit-line-clamp: 1;
|
text-overflow: ellipsis;
|
overflow: hidden;
|
word-wrap: break-word;
|
white-space: nowrap;
|
word-break: break-all;
|
}
|
}
|
|
.mySecret {
|
height: 315px;
|
}
|
|
.mySecret,
|
.introduce {
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
padding-left: auto;
|
align-items: center;
|
}
|
|
.mySecretSamll,
|
.introduceSamll {
|
padding: 30px 10px 10px;
|
height: 115px;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
padding-left: auto;
|
align-items: center;
|
}
|
|
|
.markdown-body,
|
.articleComment {
|
min-height: 70%;
|
padding: 30px 20px 20px 20px;
|
box-shadow: 8px 8px 18px rgba(0, 0, 0, 0.1),
|
-8px -8px 18px #ffffff;
|
}
|
|
|
@media screen and (max-width:768px) {
|
.articleInfoMiniData {
|
.myTitleDeal {
|
max-width: 120px;
|
}
|
}
|
|
.countMeta {
|
bottom: 10px;
|
}
|
}
|
</style>
|