修改页面布局大修改
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
const { seo } = useAppConfig()
|
const { seo } = useAppConfig()
|
||||||
|
|
||||||
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
|
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
|
||||||
|
const { data: blogNavigation } = await useAsyncData('blogNavigation', () => queryCollectionNavigation('blog'))
|
||||||
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'), {
|
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'), {
|
||||||
server: false
|
server: false
|
||||||
})
|
})
|
||||||
@@ -45,6 +46,7 @@ useSeoMeta({
|
|||||||
})
|
})
|
||||||
|
|
||||||
provide('navigation', navigation)
|
provide('navigation', navigation)
|
||||||
|
provide('blogNavigation', blogNavigation)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
85
app/components/blog/BlogSidebar.vue
Normal file
85
app/components/blog/BlogSidebar.vue
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<UPage>
|
||||||
|
<div
|
||||||
|
class="w-64 bg-white dark:bg-gray-900
|
||||||
|
flex flex-col h-screen border-r border-gray-200 dark:border-gray-700
|
||||||
|
overflow-hidden"
|
||||||
|
>
|
||||||
|
<div class="flex-shrink-0 p-4 border-gray-200 dark:border-gray-700">
|
||||||
|
<!-- Logo -->
|
||||||
|
<LogoPro />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Search Box -->
|
||||||
|
<div class="p-4 border-gray-200 dark:border-gray-700">
|
||||||
|
<ClientOnly>
|
||||||
|
<UContentSearchButton
|
||||||
|
:collapsed="false"
|
||||||
|
label="搜索文档"
|
||||||
|
class="w-full"
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 可滚动的导航区域 -->
|
||||||
|
<div class=" h-full overflow-y-auto ">
|
||||||
|
<!-- 导航 Section -->
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<NuxtLink
|
||||||
|
to="/"
|
||||||
|
class="flex items-center px-4 py-2 text-sm font-medium rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 hover:shadow-sm transition-all duration-200"
|
||||||
|
:class="{
|
||||||
|
' text-blue-600 dark:text-blue-400 ':
|
||||||
|
useRoute().path === '/'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="lucide-home"
|
||||||
|
class="text-primary mr-2"
|
||||||
|
size="20"
|
||||||
|
/>
|
||||||
|
站点首页
|
||||||
|
</NuxtLink>
|
||||||
|
<div class="px-2">
|
||||||
|
<DocsAsideLeftTop />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分隔线 -->
|
||||||
|
<div class="mt-4 uppercase tracking-wider border-t border-gray-200 dark:border-gray-700 w-7/9 mx-5" />
|
||||||
|
|
||||||
|
<!-- 文档目录导航 -->
|
||||||
|
<div class="mt-6 flex items-center justify-start pl-4 w-full pb-3">
|
||||||
|
<UContentNavigation
|
||||||
|
highlight
|
||||||
|
:navigation="docsNavigation"
|
||||||
|
color="primary"
|
||||||
|
type="single"
|
||||||
|
variant="pill"
|
||||||
|
trailing-icon="lucide:chevron-right"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ContentNavigationItem } from '@nuxt/content'
|
||||||
|
|
||||||
|
const navigation = inject<Ref<ContentNavigationItem[]>>('blogNavigation')
|
||||||
|
|
||||||
|
// 提取 docs 目录下的子目录作为顶级导航
|
||||||
|
const docsNavigation = computed(() => {
|
||||||
|
if (!navigation?.value) return []
|
||||||
|
// 查找 docs 目录
|
||||||
|
const docsItem = navigation.value.find(item => item.title === 'blog' || item.path === '/blog')
|
||||||
|
|
||||||
|
if (!docsItem?.children) return []
|
||||||
|
|
||||||
|
// 返回 docs 目录下的子目录
|
||||||
|
return docsItem.children
|
||||||
|
})
|
||||||
|
</script>
|
115
app/components/blog/indexBlog.vue
Normal file
115
app/components/blog/indexBlog.vue
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
// 获取 blog 集合的所有文章
|
||||||
|
const { data: articles } = await useAsyncData('blog-articles', () => {
|
||||||
|
return queryCollection('blog')
|
||||||
|
.select('path', 'title', 'description', 'img', 'date')
|
||||||
|
.where('path', 'NOT LIKE', '%navigation%')
|
||||||
|
.all()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (date: any) => {
|
||||||
|
if (!date) return '未知时间'
|
||||||
|
try {
|
||||||
|
const d = new Date(date)
|
||||||
|
return d.toLocaleDateString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
})
|
||||||
|
} catch {
|
||||||
|
return '未知时间'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算阅读时间(基于文章内容长度估算)
|
||||||
|
const getReadingTime = (content: any) => {
|
||||||
|
if (!content) return 1
|
||||||
|
try {
|
||||||
|
const wordsPerMinute = 200
|
||||||
|
const wordCount = String(content).split(/\s+/).length
|
||||||
|
return Math.max(1, Math.ceil(wordCount / wordsPerMinute))
|
||||||
|
} catch {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full bg-gray-50 dark:bg-gray-900 min-h-screen mt-4">
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- 页面标题 -->
|
||||||
|
<div class="mb-8">
|
||||||
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||||
|
博客文章
|
||||||
|
</h1>
|
||||||
|
<p class="text-gray-600 dark:text-gray-400">
|
||||||
|
分享技术见解和心得体会
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 文章列表 -->
|
||||||
|
<div class="space-y-6">
|
||||||
|
<NuxtLink
|
||||||
|
v-for="item in articles"
|
||||||
|
:key="item.path"
|
||||||
|
:to="item.path"
|
||||||
|
class="block"
|
||||||
|
>
|
||||||
|
<article
|
||||||
|
class="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-6 hover:shadow-md transition-all duration-200 cursor-pointer group"
|
||||||
|
>
|
||||||
|
<!-- 文章头部 -->
|
||||||
|
<div class="flex items-start justify-between mb-4">
|
||||||
|
<div class="flex-1">
|
||||||
|
<h2 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
|
||||||
|
{{ item.title }}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<!-- 文章描述 -->
|
||||||
|
<p
|
||||||
|
v-if="item.description"
|
||||||
|
class="text-gray-600 dark:text-gray-300 text-sm mb-3 line-clamp-2"
|
||||||
|
>
|
||||||
|
{{ item.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 文章元信息 -->
|
||||||
|
<div class="flex items-center justify-between text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<!-- 文章时间 -->
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<UIcon
|
||||||
|
name="lucide-clock"
|
||||||
|
size="14"
|
||||||
|
/>
|
||||||
|
<span>{{ formatDate(item.date) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<div
|
||||||
|
v-if="!articles || articles.length === 0"
|
||||||
|
class="text-center py-12"
|
||||||
|
>
|
||||||
|
<UIcon
|
||||||
|
name="lucide-file-text"
|
||||||
|
class="mx-auto text-4xl text-gray-400 mb-4"
|
||||||
|
/>
|
||||||
|
<h3 class="text-lg font-medium text-gray-900 dark:text-white mb-2">
|
||||||
|
暂无文章
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray-500 dark:text-gray-400">
|
||||||
|
还没有发布任何博客文章
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
@@ -10,10 +10,23 @@ const items = ref<NavigationMenuItem[][]>([
|
|||||||
target: '_blank'
|
target: '_blank'
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: '博客',
|
||||||
|
icon: 'lucide-pen-line',
|
||||||
|
to: '/blog'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: '简单文档',
|
||||||
|
icon: 'lucide-book',
|
||||||
|
to: '/docs'
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: '组件速查',
|
label: '组件速查',
|
||||||
icon: 'lucide-box',
|
icon: 'lucide-box',
|
||||||
to: '/简单文档/components/api'
|
to: '/docs/简单文档/components/api'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '关于',
|
label: '关于',
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
class="flex items-center px-4 py-2 text-sm font-medium rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 hover:shadow-sm transition-all duration-200"
|
class="flex items-center px-4 py-2 text-sm font-medium rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 hover:shadow-sm transition-all duration-200"
|
||||||
:class="{
|
:class="{
|
||||||
' text-blue-600 dark:text-blue-400 ':
|
' text-blue-600 dark:text-blue-400 ':
|
||||||
$route.path === '/'
|
useRoute().path === '/'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<div class="mt-6 flex items-center justify-start pl-4 w-full pb-3">
|
<div class="mt-6 flex items-center justify-start pl-4 w-full pb-3">
|
||||||
<UContentNavigation
|
<UContentNavigation
|
||||||
highlight
|
highlight
|
||||||
:navigation="navigation"
|
:navigation="docsNavigation"
|
||||||
color="primary"
|
color="primary"
|
||||||
type="single"
|
type="single"
|
||||||
variant="pill"
|
variant="pill"
|
||||||
@@ -70,4 +70,16 @@
|
|||||||
import type { ContentNavigationItem } from '@nuxt/content'
|
import type { ContentNavigationItem } from '@nuxt/content'
|
||||||
|
|
||||||
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
||||||
|
|
||||||
|
// 提取 docs 目录下的子目录作为顶级导航
|
||||||
|
const docsNavigation = computed(() => {
|
||||||
|
if (!navigation?.value) return []
|
||||||
|
// 查找 docs 目录
|
||||||
|
const docsItem = navigation.value.find(item => item.title === 'docs' || item.path === '/docs')
|
||||||
|
|
||||||
|
if (!docsItem?.children) return []
|
||||||
|
|
||||||
|
// 返回 docs 目录下的子目录
|
||||||
|
return docsItem.children
|
||||||
|
})
|
||||||
</script>
|
</script>
|
@@ -8,7 +8,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 侧边栏 -->
|
<!-- 侧边栏 -->
|
||||||
<AppSidebar
|
<BlogSidebar
|
||||||
class="fixed top-0 bottom-0 z-50 transition-transform duration-300 ease-in-out"
|
class="fixed top-0 bottom-0 z-50 transition-transform duration-300 ease-in-out"
|
||||||
:class="isSidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'"
|
:class="isSidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'"
|
||||||
/>
|
/>
|
@@ -1,22 +1,46 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { ContentNavigationItem } from '@nuxt/content'
|
|
||||||
|
|
||||||
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UContainer>
|
<div class="min-h-screen bg-gray-50 dark:bg-gray-900 flex">
|
||||||
<UPage>
|
<!-- 移动端遮罩层 -->
|
||||||
<template #left>
|
<div
|
||||||
<UPageAside>
|
v-if="isSidebarOpen"
|
||||||
<UContentNavigation
|
class="fixed inset-0 bg-gray-900/50 z-40 lg:hidden"
|
||||||
highlight
|
@click="isSidebarOpen = false"
|
||||||
:navigation="navigation"
|
/>
|
||||||
/>
|
|
||||||
</UPageAside>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<slot />
|
<!-- 侧边栏 -->
|
||||||
</UPage>
|
<DocsSidebar
|
||||||
</UContainer>
|
class="fixed top-0 bottom-0 z-50 transition-transform duration-300 ease-in-out"
|
||||||
|
:class="isSidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Right Content Area -->
|
||||||
|
<div class="flex-1 lg:ml-64 flex flex-col min-w-0">
|
||||||
|
<!-- Fixed Header -->
|
||||||
|
<AppHeader
|
||||||
|
:is-sidebar-open="isSidebarOpen"
|
||||||
|
:toggle-sidebar="toggleSidebar"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<UMain class="flex-1 overflow-y-auto">
|
||||||
|
<div class="mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</UMain>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<AppFooter />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const isSidebarOpen = ref(false)
|
||||||
|
|
||||||
|
// 切换侧边栏
|
||||||
|
const toggleSidebar = () => {
|
||||||
|
isSidebarOpen.value = !isSidebarOpen.value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
197
app/pages/blog/[...slug].vue
Normal file
197
app/pages/blog/[...slug].vue
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
<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('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>
|
24
app/pages/blog/index.vue
Normal file
24
app/pages/blog/index.vue
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
layout: 'blog'
|
||||||
|
})
|
||||||
|
|
||||||
|
const title = 'Estel Blog'
|
||||||
|
const description = 'Estel Blog'
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
titleTemplate: '',
|
||||||
|
title,
|
||||||
|
ogTitle: title,
|
||||||
|
description,
|
||||||
|
ogDescription: description,
|
||||||
|
ogImage: 'https://assets.hub.nuxt.com/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RvY3MtdGVtcGxhdGUubnV4dC5kZXYiLCJpYXQiOjE3Mzk0NjM0MTd9.ltVAqPgKG38O01X1zl6MXfrJc55nf9OewXNFjpZ_2JY.jpg?theme=light',
|
||||||
|
twitterImage: 'https://assets.hub.nuxt.com/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RvY3MtdGVtcGxhdGUubnV4dC5kZXYiLCJpYXQiOjE3Mzk0NjM0MTd9.ltVAqPgKG38O01X1zl6MXfrJc55nf9OewXNFjpZ_2JY.jpg?theme=light'
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<BlogIndexBlog />
|
||||||
|
</div>
|
||||||
|
</template>
|
@@ -2,9 +2,9 @@
|
|||||||
import type { ContentNavigationItem } from '@nuxt/content'
|
import type { ContentNavigationItem } from '@nuxt/content'
|
||||||
import { findPageHeadline } from '#ui-pro/utils/content'
|
import { findPageHeadline } from '#ui-pro/utils/content'
|
||||||
|
|
||||||
// definePageMeta({
|
definePageMeta({
|
||||||
// layout: 'docs'
|
layout: 'docs'
|
||||||
// })
|
})
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const appConfig = useAppConfig()
|
const appConfig = useAppConfig()
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'default'
|
layout: 'docs'
|
||||||
})
|
})
|
||||||
|
|
||||||
const title = 'Estel Docs'
|
const title = 'Estel Docs'
|
||||||
@@ -19,7 +19,7 @@ useSeoMeta({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<IndexHero />
|
<DocsIndexHero />
|
||||||
<IndexCard />
|
<DocsIndexCard />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
5
app/pages/index.vue
Normal file
5
app/pages/index.vue
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>首页</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
@@ -2,9 +2,6 @@
|
|||||||
import type { ContentNavigationItem } from '@nuxt/content'
|
import type { ContentNavigationItem } from '@nuxt/content'
|
||||||
import { findPageHeadline } from '#ui-pro/utils/content'
|
import { findPageHeadline } from '#ui-pro/utils/content'
|
||||||
|
|
||||||
// definePageMeta({
|
|
||||||
// layout: 'docs'
|
|
||||||
// })
|
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const appConfig = useAppConfig()
|
const appConfig = useAppConfig()
|
||||||
@@ -47,9 +44,15 @@ const queryPath = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 根据路径判断查询的集合
|
||||||
|
const collection = computed(() => {
|
||||||
|
return queryPath.value.startsWith('/blog') ? 'blog' : 'docs'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const { data: page } = await useAsyncData(
|
const { data: page } = await useAsyncData(
|
||||||
`page-${route.path}`, // 使用更具体的 key
|
`page-${route.path}`, // 使用更具体的 key
|
||||||
() => queryCollection('docs').path(queryPath.value).first(),
|
() => queryCollection(collection.value).path(queryPath.value).first(),
|
||||||
{
|
{
|
||||||
default: () => null // 提供默认值
|
default: () => null // 提供默认值
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,8 @@ export default defineContentConfig({
|
|||||||
},
|
},
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
rawbody: z.string(),
|
rawbody: z.string(),
|
||||||
|
img: z.string(),
|
||||||
|
date: z.string(),
|
||||||
links: z.array(z.object({
|
links: z.array(z.object({
|
||||||
label: z.string(),
|
label: z.string(),
|
||||||
icon: z.string(),
|
icon: z.string(),
|
||||||
|
3
content/blog/1.技术栈/.navigation.yml
Normal file
3
content/blog/1.技术栈/.navigation.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
title: 技术栈
|
||||||
|
description: 记录日常开发中遇到的技术问题和解决方案
|
||||||
|
icon: lucide-code
|
238
content/blog/1.技术栈/01.index.md
Normal file
238
content/blog/1.技术栈/01.index.md
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
---
|
||||||
|
title: 记录技术栈
|
||||||
|
description: 记录日常开发中遇到的技术问题和解决方案
|
||||||
|
date: 2025-08-07
|
||||||
|
navigation:
|
||||||
|
icon: lucide-house
|
||||||
|
---
|
||||||
|
|
||||||
|
## 博客
|
||||||
|
|
||||||
|
使用过市面上的很多文档系统,但是或多或少都有一些自己不满意的功能.
|
||||||
|
于是自己动手,丰衣足食.
|
||||||
|
同时在 Markdown 语法的基础上增加了许多**魔法(自定义组件)**,比如:
|
||||||
|
|
||||||
|
|
||||||
|
::code-group
|
||||||
|
```mdc [index.md]
|
||||||
|
在 Markdown 中使用::card 标签,即可创建一个卡片,卡片里可以放置任何内容。比如以下内容:
|
||||||
|
::card
|
||||||
|
这里是卡片里的内容
|
||||||
|
::
|
||||||
|
```
|
||||||
|
|
||||||
|
```html [Card.vue]
|
||||||
|
<!-- Card组件: components/content/Card.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="p-2 border bg-white dark:bg-black dark:border-gray-700 rounded">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
:::code-preview{icon="i-lucide-eye" label="Preview"}
|
||||||
|
::::example-card
|
||||||
|
这里是卡片里的内容
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
:::UPageCard{icon="lucide-code" title="代码组" description="这个组件使用 自定义的 Markdown 语法,从 Markdown 中提取代码块,并展示在页面上 (而其自身亦是一个卡片组)"}
|
||||||
|
|
||||||
|
::code-tree{defaultValue="nuxt.config.ts"}
|
||||||
|
|
||||||
|
```css [app/assets/main.css]
|
||||||
|
@import "tailwindcss" theme(static);
|
||||||
|
@import "@nuxt/ui-pro";
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [app/app.config.ts]
|
||||||
|
export default defineAppConfig({
|
||||||
|
ui: {
|
||||||
|
colors: {
|
||||||
|
primary: 'sky',
|
||||||
|
colors: 'slate'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```vue [app/app.vue]
|
||||||
|
<template>
|
||||||
|
<UApp>
|
||||||
|
<NuxtPage />
|
||||||
|
</UApp>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
```json [package.json]
|
||||||
|
{
|
||||||
|
"name": "nuxt-app",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt build",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare",
|
||||||
|
"typecheck": "nuxt typecheck"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@iconify-json/lucide": "^1.2.18",
|
||||||
|
"@nuxt/ui-pro": "3.0.0-alpha.10",
|
||||||
|
"nuxt": "^3.15.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.7.2",
|
||||||
|
"vue-tsc": "^2.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json [tsconfig.json]
|
||||||
|
{
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [nuxt.config.ts]
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
modules: ['@nuxt/ui-pro'],
|
||||||
|
|
||||||
|
future: {
|
||||||
|
compatibilityVersion: 4
|
||||||
|
},
|
||||||
|
|
||||||
|
css: ['~/assets/main.css']
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [README.md]
|
||||||
|
# Nuxt 3 Minimal Starter
|
||||||
|
|
||||||
|
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install the dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||||
|
````
|
||||||
|
|
||||||
|
::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::code-group
|
||||||
|
```md [搜索.md]
|
||||||
|
#### 此组件打开一个模态搜索框,进行搜索
|
||||||
|
::::example-fulltext-content-search
|
||||||
|
::::
|
||||||
|
|
||||||
|
#### 此组件建立一个mini搜索框,进行搜索
|
||||||
|
::::example-fulltext-mini-search
|
||||||
|
::::
|
||||||
|
```
|
||||||
|
|
||||||
|
:::code-preview{label="预览模态组件" icon="i-lucide-eye"}
|
||||||
|
::::example-fulltext-content-search
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
:::code-preview{label="预览搜索框组件" icon="i-lucide-eye"}
|
||||||
|
::::example-fulltext-mini-search
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
::tip{icon="lucide-info" color="primary" class="text-black dark:text-white"}
|
||||||
|
阅读更多关于 [`自定义组件`](/简单文档/components/api) 的内容.
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
- 基于 Nuxt 4 , Content v3 , Nuxt UI Pro 构建的文档系统。
|
||||||
|
- 完美支持 Markdown 和 相关扩展。
|
||||||
|
- 和 Vue 组件高度集成。
|
||||||
|
- 支持搜索,由Content v3 赋能。
|
||||||
|
- 支持多主题,使用Nuxt UI Pro。
|
||||||
|
- 开源且免费。
|
||||||
|
- 支持移动端。
|
||||||
|
|
||||||
|
## 致谢
|
||||||
|
|
||||||
|
- Nuxt Content:为 Vue 开发者简化内容管理。
|
||||||
|
- Nuxt UI Pro :文档系统 UI 组件。
|
||||||
|
- Docus:获取灵感及一些文档组件源代码。
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
3
content/blog/2.AI/.navigation.yml
Normal file
3
content/blog/2.AI/.navigation.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
title: AI
|
||||||
|
description: AI 改变世界
|
||||||
|
icon: lucide-brain
|
238
content/blog/2.AI/01.index.md
Normal file
238
content/blog/2.AI/01.index.md
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
---
|
||||||
|
title: 记录AI
|
||||||
|
description: 学习 AI 相关知识
|
||||||
|
date: 2025-08-07
|
||||||
|
navigation:
|
||||||
|
icon: lucide-house
|
||||||
|
---
|
||||||
|
|
||||||
|
## 博客
|
||||||
|
|
||||||
|
使用过市面上的很多文档系统,但是或多或少都有一些自己不满意的功能.
|
||||||
|
于是自己动手,丰衣足食.
|
||||||
|
同时在 Markdown 语法的基础上增加了许多**魔法(自定义组件)**,比如:
|
||||||
|
|
||||||
|
|
||||||
|
::code-group
|
||||||
|
```mdc [index.md]
|
||||||
|
在 Markdown 中使用::card 标签,即可创建一个卡片,卡片里可以放置任何内容。比如以下内容:
|
||||||
|
::card
|
||||||
|
这里是卡片里的内容
|
||||||
|
::
|
||||||
|
```
|
||||||
|
|
||||||
|
```html [Card.vue]
|
||||||
|
<!-- Card组件: components/content/Card.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="p-2 border bg-white dark:bg-black dark:border-gray-700 rounded">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
:::code-preview{icon="i-lucide-eye" label="Preview"}
|
||||||
|
::::example-card
|
||||||
|
这里是卡片里的内容
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
:::UPageCard{icon="lucide-code" title="代码组" description="这个组件使用 自定义的 Markdown 语法,从 Markdown 中提取代码块,并展示在页面上 (而其自身亦是一个卡片组)"}
|
||||||
|
|
||||||
|
::code-tree{defaultValue="nuxt.config.ts"}
|
||||||
|
|
||||||
|
```css [app/assets/main.css]
|
||||||
|
@import "tailwindcss" theme(static);
|
||||||
|
@import "@nuxt/ui-pro";
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [app/app.config.ts]
|
||||||
|
export default defineAppConfig({
|
||||||
|
ui: {
|
||||||
|
colors: {
|
||||||
|
primary: 'sky',
|
||||||
|
colors: 'slate'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```vue [app/app.vue]
|
||||||
|
<template>
|
||||||
|
<UApp>
|
||||||
|
<NuxtPage />
|
||||||
|
</UApp>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
```json [package.json]
|
||||||
|
{
|
||||||
|
"name": "nuxt-app",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt build",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare",
|
||||||
|
"typecheck": "nuxt typecheck"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@iconify-json/lucide": "^1.2.18",
|
||||||
|
"@nuxt/ui-pro": "3.0.0-alpha.10",
|
||||||
|
"nuxt": "^3.15.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.7.2",
|
||||||
|
"vue-tsc": "^2.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json [tsconfig.json]
|
||||||
|
{
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [nuxt.config.ts]
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
modules: ['@nuxt/ui-pro'],
|
||||||
|
|
||||||
|
future: {
|
||||||
|
compatibilityVersion: 4
|
||||||
|
},
|
||||||
|
|
||||||
|
css: ['~/assets/main.css']
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [README.md]
|
||||||
|
# Nuxt 3 Minimal Starter
|
||||||
|
|
||||||
|
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install the dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||||
|
````
|
||||||
|
|
||||||
|
::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::code-group
|
||||||
|
```md [搜索.md]
|
||||||
|
#### 此组件打开一个模态搜索框,进行搜索
|
||||||
|
::::example-fulltext-content-search
|
||||||
|
::::
|
||||||
|
|
||||||
|
#### 此组件建立一个mini搜索框,进行搜索
|
||||||
|
::::example-fulltext-mini-search
|
||||||
|
::::
|
||||||
|
```
|
||||||
|
|
||||||
|
:::code-preview{label="预览模态组件" icon="i-lucide-eye"}
|
||||||
|
::::example-fulltext-content-search
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
:::code-preview{label="预览搜索框组件" icon="i-lucide-eye"}
|
||||||
|
::::example-fulltext-mini-search
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
::tip{icon="lucide-info" color="primary" class="text-black dark:text-white"}
|
||||||
|
阅读更多关于 [`自定义组件`](/简单文档/components/api) 的内容.
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
- 基于 Nuxt 4 , Content v3 , Nuxt UI Pro 构建的文档系统。
|
||||||
|
- 完美支持 Markdown 和 相关扩展。
|
||||||
|
- 和 Vue 组件高度集成。
|
||||||
|
- 支持搜索,由Content v3 赋能。
|
||||||
|
- 支持多主题,使用Nuxt UI Pro。
|
||||||
|
- 开源且免费。
|
||||||
|
- 支持移动端。
|
||||||
|
|
||||||
|
## 致谢
|
||||||
|
|
||||||
|
- Nuxt Content:为 Vue 开发者简化内容管理。
|
||||||
|
- Nuxt UI Pro :文档系统 UI 组件。
|
||||||
|
- Docus:获取灵感及一些文档组件源代码。
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
3
content/blog/3.生活/.navigation.yml
Normal file
3
content/blog/3.生活/.navigation.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
title: 生活
|
||||||
|
description: 生活中一些有趣的事情
|
||||||
|
icon: lucide-heart
|
238
content/blog/3.生活/01.index.md
Normal file
238
content/blog/3.生活/01.index.md
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
---
|
||||||
|
title: 记录生活
|
||||||
|
description: 记录生活点点滴滴
|
||||||
|
date: 2025-08-07
|
||||||
|
navigation:
|
||||||
|
icon: lucide-house
|
||||||
|
---
|
||||||
|
|
||||||
|
## 博客
|
||||||
|
|
||||||
|
使用过市面上的很多文档系统,但是或多或少都有一些自己不满意的功能.
|
||||||
|
于是自己动手,丰衣足食.
|
||||||
|
同时在 Markdown 语法的基础上增加了许多**魔法(自定义组件)**,比如:
|
||||||
|
|
||||||
|
|
||||||
|
::code-group
|
||||||
|
```mdc [index.md]
|
||||||
|
在 Markdown 中使用::card 标签,即可创建一个卡片,卡片里可以放置任何内容。比如以下内容:
|
||||||
|
::card
|
||||||
|
这里是卡片里的内容
|
||||||
|
::
|
||||||
|
```
|
||||||
|
|
||||||
|
```html [Card.vue]
|
||||||
|
<!-- Card组件: components/content/Card.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="p-2 border bg-white dark:bg-black dark:border-gray-700 rounded">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
:::code-preview{icon="i-lucide-eye" label="Preview"}
|
||||||
|
::::example-card
|
||||||
|
这里是卡片里的内容
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
:::UPageCard{icon="lucide-code" title="代码组" description="这个组件使用 自定义的 Markdown 语法,从 Markdown 中提取代码块,并展示在页面上 (而其自身亦是一个卡片组)"}
|
||||||
|
|
||||||
|
::code-tree{defaultValue="nuxt.config.ts"}
|
||||||
|
|
||||||
|
```css [app/assets/main.css]
|
||||||
|
@import "tailwindcss" theme(static);
|
||||||
|
@import "@nuxt/ui-pro";
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [app/app.config.ts]
|
||||||
|
export default defineAppConfig({
|
||||||
|
ui: {
|
||||||
|
colors: {
|
||||||
|
primary: 'sky',
|
||||||
|
colors: 'slate'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```vue [app/app.vue]
|
||||||
|
<template>
|
||||||
|
<UApp>
|
||||||
|
<NuxtPage />
|
||||||
|
</UApp>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
```json [package.json]
|
||||||
|
{
|
||||||
|
"name": "nuxt-app",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt build",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare",
|
||||||
|
"typecheck": "nuxt typecheck"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@iconify-json/lucide": "^1.2.18",
|
||||||
|
"@nuxt/ui-pro": "3.0.0-alpha.10",
|
||||||
|
"nuxt": "^3.15.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.7.2",
|
||||||
|
"vue-tsc": "^2.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json [tsconfig.json]
|
||||||
|
{
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [nuxt.config.ts]
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
modules: ['@nuxt/ui-pro'],
|
||||||
|
|
||||||
|
future: {
|
||||||
|
compatibilityVersion: 4
|
||||||
|
},
|
||||||
|
|
||||||
|
css: ['~/assets/main.css']
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [README.md]
|
||||||
|
# Nuxt 3 Minimal Starter
|
||||||
|
|
||||||
|
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install the dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||||
|
````
|
||||||
|
|
||||||
|
::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::code-group
|
||||||
|
```md [搜索.md]
|
||||||
|
#### 此组件打开一个模态搜索框,进行搜索
|
||||||
|
::::example-fulltext-content-search
|
||||||
|
::::
|
||||||
|
|
||||||
|
#### 此组件建立一个mini搜索框,进行搜索
|
||||||
|
::::example-fulltext-mini-search
|
||||||
|
::::
|
||||||
|
```
|
||||||
|
|
||||||
|
:::code-preview{label="预览模态组件" icon="i-lucide-eye"}
|
||||||
|
::::example-fulltext-content-search
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
:::code-preview{label="预览搜索框组件" icon="i-lucide-eye"}
|
||||||
|
::::example-fulltext-mini-search
|
||||||
|
::::
|
||||||
|
:::
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
::tip{icon="lucide-info" color="primary" class="text-black dark:text-white"}
|
||||||
|
阅读更多关于 [`自定义组件`](/简单文档/components/api) 的内容.
|
||||||
|
::
|
||||||
|
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
- 基于 Nuxt 4 , Content v3 , Nuxt UI Pro 构建的文档系统。
|
||||||
|
- 完美支持 Markdown 和 相关扩展。
|
||||||
|
- 和 Vue 组件高度集成。
|
||||||
|
- 支持搜索,由Content v3 赋能。
|
||||||
|
- 支持多主题,使用Nuxt UI Pro。
|
||||||
|
- 开源且免费。
|
||||||
|
- 支持移动端。
|
||||||
|
|
||||||
|
## 致谢
|
||||||
|
|
||||||
|
- Nuxt Content:为 Vue 开发者简化内容管理。
|
||||||
|
- Nuxt UI Pro :文档系统 UI 组件。
|
||||||
|
- Docus:获取灵感及一些文档组件源代码。
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
Reference in New Issue
Block a user