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

166 lines
4.5 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: 'docs'
// })
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(() => {
const slug = route.params.slug;
// 处理 slug 参数
if (!slug) {
return '/'; // 如果没有 slug返回根路径
}
const pathValue = Array.isArray(slug) ? slug.join("/") : slug;
// 确保路径以 / 开头,不以 / 结尾
const normalizedPath = `/${pathValue}`.replace(/\/+$/, ""); // 使用 /+ 匹配多个连续的斜杠
return normalizedPath;
});
// 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('docs').path(queryPath.value).first(),
{
default: () => null // 提供默认值
}
);
if (!page.value) {
throw createError({
statusCode: 404,
statusMessage: '文档不存在',
message: '当前页面不存在,请您检查路径是否正确',
fatal: true
});
}
const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
return queryCollectionItemSurroundings('docs', 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="pageFontSizeClass">
<UPageHeader :title="page.title" :description="page.description" :headline="headline" :ui="{
wrapper: 'flex-row items-center flex-wrap justify-between ',
}">
<template #links>
<UButton v-for="(link, index) in page.links" :key="index" size="sm" v-bind="link" />
<DocsPageHeaderLinks />
</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" />
</UPageBody>
<template v-if="page?.body?.toc?.links?.length" #right>
<div class="fixed top-24 right-15 w-auto">
<UContentToc :title="appConfig.toc?.title" :links="page.body?.toc?.links">
<template v-if="appConfig.toc?.bottom" #bottom>
<div class="hidden lg:block space-y-6 " :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>