分离blog和docs的布局

This commit is contained in:
2025-08-07 15:52:23 +08:00
parent df43c1845e
commit bf0add6dc6
8 changed files with 581 additions and 1 deletions

View File

@@ -0,0 +1,155 @@
<script setup lang="ts">
// import type { NavigationMenuItem } from '@nuxt/ui'
import type { ContentNavigationItem } from '@nuxt/content'
const navigation = inject<Ref<ContentNavigationItem[]>>('blogNavigation')
// 提取 blog 目录下的子目录作为顶级导航
const blogNavigation = 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
})
const isSettingsOpen = ref(false)
const isLoginModalOpen = ref(false)
const isRegisterModalOpen = ref(false)
// const { header } = useAppConfig();
// 定义 props 来接收侧边栏状态和切换函数
interface Props {
isSidebarOpen?: boolean
toggleSidebar?: () => void
}
const Props = withDefaults(defineProps<Props>(), {
isSidebarOpen: false,
toggleSidebar: () => { }
})
// 登录注册函数
const handleLoginRegister = (type: 'login' | 'register') => {
if (type === 'login') {
isLoginModalOpen.value = true
} else if (type === 'register') {
isRegisterModalOpen.value = true
}
}
</script>
<template>
<UHeader
toggle-side="left"
title="Estel Docs"
mode="modal"
class="bg-gray-50 dark:bg-gray-900"
>
<template #title>
<h6 />
</template>
<template #body>
<LogoPro class="h-5 w-auto mb-4" />
<DocsAsideLeftTop />
<div class="mt-4 mb-4 border-t border-gray-200 dark:border-gray-700 w-9/10 mx-5" />
<UContentNavigation
highlight
:navigation="blogNavigation"
color="primary"
type="single"
variant="pill"
/>
</template>
<template #right>
<UContentSearchButton class="lg:hidden" />
<UColorModeButton />
<button
class=" p-2 rounded-md text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
title="页面设置"
@click="isSettingsOpen = !isSettingsOpen"
>
<svg
class="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
</button>
<UTooltip
text="Open on GitHub"
:kbds="['meta', 'G']"
>
<UButton
color="neutral"
variant="ghost"
to="https://github.com/estel-li"
target="_blank"
icon="simple-icons-github"
aria-label="GitHub"
/>
</UTooltip>
<div class="flex items-center space-x-2">
<button
class="px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors"
@click="handleLoginRegister('login')"
>
登录
</button>
<button
class="text-sm font-medium text-white bg-primary rounded-md px-3 py-2 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition-colors"
@click="handleLoginRegister('register')"
>
注册
</button>
</div>
</template>
</UHeader>
<!-- Theme Settings Panel -->
<ThemeSettings
:is-open="isSettingsOpen"
@close="isSettingsOpen = false"
/>
<!-- 登录模态框 -->
<UModal
v-model:open="isLoginModalOpen"
title="登录"
:dismissible="false"
>
<template #body>
<authLogin />
</template>
</UModal>
<!-- 注册模态框 -->
<UModal
v-model:open="isRegisterModalOpen"
title="注册"
:dismissible="false"
>
<template #body>
<authRegister />
</template>
</UModal>
</template>

View File

@@ -0,0 +1,40 @@
<template>
<div class="relative w-full h-64 md:h-80 lg:h-96 overflow-hidden rounded-xl">
<!-- 背景图片 -->
<NuxtImg
src="https://lijue-me.oss-cn-chengdu.aliyuncs.com/%E8%83%8C%E6%99%AF.jpg"
alt="Blog Hero"
class="w-full h-full object-cover"
placeholder
loading="lazy"
sizes="100vw sm:50vw md:33vw"
/>
<!-- 渐变遮罩 -->
<!-- <div class="absolute inset-0 bg-gradient-to-r from-black/60 via-black/40 to-transparent"></div> -->
<!-- 内容区域 -->
<!-- <div class="absolute inset-0 flex items-center justify-start p-8">
<div class="max-w-2xl">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-white mb-4">
博客文章
</h1>
<p class="text-lg md:text-xl text-gray-200 mb-6">
分享技术见解和心得体会
</p>
<div class="flex items-center gap-4 text-white/80">
<div class="flex items-center gap-2">
<UIcon name="lucide-pen-tool" size="20" />
<span class="text-sm">技术分享</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="lucide-calendar" size="20" />
<span class="text-sm">持续更新</span>
</div>
</div>
</div>
</div> -->
</div>
</template>

View File

@@ -0,0 +1,155 @@
<script setup lang="ts">
// import type { NavigationMenuItem } from '@nuxt/ui'
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
})
const isSettingsOpen = ref(false)
const isLoginModalOpen = ref(false)
const isRegisterModalOpen = ref(false)
// const { header } = useAppConfig();
// 定义 props 来接收侧边栏状态和切换函数
interface Props {
isSidebarOpen?: boolean
toggleSidebar?: () => void
}
const Props = withDefaults(defineProps<Props>(), {
isSidebarOpen: false,
toggleSidebar: () => { }
})
// 登录注册函数
const handleLoginRegister = (type: 'login' | 'register') => {
if (type === 'login') {
isLoginModalOpen.value = true
} else if (type === 'register') {
isRegisterModalOpen.value = true
}
}
</script>
<template>
<UHeader
toggle-side="left"
title="Estel Docs"
mode="modal"
class="bg-gray-50 dark:bg-gray-900"
>
<template #title>
<h6 />
</template>
<template #body>
<LogoPro class="h-5 w-auto mb-4" />
<DocsAsideLeftTop />
<div class="mt-4 mb-4 border-t border-gray-200 dark:border-gray-700 w-9/10 mx-5" />
<UContentNavigation
highlight
:navigation="docsNavigation"
color="primary"
type="single"
variant="pill"
/>
</template>
<template #right>
<UContentSearchButton class="lg:hidden" />
<UColorModeButton />
<button
class=" p-2 rounded-md text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
title="页面设置"
@click="isSettingsOpen = !isSettingsOpen"
>
<svg
class="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
</button>
<UTooltip
text="Open on GitHub"
:kbds="['meta', 'G']"
>
<UButton
color="neutral"
variant="ghost"
to="https://github.com/estel-li"
target="_blank"
icon="simple-icons-github"
aria-label="GitHub"
/>
</UTooltip>
<div class="flex items-center space-x-2">
<button
class="px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors"
@click="handleLoginRegister('login')"
>
登录
</button>
<button
class="text-sm font-medium text-white bg-primary rounded-md px-3 py-2 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition-colors"
@click="handleLoginRegister('register')"
>
注册
</button>
</div>
</template>
</UHeader>
<!-- Theme Settings Panel -->
<ThemeSettings
:is-open="isSettingsOpen"
@close="isSettingsOpen = false"
/>
<!-- 登录模态框 -->
<UModal
v-model:open="isLoginModalOpen"
title="登录"
:dismissible="false"
>
<template #body>
<authLogin />
</template>
</UModal>
<!-- 注册模态框 -->
<UModal
v-model:open="isRegisterModalOpen"
title="注册"
:dismissible="false"
>
<template #body>
<authRegister />
</template>
</UModal>
</template>

View File

@@ -16,7 +16,7 @@
<!-- Right Content Area --> <!-- Right Content Area -->
<div class="flex-1 lg:ml-64 flex flex-col min-w-0"> <div class="flex-1 lg:ml-64 flex flex-col min-w-0">
<!-- Fixed Header --> <!-- Fixed Header -->
<AppHeader <BlogHeader
:is-sidebar-open="isSidebarOpen" :is-sidebar-open="isSidebarOpen"
:toggle-sidebar="toggleSidebar" :toggle-sidebar="toggleSidebar"
/> />

View File

@@ -19,6 +19,7 @@ useSeoMeta({
<template> <template>
<div> <div>
<!-- <BlogHero /> -->
<BlogIndexBlog /> <BlogIndexBlog />
</div> </div>
</template> </template>

View File

@@ -2,6 +2,7 @@
title: 记录技术栈 title: 记录技术栈
description: 记录日常开发中遇到的技术问题和解决方案 description: 记录日常开发中遇到的技术问题和解决方案
date: 2025-08-07 date: 2025-08-07
img: https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250806105153532.png
navigation: navigation:
icon: lucide-house icon: lucide-house
--- ---

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@@ -0,0 +1,228 @@
# Estel Docs 文档系统 - 项目简介
## 📋 项目概述
**Estel Docs** 是一个基于 Nuxt 4 构建的现代化文档系统,采用简约设计但功能强大。系统支持文档管理和博客发布,提供完整的 Markdown 内容管理解决方案。
## 🏗️ 技术架构
### 核心技术栈
- **框架**: Nuxt 4 (Vue 3 + Vite)
- **UI 组件库**: Nuxt UI Pro
- **内容管理**: Nuxt Content 3
- **图片优化**: Nuxt Image
- **图标系统**: Lucide + Iconify
- **类型安全**: TypeScript
- **包管理**: pnpm
- **代码规范**: ESLint
### 主要模块
```typescript
modules: [
'@nuxt/eslint', // 代码规范
'@nuxt/image', // 图片优化
'@nuxt/ui-pro', // UI 组件库
'@nuxt/content', // 内容管理
'nuxt-og-image', // Open Graph 图片生成
'@nuxt/fonts', // 字体优化
'nuxt-llms' // AI 集成
]
```
## 📁 项目结构
```
项目根目录/
├── app/ # 应用核心代码
│ ├── components/ # Vue 组件
│ │ ├── blog/ # 博客相关组件
│ │ ├── docs/ # 文档相关组件
│ │ └── shared/ # 共享组件
│ ├── layouts/ # 布局组件
│ │ ├── blog.vue # 博客布局
│ │ └── docs.vue # 文档布局
│ ├── pages/ # 页面路由
│ └── composables/ # 组合式函数
├── content/ # 内容目录
│ ├── docs/ # 文档内容
│ │ ├── 1.简单文档/
│ │ └── 2.无人自助系统/
│ └── blog/ # 博客内容
│ ├── 1.技术栈/
│ ├── 2.AI/
│ └── 3.生活/
├── public/ # 静态资源
└── nuxt.config.ts # Nuxt 配置
```
## 🎯 核心功能
### 1. 文档系统 (Docs)
- **Markdown 支持**: 完整的 Markdown 语法支持
- **目录导航**: 自动生成文档目录结构
- **搜索功能**: 全文搜索和导航搜索
- **代码高亮**: 语法高亮和代码块
- **响应式设计**: 适配各种设备屏幕
- **深色模式**: 支持明暗主题切换
### 2. 博客系统 (Blog)
- **文章列表**: 响应式卡片布局展示
- **图片预览**: 支持文章封面图片
- **分类管理**: 按技术栈、AI、生活等分类
- **时间显示**: 文章发布时间展示
- **原始内容查看**: 支持查看 Markdown 原始内容
### 3. 内容管理
- **双集合架构**: docs 和 blog 两个独立内容集合
- **Schema 验证**: 使用 Zod 进行内容结构验证
- **导航配置**: 支持 .navigation.yml 文件配置
- **SEO 优化**: 自动生成 Open Graph 图片
## 🎨 前端样式与呈现
### 设计理念
- **简约现代**: 采用简洁的设计语言
- **响应式优先**: 移动端优先的响应式设计
- **可访问性**: 遵循 WCAG 可访问性标准
- **性能优化**: 图片懒加载、代码分割等
### 主要样式特点
1. **卡片式布局**: 博客文章采用卡片式展示
2. **渐变效果**: Hero 区域使用渐变背景
3. **悬停动画**: 丰富的交互动画效果
4. **圆角设计**: 统一的圆角设计语言
5. **阴影层次**: 合理的阴影层次营造深度感
### 组件系统
- **BlogHero**: 博客首页 Hero 区域
- **BlogHeader**: 博客页面头部导航
- **IndexBlog**: 博客文章列表组件
- **AppSidebar**: 侧边栏导航组件
- **AppHeader**: 顶部导航组件
## 🔧 实现方式
### 1. 内容管理实现
```typescript
// content.config.ts
collections: {
docs: defineCollection({
type: 'page',
source: { include: 'docs/**' },
schema: z.object({
rawbody: z.string(),
links: z.array(z.object({
label: z.string(),
icon: z.string(),
to: z.string()
})).optional()
})
}),
blog: defineCollection({
type: 'page',
source: { include: 'blog/**' },
schema: z.object({
rawbody: z.string(),
img: z.string(),
date: z.string()
})
})
}
```
### 2. 路由系统
- **动态路由**: `[...slug].vue` 处理所有内容页面
- **布局切换**: 根据路径自动选择 docs 或 blog 布局
- **原始内容**: `/raw/[...slug]` 查看 Markdown 原始内容
### 3. 数据查询
```typescript
// 查询文档内容
const { data: page } = await useAsyncData(
`page-${route.path}`,
() => queryCollection('docs').path(queryPath.value).first()
)
// 查询博客文章
const { data: articles } = await useAsyncData(
'blog-articles',
() => queryCollection('blog')
.select('path', 'title', 'description', 'img', 'date')
.where('path', 'NOT LIKE', '%navigation%')
.all()
)
```
## ⚠️ 注意事项
### 1. 开发环境
- **Node.js 版本**: 建议使用 Node.js 18+
- **包管理器**: 使用 pnpm 作为包管理器
- **TypeScript**: 严格模式,注意类型安全
### 2. 内容管理
- **文件命名**: 使用数字前缀确保排序 (如: `1.技术栈/`)
- **导航配置**: 在目录下创建 `.navigation.yml` 配置导航
- **图片路径**: 使用相对路径或外部 CDN 链接
### 3. 部署相关
- **静态生成**: 支持静态站点生成 (SSG)
- **服务端渲染**: 支持服务端渲染 (SSR)
- **环境变量**: 注意配置必要的环境变量
### 4. 性能优化
- **图片优化**: 使用 Nuxt Image 进行图片优化
- **代码分割**: 自动代码分割和懒加载
- **缓存策略**: 合理配置缓存策略
## 🚀 还需要什么
### 1. 功能增强
- [ ] **评论系统**: 集成评论功能
- [ ] **用户认证**: 添加用户登录注册
- [ ] **内容编辑**: 在线 Markdown 编辑器
- [ ] **版本控制**: 内容版本管理
- [ ] **多语言**: 国际化支持
### 2. 性能优化
- [ ] **CDN 配置**: 配置 CDN 加速
- [ ] **缓存策略**: 优化缓存配置
- [ ] **图片压缩**: 自动图片压缩
- [ ] **代码分割**: 进一步优化代码分割
### 3. 开发工具
- [ ] **自动化测试**: 添加单元测试和集成测试
- [ ] **CI/CD**: 配置自动化部署流程
- [ ] **监控系统**: 添加性能监控
- [ ] **错误追踪**: 集成错误追踪系统
### 4. 内容管理
- [ ] **内容备份**: 自动内容备份策略
- [ ] **SEO 优化**: 进一步优化 SEO
- [ ] **搜索增强**: 改进搜索功能
- [ ] **内容导入**: 支持批量内容导入
### 5. 用户体验
- [ ] **PWA 支持**: 添加 PWA 功能
- [ ] **离线支持**: 离线内容访问
- [ ] **阅读模式**: 专注阅读模式
- [ ] **分享功能**: 社交媒体分享
## 📊 技术指标
- **构建时间**: < 30s
- **首屏加载**: < 2s
- **Lighthouse 评分**: > 90
- **SEO 评分**: > 95
- **可访问性**: > 90
## 🔗 相关链接
- **项目仓库**: https://github.com/estel-li/estel-docs
- **在线演示**: https://docs.jiwei.xin
- **个人博客**: https://lijue.me
- **技术文档**: https://nuxt.com/docs
---
*最后更新: 2024年12月*