93 lines
2.8 KiB
Vue
93 lines
2.8 KiB
Vue
<script setup lang="ts">
|
|
const route = useRoute(),
|
|
cid = route.params.cid as string,
|
|
content = ref<IBlogResponse<IPostFull>>(),
|
|
toc = ref<HTMLDivElement | null>(null),
|
|
|
|
getPost = get<IBlogResponse<IPostFull>, unknown>('/blog/index.php/api/post', {
|
|
params: {
|
|
cid,
|
|
md: false,
|
|
},
|
|
}),
|
|
|
|
title = computed(() => content.value?.data.title || 'Can not see me... can not see me...'),
|
|
text = computed(() => content.value ? content.value.data.text + '[[toc]]' : '## Ops!'),
|
|
date = computed(() => new Date((content.value?.data.date.timeStamp || 0) * 1000)
|
|
.toISOString()
|
|
.split('T')[0],
|
|
),
|
|
category = computed(() => content.value?.data.category || 'default'),
|
|
url = computed(() => content.value?.data.url || '/error/404'),
|
|
bindAnchorClickEvent = () => {
|
|
const autoGenTOC = document.querySelector('#toc')
|
|
if (!autoGenTOC || !toc.value) return
|
|
|
|
toc.value.innerHTML = autoGenTOC.innerHTML
|
|
autoGenTOC.remove()
|
|
|
|
toc.value.querySelectorAll('a').forEach((elem: HTMLElement) => {
|
|
elem.onclick = (event: MouseEvent) => {
|
|
event.preventDefault()
|
|
|
|
let id = elem.getAttribute('href') || ''
|
|
if (id.startsWith('#'))
|
|
id = id.replace('#', '')
|
|
|
|
const element = document.getElementById(id)
|
|
if (element) {
|
|
const offsetTop = element.offsetTop - 70
|
|
window.scrollTo({ top: offsetTop, behavior: 'smooth' })
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
content.value = await getPost()
|
|
|
|
onMounted(() => {
|
|
bindAnchorClickEvent()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex container m-4 mx-auto xl:max-w-screen-xl gap-4">
|
|
<section class="container mx-auto rounded-xl bg-white p-8 shadow-md flex-shrink-0 lg:max-w-screen-lg">
|
|
<div class="mb-4 border-b-2 border-dashed border-gray-200 pb-4">
|
|
<h1 class="text-center text-3xl font-bold">
|
|
{{ title }}
|
|
</h1>
|
|
<div class="flex w-full items-center justify-center gap-4 text-gray-600">
|
|
<!-- 日期 -->
|
|
<div class="flex items-center gap-2">
|
|
<font-awesome-icon :icon="['far', 'clock']" />
|
|
<time>{{ date }}</time>
|
|
</div>
|
|
<!-- 分类 -->
|
|
<div class="flex items-center gap-2">
|
|
<font-awesome-icon :icon="['far', 'folder']" />
|
|
<span>{{ category }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<font-awesome-icon :icon="['fas', 'link']" />
|
|
<a :href="url">原文链接</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<markdown-section :content="text" />
|
|
</section>
|
|
|
|
<aside class="flex-1 overflow-hidden">
|
|
<div class="rounded-xl p-8 bg-white shadow-md">
|
|
<div ref="toc" />
|
|
</div>
|
|
</aside>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.toc-style {
|
|
@apply truncate
|
|
}
|
|
</style>
|