# hello-blog **Repository Path**: dkbnull/hello-blog ## Basic Information - **Project Name**: hello-blog - **Description**: 个人博客系统,用于分享技术文章、开发笔记与生活感悟。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: https://blog.wbnull.cn - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-11 - **Last Updated**: 2026-07-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Hello Blog
Hello Blog

--- ## 项目简介 Hello Blog 是一个基于 Vue 3 + Vite 构建的个人博客系统,用于分享技术文章、开发笔记与生活感悟。 ## 功能特性 ### 📝 文章管理 - 文章分类浏览 - 文章标签筛选 - 支持 HTML 和 Markdown 两种格式文章展示 - 文章内容缓存,避免重复请求 - 文章与分类运行时动态加载,新增文章无需编译(fetch `categories.json` + 各分类 `meta.json`) ### 🔍 搜索功能 - 全站模糊搜索,支持按标题、分类、标签匹配 - 独立搜索结果页面 ### 🎨 界面设计 - 响应式布局,适配桌面端/移动端 - 深色/浅色模式切换(状态持久化至 localStorage) - CSS 变量统一主题配色(主题色 #42b883) - 卡片式设计,简洁美观 - 默认布局组件(Header + Main + Footer + BackToTop) ### ⚡ 性能优化 - 路由懒加载 - 构建资源自动哈希 - Vite 手动分包(vue/markdown 独立 chunk) - API 与组件自动导入(unplugin-auto-import / unplugin-vue-components) ### 🔎 SEO 优化 - 构建时注入 SEO 元标签(description、keywords、OG、Twitter Card) - 构建时注入 JSON-LD 结构化数据(WebSite + SearchAction) - 运行时路由级 SEO 元信息自动更新 - 文章详情页动态 SEO - Canonical URL 设置 ### 📊 数据统计 - 百度统计集成(整站 PV/UV) - 页面浏览自动上报 - 自定义事件上报支持 - 文章点击量统计(基于 countapi.mileshilliard.com 第三方计数服务) - 文章卡片与详情页同步展示点击量 - 同一会话防刷:基于 sessionStorage,刷新页面不重复计数 ### 📄 分页与排序 - 文章列表分页(每页 10 篇) - 按日期升序/降序排序 ## 技术栈 | 技术 | 版本 | 说明 | |--------------------------|--------|-------------| | Vue | 3.5.30 | 前端框架 | | Vue Router | 5.0.3 | 路由管理 | | Pinia | 3.0.4 | 状态管理 | | Vite | 8.0.8 | 构建工具 | | @vitejs/plugin-vue | 6.0.2 | Vue SFC 编译 | | marked | 17.0.4 | Markdown 解析 | | unplugin-auto-import | 21.0.0 | API 自动导入 | | unplugin-vue-components | 32.0.0 | 组件自动导入 | | vite-plugin-vue-devtools | 8.1.1 | Vue 开发者工具 | ## 如何添加文章 文章与分类在**运行时**通过 fetch `categories.json` + 各分类 `meta.json` 动态加载,新增文章无需编译,刷新页面即可生效。 ### 1. 新增文章 1. 将文章文件放入对应分类目录,命名格式为 `{id}-{title}.html` 或 `{id}-{title}.md`: ``` public/articles/ ├── frontend/ │ ├── 01-Vue 3 新特性详解.html │ └── 02-TypeScript 入门指南.html ├── backend/ │ ├── 01-Node.js 性能优化技巧.html │ └── ... └── ... ``` - `id`:文章在分类下的唯一标识(如 01、02),按倒序排列展示 - `title`:文章标题,需与文件名中 `-` 后的部分一致 2. 在该分类的 `meta.json` 中添加一条文章记录: ```json { "articles": { "02": { "title": "TypeScript 入门指南", "ext": "html", "date": "2026-06-28", "author": "null", "tags": ["TypeScript", "前端"], "image": "typescript.svg" } } } ``` | 字段 | 类型 | 必填 | 说明 | |----------|----------|------|--------------------------------------------| | `title` | string | 是 | 文章标题,需与文件名一致 | | `ext` | string | 是 | 文件扩展名(`html` 或 `md`) | | `date` | string | 是 | 发布日期(YYYY-MM-DD) | | `author` | string | 否 | 作者,默认 `null` | | `tags` | string[] | 否 | 标签数组,未配置时继承分类默认 tags | | `image` | string | 是 | 封面图文件名,放在 `public/images/{分类}/` | 3. 将封面图放入 `public/images/{分类}/` 目录: ``` public/images/ ├── frontend/ │ ├── vue3.svg │ └── typescript.svg └── backend/ └── nodejs.svg ``` `meta.json` 中填写文件名即可,运行时自动解析为 `/images/{分类}/{文件名}`。 ### 2. 新增分类 1. 在 `public/articles/` 下创建分类目录(目录名即分类 id),并添加 `meta.json`: ```json { "articles": {} } ``` 2. 在 `public/articles/categories.json` 添加分类配置: ```json { "categories": [ { "id": "frontend", "name": "前端开发", "icon": "frontend.svg", "image": "frontend.png", "tags": ["前端"] } ] } ``` - `icon`:分类图标,放在 `public/icons/` 目录,填写文件名 - `image`:分类默认封面图,放在 `public/images/{分类}/` 目录,填写文件名 - `tags`:分类默认标签,文章未配置 tags 时继承 3. `icon` 字段支持三种写法:文件名(`frontend.svg` → 解析为 `/icons/frontend.svg`)、`/` 开头的 public 路径、完整 URL。 ### 3. 数据加载机制 - 应用启动时(`App.vue` 的 `onMounted`)调用 `loadArticlesData()` - 并发 fetch `categories.json` + 所有分类的 `meta.json` - 数据存入 `ref`,组件通过 `computed` 自动响应更新 - 加载过程中 Sidebar 和 Home 显示 loading 动画 - 文章内容(HTML/MD 文件)在访问详情页时按需 fetch,并缓存避免重复请求 ## 许可证 Apache License 2.0 ---