first commit
This commit is contained in:
344
pages/post/_id.vue
Normal file
344
pages/post/_id.vue
Normal file
@ -0,0 +1,344 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
article.articleDetails
|
||||
.articleTitle
|
||||
| {{ Articels.post_title }}
|
||||
.articalMeta
|
||||
ul
|
||||
li
|
||||
Icon(:icon="['far', 'calendar-alt']")
|
||||
| {{ Articels.post_date }}
|
||||
li
|
||||
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")
|
||||
span
|
||||
| {{ relationships.term_taxonomy.term.name }}
|
||||
li(v-if='Articels.postmetum.meta_value !== 0')
|
||||
Icon(:icon="['fas', 'thermometer-' + Articels.hotValue]")
|
||||
| {{ Articels.postmetum.meta_value }}
|
||||
#articelToc.articelToc(v-if="Articels.post_toc_show")
|
||||
.articelTitle 目录
|
||||
.articelTocList(v-html="Articels.post_toc")
|
||||
.articelContent(v-html='Articels.post_content')
|
||||
.articelRightToc(v-show="Articels.post_toc_show && showRightToc", @click="articelRightTocClick")
|
||||
.articelTitle 目录
|
||||
.articelTocList(v-html="Articels.post_toc")
|
||||
nuxt-link(:to="Articels.last ? '/post/' + Articels.last.ID : ''")
|
||||
.btnFooter.btnPrevt(:style="'color: ' + (Articels.last ? '#333' : '#ccc')")
|
||||
Icon(:icon="['fas', 'chevron-left']")
|
||||
| 上一篇 {{ Articels.last ? '(' + decodeURIComponent(Articels.last.post_name) + ')' : ''}}
|
||||
nuxt-link(:to="Articels.next ? '/post/' + Articels.next.ID : ''")
|
||||
.btnFooter.btnNext(:style="'color: ' + (Articels.next ? '#333' : '#ccc')")
|
||||
| 下一篇 {{ Articels.next ? '(' + decodeURIComponent(Articels.next.post_name) + ')' : ''}}
|
||||
Icon(:icon="['fas', 'chevron-right']")
|
||||
.comment
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
async asyncData({ route, app, $axios }) {
|
||||
const { data } = await $axios.$get(`/public/article/details?id=${route.params.id}`)
|
||||
const result = data.result
|
||||
result.post_date = app.$moment(result.post_date).utc().format('lll')// 格式化时间
|
||||
// 热度值计算
|
||||
if (result.postmetum !== null && result.postmetum !== '') {
|
||||
result.hotValue = app.$getHatValue(result.postmetum.meta_value)
|
||||
} else {
|
||||
result.hotValue = 0
|
||||
result.postmetum = {}
|
||||
result.postmetum.meta_value = 0
|
||||
}
|
||||
|
||||
return {
|
||||
Articels: result,
|
||||
showRightToc: false,
|
||||
tocIds: result.post_toc_ids
|
||||
}
|
||||
},
|
||||
head() {
|
||||
return {
|
||||
title: `${this.Articels.post_title} - 轶哥博客`
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$finishLoad()
|
||||
|
||||
if (this.Articels.post_toc_show) {
|
||||
const tocShow = () => {
|
||||
if (window.addEvent) {
|
||||
window.addEvent(window, 'scroll', () => {
|
||||
const windowWidth = window.innerWidth || document.documentElement.clientWidth
|
||||
if (document.getElementById('articelToc') && !this.isOnScreen(document.getElementById('articelToc'))) {
|
||||
if (windowWidth < 768) {
|
||||
this.showRightToc = false
|
||||
document.getElementById('mobileToc').style.display = 'block'
|
||||
} else {
|
||||
this.showRightToc = true
|
||||
}
|
||||
} else {
|
||||
this.showRightToc = false
|
||||
if (windowWidth < 768) {
|
||||
document.getElementById('mobileToc').style.display = 'none'
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
tocShow()
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
tocShow()
|
||||
|
||||
const tocIdsTop = []
|
||||
const tocIdsTopMap = new Map()
|
||||
for (const n in this.tocIds) {
|
||||
const tTop = document.getElementById(this.tocIds[n]).offsetTop
|
||||
tocIdsTop.push(tTop)
|
||||
tocIdsTopMap.set(tTop, '#' + this.tocIds[n])
|
||||
}
|
||||
console.log(tocIdsTop)
|
||||
|
||||
const findInIds = (arr, num) => { for (let x = 0; x < arr.length; x++) { if (arr[x] > num) { return x - 1 } } }
|
||||
|
||||
let debounce = null
|
||||
let lastIdInx = null
|
||||
|
||||
const scrollToc = () => {
|
||||
let scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop
|
||||
const windowWidth = window.innerWidth || document.documentElement.clientWidth
|
||||
if (windowWidth < 768) scrollTop = scrollTop * 2.7 + 175
|
||||
const tocIdsInx = findInIds(tocIdsTop, scrollTop + 130)
|
||||
if (tocIdsInx !== -1 && lastIdInx !== tocIdsInx && document.getElementsByClassName('articelRightToc')[0]) {
|
||||
const tocAList = document.getElementsByClassName('articelRightToc')[0].getElementsByTagName('a')
|
||||
const nowId = tocIdsTopMap.get(tocIdsTop[tocIdsInx])
|
||||
for (const i in tocAList) {
|
||||
if (tocAList[i] && tocAList[i].getAttribute && tocAList[i].getAttribute('href') === nowId) {
|
||||
tocAList[i].style.color = '#ff8a8a'
|
||||
} else if (tocAList[i] && tocAList[i].style) {
|
||||
tocAList[i].style.color = '#bbb'
|
||||
}
|
||||
}
|
||||
lastIdInx = tocIdsInx
|
||||
}
|
||||
}
|
||||
window.addEvent(window, 'scroll', () => {
|
||||
clearTimeout(debounce)
|
||||
debounce = setTimeout(() => {
|
||||
scrollToc()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
document.getElementById('mobileToc').onclick = () => {
|
||||
this.showRightToc = !this.showRightToc
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
articelRightTocClick() {
|
||||
const windowWidth = window.innerWidth || document.documentElement.clientWidth
|
||||
if (windowWidth < 768) {
|
||||
this.showRightToc = false
|
||||
}
|
||||
},
|
||||
isOnScreen(element) {
|
||||
const ON_SCREEN_HEIGHT = 50
|
||||
const ON_SCREEN_WIDTH = 50
|
||||
|
||||
const rect = element.getBoundingClientRect()
|
||||
const windowHeight = window.innerHeight || document.documentElement.clientHeight
|
||||
const windowWidth = window.innerWidth || document.documentElement.clientWidth
|
||||
|
||||
const elementHeight = element.offsetHeight
|
||||
const elementWidth = element.offsetWidth
|
||||
|
||||
const onScreenHeight = ON_SCREEN_HEIGHT > elementHeight ? elementHeight : ON_SCREEN_HEIGHT
|
||||
const onScreenWidth = ON_SCREEN_WIDTH > elementWidth ? elementWidth : ON_SCREEN_WIDTH
|
||||
|
||||
// 元素在屏幕上方
|
||||
const elementBottomToWindowTop = rect.top + elementHeight
|
||||
const bottomBoundingOnScreen = elementBottomToWindowTop >= onScreenHeight
|
||||
|
||||
// 元素在屏幕下方
|
||||
const elementTopToWindowBottom = windowHeight - (rect.bottom - elementHeight)
|
||||
const topBoundingOnScreen = elementTopToWindowBottom >= onScreenHeight
|
||||
|
||||
// 元素在屏幕左侧
|
||||
const elementRightToWindowLeft = rect.left + elementWidth
|
||||
const rightBoundingOnScreen = elementRightToWindowLeft >= onScreenWidth
|
||||
|
||||
// 元素在屏幕右侧
|
||||
const elementLeftToWindowRight = windowWidth - (rect.right - elementWidth)
|
||||
const leftBoundingOnScreen = elementLeftToWindowRight >= onScreenWidth
|
||||
|
||||
return bottomBoundingOnScreen && topBoundingOnScreen && rightBoundingOnScreen && leftBoundingOnScreen
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" socped>
|
||||
.articleDetails
|
||||
margin-top 30px
|
||||
background-color #fff
|
||||
padding 50px 10px
|
||||
|
||||
.articleTitle
|
||||
text-align center
|
||||
font-size 24px
|
||||
|
||||
.articalMeta
|
||||
text-align center
|
||||
padding 20px 0
|
||||
font-size 12px
|
||||
color #a1887f
|
||||
|
||||
ul
|
||||
list-style none
|
||||
padding-right 20px
|
||||
|
||||
> li
|
||||
display inline-block
|
||||
margin-left 20px
|
||||
line-height 2
|
||||
|
||||
> i
|
||||
margin-right 8px
|
||||
|
||||
> span a
|
||||
color #a1887f
|
||||
margin-left 10px
|
||||
|
||||
a span
|
||||
color #a1887f
|
||||
|
||||
> span a:first-child
|
||||
margin-left 0
|
||||
|
||||
> li :first-child
|
||||
margin-left 0
|
||||
|
||||
.articelContent
|
||||
margin-top 20px
|
||||
line-height 2
|
||||
font-weight 300
|
||||
font-size responsive
|
||||
|
||||
pre
|
||||
text-align 0.16rem
|
||||
overflow-x auto
|
||||
line-height 1
|
||||
|
||||
code
|
||||
padding 16px
|
||||
|
||||
code
|
||||
color #24292e
|
||||
background-color rgba(27, 31, 35, 0.05)
|
||||
border-radius 3px
|
||||
font-size 85%
|
||||
padding 2px 5px
|
||||
|
||||
.comment
|
||||
width 100%
|
||||
|
||||
.btnFooter
|
||||
font-size 12px
|
||||
margin-top 50px
|
||||
|
||||
i
|
||||
margin 10px
|
||||
|
||||
.btnPrevt
|
||||
float left
|
||||
|
||||
.btnNext
|
||||
float right
|
||||
|
||||
footer .footer
|
||||
color #cccccc
|
||||
text-align left
|
||||
line-height 1.5
|
||||
margin 20px 0
|
||||
|
||||
.anchor-fix
|
||||
display block
|
||||
height 70px /* same height as header */
|
||||
margin-top -70px /* same height as header */
|
||||
visibility hidden
|
||||
|
||||
.articelRightToc
|
||||
position fixed
|
||||
width 15%
|
||||
top 0
|
||||
right 0
|
||||
overflow-y auto
|
||||
background-color #000
|
||||
padding 10px
|
||||
box-shadow 0 0 8px #000
|
||||
|
||||
.articelToc
|
||||
width 100%
|
||||
|
||||
.articelToc, .articelRightToc
|
||||
color #bbb
|
||||
user-select none
|
||||
|
||||
.articelTitle
|
||||
font-weight 400
|
||||
margin-bottom 10px
|
||||
|
||||
.articelTocList
|
||||
color #bbb
|
||||
|
||||
a
|
||||
color #bbb
|
||||
|
||||
&:visited
|
||||
color #bbb
|
||||
|
||||
&:hover
|
||||
color #d01c2e
|
||||
|
||||
ol.toc, ol.toc ol
|
||||
counter-reset toc
|
||||
list-style none
|
||||
|
||||
ol li
|
||||
counter-increment toc
|
||||
|
||||
.toc li:before
|
||||
content counters(toc, '.') ' '
|
||||
|
||||
ol
|
||||
margin-left 20px
|
||||
|
||||
li
|
||||
font-weight 400
|
||||
|
||||
ol
|
||||
margin-left 20px
|
||||
|
||||
li
|
||||
font-weight 300
|
||||
|
||||
@media (max-width: 768px)
|
||||
.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>
|
Reference in New Issue
Block a user