修改页面布局大修改

This commit is contained in:
2025-08-07 13:39:05 +08:00
parent 41e273ed07
commit 25470fc7f8
23 changed files with 1238 additions and 33 deletions

View 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>

View 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>

View File

@@ -10,10 +10,23 @@ const items = ref<NavigationMenuItem[][]>([
target: '_blank'
},
{
label: '博客',
icon: 'lucide-pen-line',
to: '/blog'
},
{
label: '简单文档',
icon: 'lucide-book',
to: '/docs'
},
{
label: '组件速查',
icon: 'lucide-box',
to: '/简单文档/components/api'
to: '/docs/简单文档/components/api'
},
{
label: '关于',

View File

@@ -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="{
' text-blue-600 dark:text-blue-400 ':
$route.path === '/'
useRoute().path === '/'
}"
>
<Icon
@@ -54,7 +54,7 @@
<div class="mt-6 flex items-center justify-start pl-4 w-full pb-3">
<UContentNavigation
highlight
:navigation="navigation"
:navigation="docsNavigation"
color="primary"
type="single"
variant="pill"
@@ -70,4 +70,16 @@
import type { ContentNavigationItem } from '@nuxt/content'
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>