Compare commits
54 Commits
c618c83f9b
...
master
Author | SHA1 | Date | |
---|---|---|---|
c1d8c639a3 | |||
8c3bb44cf8 | |||
1cef9e1dbf | |||
d7ab590958 | |||
62763af8ff | |||
e41cccd4cc | |||
6e9a818d10 | |||
bc6327c556 | |||
e5ca37faed | |||
58821bef70 | |||
dc4681c032 | |||
184347c4f9 | |||
1449524d4e | |||
76de2e555f | |||
995f875616 | |||
fc08315bf8 | |||
0e2e8ca254 | |||
dbebc68cb0 | |||
26cdfd79b2 | |||
4c6ad37f3a | |||
24a603c755 | |||
35e5523b93 | |||
93f32fc016 | |||
295d959e6e | |||
8851dd8c47 | |||
c0d2f24c65 | |||
8520e5567a | |||
ea90eac506 | |||
912d48bf71 | |||
dd89e298b9 | |||
f4da5d9455 | |||
20345ae9ce | |||
39be6a3439 | |||
0b02bf7838 | |||
209d25f204 | |||
687f5c5c68 | |||
fa69d02bc6 | |||
78ff669765 | |||
dd78f3af82 | |||
ca2ec55a72 | |||
719e716c6f | |||
5d744b5e84 | |||
868fc81fd1 | |||
ada4718146 | |||
af2b675052 | |||
4030b22f41 | |||
befa2e1679 | |||
41875a39e8 | |||
f85dddf4b8 | |||
9add042253 | |||
b0c6b81951 | |||
4241d13d33 | |||
3121a2bdb5 | |||
ac0bc41842 |
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -1,7 +1,10 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"Fhacks",
|
||||||
"Weibo",
|
"Weibo",
|
||||||
"Weixin",
|
"Weixin",
|
||||||
|
"autorestart",
|
||||||
|
"categorys",
|
||||||
"consola",
|
"consola",
|
||||||
"eslintignore",
|
"eslintignore",
|
||||||
"fontawesome",
|
"fontawesome",
|
||||||
@ -13,6 +16,7 @@
|
|||||||
"nuxtjs",
|
"nuxtjs",
|
||||||
"styl",
|
"styl",
|
||||||
"vditor",
|
"vditor",
|
||||||
|
"viewerjs",
|
||||||
"vmodal",
|
"vmodal",
|
||||||
"wangeditor"
|
"wangeditor"
|
||||||
]
|
]
|
||||||
|
14
app.html
Normal file
14
app.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html {{ HTML_ATTRS }}>
|
||||||
|
|
||||||
|
<head {{ HEAD_ATTRS }}>
|
||||||
|
{{ HEAD }}
|
||||||
|
<script src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async
|
||||||
|
data-ad-client="ca-pub-2143583075951360"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body {{ BODY_ATTRS }}>
|
||||||
|
{{ APP }}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -1,13 +1,18 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
footer
|
footer
|
||||||
a#gotop.scroll-top(href='javascript:;', style='display: none;')
|
a#gotop.scroll-top(href='javascript:;', style='display: none')
|
||||||
Icon(:icon="['fas', 'angle-double-up']")
|
Icon(:icon='["fas", "angle-double-up"]')
|
||||||
#mobileToc.mobileToc(style='display: none;')
|
#mobileToc.mobileToc(style='display: none')
|
||||||
| 目录
|
| 目录
|
||||||
.footer
|
.footer
|
||||||
| Copyright © 2020 WangYi.
|
| Copyright © 2009-2020 WangYi.
|
||||||
br
|
br
|
||||||
| All Rights Reserved.
|
| All Rights Reserved.
|
||||||
a(href='http://www.beian.miit.gov.cn', target='_blank', rel='external nofollow', style='color: #ccc; margin-left: 5px')
|
a(
|
||||||
|
href='https://beian.miit.gov.cn',
|
||||||
|
target='_blank',
|
||||||
|
rel='external nofollow',
|
||||||
|
style='color: #ccc; margin-left: 5px'
|
||||||
|
)
|
||||||
| 浙ICP备14013313号-2
|
| 浙ICP备14013313号-2
|
||||||
</template>
|
</template>
|
||||||
|
@ -13,20 +13,32 @@
|
|||||||
.social
|
.social
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
a(href='https://github.com/yi-ge', target='_blank', rel='external nofollow')
|
a(
|
||||||
Icon(:icon="['fab', 'github']")
|
href='https://github.com/yi-ge',
|
||||||
|
target='_blank',
|
||||||
|
rel='external nofollow'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fab", "github"]')
|
||||||
li
|
li
|
||||||
Icon(:icon="['fab', 'qq']" @click="info('qq')")
|
Icon(:icon='["fab", "qq"]', @click='info("qq")')
|
||||||
li
|
li
|
||||||
Icon(:icon="['fab', 'weixin']" @click="info('weixin')")
|
Icon(:icon='["fab", "weixin"]', @click='info("weixin")')
|
||||||
li
|
li
|
||||||
a(href='http://weibo.com/syxj', target='_blank', rel='external nofollow')
|
a(
|
||||||
Icon(:icon="['fab', 'weibo']")
|
href='http://weibo.com/syxj',
|
||||||
|
target='_blank',
|
||||||
|
rel='external nofollow'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fab", "weibo"]')
|
||||||
li
|
li
|
||||||
Icon(:icon="['fas', 'envelope']" @click="info('email')")
|
Icon(:icon='["fas", "envelope"]', @click='info("email")')
|
||||||
li
|
li
|
||||||
a(href='https://www.wyr.me/rss.xml', target='_blank', rel='external nofollow')
|
a(
|
||||||
Icon(:icon="['fas', 'rss']")
|
href='https://www.wyr.me/rss.xml',
|
||||||
|
target='_blank',
|
||||||
|
rel='external nofollow'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "rss"]')
|
||||||
.social-info-box(v-if='socialInfo')
|
.social-info-box(v-if='socialInfo')
|
||||||
| {{ socialInfo }}
|
| {{ socialInfo }}
|
||||||
#navication.widget.navication
|
#navication.widget.navication
|
||||||
@ -35,62 +47,89 @@
|
|||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
nuxt-link(to='/') 主页
|
nuxt-link(to='/') 主页
|
||||||
li(v-for='(categorys, index) in $store.state.categorys', :key='index', v-show="categorys.name !== '未分类'")
|
li(
|
||||||
nuxt-link(:to="'/' + categorys.slug") {{ categorys.name }}
|
v-for='(categorys, index) in $store.state.categorys',
|
||||||
|
:key='index',
|
||||||
|
v-show='categorys.name !== \'未分类\''
|
||||||
|
)
|
||||||
|
nuxt-link(:to='"/" + categorys.slug') {{ categorys.name }}
|
||||||
li
|
li
|
||||||
a(:href="'https://driver.wyr.me/'" target="_blank") MAC N卡驱动更新提示
|
a(:href='"https://driver.wyr.me/"', target='_blank') MAC N卡驱动更新提示
|
||||||
.search-box
|
.search-box
|
||||||
input.search(type='text', placeholder='搜索', v-model='searchVal', @keyup.enter='search')
|
input.search(
|
||||||
Icon(:icon="['fas', 'search']" @click="search")
|
type='text',
|
||||||
|
placeholder='搜索',
|
||||||
|
v-model='searchVal',
|
||||||
|
@keyup.enter='search'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "search"]', @click='search')
|
||||||
.widget.comment
|
.widget.comment
|
||||||
.widgetTitle
|
.widgetTitle
|
||||||
label 最新评论
|
label 最新评论
|
||||||
ul
|
ul
|
||||||
li(v-for='(newComment, index) in $store.state.newComments', :key='index')
|
li(
|
||||||
|
v-for='(newComment, index) in $store.state.newComments',
|
||||||
|
:key='index'
|
||||||
|
)
|
||||||
strong {{ newComment.comment_author }}:
|
strong {{ newComment.comment_author }}:
|
||||||
span
|
span
|
||||||
nuxt-link(:to="'/post/' + newComment.post.ID + '#comments'") {{ newComment.comment_content }}
|
nuxt-link(
|
||||||
|
:to='"/post/" + newComment.post.ID + "#comments"',
|
||||||
|
v-html='newComment.comment_content_html'
|
||||||
|
)
|
||||||
.meta
|
.meta
|
||||||
span
|
span
|
||||||
Icon(:icon="['far', 'clock']")
|
Icon(:icon='["far", "clock"]')
|
||||||
| {{ newComment.comment_date }}
|
| {{ newComment.comment_date }}
|
||||||
span
|
span
|
||||||
| —
|
| —
|
||||||
nuxt-link(:to="'/post/' + newComment.post.ID") {{ newComment.post.post_title }}
|
nuxt-link(:to='"/post/" + newComment.post.ID') {{ newComment.post.post_title }}
|
||||||
.widget.posts
|
.widget.posts
|
||||||
.widgetTitle
|
.widgetTitle
|
||||||
label 热门文章
|
label 热门文章
|
||||||
ul
|
ul
|
||||||
li(v-for='(hotArticle, index) in $store.state.hotArticle', :key='index')
|
li(
|
||||||
.thumbnail(v-if='hotArticle.postimages[0]')
|
v-for='(hotArticle, index) in $store.state.hotArticle',
|
||||||
img(width='150', :src="hotArticle.postimages[0].guid + '?x-oss-process=image/resize,m_lfit,h_150,w_150'")
|
:key='index'
|
||||||
.detail(:style='hotArticle.postimages[0] ? "margin-left: 70px" : "margin-left: 0"')
|
)
|
||||||
nuxt-link(:to="'/post/' + hotArticle.ID", :title='hotArticle.post_title') {{ hotArticle.post_title }}
|
.thumbnail(
|
||||||
|
v-if='hotArticle && hotArticle.postimages && hotArticle.postimages[0]'
|
||||||
|
)
|
||||||
|
img(
|
||||||
|
width='150',
|
||||||
|
:src='hotArticle.postimages[0].guid + "?x-oss-process=image/resize,m_lfit,h_150,w_150"'
|
||||||
|
)
|
||||||
|
.detail(
|
||||||
|
:style='hotArticle && hotArticle.postimages && hotArticle.postimages[0] ? "margin-left: 70px" : "margin-left: 0"'
|
||||||
|
)
|
||||||
|
nuxt-link(
|
||||||
|
:to='"/post/" + hotArticle.ID',
|
||||||
|
:title='hotArticle.post_title'
|
||||||
|
) {{ hotArticle.post_title }}
|
||||||
.meta {{ hotArticle.post_modified }}
|
.meta {{ hotArticle.post_modified }}
|
||||||
.widget.links(v-if="$route.path === '/'")
|
.widget.links(v-if='$route.path === "/"')
|
||||||
.widgetTitle
|
.widgetTitle
|
||||||
label 友情链接
|
label 友情链接
|
||||||
.links
|
.links
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
a(href="https://wintc.top/" target="_blank") 木马tc个人博客
|
a(href='https://wintc.top/', target='_blank') 沐码小站
|
||||||
li
|
li
|
||||||
a(href="https://johnsonlee.site/" target="_blank") Johnson Blog
|
a(href='https://johnsonlee.site/', target='_blank') Johnson Blog
|
||||||
li
|
li
|
||||||
a(href="https://www.lzhpo.com/" target="_blank") 会打篮球的程序猿
|
a(href='https://www.lfhacks.com/', target='_blank') LFhacks
|
||||||
li
|
li
|
||||||
a(href="https://www.lfhacks.com/" target="_blank") LFhacks
|
nuxt-link(to='/links', title='更多友链') 更多友链
|
||||||
li
|
|
||||||
a(href="https://www.ixiqin.com/" target="_blank") 西秦公子
|
|
||||||
li
|
|
||||||
a(href="https://8code.net/" target="_blank") 前端视角
|
|
||||||
li
|
|
||||||
a(href="http://www.zzfly.net/" target="_blank") 烟花易冷
|
|
||||||
#tags.widget.tags
|
#tags.widget.tags
|
||||||
.widgetTitle
|
.widgetTitle
|
||||||
label 标签
|
label 标签
|
||||||
.tagcloud
|
.tagcloud
|
||||||
nuxt-link(:to="'/tag/' + tag.slug", :title='tag.name', v-for='tag in $store.state.tags', :key='tag.term_id') {{ tag.name }}
|
nuxt-link(
|
||||||
|
:to='"/tag/" + tag.slug',
|
||||||
|
:title='tag.name',
|
||||||
|
v-for='tag in $store.state.tags',
|
||||||
|
:key='tag.term_id'
|
||||||
|
) {{ tag.name }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -1,414 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="swiper-container"
|
|
||||||
@touchmove="fn"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="default-swiper-box"
|
|
||||||
:class="box"
|
|
||||||
@transitionend="transitionend"
|
|
||||||
@touchstart="s"
|
|
||||||
@touchmove="m"
|
|
||||||
@touchend="e"
|
|
||||||
@mousedown="s"
|
|
||||||
@mousemove="m"
|
|
||||||
@mouseup="e"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<slot name="pagination">
|
|
||||||
<!-- 默认提供了一个 pagination -->
|
|
||||||
<div
|
|
||||||
v-if="pagination"
|
|
||||||
class="swiper-pagination"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="(value, key) in reallySlidesNumber"
|
|
||||||
:key="key"
|
|
||||||
class="swiper-dot"
|
|
||||||
:class="{'swiper-dot-active': currentSlide === key}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</slot>
|
|
||||||
<!-- 这两个就不默认提供了 -->
|
|
||||||
<slot name="arrowLeft" />
|
|
||||||
<slot name="arrowRight" />
|
|
||||||
|
|
||||||
<!-- 当你需要在全局的内容里面加一些玩意的时候 -->
|
|
||||||
<slot name="g" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function toArray (arraylike) {
|
|
||||||
return Array.prototype.slice.call(arraylike)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Swiper',
|
|
||||||
props: {
|
|
||||||
/* 一次滑动的默认时间 */
|
|
||||||
duration: {
|
|
||||||
type: Number,
|
|
||||||
default: 500
|
|
||||||
},
|
|
||||||
/* 两次滑动的间隔时间 */
|
|
||||||
interval: {
|
|
||||||
type: Number,
|
|
||||||
default: 2500
|
|
||||||
},
|
|
||||||
/* 是否自动播放 */
|
|
||||||
autoplay: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
/* 用户滑动多少距离, 翻页 */
|
|
||||||
therehold: {
|
|
||||||
type: Number,
|
|
||||||
default: 110
|
|
||||||
},
|
|
||||||
defaultSlide: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
pagination: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
/* 有时候全屏滚动, 的确想要禁用垂直方向的滚动的时候 */
|
|
||||||
vLock: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
swiper: null,
|
|
||||||
swiperWidth: 0,
|
|
||||||
slides: null,
|
|
||||||
slidesNumber: 0,
|
|
||||||
reallySlidesNumber: 0,
|
|
||||||
currentSlide: 0,
|
|
||||||
timer: null,
|
|
||||||
userDuration: 200,
|
|
||||||
pos: {
|
|
||||||
startX: 0,
|
|
||||||
moveX: 0,
|
|
||||||
endX: 0,
|
|
||||||
local: 0,
|
|
||||||
distance: 0
|
|
||||||
},
|
|
||||||
moving: false,
|
|
||||||
unlock: false,
|
|
||||||
activeId: '',
|
|
||||||
mousedown: false,
|
|
||||||
box: '',
|
|
||||||
isOnly: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
this.box = 'swiper-box-' + Math.random().toFixed(2) * 1000
|
|
||||||
setTimeout(() => {
|
|
||||||
/* 初始化的时候, 拿到所有的 DOM 元素以及相关属性 */
|
|
||||||
this.initElement()
|
|
||||||
if (this.isOnly) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
/* 克隆两个节点, 用来实现 loop 效果 */
|
|
||||||
this.cloneSlide()
|
|
||||||
/* 克隆结束之后, 需要设置默认显示的slide */
|
|
||||||
this.setDefaultSlide()
|
|
||||||
/*
|
|
||||||
## start
|
|
||||||
设置默认slide之后, 就需要开始设置定时器, 自动轮播
|
|
||||||
*/
|
|
||||||
if (this.autoplay) {
|
|
||||||
this.play()
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
/* 阻止容器的上下滚动, 并且只有在水平方向上面滚动超过 10px 才可以阻止 */
|
|
||||||
fn (e) {
|
|
||||||
if (this.vLock || Math.abs(this.pos.startX - this.pos.moveX) > 10) {
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/* 滑动到指定的页面 */
|
|
||||||
slideTo (index) {
|
|
||||||
if (!this.moving) {
|
|
||||||
const currentSlide = Math.round(Math.abs(this.left()) / this.swiperWidth)
|
|
||||||
/* 如果索引值不合法 或者和目前的值相等 */
|
|
||||||
if (index > this.slidesNumber - 2 - 1 || index < 0 || currentSlide === index + 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.moving = true
|
|
||||||
clearTimeout(this.timer)
|
|
||||||
/*
|
|
||||||
说明要往右边滑动
|
|
||||||
注意这里不管需要滑动多少个, duration 都是 300, 这个如果需要, 可以
|
|
||||||
自己根据起点/终点计算出一个合适的值.
|
|
||||||
*/
|
|
||||||
this.transitionDuration(300)
|
|
||||||
|
|
||||||
this.translateX(-this.swiperWidth * (index + 1))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
next () {
|
|
||||||
if (!this.moving) {
|
|
||||||
clearTimeout(this.timer)
|
|
||||||
this.moving = true
|
|
||||||
this.transitionDuration(this.userDuration)
|
|
||||||
this.translateX(this.left() - this.swiperWidth)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
previous () {
|
|
||||||
if (!this.moving) {
|
|
||||||
clearTimeout(this.timer)
|
|
||||||
this.moving = true
|
|
||||||
this.transitionDuration(this.userDuration)
|
|
||||||
this.translateX(this.left() + this.swiperWidth)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initElement () {
|
|
||||||
/* 因为传递过来的是个字符串, 所以要手动加点 */
|
|
||||||
this.swiper = document.querySelector('.' + this.box)
|
|
||||||
this.swiperWidth = this.swiper.clientWidth
|
|
||||||
this.slides = toArray(this.swiper.children)
|
|
||||||
this.slidesNumber = this.slides.length
|
|
||||||
/* 实际的 slide 个数, 因为 slidesNumber 会在后面重新赋值 */
|
|
||||||
this.reallySlidesNumber = this.slides.length
|
|
||||||
/* 如果就仅仅只有一个 slide, 那么不克隆, 不绑定, 就纯展示就可以了 */
|
|
||||||
if (this.reallySlidesNumber === 1) {
|
|
||||||
this.isOnly = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cloneSlide () {
|
|
||||||
const head = this.slides[0].cloneNode(this.slides[0], true)
|
|
||||||
const tail = this.slides[this.slidesNumber - 1].cloneNode(this.slides[this.slidesNumber - 1], true)
|
|
||||||
this.swiper.appendChild(head)
|
|
||||||
this.swiper.insertBefore(tail, this.slides[0])
|
|
||||||
/* 克隆节点之后, 需要重置一些属性 */
|
|
||||||
this.slides = toArray(this.swiper.children)
|
|
||||||
this.slidesNumber = this.slides.length
|
|
||||||
},
|
|
||||||
/* 根据用户给定的 defaultSlide 设置 init slide 的值 */
|
|
||||||
setDefaultSlide () {
|
|
||||||
/*
|
|
||||||
一切用户给定的值, 都是从 0 - x 开始, 比如用户数据里面有 6个数据
|
|
||||||
那么给定的就是 0 - 5
|
|
||||||
但是我们内部运算的时候, 实际上我们的索引能到 0 - 7
|
|
||||||
0 是实际的 5 的拷贝, 7 实际上是实际的0的拷贝
|
|
||||||
|
|
||||||
所以当用户给定的 defaultSlide =0, 我们实际上是要让展示内部索引为 1 的元素
|
|
||||||
*/
|
|
||||||
/* 如果用户设置了一个非法值, 直接抛出异常 */
|
|
||||||
if (this.defaultSlide < 0 || this.defaultSlide > this.slidesNumber - 2 - 1) {
|
|
||||||
throw new Error('[swiper:Error]: You have set a wrong defaultSlide value with defaultSlide = ' + this.defaultSlide)
|
|
||||||
}
|
|
||||||
this.translateX(-this.swiperWidth * (this.defaultSlide + 1))
|
|
||||||
//
|
|
||||||
// this.currentSlide = this.defaultSlide;
|
|
||||||
},
|
|
||||||
/*
|
|
||||||
## start
|
|
||||||
*/
|
|
||||||
play () {
|
|
||||||
this.timer = setTimeout(() => {
|
|
||||||
clearTimeout(this.timer)
|
|
||||||
this.moving = true
|
|
||||||
this.unlock = false
|
|
||||||
this.transitionDuration(this.duration)
|
|
||||||
this.translateX(-(this.swiperWidth + Math.abs(this.left())))
|
|
||||||
}, this.interval)
|
|
||||||
},
|
|
||||||
transitionend () {
|
|
||||||
this.transitionDuration(0)
|
|
||||||
/*
|
|
||||||
一次滑动结束之后, 通过计算, 实际上我们可以拿到当前处于内部索引的第几个 slide
|
|
||||||
拿到这个 currentSlide 我们就知道当前是不是滚动到最后一个了
|
|
||||||
*/
|
|
||||||
const currentSlide = Math.round(Math.abs(this.left()) / this.swiperWidth)
|
|
||||||
this.currentSlide = currentSlide - 1
|
|
||||||
/* 如果滚动到最后一个, 那么就要瞬间跳转一下, 到外部看起来的第一个, 内部的 */
|
|
||||||
if (currentSlide === this.slidesNumber - 1) {
|
|
||||||
this.translateX(-this.swiperWidth)
|
|
||||||
this.currentSlide = 0
|
|
||||||
}
|
|
||||||
if (currentSlide === 0) {
|
|
||||||
this.translateX(-this.swiperWidth * (this.slidesNumber - 2))
|
|
||||||
this.currentSlide = this.slidesNumber - 3
|
|
||||||
}
|
|
||||||
this.$emit('transitionend', this.currentSlide)
|
|
||||||
/*
|
|
||||||
防止极限操作, 用户在滑动结束之后事件还没发送出去又滑动导致计算
|
|
||||||
结果错误, 所以等事件发出去之后再解开
|
|
||||||
*/
|
|
||||||
this.moving = false
|
|
||||||
/*
|
|
||||||
##start
|
|
||||||
*/
|
|
||||||
if (this.autoplay) {
|
|
||||||
this.play()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/* toushstart handler */
|
|
||||||
s (e) {
|
|
||||||
if (this.isOnly) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (e.type === 'mousedown' && !this.moving) {
|
|
||||||
this.mousedown = true
|
|
||||||
this.pos.startX = e.pageX
|
|
||||||
this.pos.local = this.left()
|
|
||||||
clearTimeout(this.timer)
|
|
||||||
this.transitionDuration(0)
|
|
||||||
} else {
|
|
||||||
this.activeId = toArray(e.changedTouches)[0].identifier
|
|
||||||
if (!this.moving) {
|
|
||||||
const active = e.touches.length - 1
|
|
||||||
clearTimeout(this.timer)
|
|
||||||
this.transitionDuration(0)
|
|
||||||
this.unlock = true
|
|
||||||
this.pos.startX = e.touches[active].clientX
|
|
||||||
/* 一次 touch 的 起始local 点, 是固定的 */
|
|
||||||
this.pos.local = this.left()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/* toushmove handler */
|
|
||||||
m (e) {
|
|
||||||
if (this.isOnly) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (e.type === 'mousemove' && this.mousedown && !this.moving) {
|
|
||||||
this.pos.moveX = e.pageX
|
|
||||||
this.pos.distance = this.pos.moveX - this.pos.startX
|
|
||||||
this.translateX(this.pos.local + this.pos.distance)
|
|
||||||
} else if (!this.moving && this.unlock) {
|
|
||||||
const active = e.touches.length - 1
|
|
||||||
this.pos.moveX = e.touches[active].clientX
|
|
||||||
this.pos.distance = this.pos.moveX - this.pos.startX
|
|
||||||
this.translateX(this.pos.local + this.pos.distance)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/* toushend handler */
|
|
||||||
e (e) {
|
|
||||||
if (this.isOnly) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (e.type === 'mouseup' && this.mousedown && !this.moving) {
|
|
||||||
this.mousedown = false
|
|
||||||
this.pos.endX = e.pageX
|
|
||||||
this.pos.distance = this.pos.endX - this.pos.startX
|
|
||||||
this.recover()
|
|
||||||
} else {
|
|
||||||
const curId = toArray(e.changedTouches)[0].identifier
|
|
||||||
if (!this.moving && this.unlock && (curId === this.activeId)) {
|
|
||||||
this.unlock = false
|
|
||||||
this.pos.endX = e.changedTouches[0].clientX
|
|
||||||
this.pos.distance = this.pos.endX - this.pos.startX
|
|
||||||
this.recover()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/* 响应用户滚动行为 */
|
|
||||||
recover () {
|
|
||||||
this.transitionDuration(this.userDuration)
|
|
||||||
const distance = Math.abs(this.left()) % this.swiperWidth
|
|
||||||
let point = []
|
|
||||||
let direction = ''
|
|
||||||
/*
|
|
||||||
主要是为了拿到当前状态下面, swiper 距离正常状态的, 左右移动的距离分别是多少.
|
|
||||||
*/
|
|
||||||
if (this.left() > 0) {
|
|
||||||
point = [distance, this.swiperWidth - distance]
|
|
||||||
} else {
|
|
||||||
point = [this.swiperWidth - distance, distance]
|
|
||||||
}
|
|
||||||
if (this.pos.distance > 0) {
|
|
||||||
direction = 'to-right'
|
|
||||||
} else if (this.pos.distance < 0) {
|
|
||||||
direction = 'to-left'
|
|
||||||
} else {
|
|
||||||
direction = 'none'
|
|
||||||
}
|
|
||||||
if (direction === 'none') {
|
|
||||||
if (this.autoplay) {
|
|
||||||
this.play()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (direction === 'to-right') {
|
|
||||||
this.moving = true
|
|
||||||
/* 说明需要向右边移动 */
|
|
||||||
if (point[0] > this.therehold) {
|
|
||||||
this.translateX(this.left() + point[1])
|
|
||||||
const next = (this.left() + point[1]) / this.swiperWidth
|
|
||||||
if (Math.abs(next) === 0) {
|
|
||||||
this.unlock = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.translateX(this.left() - point[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (direction === 'to-left') {
|
|
||||||
this.moving = true
|
|
||||||
if (point[1] > this.therehold) {
|
|
||||||
this.translateX(this.left() - point[0])
|
|
||||||
const next = (this.left() - point[0]) / this.swiperWidth
|
|
||||||
if (Math.abs(next) === this.slidesNumber - 1) {
|
|
||||||
this.unlock = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.translateX(this.left() + point[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
translateX (value) {
|
|
||||||
this.swiper.style.transform = 'translate3d(' + value + 'px, 0, 0)'
|
|
||||||
},
|
|
||||||
transitionDuration (ms) {
|
|
||||||
this.swiper.style.transitionDuration = ms + 'ms'
|
|
||||||
},
|
|
||||||
left () {
|
|
||||||
return this.swiper.getBoundingClientRect().left
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="stylus">
|
|
||||||
.swiper-container
|
|
||||||
position relative
|
|
||||||
width 100%
|
|
||||||
overflow hidden
|
|
||||||
|
|
||||||
.default-swiper-box
|
|
||||||
height 100%
|
|
||||||
width 100%
|
|
||||||
display flex
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.swiper-pagination
|
|
||||||
position absolute
|
|
||||||
bottom 10px
|
|
||||||
height 18px
|
|
||||||
width 100%
|
|
||||||
background transparent
|
|
||||||
display flex
|
|
||||||
align-items center
|
|
||||||
justify-content center
|
|
||||||
|
|
||||||
.swiper-dot
|
|
||||||
height 8px
|
|
||||||
width 8px
|
|
||||||
background #000
|
|
||||||
opacity 0.2
|
|
||||||
margin 0 5px
|
|
||||||
border-radius 50%
|
|
||||||
|
|
||||||
.swiper-dot-active
|
|
||||||
opacity 1
|
|
||||||
background #3498db
|
|
||||||
</style>
|
|
16
ecosystem.config.js
Normal file
16
ecosystem.config.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [{
|
||||||
|
name: 'blog-client',
|
||||||
|
script: './server/index.js',
|
||||||
|
watch: false,
|
||||||
|
max_memory_restart: '3G', // 超过多大内存自动重启,仅防止内存泄露有意义,需要根据自己的业务设置
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
HOST: '0.0.0.0',
|
||||||
|
PORT: 8080
|
||||||
|
},
|
||||||
|
exec_mode: 'cluster', // 开启多线程模式,用于负载均衡
|
||||||
|
instances: 'max', // 启用多少个实例,可用于负载均衡
|
||||||
|
autorestart: true // 程序崩溃后自动重启
|
||||||
|
}]
|
||||||
|
}
|
@ -2,6 +2,12 @@
|
|||||||
margin 0
|
margin 0
|
||||||
padding 0
|
padding 0
|
||||||
|
|
||||||
|
html
|
||||||
|
overflow hidden
|
||||||
|
|
||||||
|
body
|
||||||
|
overflow auto
|
||||||
|
|
||||||
body, html
|
body, html
|
||||||
color #2e2f30
|
color #2e2f30
|
||||||
letter-spacing 0.5px
|
letter-spacing 0.5px
|
||||||
@ -12,7 +18,6 @@ body, html
|
|||||||
|
|
||||||
#__nuxt, .content
|
#__nuxt, .content
|
||||||
width 100%
|
width 100%
|
||||||
height 100%
|
|
||||||
max-width 1040px
|
max-width 1040px
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
position relative
|
position relative
|
||||||
@ -87,7 +92,7 @@ footer
|
|||||||
position fixed
|
position fixed
|
||||||
right 8px
|
right 8px
|
||||||
bottom 8px
|
bottom 8px
|
||||||
z-index 999
|
z-index 998
|
||||||
padding 4px
|
padding 4px
|
||||||
|
|
||||||
i
|
i
|
||||||
@ -209,6 +214,10 @@ input:-moz-placeholder
|
|||||||
|
|
||||||
.links
|
.links
|
||||||
margin-bottom 20px
|
margin-bottom 20px
|
||||||
|
font-weight 300
|
||||||
|
|
||||||
|
li
|
||||||
|
margin-top 5px
|
||||||
|
|
||||||
.widgetTitle
|
.widgetTitle
|
||||||
font-size 18px
|
font-size 18px
|
||||||
@ -358,6 +367,9 @@ input:-moz-placeholder
|
|||||||
white-space nowrap
|
white-space nowrap
|
||||||
text-overflow ellipsis
|
text-overflow ellipsis
|
||||||
|
|
||||||
|
img
|
||||||
|
width 100%
|
||||||
|
|
||||||
.posts
|
.posts
|
||||||
margin-bottom 40px
|
margin-bottom 40px
|
||||||
|
|
||||||
@ -409,9 +421,11 @@ input:-moz-placeholder
|
|||||||
|
|
||||||
// 文章列表
|
// 文章列表
|
||||||
.pageList
|
.pageList
|
||||||
|
.articleList:not(:first-child)
|
||||||
|
margin-top 30px
|
||||||
|
|
||||||
.articleList
|
.articleList
|
||||||
background-color #fff
|
background-color #fff
|
||||||
margin-top 30px
|
|
||||||
|
|
||||||
.articleImgs
|
.articleImgs
|
||||||
width 100%
|
width 100%
|
||||||
@ -510,7 +524,7 @@ input:-moz-placeholder
|
|||||||
@media (max-width 768px)
|
@media (max-width 768px)
|
||||||
.header
|
.header
|
||||||
position fixed
|
position fixed
|
||||||
z-index 999999
|
z-index 99999
|
||||||
width 100%
|
width 100%
|
||||||
display block
|
display block
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
@ -559,3 +573,6 @@ blockquote
|
|||||||
.articelContent
|
.articelContent
|
||||||
a
|
a
|
||||||
color #de8787
|
color #de8787
|
||||||
|
|
||||||
|
.toasted-container
|
||||||
|
z-index 9999999 !important
|
@ -1,8 +1,8 @@
|
|||||||
const pkg = require('./package')
|
const pkg = require('./package')
|
||||||
|
|
||||||
const DevBaseUrl = 'http://127.0.0.1:65534'
|
const DevBaseUrl = 'http://127.0.0.1:65534'
|
||||||
// const DevBaseUrl = 'https://api.wyr.me'
|
|
||||||
const ProdBashUrl = 'https://api.wyr.me'
|
const ProdBashUrl = 'https://api.wyr.me'
|
||||||
|
const ProdServerBashUrl = 'http://127.0.0.1:65534'
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: 'universal',
|
mode: 'universal',
|
||||||
@ -50,9 +50,6 @@ module.exports = {
|
|||||||
type: 'image/x-icon',
|
type: 'image/x-icon',
|
||||||
href: '/favicon.ico'
|
href: '/favicon.ico'
|
||||||
}
|
}
|
||||||
],
|
|
||||||
script: [
|
|
||||||
{ src: 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', async: true, 'data-ad-client': 'ca-pub-2143583075951360' }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -82,7 +79,9 @@ module.exports = {
|
|||||||
src: '~/plugins/browser.js',
|
src: '~/plugins/browser.js',
|
||||||
ssr: false
|
ssr: false
|
||||||
},
|
},
|
||||||
{ src: '~/plugins/vue-js-modal', mode: 'client' }
|
{ src: '~/plugins/vue-js-modal', mode: 'client' },
|
||||||
|
{ src: '~/plugins/vue-toasted', mode: 'client' },
|
||||||
|
{ src: '~/plugins/v-viewer', mode: 'client' }
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -97,7 +96,19 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
axios: {
|
axios: {
|
||||||
// See https://github.com/nuxt-community/axios-module#options
|
// See https://github.com/nuxt-community/axios-module#options
|
||||||
baseURL: process.env.NODE_ENV === 'development' ? DevBaseUrl : ProdBashUrl // 配置API接口地址
|
baseURL: process.env.NODE_ENV === 'development' ? DevBaseUrl : ProdServerBashUrl // 配置API接口地址
|
||||||
|
},
|
||||||
|
|
||||||
|
publicRuntimeConfig: {
|
||||||
|
axios: {
|
||||||
|
browserBaseURL: process.env.NODE_ENV === 'development' ? DevBaseUrl : ProdBashUrl
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
privateRuntimeConfig: {
|
||||||
|
axios: {
|
||||||
|
baseURL: process.env.NODE_ENV === 'development' ? DevBaseUrl : ProdServerBashUrl
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -118,7 +129,18 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
vendor: ['moment']
|
vendor: ['moment'],
|
||||||
|
babel: {
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
'component',
|
||||||
|
{
|
||||||
|
libraryName: 'element-ui',
|
||||||
|
styleLibraryName: 'theme-chalk'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
version: pkg.version,
|
version: pkg.version,
|
||||||
|
66
package.json
66
package.json
@ -7,43 +7,49 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
|
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
"start": "cross-env NODE_ENV=production HOST=0.0.0.0 PORT=80 node server/index.js",
|
"start": "cross-env NODE_ENV=production HOST=0.0.0.0 PORT=8080 node server/index.js",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --ignore-path .eslintignore .",
|
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --ignore-path .eslintignore .",
|
||||||
"precommit": "npm run lint"
|
"precommit": "npm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.26",
|
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
||||||
"@fortawesome/free-brands-svg-icons": "^5.12.0",
|
"@fortawesome/free-brands-svg-icons": "^5.15.3",
|
||||||
"@fortawesome/free-regular-svg-icons": "^5.12.0",
|
"@fortawesome/free-regular-svg-icons": "^5.15.3",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
||||||
"@fortawesome/vue-fontawesome": "^0.1.8",
|
"@fortawesome/vue-fontawesome": "^2.0.2",
|
||||||
"@nuxtjs/axios": "^5.8.0",
|
"@nuxtjs/axios": "^5.13.6",
|
||||||
"cross-env": "^6.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"highlight.js": "^9.17.1",
|
"element-ui": "^2.15.4",
|
||||||
"koa": "^2.11.0",
|
"highlight.js": "^11.2.0",
|
||||||
"moment": "^2.27.0",
|
"koa": "^2.13.1",
|
||||||
"nuxt": "^2.12.2",
|
"moment": "^2.29.1",
|
||||||
"vditor": "^3.3.3",
|
"nuxt": "^2.15.7",
|
||||||
"vue-js-modal": "^2.0.0-rc.3"
|
"remark": "12.0.1",
|
||||||
|
"strip-markdown": "^4.1.0",
|
||||||
|
"v-viewer": "^1.6.4",
|
||||||
|
"vditor": "^3.8.6",
|
||||||
|
"vue-js-modal": "^2.0.1",
|
||||||
|
"vue-toasted": "^1.1.28"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxtjs/eslint-config": "^2.0.0",
|
"@nuxtjs/eslint-config": "^6.0.1",
|
||||||
"babel-eslint": "^10.0.3",
|
"babel-eslint": "^10.0.3",
|
||||||
"eslint": "^6.7.2",
|
"babel-plugin-component": "^1.1.1",
|
||||||
"eslint-config-standard": ">=14.1.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-loader": "^3.0.3",
|
"eslint-config-standard": ">=16.0.3",
|
||||||
"eslint-plugin-html": "^6.0.2",
|
"eslint-loader": "^4.0.2",
|
||||||
"eslint-plugin-import": ">=2.19.1",
|
"eslint-plugin-html": "^6.1.2",
|
||||||
"eslint-plugin-jest": "^23.1.1",
|
"eslint-plugin-import": ">=2.23.4",
|
||||||
|
"eslint-plugin-jest": "^24.4.0",
|
||||||
"eslint-plugin-node": ">=10.0.0",
|
"eslint-plugin-node": ">=10.0.0",
|
||||||
"eslint-plugin-promise": ">=4.2.1",
|
"eslint-plugin-promise": ">=5.1.0",
|
||||||
"eslint-plugin-standard": ">=4.0.1",
|
"eslint-plugin-standard": ">=5.0.0",
|
||||||
"eslint-plugin-vue": "^6.0.1",
|
"eslint-plugin-vue": "^7.15.1",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "^2.0.12",
|
||||||
"pug": "^2.0.4",
|
"pug": "^3.0.2",
|
||||||
"pug-plain-loader": "^1.0.0",
|
"pug-plain-loader": "^1.1.0",
|
||||||
"stylus": "^0.54.7",
|
"stylus": "^0.54.8",
|
||||||
"stylus-loader": "^3.0.2"
|
"stylus-loader": "3.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,43 +2,54 @@
|
|||||||
.pageList
|
.pageList
|
||||||
.articleContent(ref='articleImgs', v-if='Articels')
|
.articleContent(ref='articleImgs', v-if='Articels')
|
||||||
article.articleList(v-for='(post, index) in Articels', :key='index')
|
article.articleList(v-for='(post, index) in Articels', :key='index')
|
||||||
.articleImgs(v-if='post.postImages.length')
|
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
|
||||||
Swiper(:style="'height: ' + imageHeight + 'px'")
|
|
||||||
Slide(v-for="(imgUrl, inx) in post.postImages" :key="inx")
|
|
||||||
img(:src='imgUrl')
|
|
||||||
.articleAbstract
|
.articleAbstract
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
nuxt-link(:to='"/post/" + post.ID')
|
||||||
.articleTitle(v-html='post.post_title')
|
.articleTitle(v-html='post.post_title')
|
||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ post.post_date }}
|
| {{ post.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, idx) in post.term_relationships', :key='idx', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, idx) in post.term_relationships',
|
||||||
|
:key='idx',
|
||||||
|
v-if='relationships.term_taxonomy',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='post.postmetum.meta_value !== 0')
|
li(v-if='post.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + post.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + post.hotValue]')
|
||||||
| {{ post.postmetum.meta_value }}
|
| {{ post.postmetum.meta_value }}
|
||||||
.articelAbstractContent(v-html='post.post_excerpt || post.post_content')
|
.articelAbstractContent(
|
||||||
|
v-html='post.post_excerpt || post.post_content'
|
||||||
|
)
|
||||||
.readMore
|
.readMore
|
||||||
nuxt-link.readMoreBtn(:to="'/post/' + post.ID")
|
nuxt-link.readMoreBtn(:to='"/post/" + post.ID')
|
||||||
| READ MORE
|
| READ MORE
|
||||||
.Info(v-if='Info')
|
.Info(v-if='Info')
|
||||||
| {{ Info }}
|
| {{ Info }}
|
||||||
nuxt-link(:to="nowPage > 2 ? nowPath + '/page/' + (nowPage - 1) : nowPath + '/'", :class="nowPage > 1 ? 'btn-footer btn-prev ' : 'btn-footer btn-prev btn-disable'")
|
nuxt-link(
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
:to='nowPage > 2 ? nowPath + "/page/" + (nowPage - 1) : nowPath + "/"',
|
||||||
|
:class='nowPage > 1 ? "btn-footer btn-prev " : "btn-footer btn-prev btn-disable"'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一页
|
| 上一页
|
||||||
nuxt-link(:to="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? nowPath + '/page/' + (nowPage + 1) : '#'", :class="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? 'btn-footer btn-next' : 'btn-footer btn-next btn-disable'")
|
nuxt-link(
|
||||||
|
:to='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? nowPath + "/page/" + (nowPage + 1) : "#"',
|
||||||
|
:class='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? "btn-footer btn-next" : "btn-footer btn-next btn-disable"'
|
||||||
|
)
|
||||||
| 下一页
|
| 下一页
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
validate ({ params }) {
|
||||||
|
return (params && params.terms) !== '404'
|
||||||
|
},
|
||||||
async asyncData ({ app, params, $axios }) {
|
async asyncData ({ app, params, $axios }) {
|
||||||
let Info = null
|
let Info = null
|
||||||
let Articels = []
|
let Articels = []
|
||||||
@ -64,11 +75,11 @@ export default {
|
|||||||
Articels[n].postmetum = {}
|
Articels[n].postmetum = {}
|
||||||
Articels[n].postmetum.meta_value = 0
|
Articels[n].postmetum.meta_value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Articels[n].postImages = []
|
|
||||||
}
|
}
|
||||||
} else if (data.status === 404) {
|
} else if (data.status === 404) {
|
||||||
Info = '未找到文章。'
|
Info = '未找到文章。'
|
||||||
|
// redirect('/404')
|
||||||
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -82,25 +93,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$finishLoad()
|
this.$finishLoad()
|
||||||
this.analyseImages()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async analyseImages () { // 图片大小分析及处理
|
|
||||||
const articleImgsWidth = this.$refs.articleImgs.getBoundingClientRect().width
|
|
||||||
this.imageHeight = articleImgsWidth * 0.5625
|
|
||||||
for (const n in this.Articels) {
|
|
||||||
if (this.Articels[n].postimages.length !== 0) {
|
|
||||||
for (const i in this.Articels[n].postimages) {
|
|
||||||
const data = await this.$axios.$get(this.Articels[n].postimages[i].guid + '?x-oss-process=image/info')
|
|
||||||
const widthValue = data.ImageWidth.value
|
|
||||||
const heightValue = data.ImageHeight.value
|
|
||||||
if (widthValue > articleImgsWidth && (articleImgsWidth * heightValue / widthValue > this.imageHeight) && this.Articels[n].postImages.length < 10) {
|
|
||||||
this.Articels[n].postImages.push(this.Articels[n].postimages[i].guid + '?x-oss-process=image/resize,m_lfit,w_' + articleImgsWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,39 +2,47 @@
|
|||||||
.pageList
|
.pageList
|
||||||
.articleContent(ref='articleImgs', v-if='Articels')
|
.articleContent(ref='articleImgs', v-if='Articels')
|
||||||
article.articleList(v-for='(post, index) in Articels', :key='index')
|
article.articleList(v-for='(post, index) in Articels', :key='index')
|
||||||
.articleImgs(v-if='post.postImages.length')
|
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
|
||||||
Swiper(:style="'height: ' + imageHeight + 'px'")
|
|
||||||
Slide(v-for="(imgUrl, inx) in post.postImages" :key="inx")
|
|
||||||
img(:src='imgUrl')
|
|
||||||
.articleAbstract
|
.articleAbstract
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
nuxt-link(:to='"/post/" + post.ID')
|
||||||
.articleTitle(v-html='post.post_title')
|
.articleTitle(v-html='post.post_title')
|
||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ post.post_date }}
|
| {{ post.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, idx) in post.term_relationships', :key='idx', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, idx) in post.term_relationships',
|
||||||
|
:key='idx',
|
||||||
|
v-if='relationships.term_taxonomy',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='post.postmetum.meta_value !== 0')
|
li(v-if='post.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + post.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + post.hotValue]')
|
||||||
| {{ post.postmetum.meta_value }}
|
| {{ post.postmetum.meta_value }}
|
||||||
.articelAbstractContent(v-html='post.post_excerpt || post.post_content')
|
.articelAbstractContent(
|
||||||
|
v-html='post.post_excerpt || post.post_content'
|
||||||
|
)
|
||||||
.readMore
|
.readMore
|
||||||
nuxt-link.readMoreBtn(:to="'/post/' + post.ID")
|
nuxt-link.readMoreBtn(:to='"/post/" + post.ID')
|
||||||
| READ MORE
|
| READ MORE
|
||||||
.Info(v-if='Info')
|
.Info(v-if='Info')
|
||||||
| {{ Info }}
|
| {{ Info }}
|
||||||
nuxt-link(:to="nowPage > 2 ? nowPath + '/page/' + (nowPage - 1) : nowPath + '/'", :class="nowPage > 1 ? 'btn-footer btn-prev' : 'btn-footer btn-prev btn-disable'")
|
nuxt-link(
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
:to='nowPage > 2 ? nowPath + "/page/" + (nowPage - 1) : nowPath + "/"',
|
||||||
|
:class='nowPage > 1 ? "btn-footer btn-prev" : "btn-footer btn-prev btn-disable"'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一页
|
| 上一页
|
||||||
nuxt-link(:to="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? nowPath + '/page/' + (nowPage + 1) : ''", :class="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? 'btn-footer btn-next' : 'btn-footer btn-next btn-disable'")
|
nuxt-link(
|
||||||
|
:to='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? nowPath + "/page/" + (nowPage + 1) : ""',
|
||||||
|
:class='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? "btn-footer btn-next" : "btn-footer btn-next btn-disable"'
|
||||||
|
)
|
||||||
| 下一页
|
| 下一页
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -64,11 +72,11 @@ export default {
|
|||||||
Articels[n].postmetum = {}
|
Articels[n].postmetum = {}
|
||||||
Articels[n].postmetum.meta_value = 0
|
Articels[n].postmetum.meta_value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Articels[n].postImages = []
|
|
||||||
}
|
}
|
||||||
} else if (data.status === 404) {
|
} else if (data.status === 404) {
|
||||||
Info = '未找到文章。'
|
Info = '未找到文章。'
|
||||||
|
// redirect('/404')
|
||||||
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -82,25 +90,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$finishLoad()
|
this.$finishLoad()
|
||||||
this.analyseImages()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async analyseImages () { // 图片大小分析及处理
|
|
||||||
const articleImgsWidth = this.$refs.articleImgs.getBoundingClientRect().width
|
|
||||||
this.imageHeight = articleImgsWidth * 0.5625
|
|
||||||
for (const n in this.Articels) {
|
|
||||||
if (this.Articels[n].postimages.length !== 0) {
|
|
||||||
for (const i in this.Articels[n].postimages) {
|
|
||||||
const data = await this.$axios.$get(this.Articels[n].postimages[i].guid + '?x-oss-process=image/info')
|
|
||||||
const widthValue = data.ImageWidth.value
|
|
||||||
const heightValue = data.ImageHeight.value
|
|
||||||
if (widthValue > articleImgsWidth && (articleImgsWidth * heightValue / widthValue > this.imageHeight) && this.Articels[n].postImages.length < 10) {
|
|
||||||
this.Articels[n].postImages.push(this.Articels[n].postimages[i].guid + '?x-oss-process=image/resize,m_lfit,w_' + articleImgsWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -12,9 +12,56 @@ export default {
|
|||||||
},
|
},
|
||||||
async mounted () {
|
async mounted () {
|
||||||
const code = this.$route.query.code
|
const code = this.$route.query.code
|
||||||
|
const type = this.$route.query.type
|
||||||
|
const state = this.$route.query.state.split('-')
|
||||||
|
|
||||||
if (!code) { this.notice = '<p style="color: #999">非法访问,缺少授权参数"code"。<p><br><br> <a href="https://www.wyr.me" target="_blank">返回首页<a>'; this.$finishLoad(); return }
|
if (!code) { this.notice = '<p style="color: #999">非法访问,缺少授权参数"code"。<p><br><br> <a href="https://www.wyr.me" target="_blank">返回首页<a>'; this.$finishLoad(); return }
|
||||||
|
|
||||||
|
if (type === 'weixin') {
|
||||||
|
const { data } = await this.$axios.post(`${process.env.baseURL}/visitor/user/weixin`, {
|
||||||
|
code,
|
||||||
|
app: 'wx9d5e677f533d1e84'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data.status !== 1) {
|
||||||
|
this.$toasted.show('微信登录失败,请重试或换用其它登录方式。', {
|
||||||
|
position: 'top-center'
|
||||||
|
})
|
||||||
|
this.$finishLoad()
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
window.localStorage.visitorToken = data.result.token
|
||||||
|
window.localStorage.visitorInfo = JSON.stringify(data.result.visitorInfo)
|
||||||
|
window.location.href = 'https://www.wyr.me/post/' + state[1] + '?hash=comment'
|
||||||
|
} catch (_) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state[0] === 'weibo' || state[0] === 'qq') {
|
||||||
|
const { data } = await this.$axios.post(`${process.env.baseURL}/visitor/user/` + state[0], {
|
||||||
|
code
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data.status !== 1) {
|
||||||
|
this.$toasted.show((state[0] === 'weibo' ? '微博' : 'QQ') + '登录失败,请重试或换用其它登录方式。', {
|
||||||
|
position: 'top-center'
|
||||||
|
})
|
||||||
|
this.$finishLoad()
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
window.localStorage.visitorToken = data.result.token
|
||||||
|
window.localStorage.visitorInfo = JSON.stringify(data.result.visitorInfo)
|
||||||
|
window.location.href = 'https://www.wyr.me/post/' + state[1] + '?hash=comment'
|
||||||
|
} catch (_) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const { data } = await this.$axios.post('/visitor/user/auth', {
|
const { data } = await this.$axios.post('/visitor/user/auth', {
|
||||||
type: 'github',
|
type: 'github',
|
||||||
code
|
code
|
||||||
|
@ -2,39 +2,47 @@
|
|||||||
.pageList
|
.pageList
|
||||||
.articleContent(ref='articleImgs', v-if='Articels')
|
.articleContent(ref='articleImgs', v-if='Articels')
|
||||||
article.articleList(v-for='(post, index) in Articels', :key='index')
|
article.articleList(v-for='(post, index) in Articels', :key='index')
|
||||||
.articleImgs(v-if='post.postImages.length')
|
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
|
||||||
Swiper(:style="'height: ' + imageHeight + 'px'")
|
|
||||||
Slide(v-for="(imgUrl, inx) in post.postImages" :key="inx")
|
|
||||||
img(:src='imgUrl')
|
|
||||||
.articleAbstract
|
.articleAbstract
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
nuxt-link(:to='"/post/" + post.ID')
|
||||||
.articleTitle(v-html='post.post_title')
|
.articleTitle(v-html='post.post_title')
|
||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ post.post_date }}
|
| {{ post.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, idx) in post.term_relationships', :key='idx', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, idx) in post.term_relationships',
|
||||||
|
:key='idx',
|
||||||
|
v-if='relationships.term_taxonomy',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='post.postmetum.meta_value !== 0')
|
li(v-if='post.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + post.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + post.hotValue]')
|
||||||
| {{ post.postmetum.meta_value }}
|
| {{ post.postmetum.meta_value }}
|
||||||
.articelAbstractContent(v-html='post.post_excerpt || post.post_content')
|
.articelAbstractContent(
|
||||||
|
v-html='post.post_excerpt || post.post_content'
|
||||||
|
)
|
||||||
.readMore
|
.readMore
|
||||||
nuxt-link.readMoreBtn(:to="'/post/' + post.ID")
|
nuxt-link.readMoreBtn(:to='"/post/" + post.ID')
|
||||||
| READ MORE
|
| READ MORE
|
||||||
.Info(v-if='Info')
|
.Info(v-if='Info')
|
||||||
| {{ Info }}
|
| {{ Info }}
|
||||||
nuxt-link(:to="nowPage > 2 ? nowPath + '/page/' + (nowPage - 1) : nowPath + '/'", :class="nowPage > 1 ? 'btn-footer btn-prev ' : 'btn-footer btn-prev btn-disable'")
|
nuxt-link(
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
:to='nowPage > 2 ? nowPath + "/page/" + (nowPage - 1) : nowPath + "/"',
|
||||||
|
:class='nowPage > 1 ? "btn-footer btn-prev " : "btn-footer btn-prev btn-disable"'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一页
|
| 上一页
|
||||||
nuxt-link(:to="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? nowPath + '/page/' + (nowPage + 1) : '#'", :class="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? 'btn-footer btn-next' : 'btn-footer btn-next btn-disable'")
|
nuxt-link(
|
||||||
|
:to='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? nowPath + "/page/" + (nowPage + 1) : "#"',
|
||||||
|
:class='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? "btn-footer btn-next" : "btn-footer btn-next btn-disable"'
|
||||||
|
)
|
||||||
| 下一页
|
| 下一页
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -65,11 +73,11 @@ export default {
|
|||||||
Articels[n].postmetum = {}
|
Articels[n].postmetum = {}
|
||||||
Articels[n].postmetum.meta_value = 0
|
Articels[n].postmetum.meta_value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Articels[n].postImages = []
|
|
||||||
}
|
}
|
||||||
} else if (data.status === 404) {
|
} else if (data.status === 404) {
|
||||||
Info = '未找到文章。'
|
Info = '未找到文章。'
|
||||||
|
// redirect('/404')
|
||||||
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -83,25 +91,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$finishLoad()
|
this.$finishLoad()
|
||||||
this.analyseImages()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async analyseImages () { // 图片大小分析及处理
|
|
||||||
const articleImgsWidth = this.$refs.articleImgs.getBoundingClientRect().width
|
|
||||||
this.imageHeight = articleImgsWidth * 0.5625
|
|
||||||
for (const n in this.Articels) {
|
|
||||||
if (this.Articels[n].postimages.length !== 0) {
|
|
||||||
for (const i in this.Articels[n].postimages) {
|
|
||||||
const data = await this.$axios.$get(this.Articels[n].postimages[i].guid + '?x-oss-process=image/info')
|
|
||||||
const widthValue = data.ImageWidth.value
|
|
||||||
const heightValue = data.ImageHeight.value
|
|
||||||
if (widthValue > articleImgsWidth && (articleImgsWidth * heightValue / widthValue > this.imageHeight) && this.Articels[n].postImages.length < 10) {
|
|
||||||
this.Articels[n].postImages.push(this.Articels[n].postimages[i].guid + '?x-oss-process=image/resize,m_lfit,w_' + articleImgsWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
63
pages/links.vue
Normal file
63
pages/links.vue
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.links
|
||||||
|
.Info(v-if='Info')
|
||||||
|
| {{ Info }}
|
||||||
|
|
||||||
|
h1.title
|
||||||
|
| 首页友链
|
||||||
|
ul
|
||||||
|
li
|
||||||
|
a(href='https://wintc.top/', target='_blank') 沐码小站
|
||||||
|
li
|
||||||
|
a(href='https://johnsonlee.site/', target='_blank') Johnson Blog
|
||||||
|
li
|
||||||
|
a(href='https://www.lfhacks.com/', target='_blank') LFhacks
|
||||||
|
|
||||||
|
h1.title
|
||||||
|
| 内页友链
|
||||||
|
ul
|
||||||
|
li
|
||||||
|
a(href='http://www.zzfly.net/', target='_blank') 烟花易冷
|
||||||
|
|
||||||
|
h1.title
|
||||||
|
| 暂时取消的友链
|
||||||
|
ul
|
||||||
|
li
|
||||||
|
| 前端视角 (网站无法访问)
|
||||||
|
li
|
||||||
|
| 会打篮球的程序猿 (网站无法访问)
|
||||||
|
li
|
||||||
|
| 西秦公子 (友链长期缺失)
|
||||||
|
|
||||||
|
h1.title
|
||||||
|
| 友链说明
|
||||||
|
p
|
||||||
|
| 本站友链遵循对等原则,即您的友链放置于首页,我的友链也放置于首页。
|
||||||
|
p
|
||||||
|
| 交换友链请通过左侧头像下方的联系方式与我联系。只要网站/博客能正常打开,不定时更新原创文章即可。
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
asyncData ({ app, params, $axios }) {
|
||||||
|
return {
|
||||||
|
Info: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$finishLoad()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.links
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
padding 50px
|
||||||
|
|
||||||
|
.title
|
||||||
|
margin-top 60px
|
||||||
|
margin-bottom 20px
|
||||||
|
font-weight 500
|
||||||
|
</style>
|
47
pages/p.vue
Normal file
47
pages/p.vue
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.pClass
|
||||||
|
Form(ref='form', :model='form', label-width='120px')
|
||||||
|
FormItem(label='请输入文章编号')
|
||||||
|
Input(v-model='form.no', size='small', @keyup.enter='onSubmit')
|
||||||
|
FormItem
|
||||||
|
Button(type='primary', size='small', @click='onSubmit')
|
||||||
|
| 确定
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Form, FormItem, Input, Switch, Button } from 'element-ui'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Form, FormItem, Input, VueSwitch: Switch, Button
|
||||||
|
},
|
||||||
|
layout: 'auth',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
no: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$finishLoad()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSubmit () {
|
||||||
|
if (!this.form.no) {
|
||||||
|
alert('请输入文章编号')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$router.push('/post/' + this.form.no + '#comment')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.pClass
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
padding 50px 20px
|
||||||
|
box-sizing border-box
|
||||||
|
</style>
|
@ -2,39 +2,47 @@
|
|||||||
.pageList
|
.pageList
|
||||||
.articleContent(ref='articleImgs', v-if='Articels')
|
.articleContent(ref='articleImgs', v-if='Articels')
|
||||||
article.articleList(v-for='(post, index) in Articels', :key='index')
|
article.articleList(v-for='(post, index) in Articels', :key='index')
|
||||||
.articleImgs(v-if='post.postImages.length')
|
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
|
||||||
Swiper(:style="'height: ' + imageHeight + 'px'")
|
|
||||||
Slide(v-for="(imgUrl, inx) in post.postImages" :key="inx")
|
|
||||||
img(:src='imgUrl')
|
|
||||||
.articleAbstract
|
.articleAbstract
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
nuxt-link(:to='"/post/" + post.ID')
|
||||||
.articleTitle(v-html='post.post_title')
|
.articleTitle(v-html='post.post_title')
|
||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ post.post_date }}
|
| {{ post.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, idx) in post.term_relationships', :key='idx', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, idx) in post.term_relationships',
|
||||||
|
:key='idx',
|
||||||
|
v-if='relationships.term_taxonomy',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='post.postmetum.meta_value !== 0')
|
li(v-if='post.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + post.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + post.hotValue]')
|
||||||
| {{ post.postmetum.meta_value }}
|
| {{ post.postmetum.meta_value }}
|
||||||
.articelAbstractContent(v-html='post.post_excerpt || post.post_content')
|
.articelAbstractContent(
|
||||||
|
v-html='post.post_excerpt || post.post_content'
|
||||||
|
)
|
||||||
.readMore
|
.readMore
|
||||||
nuxt-link.readMoreBtn(:to="'/post/' + post.ID")
|
nuxt-link.readMoreBtn(:to='"/post/" + post.ID')
|
||||||
| READ MORE
|
| READ MORE
|
||||||
.Info(v-if='Info')
|
.Info(v-if='Info')
|
||||||
| {{ Info }}
|
| {{ Info }}
|
||||||
nuxt-link(:to="nowPage > 2 ? nowPath + '/page/' + (nowPage - 1) : nowPath + '/'", :class="nowPage > 1 ? 'btn-footer btn-prev ' : 'btn-footer btn-prev btn-disable'")
|
nuxt-link(
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
:to='nowPage > 2 ? nowPath + "/page/" + (nowPage - 1) : nowPath + "/"',
|
||||||
|
:class='nowPage > 1 ? "btn-footer btn-prev " : "btn-footer btn-prev btn-disable"'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一页
|
| 上一页
|
||||||
nuxt-link(:to="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? nowPath + '/page/' + (nowPage + 1) : '#'", :class="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? 'btn-footer btn-next' : 'btn-footer btn-next btn-disable'")
|
nuxt-link(
|
||||||
|
:to='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? nowPath + "/page/" + (nowPage + 1) : "#"',
|
||||||
|
:class='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? "btn-footer btn-next" : "btn-footer btn-next btn-disable"'
|
||||||
|
)
|
||||||
| 下一页
|
| 下一页
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -64,11 +72,11 @@ export default {
|
|||||||
Articels[n].postmetum = {}
|
Articels[n].postmetum = {}
|
||||||
Articels[n].postmetum.meta_value = 0
|
Articels[n].postmetum.meta_value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Articels[n].postImages = []
|
|
||||||
}
|
}
|
||||||
} else if (data.status === 404) {
|
} else if (data.status === 404) {
|
||||||
Info = '未找到文章。'
|
Info = '未找到文章。'
|
||||||
|
// redirect('/404')
|
||||||
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -82,25 +90,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$finishLoad()
|
this.$finishLoad()
|
||||||
this.analyseImages()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async analyseImages () { // 图片大小分析及处理
|
|
||||||
const articleImgsWidth = this.$refs.articleImgs.getBoundingClientRect().width
|
|
||||||
this.imageHeight = articleImgsWidth * 0.5625
|
|
||||||
for (const n in this.Articels) {
|
|
||||||
if (this.Articels[n].postimages.length !== 0) {
|
|
||||||
for (const i in this.Articels[n].postimages) {
|
|
||||||
const data = await this.$axios.$get(this.Articels[n].postimages[i].guid + '?x-oss-process=image/info')
|
|
||||||
const widthValue = data.ImageWidth.value
|
|
||||||
const heightValue = data.ImageHeight.value
|
|
||||||
if (widthValue > articleImgsWidth && (articleImgsWidth * heightValue / widthValue > this.imageHeight) && this.Articels[n].postImages.length < 10) {
|
|
||||||
this.Articels[n].postImages.push(this.Articels[n].postimages[i].guid + '?x-oss-process=image/resize,m_lfit,w_' + articleImgsWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,86 +6,204 @@
|
|||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ articels.post_date }}
|
| {{ articels.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, index) in articels.term_relationships', :key='index', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, index) in articels.term_relationships',
|
||||||
|
:key='index',
|
||||||
|
v-if='relationships.term_taxonomy && relationships.term_taxonomy.term && relationships.term_taxonomy.taxonomy === "category"',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='articels.postmetum.meta_value !== 0')
|
li(v-if='articels.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + articels.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + articels.hotValue]')
|
||||||
| {{ articels.postmetum.meta_value }}
|
| {{ articels.postmetum.meta_value }}
|
||||||
#articelToc.articelToc(v-if="articels.post_toc_show")
|
#articelToc.articelToc(v-if='articels.post_toc_show')
|
||||||
.articelTitle 目录
|
.articelTitle 目录
|
||||||
.articelTocList(v-html="articels.post_toc")
|
.articelTocList(v-html='articels.post_toc')
|
||||||
.articelContent(v-html='articels.post_content')
|
.articelContent(v-html='articels.post_content', v-viewer)
|
||||||
|
.copyright
|
||||||
|
| 除特别注明外,本站所有文章均为原创。原创文章均已备案且受著作权保护,未经作者书面授权,请勿转载。
|
||||||
.tools
|
.tools
|
||||||
.reward(@click="reward") 打赏
|
.reward(@click='reward') 打赏
|
||||||
.comment(id="comment")
|
#comment.comment
|
||||||
.comment-title 交流区
|
.comment-title 交流区
|
||||||
span(v-if="comments.length") ({{commentAmount}})
|
span(v-if='comments.length') ({{ commentAmount }})
|
||||||
.comment-item(v-for="(item, index) in comments", :id="'comment_ID_' + item.comment_ID", :key="index")
|
.comment-item(
|
||||||
|
v-for='(item, index) in comments',
|
||||||
|
:id='"comment_ID_" + item.comment_ID',
|
||||||
|
:key='index'
|
||||||
|
)
|
||||||
.comment-avatar
|
.comment-avatar
|
||||||
img(:src="item.comment_author_avatar_url ? item.comment_author_avatar_url : 'https://picsum.photos/100/100/?blur=' + item.user_id")
|
img(
|
||||||
|
:src='item.comment_author_avatar_url ? item.comment_author_avatar_url : "https://picsum.photos/100/100/?blur=" + item.user_id'
|
||||||
|
)
|
||||||
.comment-area
|
.comment-area
|
||||||
.comment-author {{ item.comment_author }}
|
.comment-author {{ item.comment_author }}
|
||||||
.comment-content(v-html="item.comment_content_html")
|
span.comment-status(v-if='item.comment_approved === "0"') 此内容正在审核中...
|
||||||
|
.comment-content(v-html='item.comment_content_html', v-viewer)
|
||||||
.comment-info {{ item.comment_date }}
|
.comment-info {{ item.comment_date }}
|
||||||
span.reply(@click="reply(item.comment_ID, null, true)" v-if="replyLastID === null && item.comment_ID === replyID") 取消回复
|
span.reply(
|
||||||
span.reply(@click="reply(item.comment_ID, null)" v-else) 回复
|
@click='reply(item.comment_ID, null, true)',
|
||||||
.comment-item(v-for="(i, inx) in item.children", :id="'comment_ID_' + i.comment_ID", :key="inx", style="margin-top: 15px; margin-left: 50px; background-color: #eeeeee; border-radius: 4px;")
|
v-if='replyLastID === null && item.comment_ID === replyID'
|
||||||
|
) 取消回复
|
||||||
|
span.reply(@click='reply(item.comment_ID, null)', v-else) 回复
|
||||||
|
span.reply(
|
||||||
|
@click='check(item.comment_ID)',
|
||||||
|
v-if='item.comment_approved === "0" && visitorInfo.manage'
|
||||||
|
) 通过审核
|
||||||
|
span.reply(
|
||||||
|
@click='check(item.comment_ID, 2)',
|
||||||
|
v-else-if='visitorInfo.manage'
|
||||||
|
) 设为垃圾评论
|
||||||
|
.comment-item(
|
||||||
|
v-for='(i, inx) in item.children',
|
||||||
|
:id='"comment_ID_" + i.comment_ID',
|
||||||
|
:key='inx',
|
||||||
|
style='margin-top: 15px; margin-left: 50px; background-color: #eeeeee; border-radius: 4px'
|
||||||
|
)
|
||||||
.comment-avatar
|
.comment-avatar
|
||||||
img(:src="i.comment_author_avatar_url ? i.comment_author_avatar_url : 'https://picsum.photos/100/100/?blur=' + i.user_id")
|
img(
|
||||||
|
:src='i.comment_author_avatar_url ? i.comment_author_avatar_url : "https://picsum.photos/100/100/?blur=" + i.user_id'
|
||||||
|
)
|
||||||
.comment-area
|
.comment-area
|
||||||
.comment-author {{ i.comment_author }}
|
.comment-author {{ i.comment_author }}
|
||||||
.comment-content(v-html="i.comment_content_html")
|
span.comment-status(v-if='i.comment_approved === "0"') 此内容正在审核中...
|
||||||
|
.comment-content(v-html='i.comment_content_html')
|
||||||
.comment-info {{ i.comment_date }}
|
.comment-info {{ i.comment_date }}
|
||||||
span.reply(@click="reply(item.comment_ID, i.comment_ID)" v-if="replyLastID !== i.comment_ID") 回复
|
span.reply(
|
||||||
span.reply(@click="reply(item.comment_ID, i.comment_ID, true)" v-else) 取消回复
|
@click='reply(item.comment_ID, i.comment_ID)',
|
||||||
p(v-if="!comments.length", style="color: #cecece; text-align: center; margin-top: 40px") 暂无内容
|
v-if='replyLastID !== i.comment_ID'
|
||||||
|
) 回复
|
||||||
|
span.reply(
|
||||||
|
@click='reply(item.comment_ID, i.comment_ID, true)',
|
||||||
|
v-else
|
||||||
|
) 取消回复
|
||||||
|
span.reply(
|
||||||
|
@click='check(i.comment_ID)',
|
||||||
|
v-if='i.comment_approved === "0" && visitorInfo.manage'
|
||||||
|
) 通过审核
|
||||||
|
span.reply(
|
||||||
|
@click='check(i.comment_ID, 2)',
|
||||||
|
v-else-if='visitorInfo.manage'
|
||||||
|
) 设为垃圾评论
|
||||||
|
p(
|
||||||
|
v-if='!comments.length',
|
||||||
|
style='color: #cecece; text-align: center; margin-top: 40px'
|
||||||
|
) 暂无内容
|
||||||
.comment-default-commit
|
.comment-default-commit
|
||||||
.login(v-if="!visitorToken", @click="login")
|
.login(v-show='!visitorToken')
|
||||||
img(src="https://cdn.wyr.me/imgs/GitHub-Login.png")
|
.item(v-for='(item, index) in loginPlatform', :key='index')
|
||||||
|
transition(name='qrcode')
|
||||||
|
img.qrcode(
|
||||||
|
v-show='!commentLoading && useWeixinLogin && currentLoginType === item.type',
|
||||||
|
:src='weixinLoginQrcode'
|
||||||
|
)
|
||||||
|
img.logo(
|
||||||
|
:class='{ active: currentLoginType === item.type && useWeixinLogin && !commentLoading, loading: commentLoading && currentLoginType === item.type }',
|
||||||
|
:src='item.logo',
|
||||||
|
@click.stop='login(item.type)'
|
||||||
|
)
|
||||||
#editor
|
#editor
|
||||||
.comment-toolbar
|
.comment-toolbar
|
||||||
.comment-no-userinfo(v-if="!visitorToken") 尚未登陆
|
.comment-no-userinfo(v-if='!visitorToken') 尚未登陆
|
||||||
.comment-userinfo(v-else)
|
.comment-userinfo(v-else)
|
||||||
.comment-avatar
|
.comment-avatar
|
||||||
img(:src="visitorInfo.avatarURL")
|
img(:src='visitorInfo.avatarURL')
|
||||||
.comment-nickname {{ visitorInfo.nickname }}
|
.comment-nickname {{ visitorInfo.nickname ? visitorInfo.nickname : visitorInfo.username || "匿名" }}
|
||||||
.comment-logout(@click="commentLogout") 退出
|
.comment-setting(@click='commentSetting') 设置
|
||||||
.comment-btn(@click="commentCommit('editor')") 发布
|
.comment-logout(@click='commentLogout') 退出
|
||||||
.comment-reply-commit(id="comment-reply-commit", v-show="replyID")
|
.comment-btn(@click='commentCommit("editor")') 发布
|
||||||
.login(v-show="!visitorToken", @click="login")
|
#comment-reply-commit.comment-reply-commit(, v-show='replyID')
|
||||||
img(src="https://cdn.wyr.me/imgs/GitHub-Login.png")
|
.login(v-show='!visitorToken')
|
||||||
|
.item(v-for='(item, index) in loginPlatform', :key='index')
|
||||||
|
transition(name='qrcode')
|
||||||
|
img.qrcode(
|
||||||
|
v-show='!commentLoading && useWeixinLogin && currentLoginType === item.type',
|
||||||
|
:src='weixinLoginQrcode'
|
||||||
|
)
|
||||||
|
img.logo(
|
||||||
|
:class='{ active: currentLoginType === item.type && useWeixinLogin && !commentLoading, loading: commentLoading && currentLoginType === item.type }',
|
||||||
|
:src='item.logo',
|
||||||
|
@click.stop='login(item.type)'
|
||||||
|
)
|
||||||
#editor-reply
|
#editor-reply
|
||||||
.comment-toolbar
|
.comment-toolbar
|
||||||
.comment-no-userinfo(v-if="!visitorToken") 尚未登陆
|
.comment-no-userinfo(v-if='!visitorToken') 尚未登陆
|
||||||
.comment-userinfo(v-else)
|
.comment-userinfo(v-else)
|
||||||
.comment-avatar
|
.comment-avatar
|
||||||
img(:src="visitorInfo.avatarURL")
|
img(:src='visitorInfo.avatarURL')
|
||||||
.comment-nickname {{ visitorInfo.nickname }}
|
.comment-nickname {{ visitorInfo.nickname ? visitorInfo.nickname : visitorInfo.username || "匿名" }}
|
||||||
.comment-logout(@click="commentLogout") 退出
|
.comment-setting(@click='commentSetting') 设置
|
||||||
.comment-btn(@click="commentCommit('editor-reply')") 发布
|
.comment-logout(@click='commentLogout') 退出
|
||||||
ins.adsbygoogle(style="display:block; text-align:center; margin-top:20px;", data-ad-layout="in-article", data-ad-format="fluid", data-ad-client="ca-pub-2143583075951360", data-ad-slot="4741804954")
|
.comment-btn(@click='commentCommit("editor-reply")') 发布
|
||||||
.articelRightToc(v-show="articels.post_toc_show && showRightToc", @click="articelRightTocClick")
|
ins.adsbygoogle(
|
||||||
|
style='display: block; text-align: center; margin-top: 20px',
|
||||||
|
data-ad-layout='in-article',
|
||||||
|
data-ad-format='fluid',
|
||||||
|
data-ad-client='ca-pub-2143583075951360',
|
||||||
|
data-ad-slot='4741804954'
|
||||||
|
)
|
||||||
|
.articelRightToc(
|
||||||
|
v-show='articels.post_toc_show && showRightToc',
|
||||||
|
@click='articelRightTocClick'
|
||||||
|
)
|
||||||
.articelTitle 目录
|
.articelTitle 目录
|
||||||
.articelTocList(v-html="articels.post_toc")
|
.articelTocList(v-html='articels.post_toc')
|
||||||
nuxt-link(:to="articels.last ? '/post/' + articels.last.ID : ''")
|
nuxt-link(:to='articels.last ? "/post/" + articels.last.ID : ""')
|
||||||
.btnFooter.btnPrevt(:style="'color: ' + (articels.last ? '#333' : '#ccc')")
|
.btnFooter.btnPrevt(:style='"color: " + (articels.last ? "#333" : "#ccc")')
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一篇 {{ articels.last ? '(' + decodeTitle(articels.last.post_name) + ')' : ''}}
|
| 上一篇 {{ articels.last ? "(" + decodeTitle(articels.last.post_name) + ")" : "" }}
|
||||||
nuxt-link(:to="articels.next ? '/post/' + articels.next.ID : ''")
|
nuxt-link(:to='articels.next ? "/post/" + articels.next.ID : ""')
|
||||||
.btnFooter.btnNext(:style="'color: ' + (articels.next ? '#333' : '#ccc')")
|
.btnFooter.btnNext(:style='"color: " + (articels.next ? "#333" : "#ccc")')
|
||||||
| 下一篇 {{ articels.next ? '(' + decodeTitle(articels.next.post_name) + ')' : ''}}
|
| 下一篇 {{ articels.next ? "(" + decodeTitle(articels.next.post_name) + ")" : "" }}
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
|
modal.modal-setting(name='setting')
|
||||||
|
.vue-modal-content(v-loading='form.loading')
|
||||||
|
p.vue-modal-title
|
||||||
|
| 评论回复提醒
|
||||||
|
Form(ref='form', :model='form', label-width='130px')
|
||||||
|
FormItem(label='手机号')
|
||||||
|
Input(v-model='form.phone', size='small')
|
||||||
|
FormItem(label='发送提醒到手机')
|
||||||
|
VueSwitch(v-model='form.sendPhone')
|
||||||
|
FormItem(label='邮箱')
|
||||||
|
Input(v-model='form.email', size='small')
|
||||||
|
FormItem(label='发送提醒到邮箱')
|
||||||
|
VueSwitch(v-model='form.sendEmail')
|
||||||
|
.vue-modal-buttons
|
||||||
|
button.vue-modal-button(type='button', @click.stop='hideSettings')
|
||||||
|
| 关闭
|
||||||
|
button.vue-modal-button(
|
||||||
|
type='button',
|
||||||
|
@click.stop='saveSettings',
|
||||||
|
style='background-color: #409eff; color: #fff'
|
||||||
|
)
|
||||||
|
| 保存
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import remark from 'remark'
|
||||||
|
import strip from 'strip-markdown'
|
||||||
|
import { Form, FormItem, Input, Switch } from 'element-ui'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async asyncData ({ route, app, $axios }) {
|
components: {
|
||||||
const data = await $axios.$get(`/public/article/details?id=${route.params.id}`)
|
Form, FormItem, Input, VueSwitch: Switch
|
||||||
|
},
|
||||||
|
async asyncData ({ route, app, $axios, redirect }) {
|
||||||
|
let draftStr = ''
|
||||||
|
if (route.query && route.query.draft === 'true') {
|
||||||
|
draftStr = '&draft=true'
|
||||||
|
}
|
||||||
|
const data = await $axios.$get(`/public/article/details?id=${route.params.id}${draftStr}`)
|
||||||
|
if (data.status === 404) {
|
||||||
|
redirect('/404')
|
||||||
|
return
|
||||||
|
}
|
||||||
const result = data.result
|
const result = data.result
|
||||||
result.post_date = app.$moment(result.post_date).utc().format('lll')// 格式化时间
|
result.post_date = app.$moment(result.post_date).utc().format('lll')// 格式化时间
|
||||||
// 热度值计算
|
// 热度值计算
|
||||||
@ -97,14 +215,35 @@ export default {
|
|||||||
result.postmetum.meta_value = 0
|
result.postmetum.meta_value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const truncated = (str, num) => {
|
||||||
|
return Array.from(str).slice(0, num).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeMarkdownFormat = (str) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
remark()
|
||||||
|
.use(strip)
|
||||||
|
.process(str, function (err, file) {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resolve(String(file))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 获取评论
|
// 获取评论
|
||||||
const tmp = await $axios.$get(`/public/comments/post?ID=${route.params.id}`)
|
const tmp = await $axios.$get(`/public/comments/post?ID=${route.params.id}`)
|
||||||
const comments = tmp.result.list || []
|
const comments = tmp.result.list || []
|
||||||
const commentAmount = tmp.result.amount || 0
|
const commentAmount = tmp.result.amount || 0
|
||||||
|
const markdownToText = await removeMarkdownFormat(result.post_excerpt)
|
||||||
|
const description = truncated(markdownToText.replace(/[\r\n]/g, '').replace(/\s+/g, '').trim(), 200)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
postID: route.params.id,
|
postID: route.params.id,
|
||||||
articels: result,
|
articels: result,
|
||||||
|
description,
|
||||||
comments,
|
comments,
|
||||||
commentsMap: new Map(),
|
commentsMap: new Map(),
|
||||||
commentAmount,
|
commentAmount,
|
||||||
@ -118,33 +257,102 @@ export default {
|
|||||||
avatarURL: null,
|
avatarURL: null,
|
||||||
email: null,
|
email: null,
|
||||||
blog: null
|
blog: null
|
||||||
|
},
|
||||||
|
editorObj: null,
|
||||||
|
editorReplyObj: null,
|
||||||
|
commentLoading: false,
|
||||||
|
useWeixinLogin: false,
|
||||||
|
weixinLoginQrcode: null,
|
||||||
|
currentLoginType: null,
|
||||||
|
loginPlatform: [
|
||||||
|
{
|
||||||
|
type: 'github',
|
||||||
|
logo: 'https://cdn.wyr.me/imgs/GitHub-Login.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'weixin',
|
||||||
|
logo: 'https://cdn.wyr.me/imgs/Weixin-Login.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'qq',
|
||||||
|
logo: 'https://cdn.wyr.me/imgs/QQ-Login.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'weibo',
|
||||||
|
logo: 'https://cdn.wyr.me/imgs/Weibo-Login.png'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
form: {
|
||||||
|
loading: true,
|
||||||
|
phone: '',
|
||||||
|
sendPhone: true,
|
||||||
|
email: '',
|
||||||
|
sendEmail: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
head () {
|
||||||
|
const keywords = []
|
||||||
|
for (let i = 0; i < this.articels.term_relationships.length; i++) {
|
||||||
|
if (this.articels.term_relationships[i].term_taxonomy && this.articels.term_relationships[i].term_taxonomy.term && this.articels.term_relationships[i].term_taxonomy.taxonomy === 'post_tag') {
|
||||||
|
keywords.push(this.articels.term_relationships[i].term_taxonomy.term.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: `${this.articels.post_title} - 轶哥`,
|
||||||
|
meta: [
|
||||||
|
{
|
||||||
|
hid: 'description',
|
||||||
|
name: 'description',
|
||||||
|
content: this.description
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hid: 'keywords',
|
||||||
|
name: 'keywords',
|
||||||
|
content: keywords.join(',')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
// 创建编辑器
|
// 创建编辑器
|
||||||
this.visitorToken = window.localStorage.visitorToken
|
|
||||||
if (this.visitorToken && window.localStorage.visitorInfo) {
|
|
||||||
try {
|
|
||||||
this.visitorInfo = JSON.parse(window.localStorage.visitorInfo)
|
|
||||||
} catch (_) { }
|
|
||||||
}
|
|
||||||
if (process.client) {
|
if (process.client) {
|
||||||
|
this.visitorToken = window.localStorage.visitorToken
|
||||||
|
if (this.visitorToken && window.localStorage.visitorInfo) {
|
||||||
|
try {
|
||||||
|
this.visitorInfo = JSON.parse(window.localStorage.visitorInfo)
|
||||||
|
this.getCommentWithVisitorInfo(this.postID)
|
||||||
|
this.checkSettings()
|
||||||
|
} catch (_) { }
|
||||||
|
}
|
||||||
|
|
||||||
window.setAuthToken = (visitorToken, visitorInfo) => {
|
window.setAuthToken = (visitorToken, visitorInfo) => {
|
||||||
window.localStorage.visitorToken = visitorToken
|
window.localStorage.visitorToken = visitorToken
|
||||||
window.localStorage.visitorInfo = JSON.stringify(visitorInfo)
|
window.localStorage.visitorInfo = JSON.stringify(visitorInfo)
|
||||||
this.visitorToken = visitorToken
|
this.visitorToken = visitorToken
|
||||||
this.visitorInfo = visitorInfo
|
this.visitorInfo = visitorInfo
|
||||||
window.editorObj.vditor.options.upload.headers = {
|
this.editorObj.vditor.options.upload.headers = {
|
||||||
Authorization: 'Bearer ' + this.visitorToken
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
}
|
}
|
||||||
window.editorReplyObj.vditor.options.upload.headers = {
|
this.editorReplyObj.vditor.options.upload.headers = {
|
||||||
Authorization: 'Bearer ' + this.visitorToken
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.checkSettings()
|
||||||
}
|
}
|
||||||
if (!window.editorObj && window.Vditor) {
|
|
||||||
this.initEditor()
|
this.$nextTick(() => {
|
||||||
}
|
if (this.$route.query.hash) {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.hash = '#' + this.$route.query.hash
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.editorObj && window.Vditor) {
|
||||||
|
this.initEditor()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
this.setCommentMap()
|
this.setCommentMap()
|
||||||
}
|
}
|
||||||
@ -248,7 +456,8 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.editorObj = new window.Vditor('editor', {
|
|
||||||
|
this.editorObj = new window.Vditor('editor', {
|
||||||
toolbar: [
|
toolbar: [
|
||||||
'emoji',
|
'emoji',
|
||||||
'headings',
|
'headings',
|
||||||
@ -282,7 +491,6 @@ export default {
|
|||||||
'export',
|
'export',
|
||||||
'outline',
|
'outline',
|
||||||
'preview',
|
'preview',
|
||||||
'format',
|
|
||||||
'devtools'
|
'devtools'
|
||||||
]
|
]
|
||||||
}],
|
}],
|
||||||
@ -297,7 +505,7 @@ export default {
|
|||||||
placeholder: '我们书写的不是代码,而是人生'
|
placeholder: '我们书写的不是代码,而是人生'
|
||||||
})
|
})
|
||||||
|
|
||||||
window.editorReplyObj = new window.Vditor('editor-reply', {
|
this.editorReplyObj = new window.Vditor('editor-reply', {
|
||||||
toolbar: [
|
toolbar: [
|
||||||
'emoji',
|
'emoji',
|
||||||
'headings',
|
'headings',
|
||||||
@ -331,7 +539,6 @@ export default {
|
|||||||
'export',
|
'export',
|
||||||
'outline',
|
'outline',
|
||||||
'preview',
|
'preview',
|
||||||
'format',
|
|
||||||
'devtools'
|
'devtools'
|
||||||
]
|
]
|
||||||
}],
|
}],
|
||||||
@ -455,13 +662,13 @@ export default {
|
|||||||
this.replyLastID = replyLastID
|
this.replyLastID = replyLastID
|
||||||
document.getElementById('comment_ID_' + id).appendChild(editorReplyObject)
|
document.getElementById('comment_ID_' + id).appendChild(editorReplyObject)
|
||||||
const comment = this.commentsMap.get(replyLastID)
|
const comment = this.commentsMap.get(replyLastID)
|
||||||
window.editorReplyObj.setValue('', true)
|
this.editorReplyObj.setValue('', true)
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
window.editorReplyObj.focus()
|
this.editorReplyObj.focus()
|
||||||
if (replyLastID !== null) {
|
if (replyLastID !== null) {
|
||||||
window.editorReplyObj.insertValue('> ' + comment.comment_content + ' \n\n\n', true)
|
this.editorReplyObj.insertValue('> ' + comment.comment_content + ' \n\n\n', true)
|
||||||
} else {
|
} else {
|
||||||
window.editorReplyObj.insertValue('', true)
|
this.editorReplyObj.insertValue('', true)
|
||||||
}
|
}
|
||||||
window.location.hash = '#comment_ID_' + id
|
window.location.hash = '#comment_ID_' + id
|
||||||
})
|
})
|
||||||
@ -476,30 +683,36 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const editorObj = type === 'editor-reply' ? window.editorReplyObj : window.editorObj
|
const editorObj = type === 'editor-reply' ? this.editorReplyObj : this.editorObj
|
||||||
|
const content = editorObj.getValue()
|
||||||
|
|
||||||
|
if (!content || content === '\n') {
|
||||||
|
this.$toasted.show('请输入内容', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const { data } = await this.$axios({
|
const { data } = await this.$axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: process.env.baseURL + '/comments/commit',
|
url: process.env.baseURL + '/comments/commit',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: 'Bearer ' + window.localStorage.visitorToken
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
postID,
|
postID,
|
||||||
lastID,
|
lastID,
|
||||||
parentID,
|
parentID,
|
||||||
content: editorObj.getValue()
|
content
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (data.status === 1) {
|
if (data.status === 1) {
|
||||||
// 获取评论
|
this.replyID = null
|
||||||
const tmp = await this.$axios.get(process.env.baseURL + `/public/comments/post?ID=${postID}`)
|
this.replyLastID = null
|
||||||
const comments = tmp.data.result.list || []
|
window.location.hash = '_'
|
||||||
const commentAmount = tmp.data.result.amount || 0
|
this.getCommentWithVisitorInfo(postID)
|
||||||
this.comments = comments
|
|
||||||
this.commentAmount = commentAmount
|
|
||||||
this.setCommentMap()
|
|
||||||
editorObj.setValue('', true)
|
editorObj.setValue('', true)
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
editorObj.focus()
|
editorObj.focus()
|
||||||
@ -507,12 +720,135 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async check (ID, type) {
|
||||||
|
const { data } = await this.$axios({
|
||||||
|
method: 'post',
|
||||||
|
url: process.env.baseURL + '/comments/check',
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
ID,
|
||||||
|
type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data.status === 1) {
|
||||||
|
this.getCommentWithVisitorInfo(this.postID)
|
||||||
|
this.$toasted.show(type === 2 ? '已删除' : '已通过', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getCommentWithVisitorInfo (postID) {
|
||||||
|
// 获取评论
|
||||||
|
const tmp = await this.$axios({
|
||||||
|
method: 'get',
|
||||||
|
url: process.env.baseURL + `/public/comments/post?ID=${postID}`,
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const comments = tmp.data.result.list || []
|
||||||
|
const commentAmount = tmp.data.result.amount || 0
|
||||||
|
this.comments = comments
|
||||||
|
this.commentAmount = commentAmount
|
||||||
|
this.setCommentMap()
|
||||||
|
},
|
||||||
commentLogout () {
|
commentLogout () {
|
||||||
window.localStorage.removeItem('visitorToken')
|
window.localStorage.removeItem('visitorToken')
|
||||||
this.visitorToken = null
|
this.visitorToken = null
|
||||||
},
|
},
|
||||||
login () {
|
getCode (uuid, last) {
|
||||||
window.open('https://github.com/login/oauth/authorize?client_id=ce1673a37333e47e482d&redirect_uri=https://www.wyr.me/auth', 'Github授权', 'scrollbars=yes,resizable=yes,status=no,location=yes,toolbar=no,menubar=no,width=800,height=600,left=0,top=0')
|
try {
|
||||||
|
this.$axios({
|
||||||
|
type: 'get',
|
||||||
|
url: 'https://weixin.openapi.site/check?uuid=' + uuid + (last ? '&last=' + last : ''),
|
||||||
|
timeout: 6e4
|
||||||
|
}).then(async (res) => {
|
||||||
|
if (res.data.status === 405) {
|
||||||
|
const { data } = await this.$axios.post(`${process.env.baseURL}/visitor/user/weixin`, {
|
||||||
|
code: res.data.result.code
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data.status !== 1) {
|
||||||
|
this.$toasted.show('微信登录失败,请重试或换用其它登录方式。', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
window.authSuccess(data)
|
||||||
|
} else if (res.data.status === 404) {
|
||||||
|
this.getCode(uuid, res.data.result.wxErrCode)
|
||||||
|
} else if (res.data.status === 403) {
|
||||||
|
this.getCode(uuid, res.data.result.wxErrCode)
|
||||||
|
} else if (res.data.status === 500) {
|
||||||
|
this.login('weixin')
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.getCode(uuid)
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
setTimeout(function () {
|
||||||
|
this.getCode(uuid)
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async login (type) {
|
||||||
|
this.currentLoginType = type
|
||||||
|
this.useWeixinLogin = false
|
||||||
|
if (type === 'github') {
|
||||||
|
window.open('https://github.com/login/oauth/authorize?client_id=ce1673a37333e47e482d&redirect_uri=https://www.wyr.me/auth', 'Github授权', 'scrollbars=yes,resizable=yes,status=no,location=yes,toolbar=no,menubar=no,width=800,height=600,left=0,top=0')
|
||||||
|
} else if (type === 'weixin') {
|
||||||
|
this.useWeixinLogin = true
|
||||||
|
this.commentLoading = true
|
||||||
|
try {
|
||||||
|
if (navigator.userAgent.toLowerCase().includes('micromessenger')) { // 如果在微信中打开
|
||||||
|
this.commentLoading = false
|
||||||
|
this.currentLoginType = null
|
||||||
|
this.useWeixinLogin = false
|
||||||
|
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx9d5e677f533d1e84&redirect_uri=${encodeURIComponent('https://tool.sercretcore.com/auth.php')}&response_type=code&scope=snsapi_userinfo&state=blog-${this.postID}#wechat_redirect`
|
||||||
|
} else {
|
||||||
|
const { data } = await this.$axios.get('https://weixin.openapi.site/img?appid=wx2d1d6aa2f86768d7&redirect_uri=https://wyr.me')
|
||||||
|
|
||||||
|
if (data.status === 1) {
|
||||||
|
const uuid = data.result.wxUUID
|
||||||
|
this.weixinLoginQrcode = data.result.imgData
|
||||||
|
this.getCode(uuid)
|
||||||
|
this.commentLoading = false
|
||||||
|
} else {
|
||||||
|
this.commentLoading = false
|
||||||
|
this.currentLoginType = null
|
||||||
|
this.$toasted.show('获取微信登录所需参数错误,请重试或换用其它登录方式。', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.commentLoading = false
|
||||||
|
this.currentLoginType = null
|
||||||
|
this.useWeixinLogin = false
|
||||||
|
this.$toasted.show('暂时无法使用微信登录,请重试或换用其它登录方式。', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (type === 'qq') {
|
||||||
|
window.location.href = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101000700&redirect_uri=' + decodeURIComponent('https://www.wyr.me/auth') + '&state=qq-' + this.postID
|
||||||
|
} else if (type === 'weibo') {
|
||||||
|
window.location.href = 'https://api.weibo.com/oauth2/authorize?client_id=4159322735&redirect_uri=https://wyr.me/auth&response_type=code&state=weibo-' + this.postID
|
||||||
|
} else {
|
||||||
|
this.$toasted.show('敬请期待', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setCommentMap () {
|
setCommentMap () {
|
||||||
const comments = this.comments
|
const comments = this.comments
|
||||||
@ -524,20 +860,107 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
commentSetting () {
|
||||||
head () {
|
this.form.loading = true
|
||||||
return {
|
this.$modal.show('setting')
|
||||||
title: `${this.articels.post_title} - 轶哥`
|
this.getSettings()
|
||||||
|
},
|
||||||
|
hideSettings () {
|
||||||
|
this.$modal.hide('setting')
|
||||||
|
this.form.loading = true
|
||||||
|
if (!localStorage.checkSetting) {
|
||||||
|
localStorage.checkSetting = new Date().getTime().toString()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async checkSettings () {
|
||||||
|
if (!localStorage.checkSetting) {
|
||||||
|
// 获取设置信息
|
||||||
|
const tmp = await this.$axios({
|
||||||
|
method: 'get',
|
||||||
|
url: process.env.baseURL + '/user/settings',
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (tmp.status === 200 && tmp.data.status === 1 && tmp.data.result && tmp.data.result.sendPhone && tmp.data.result.sendEmail && (!tmp.data.result.phone || !tmp.data.result.email)) {
|
||||||
|
this.commentSetting()
|
||||||
|
this.$toasted.show('温馨提示:设置手机号或邮箱,可及时收到回复提醒', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getSettings () {
|
||||||
|
// 获取设置信息
|
||||||
|
const tmp = await this.$axios({
|
||||||
|
method: 'get',
|
||||||
|
url: process.env.baseURL + '/user/settings',
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (tmp.status === 200 && tmp.data.status === 1 && tmp.data.result) {
|
||||||
|
this.form.phone = tmp.data.result.phone
|
||||||
|
this.form.sendPhone = tmp.data.result.sendPhone
|
||||||
|
this.form.email = tmp.data.result.email
|
||||||
|
this.form.sendEmail = tmp.data.result.sendEmail
|
||||||
|
this.form.loading = false
|
||||||
|
} else {
|
||||||
|
this.$toasted.show('获取设置内容失败,请重试', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async saveSettings () {
|
||||||
|
// 获取设置信息
|
||||||
|
const tmp = await this.$axios({
|
||||||
|
method: 'post',
|
||||||
|
url: process.env.baseURL + '/user/settings',
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.visitorToken
|
||||||
|
},
|
||||||
|
data: this.form
|
||||||
|
})
|
||||||
|
|
||||||
|
if (tmp.status === 200 && tmp.data.status === 1) {
|
||||||
|
this.hideSettings()
|
||||||
|
this.$toasted.show('保存成功', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$toasted.show('保存设置失败,请重试', {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!localStorage.checkSetting) {
|
||||||
|
localStorage.checkSetting = new Date().getTime().toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
|
$qrcode-width = 96px
|
||||||
|
$qrcode-height = 96px
|
||||||
|
$logo-width = 64px
|
||||||
|
|
||||||
|
modal
|
||||||
|
display none
|
||||||
|
|
||||||
.postPage
|
.postPage
|
||||||
.articleDetails
|
.articleDetails:not(:first-child)
|
||||||
margin-top 30px
|
margin-top 30px
|
||||||
|
|
||||||
|
.articleDetails
|
||||||
background-color #fff
|
background-color #fff
|
||||||
padding 50px 10px
|
padding 50px 10px
|
||||||
|
|
||||||
@ -598,6 +1021,11 @@ export default {
|
|||||||
font-size 85%
|
font-size 85%
|
||||||
padding 2px 5px
|
padding 2px 5px
|
||||||
|
|
||||||
|
.copyright
|
||||||
|
margin-top 80px
|
||||||
|
font-size 10px
|
||||||
|
color #888
|
||||||
|
|
||||||
.comment
|
.comment
|
||||||
width 100%
|
width 100%
|
||||||
margin-top 60px
|
margin-top 60px
|
||||||
@ -683,7 +1111,17 @@ export default {
|
|||||||
text-overflow ellipsis
|
text-overflow ellipsis
|
||||||
white-space nowrap
|
white-space nowrap
|
||||||
|
|
||||||
.comment-logout
|
.comment-content
|
||||||
|
width 100%
|
||||||
|
padding 5px 0
|
||||||
|
|
||||||
|
img
|
||||||
|
max-width 100%
|
||||||
|
|
||||||
|
.comment-status
|
||||||
|
color #ca7474
|
||||||
|
|
||||||
|
.comment-logout, .comment-setting
|
||||||
width 51px
|
width 51px
|
||||||
height 100%
|
height 100%
|
||||||
line-height 30px
|
line-height 30px
|
||||||
@ -693,16 +1131,20 @@ export default {
|
|||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
display none
|
display none
|
||||||
text-align center
|
text-align center
|
||||||
|
float left
|
||||||
|
|
||||||
|
.comment-logout
|
||||||
|
margin-left 10px
|
||||||
|
|
||||||
.comment-userinfo:hover
|
.comment-userinfo:hover
|
||||||
.comment-avatar, .comment-nickname
|
.comment-avatar, .comment-nickname
|
||||||
display none
|
display none
|
||||||
|
|
||||||
.comment-logout
|
.comment-logout, .comment-setting
|
||||||
display block
|
display block
|
||||||
|
|
||||||
.comment-userinfo:active
|
.comment-userinfo:active
|
||||||
.comment-logout
|
.comment-logout, .comment-setting
|
||||||
background-color #586069
|
background-color #586069
|
||||||
color #fff
|
color #fff
|
||||||
|
|
||||||
@ -764,9 +1206,76 @@ export default {
|
|||||||
z-index 99
|
z-index 99
|
||||||
cursor pointer
|
cursor pointer
|
||||||
user-select none
|
user-select none
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
|
||||||
img
|
.item
|
||||||
margin-top 70px
|
flex 1
|
||||||
|
display flex
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
flex-direction column
|
||||||
|
align-items center
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.qrcode
|
||||||
|
width $qrcode-width
|
||||||
|
height $qrcode-height
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
background blue
|
||||||
|
border-radius 12px
|
||||||
|
margin-bottom 10px
|
||||||
|
color #fff
|
||||||
|
overflow hidden
|
||||||
|
cursor pointer
|
||||||
|
position absolute
|
||||||
|
z-index 1000
|
||||||
|
top 'calc(50% - %s / 2)' % $qrcode-height
|
||||||
|
|
||||||
|
.logo
|
||||||
|
background-color #f5f4f4
|
||||||
|
width 64px
|
||||||
|
height 64px
|
||||||
|
border-radius 50%
|
||||||
|
color #fff
|
||||||
|
user-select none
|
||||||
|
cursor pointer
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
position absolute
|
||||||
|
z-index 1000
|
||||||
|
top 'calc(50% - %s / 2)' % $logo-width
|
||||||
|
transition transform 0.2s cubic-bezier(0.075, 0.82, 0.165, 1), top 0.2s cubic-bezier(0.075, 0.82, 0.165, 1)
|
||||||
|
|
||||||
|
&.active
|
||||||
|
top 'calc(50% + %s / 2 - %s / 4 + 5px)' % ($qrcode-height $logo-width)
|
||||||
|
transform scale(0.5)
|
||||||
|
|
||||||
|
&.loading
|
||||||
|
animation spin 1s linear infinite
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background-color #fff
|
||||||
|
|
||||||
|
.qrcode-enter, .qrcode-leave-to
|
||||||
|
transform scale(0)
|
||||||
|
|
||||||
|
.qrcode-enter-active, .qrcode-leave-active
|
||||||
|
transition transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1)
|
||||||
|
|
||||||
|
.qrcode-enter-to
|
||||||
|
transform scale(1)
|
||||||
|
|
||||||
|
@keyframes spin
|
||||||
|
from
|
||||||
|
transform rotate(0)
|
||||||
|
|
||||||
|
to
|
||||||
|
transform rotate(360deg)
|
||||||
|
|
||||||
.login:hover
|
.login:hover
|
||||||
background-color #fff
|
background-color #fff
|
||||||
@ -820,7 +1329,7 @@ export default {
|
|||||||
background-color #000
|
background-color #000
|
||||||
padding 10px
|
padding 10px
|
||||||
box-shadow 0 0 8px #000
|
box-shadow 0 0 8px #000
|
||||||
z-index 999999
|
z-index 99999
|
||||||
padding-bottom 20px
|
padding-bottom 20px
|
||||||
min-width 240px
|
min-width 240px
|
||||||
max-width 300px
|
max-width 300px
|
||||||
@ -872,7 +1381,7 @@ export default {
|
|||||||
font-weight 300
|
font-weight 300
|
||||||
|
|
||||||
.tools
|
.tools
|
||||||
margin-top 80px
|
margin-top 30px
|
||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
text-align center
|
text-align center
|
||||||
user-select none
|
user-select none
|
||||||
@ -888,25 +1397,68 @@ export default {
|
|||||||
margin auto
|
margin auto
|
||||||
|
|
||||||
.vditor--fullscreen
|
.vditor--fullscreen
|
||||||
z-index 9999999
|
z-index 9999
|
||||||
|
|
||||||
@media (max-width: 768px)
|
.modal-setting
|
||||||
.postPage
|
z-index 99999
|
||||||
.articleDetails
|
|
||||||
padding 20px
|
|
||||||
margin-top 50px
|
|
||||||
|
|
||||||
.articelRightToc
|
.vue-modal-content
|
||||||
position fixed
|
padding 10px 20px 10px 10px
|
||||||
width 80%
|
box-sizing border-box
|
||||||
top 100px
|
|
||||||
bottom 95px
|
|
||||||
right 10px
|
|
||||||
background-color #000
|
|
||||||
padding 10px
|
|
||||||
overflow-y auto
|
|
||||||
box-shadow 0 0 8px #000
|
|
||||||
|
|
||||||
.mobileToc
|
.vue-modal-title
|
||||||
bottom 48px
|
text-align center
|
||||||
|
margin-top 5px
|
||||||
|
margin-bottom 10px
|
||||||
|
font-weight 500
|
||||||
|
|
||||||
|
.el-form-item
|
||||||
|
margin-bottom 10px
|
||||||
|
|
||||||
|
.vue-modal-buttons
|
||||||
|
display flex
|
||||||
|
flex 0 1 auto
|
||||||
|
width 100%
|
||||||
|
border-top 1px solid #eee
|
||||||
|
box-sizing border-box
|
||||||
|
text-align center
|
||||||
|
bottom 0
|
||||||
|
position absolute
|
||||||
|
|
||||||
|
.vue-modal-button
|
||||||
|
font-size 12px !important
|
||||||
|
background transparent
|
||||||
|
padding 0
|
||||||
|
margin 0
|
||||||
|
border 0
|
||||||
|
cursor pointer
|
||||||
|
box-sizing border-box
|
||||||
|
line-height 40px
|
||||||
|
height 40px
|
||||||
|
color inherit
|
||||||
|
font inherit
|
||||||
|
outline none
|
||||||
|
text-align center
|
||||||
|
width 100%
|
||||||
|
bottom 0
|
||||||
|
|
||||||
|
@media (max-width 768px)
|
||||||
|
.postPage
|
||||||
|
.articleDetails
|
||||||
|
padding 20px
|
||||||
|
margin-top 50px
|
||||||
|
|
||||||
|
.articelRightToc
|
||||||
|
position fixed
|
||||||
|
width 80%
|
||||||
|
top 100px
|
||||||
|
bottom 95px
|
||||||
|
right 10px
|
||||||
|
background-color #000
|
||||||
|
padding 10px
|
||||||
|
overflow-y auto
|
||||||
|
box-shadow 0 0 8px #000
|
||||||
|
|
||||||
|
.mobileToc
|
||||||
|
bottom 48px
|
||||||
</style>
|
</style>
|
||||||
|
47
pages/post/p.vue
Normal file
47
pages/post/p.vue
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.pClass
|
||||||
|
Form(ref='form', :model='form', label-width='120px')
|
||||||
|
FormItem(label='请输入文章编号')
|
||||||
|
Input(v-model='form.no', size='small', @keyup.enter='onSubmit')
|
||||||
|
FormItem
|
||||||
|
Button(type='primary', size='small', @click='onSubmit')
|
||||||
|
| 确定
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Form, FormItem, Input, Switch, Button } from 'element-ui'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Form, FormItem, Input, VueSwitch: Switch, Button
|
||||||
|
},
|
||||||
|
layout: 'auth',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
no: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$finishLoad()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSubmit () {
|
||||||
|
if (!this.form.no) {
|
||||||
|
alert('请输入文章编号')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$router.push('/post/' + this.form.no + '#comment')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.pClass
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
padding 50px 20px
|
||||||
|
box-sizing border-box
|
||||||
|
</style>
|
@ -2,44 +2,52 @@
|
|||||||
.pageList
|
.pageList
|
||||||
.articleContent(ref='articleImgs', v-if='Articels')
|
.articleContent(ref='articleImgs', v-if='Articels')
|
||||||
article.articleList(v-for='(post, index) in Articels', :key='index')
|
article.articleList(v-for='(post, index) in Articels', :key='index')
|
||||||
.articleImgs(v-if='post.postImages.length')
|
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
|
||||||
Swiper(:style="'height: ' + imageHeight + 'px'")
|
|
||||||
Slide(v-for="(imgUrl, inx) in post.postImages" :key="inx")
|
|
||||||
img(:src='imgUrl')
|
|
||||||
.articleAbstract
|
.articleAbstract
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
nuxt-link(:to='"/post/" + post.ID')
|
||||||
.articleTitle(v-html='post.post_title')
|
.articleTitle(v-html='post.post_title')
|
||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ post.post_date }}
|
| {{ post.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, idx) in post.term_relationships', :key='idx', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, idx) in post.term_relationships',
|
||||||
|
:key='idx',
|
||||||
|
v-if='relationships.term_taxonomy',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='post.postmetum.meta_value !== 0')
|
li(v-if='post.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + post.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + post.hotValue]')
|
||||||
| {{ post.postmetum.meta_value }}
|
| {{ post.postmetum.meta_value }}
|
||||||
.articelAbstractContent(v-html='post.post_excerpt || post.post_content')
|
.articelAbstractContent(
|
||||||
|
v-html='post.post_excerpt || post.post_content'
|
||||||
|
)
|
||||||
.readMore
|
.readMore
|
||||||
nuxt-link.readMoreBtn(:to="'/post/' + post.ID")
|
nuxt-link.readMoreBtn(:to='"/post/" + post.ID')
|
||||||
| READ MORE
|
| READ MORE
|
||||||
.Info(v-if='Info')
|
.Info(v-if='Info')
|
||||||
| {{ Info }}
|
| {{ Info }}
|
||||||
nuxt-link(:to="nowPage > 2 ? nowPath + '/page/' + (nowPage - 1) : nowPath + '/'", :class="nowPage > 1 ? 'btn-footer btn-prev ' : 'btn-footer btn-prev btn-disable'")
|
nuxt-link(
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
:to='nowPage > 2 ? nowPath + "/page/" + (nowPage - 1) : nowPath + "/"',
|
||||||
|
:class='nowPage > 1 ? "btn-footer btn-prev " : "btn-footer btn-prev btn-disable"'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一页
|
| 上一页
|
||||||
nuxt-link(:to="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? nowPath + '/page/' + (nowPage + 1) : '#'", :class="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? 'btn-footer btn-next' : 'btn-footer btn-next btn-disable'")
|
nuxt-link(
|
||||||
|
:to='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? nowPath + "/page/" + (nowPage + 1) : "#"',
|
||||||
|
:class='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? "btn-footer btn-next" : "btn-footer btn-next btn-disable"'
|
||||||
|
)
|
||||||
| 下一页
|
| 下一页
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
async asyncData ({ app, params, query, $axios }) {
|
async asyncData ({ app, params, query, $axios, redirect }) {
|
||||||
let Info = null
|
let Info = null
|
||||||
let Articels = []
|
let Articels = []
|
||||||
const nowPage = params.page ? parseInt(params.page) : 1
|
const nowPage = params.page ? parseInt(params.page) : 1
|
||||||
@ -69,6 +77,8 @@ export default {
|
|||||||
}
|
}
|
||||||
} else if (data.status === 404) {
|
} else if (data.status === 404) {
|
||||||
Info = '未找到文章。'
|
Info = '未找到文章。'
|
||||||
|
// redirect('/404')
|
||||||
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -82,25 +92,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$finishLoad()
|
this.$finishLoad()
|
||||||
this.analyseImages()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async analyseImages () { // 图片大小分析及处理
|
|
||||||
const articleImgsWidth = this.$refs.articleImgs.getBoundingClientRect().width
|
|
||||||
this.imageHeight = articleImgsWidth * 0.5625
|
|
||||||
for (const n in this.Articels) {
|
|
||||||
if (this.Articels[n].postimages.length !== 0) {
|
|
||||||
for (const i in this.Articels[n].postimages) {
|
|
||||||
const data = await this.$axios.$get(this.Articels[n].postimages[i].guid + '?x-oss-process=image/info')
|
|
||||||
const widthValue = data.ImageWidth.value
|
|
||||||
const heightValue = data.ImageHeight.value
|
|
||||||
if (widthValue > articleImgsWidth && (articleImgsWidth * heightValue / widthValue > this.imageHeight) && this.Articels[n].postImages.length < 10) {
|
|
||||||
this.Articels[n].postImages.push(this.Articels[n].postimages[i].guid + '?x-oss-process=image/resize,m_lfit,w_' + articleImgsWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,39 +2,47 @@
|
|||||||
.pageList
|
.pageList
|
||||||
.articleContent(ref='articleImgs', v-if='Articels')
|
.articleContent(ref='articleImgs', v-if='Articels')
|
||||||
article.articleList(v-for='(post, index) in Articels', :key='index')
|
article.articleList(v-for='(post, index) in Articels', :key='index')
|
||||||
.articleImgs(v-if='post.postImages.length')
|
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
|
||||||
Swiper(:style="'height: ' + imageHeight + 'px'")
|
|
||||||
Slide(v-for="(imgUrl, inx) in post.postImages" :key="inx")
|
|
||||||
img(:src='imgUrl')
|
|
||||||
.articleAbstract
|
.articleAbstract
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
nuxt-link(:to='"/post/" + post.ID')
|
||||||
.articleTitle(v-html='post.post_title')
|
.articleTitle(v-html='post.post_title')
|
||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ post.post_date }}
|
| {{ post.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, idx) in post.term_relationships', :key='idx', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, idx) in post.term_relationships',
|
||||||
|
:key='idx',
|
||||||
|
v-if='relationships.term_taxonomy',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='post.postmetum.meta_value !== 0')
|
li(v-if='post.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + post.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + post.hotValue]')
|
||||||
| {{ post.postmetum.meta_value }}
|
| {{ post.postmetum.meta_value }}
|
||||||
.articelAbstractContent(v-html='post.post_excerpt || post.post_content')
|
.articelAbstractContent(
|
||||||
|
v-html='post.post_excerpt || post.post_content'
|
||||||
|
)
|
||||||
.readMore
|
.readMore
|
||||||
nuxt-link.readMoreBtn(:to="'/post/' + post.ID")
|
nuxt-link.readMoreBtn(:to='"/post/" + post.ID')
|
||||||
| READ MORE
|
| READ MORE
|
||||||
.Info(v-if='Info')
|
.Info(v-if='Info')
|
||||||
| {{ Info }}
|
| {{ Info }}
|
||||||
nuxt-link(:to="nowPage > 2 ? nowPath + '/page/' + (nowPage - 1) : nowPath + '/'", :class="nowPage > 1 ? 'btn-footer btn-prev ' : 'btn-footer btn-prev btn-disable'")
|
nuxt-link(
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
:to='nowPage > 2 ? nowPath + "/page/" + (nowPage - 1) : nowPath + "/"',
|
||||||
|
:class='nowPage > 1 ? "btn-footer btn-prev " : "btn-footer btn-prev btn-disable"'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一页
|
| 上一页
|
||||||
nuxt-link(:to="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? nowPath + '/page/' + (nowPage + 1) : '#'", :class="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? 'btn-footer btn-next' : 'btn-footer btn-next btn-disable'")
|
nuxt-link(
|
||||||
|
:to='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? nowPath + "/page/" + (nowPage + 1) : "#"',
|
||||||
|
:class='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? "btn-footer btn-next" : "btn-footer btn-next btn-disable"'
|
||||||
|
)
|
||||||
| 下一页
|
| 下一页
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -64,11 +72,11 @@ export default {
|
|||||||
Articels[n].postmetum = {}
|
Articels[n].postmetum = {}
|
||||||
Articels[n].postmetum.meta_value = 0
|
Articels[n].postmetum.meta_value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Articels[n].postImages = []
|
|
||||||
}
|
}
|
||||||
} else if (data.status === 404) {
|
} else if (data.status === 404) {
|
||||||
Info = '未找到文章。'
|
Info = '未找到文章。'
|
||||||
|
// redirect('/404')
|
||||||
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -82,25 +90,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$finishLoad()
|
this.$finishLoad()
|
||||||
this.analyseImages()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async analyseImages () { // 图片大小分析及处理
|
|
||||||
const articleImgsWidth = this.$refs.articleImgs.getBoundingClientRect().width
|
|
||||||
this.imageHeight = articleImgsWidth * 0.5625
|
|
||||||
for (const n in this.Articels) {
|
|
||||||
if (this.Articels[n].postimages.length !== 0) {
|
|
||||||
for (const i in this.Articels[n].postimages) {
|
|
||||||
const data = await this.$axios.$get(this.Articels[n].postimages[i].guid + '?x-oss-process=image/info')
|
|
||||||
const widthValue = data.ImageWidth.value
|
|
||||||
const heightValue = data.ImageHeight.value
|
|
||||||
if (widthValue > articleImgsWidth && (articleImgsWidth * heightValue / widthValue > this.imageHeight) && this.Articels[n].postImages.length < 10) {
|
|
||||||
this.Articels[n].postImages.push(this.Articels[n].postimages[i].guid + '?x-oss-process=image/resize,m_lfit,w_' + articleImgsWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,39 +2,47 @@
|
|||||||
.pageList
|
.pageList
|
||||||
.articleContent(ref='articleImgs', v-if='Articels')
|
.articleContent(ref='articleImgs', v-if='Articels')
|
||||||
article.articleList(v-for='(post, index) in Articels', :key='index')
|
article.articleList(v-for='(post, index) in Articels', :key='index')
|
||||||
.articleImgs(v-if='post.postImages.length')
|
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
|
||||||
Swiper(:style="'height: ' + imageHeight + 'px'")
|
|
||||||
Slide(v-for="(imgUrl, inx) in post.postImages" :key="inx")
|
|
||||||
img(:src='imgUrl')
|
|
||||||
.articleAbstract
|
.articleAbstract
|
||||||
nuxt-link(:to="'/post/' + post.ID")
|
nuxt-link(:to='"/post/" + post.ID')
|
||||||
.articleTitle(v-html='post.post_title')
|
.articleTitle(v-html='post.post_title')
|
||||||
.articalMeta
|
.articalMeta
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'calendar-alt']")
|
Icon(:icon='["far", "calendar-alt"]')
|
||||||
| {{ post.post_date }}
|
| {{ post.post_date }}
|
||||||
li
|
li
|
||||||
Icon(:icon="['far', 'bookmark']")
|
Icon(:icon='["far", "bookmark"]')
|
||||||
nuxt-link(v-for='(relationships, idx) in post.term_relationships', :key='idx', v-if='relationships.term_taxonomy', :to="'/' + relationships.term_taxonomy.term.slug")
|
nuxt-link(
|
||||||
|
v-for='(relationships, idx) in post.term_relationships',
|
||||||
|
:key='idx',
|
||||||
|
v-if='relationships.term_taxonomy',
|
||||||
|
:to='"/" + relationships.term_taxonomy.term.slug'
|
||||||
|
)
|
||||||
span
|
span
|
||||||
| {{ relationships.term_taxonomy.term.name }}
|
| {{ relationships.term_taxonomy.term.name }}
|
||||||
li(v-if='post.postmetum.meta_value !== 0')
|
li(v-if='post.postmetum.meta_value !== 0')
|
||||||
Icon(:icon="['fas', 'thermometer-' + post.hotValue]")
|
Icon(:icon='["fas", "thermometer-" + post.hotValue]')
|
||||||
| {{ post.postmetum.meta_value }}
|
| {{ post.postmetum.meta_value }}
|
||||||
.articelAbstractContent(v-html='post.post_excerpt || post.post_content')
|
.articelAbstractContent(
|
||||||
|
v-html='post.post_excerpt || post.post_content'
|
||||||
|
)
|
||||||
.readMore
|
.readMore
|
||||||
nuxt-link.readMoreBtn(:to="'/post/' + post.ID")
|
nuxt-link.readMoreBtn(:to='"/post/" + post.ID')
|
||||||
| READ MORE
|
| READ MORE
|
||||||
.Info(v-if='Info')
|
.Info(v-if='Info')
|
||||||
| {{ Info }}
|
| {{ Info }}
|
||||||
nuxt-link(:to="nowPage > 2 ? nowPath + '/page/' + (nowPage - 1) : nowPath + '/'", :class="nowPage > 1 ? 'btn-footer btn-prev ' : 'btn-footer btn-prev btn-disable'")
|
nuxt-link(
|
||||||
Icon(:icon="['fas', 'chevron-left']")
|
:to='nowPage > 2 ? nowPath + "/page/" + (nowPage - 1) : nowPath + "/"',
|
||||||
|
:class='nowPage > 1 ? "btn-footer btn-prev " : "btn-footer btn-prev btn-disable"'
|
||||||
|
)
|
||||||
|
Icon(:icon='["fas", "chevron-left"]')
|
||||||
| 上一页
|
| 上一页
|
||||||
nuxt-link(:to="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? nowPath + '/page/' + (nowPage + 1) : '#'", :class="(nowPage + 1) <= Math.ceil(ArticelsCount / 8) ? 'btn-footer btn-next' : 'btn-footer btn-next btn-disable'")
|
nuxt-link(
|
||||||
|
:to='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? nowPath + "/page/" + (nowPage + 1) : "#"',
|
||||||
|
:class='nowPage + 1 <= Math.ceil(ArticelsCount / 8) ? "btn-footer btn-next" : "btn-footer btn-next btn-disable"'
|
||||||
|
)
|
||||||
| 下一页
|
| 下一页
|
||||||
Icon(:icon="['fas', 'chevron-right']")
|
Icon(:icon='["fas", "chevron-right"]')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -69,6 +77,8 @@ export default {
|
|||||||
}
|
}
|
||||||
} else if (data.status === 404) {
|
} else if (data.status === 404) {
|
||||||
Info = '未找到文章。'
|
Info = '未找到文章。'
|
||||||
|
// redirect('/404')
|
||||||
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -82,25 +92,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$finishLoad()
|
this.$finishLoad()
|
||||||
this.analyseImages()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async analyseImages () { // 图片大小分析及处理
|
|
||||||
const articleImgsWidth = this.$refs.articleImgs.getBoundingClientRect().width
|
|
||||||
this.imageHeight = articleImgsWidth * 0.5625
|
|
||||||
for (const n in this.Articels) {
|
|
||||||
if (this.Articels[n].postimages.length !== 0) {
|
|
||||||
for (const i in this.Articels[n].postimages) {
|
|
||||||
const data = await this.$axios.$get(this.Articels[n].postimages[i].guid + '?x-oss-process=image/info')
|
|
||||||
const widthValue = data.ImageWidth.value
|
|
||||||
const heightValue = data.ImageHeight.value
|
|
||||||
if (widthValue > articleImgsWidth && (articleImgsWidth * heightValue / widthValue > this.imageHeight) && this.Articels[n].postImages.length < 10) {
|
|
||||||
this.Articels[n].postImages.push(this.Articels[n].postimages[i].guid + '?x-oss-process=image/resize,m_lfit,w_' + articleImgsWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -65,7 +65,6 @@ window.onload = function () {
|
|||||||
window.Vditor = vditor
|
window.Vditor = vditor
|
||||||
|
|
||||||
window.authSuccess = (data) => { // eslint-disable-line
|
window.authSuccess = (data) => { // eslint-disable-line
|
||||||
console.log('授权成功', data)
|
|
||||||
if (data.status === 1) {
|
if (data.status === 1) {
|
||||||
try {
|
try {
|
||||||
if (window.setAuthToken) { window.setAuthToken(data.result.token, data.result.visitorInfo) }
|
if (window.setAuthToken) { window.setAuthToken(data.result.token, data.result.visitorInfo) }
|
||||||
|
5
plugins/v-viewer.js
Normal file
5
plugins/v-viewer.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import 'viewerjs/dist/viewer.css'
|
||||||
|
import Viewer from 'v-viewer'
|
||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
Vue.use(Viewer)
|
@ -1,4 +1,5 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import VModal from 'vue-js-modal'
|
import VModal from 'vue-js-modal/dist/ssr.nocss'
|
||||||
|
|
||||||
|
import 'vue-js-modal/dist/styles.css'
|
||||||
Vue.use(VModal, { dialog: true })
|
Vue.use(VModal, { dialog: true })
|
||||||
|
4
plugins/vue-toasted.js
Normal file
4
plugins/vue-toasted.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import Toasted from 'vue-toasted'
|
||||||
|
|
||||||
|
Vue.use(Toasted)
|
@ -30,7 +30,7 @@ import {
|
|||||||
} from '@fortawesome/free-regular-svg-icons'
|
} from '@fortawesome/free-regular-svg-icons'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||||
import hljs from 'highlight.js'
|
import hljs from 'highlight.js'
|
||||||
import Swiper from '../components/Swiper'
|
import { Loading } from 'element-ui'
|
||||||
import Slide from '../components/Slide'
|
import Slide from '../components/Slide'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
@ -59,8 +59,8 @@ library.add(
|
|||||||
)
|
)
|
||||||
|
|
||||||
Vue.component('Icon', FontAwesomeIcon)
|
Vue.component('Icon', FontAwesomeIcon)
|
||||||
Vue.component('Swiper', Vue.extend(Swiper))
|
|
||||||
Vue.component('Slide', Vue.extend(Slide))
|
Vue.component('Slide', Vue.extend(Slide))
|
||||||
|
Vue.use(Loading.directive)
|
||||||
|
|
||||||
export default function (ctx, inject) {
|
export default function (ctx, inject) {
|
||||||
inject('getHatValue', (count, hotConst = 1000) => {
|
inject('getHatValue', (count, hotConst = 1000) => {
|
||||||
|
10
release.sh
10
release.sh
@ -1,3 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
export NODE_OPTIONS=--openssl-legacy-provider
|
||||||
|
|
||||||
yarn run build
|
yarn run build
|
||||||
rsync -avr --delete-after --exclude ".git" . root@139.129.130.191:/root/site/blog-client && ssh root@139.129.130.191 'docker restart blog-client && docker restart blog-client1 && docker restart blog-client2 && docker restart blog-client3'
|
rsync -avr --delete-after --exclude ".git" --exclude "node_modules" . root@manage.wyr.me:/root/blog-client
|
||||||
|
|
||||||
|
ssh -t -t root@manage.wyr.me << remotessh
|
||||||
|
source /root/.bashrc
|
||||||
|
cd /root/blog-client
|
||||||
|
yarn && pm2 restart blog-client && exit
|
||||||
|
remotessh
|
||||||
|
@ -13,7 +13,7 @@ async function start () {
|
|||||||
const nuxt = new Nuxt(config)
|
const nuxt = new Nuxt(config)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
host = process.env.HOST || '127.0.0.1',
|
host = process.env.HOST || '0.0.0.0',
|
||||||
port = process.env.PORT || 3000
|
port = process.env.PORT || 3000
|
||||||
} = nuxt.options.server
|
} = nuxt.options.server
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
.allSpinner{position:fixed;top:0;left:0;z-index:999999;width:100%;height:100%;background-color:#fff}.spinner{position:fixed;top:50%;left:50%;z-index:9999999;margin:75pt auto 0;margin-top:-1pc;margin-left:-75px;width:150px;text-align:center}.spinner>div{display:inline-block;width:30px;height:30px;border-radius:100%;background-color:#67cf22;-webkit-animation:bouncedelay 1.4s infinite ease-in-out;animation:bouncedelay 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.spinner .bounce1{-webkit-animation-delay:-.32s;animation-delay:-.32s}.spinner .bounce2{-webkit-animation-delay:-.16s;animation-delay:-.16s}@-webkit-keyframes bouncedelay{0%,80%,to{-webkit-transform:scale(0)}40%{-webkit-transform:scale(1)}}@keyframes bouncedelay{0%,80%,to{-webkit-transform:scale(0);transform:scale(0)}40%{-webkit-transform:scale(1);transform:scale(1)}}
|
.allSpinner{position:fixed;top:0;left:0;z-index:999999;width:100%;height:100%;background-color:#fff}.spinner{position:fixed;top:50%;left:50%;z-index:9999999;margin:75pt auto 0;margin-top:-1pc;margin-left:-75px;width:150px;text-align:center}.spinner>div{display:inline-block;width:30px;height:30px;border-radius:100%;background-color:#272727;-webkit-animation:bouncedelay 1.4s infinite ease-in-out;animation:bouncedelay 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.spinner .bounce1{-webkit-animation-delay:-.32s;animation-delay:-.32s}.spinner .bounce2{-webkit-animation-delay:-.16s;animation-delay:-.16s}@-webkit-keyframes bouncedelay{0%,80%,to{-webkit-transform:scale(0)}40%{-webkit-transform:scale(1)}}@keyframes bouncedelay{0%,80%,to{-webkit-transform:scale(0);transform:scale(0)}40%{-webkit-transform:scale(1);transform:scale(1)}}
|
||||||
|
Reference in New Issue
Block a user