Files
estel_docs/app/pages/blog/[...slug].vue

218 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import type { ContentNavigationItem } from '@nuxt/content'
import { findPageHeadline } from '#ui-pro/utils/content'
definePageMeta({
layout: 'blog'
})
const route = useRoute()
const appConfig = useAppConfig()
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
// 获取主题系统的字号设置
const { selectedFontSize } = useTheme()
// 计算页面内容的字号类
const pageFontSizeClass = computed(() => {
return `text-${selectedFontSize.value}`
})
// 根据路由参数构建内容路径
const path = computed(() => route.path)
// URL 解码并验证路径
const queryPath = computed(() => {
try {
return decodeURIComponent(path.value)
} catch (error) {
console.error('URL decode error:', error)
return path.value // 如果解码失败,返回原始路径
}
})
const { data: page } = await useAsyncData(
`page-${route.path}`, // 使用更具体的 key
() => queryCollection('blog').path(decodeURIComponent(path.value)).first(),
{
default: () => null // 提供默认值
}
)
if (!page.value) {
throw createError({
statusCode: 404,
statusMessage: '文档不存在',
message: `当前页面不存在,请您检查路径是否正确: ${queryPath.value}`,
fatal: true
})
}
const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
return queryCollectionItemSurroundings('blog', route.path, {
fields: ['description']
})
})
const title = page.value.seo?.title || page.value.title
const description = page.value.seo?.description || page.value.description
useSeoMeta({
title,
ogTitle: title,
description,
ogDescription: description
})
const headline = computed(() => findPageHeadline(navigation?.value, page.value))
defineOgImageComponent('Docs', {
headline: headline.value
})
const editLink = computed(() => {
if (!appConfig.github) {
return
}
return [
appConfig.github.url,
'edit',
appConfig.github.branch,
appConfig.github.rootDir,
'content',
`${page.value?.stem}.${page.value?.extension}`
].filter(Boolean).join('/')
})
const links = computed(() => {
const links = []
if (appConfig.toc?.bottom?.edit) {
links.push({
icon: 'lucide-external-link',
label: '编辑页面',
to: `${appConfig.toc.bottom.edit}/${page?.value?.stem}.${page?.value?.extension}`,
target: '_blank'
})
}
return [...links, ...(appConfig.toc?.bottom?.links || [])].filter(Boolean)
})
</script>
<template>
<UPage
v-if="page"
:class="['lg:mr-30 lg:ml-5 sm:mt-6', pageFontSizeClass]"
>
<UPageHeader
:title="page.title"
:description="page.description"
:headline="headline"
:ui="{
wrapper: 'flex-row items-center flex-wrap justify-between '
}"
>
<span
v-if="page.date"
class="text-sm text-pretty text-muted mt-4"
> {{ page.date }} </span>
<template #links>
<UButton
v-for="(link, index) in page.links"
:key="index"
size="sm"
v-bind="link"
/>
<DocsPageHeaderLinks
:title="page.title"
:desc="page.description || page.seo?.description || page.title"
:img-url="page.img || '/images/default-blog.jpg'"
/>
</template>
</UPageHeader>
<UPageBody>
<ContentRenderer
v-if="page"
:value="page"
/>
<USeparator>
<div
v-if="editLink"
class="flex items-center gap-2 text-sm text-muted"
>
<UButton
variant="link"
color="neutral"
:to="editLink"
target="_blank"
icon="lucide-pen"
:ui="{ leadingIcon: 'size-4' }"
>
编辑页面
</UButton>
or
<UButton
variant="link"
color="neutral"
:to="`${appConfig.github.url}/issues/new/choose`"
target="_blank"
icon="lucide-alert-circle"
:ui="{ leadingIcon: 'size-4' }"
>
提交问题
</UButton>
</div>
</USeparator>
<UContentSurround :surround="surround" />
<!-- 激活后挂载分享组件无可视内容
<SharedWxShare
v-if="wxShareActive"
:url="shareLink"
:title="shareTitle"
:desc="shareDesc"
:img-url="shareImg"
/> -->
</UPageBody>
<template
v-if="page?.body?.toc?.links?.length"
#right
>
<div class="">
<UContentToc
:title="appConfig.toc?.title"
:links="page.body?.toc?.links"
:ui="{
root: 'fixed w-full xl:right-12 xl:w-64 z-50 bg-white dark:bg-gray-900 lg:border border-gray-200 dark:border-gray-700 rounded-lg lg:shadow-lg lg:mt-5'
}"
>
<template
v-if="appConfig.toc?.bottom"
#bottom
>
<div
class=""
:class="{ '!mt-5': page.body?.toc?.links?.length }"
>
<USeparator
v-if="page.body?.toc?.links?.length"
type="dashed"
/>
<UPageLinks
:title="appConfig.toc.bottom.title"
:links="links"
/>
</div>
</template>
</UContentToc>
</div>
</template>
</UPage>
</template>