# daisy-garden **Repository Path**: xinlewang1/daisy-garden ## Basic Information - **Project Name**: daisy-garden - **Description**: 个人网站源码,欢迎访问! https://daisyle.cn/ - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-02 - **Last Updated**: 2026-05-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🌼 Daisy's Garden Daisy 的个人花园 —— 博客 + 项目集 + 用户/评论系统 + `/play/` 3D 互动入口。 > 域名 `daisyle.cn`(ICP 备案中) · 部署目标:阿里云 ECS + Nginx + Let's Encrypt SSL。 --- ## 功能一览 - **内容**:Markdown 博文 + 项目集(`@nuxt/content` 双主题代码高亮) - **用户系统**:注册 / 登录 / 资料编辑(昵称、签名、邮箱、网站)/ 自定义头像上传 / 密码修改 - **评论系统**:嵌套评论(一级回复)+ 评论点赞 + 实时头像(改头像后旧评论自动跟新)+ 软删除 + 博主徽章 - **互动统计**:文章点赞 + 浏览量(IP hash 24h 去重) - **氛围层**:和风天气联动(雨/雪/雾/云/晴 7 种粒子特效)+ 浮动花瓣 + 夜空 + 暗色模式自动切换 + 自定义光标 - **活动热力图**:基于 git 提交时间生成 GitHub 风格贡献图(about 页) - **3D 场景**:`/play/` 独立 Vite SPA 子路径挂载,由同仓库的 `studio` 构建生成 ## 技术栈 | 层 | 选型 | |---|---| | 框架 | Nuxt 3.21 · Vue 3.5 · Vite 7 · Nitro | | 语言 | TypeScript(strict) | | 样式 | Tailwind CSS · `@tailwindcss/typography` · 自定义 ANIME 色盘 | | 内容 | `@nuxt/content`(MDC + Shiki `github-light` / `github-dark-dimmed` 双主题) | | 状态 | `@vueuse/nuxt` · `@pinia/nuxt` | | 数据 | `better-sqlite3`(WAL 模式,单文件) | | 字体 | 本地 npm:Inter · Caveat · 霞鹜文楷 Lite —— 不走 CDN | | 主色 | 薰衣草紫 `#E8D7F5` | --- ## 快速开始 ```bash # 1. 安装依赖(postinstall 会自动 nuxt prepare) npm install # 2. 配置环境变量(至少填 QWeather key 才能解锁天气) cp .env.example .env # 3. 起开发服 npm run dev # http://localhost:3000 ``` 首次启动时,`server/utils/db.ts` 会自动创建 `data/blog.db` 并跑 schema 迁移。 ## 目录结构 ``` blog/ ├─ pages/ # 路由页面(首页/文章/项目/关于/账号) │ ├─ index.vue # Hero + 最新文章 + 入口卡 │ ├─ posts/{index,[slug]}.vue │ ├─ projects/{index,[slug]}.vue │ ├─ about.vue # 自我介绍 + 天气 + 活动热力图 │ └─ account.vue # 账号设置(头像 / 资料 / 密码) │ ├─ layouts/default.vue # 全局壳:Header / 弹窗 / 天气层 / Footer ├─ components/ # UI(顶层独立 + 子目录模块) │ ├─ UserAvatar.vue # 共享头像(fallback 链 + 博主徽章) │ ├─ PostCard.vue / BackToTop / ColorModeToggle / CustomCursor / ... │ ├─ auth/ # Modal(登录注册)+ UserMenu(头部菜单) │ ├─ comments/ # Section / Form / Item / Count / ViewCounter │ ├─ weather/ # Clouds / Fog / Lightning / Rain / Snow / Stars / SunGlow │ ├─ activity/Heatmap.vue │ ├─ likes/Button.vue │ └─ games/MiniMaze.vue # 首页迷你迷宫车(纯 Canvas 2D) │ ├─ composables/ # 前端 hooks │ ├─ useAuth.ts # 登录态 + 资料/密码/头像方法 │ ├─ useComments.ts # 评论 CRUD(CommentDTO) │ ├─ useLikeButton / usePostStats / useViews / useWeather │ ├─ server/ # Nitro │ ├─ api/ # 见下方 API 端点章节 │ └─ utils/ │ ├─ db.ts # sqlite 单例 + migrate / migrateAdditive │ ├─ auth.ts # 会话 / cookie / PublicUser │ ├─ avatar.ts # 头像存储 / magic byte 检测 / 删除 │ ├─ hash.ts # sha256 / md5 / ipHashFor │ └─ rate-limit.ts # 内存限流 │ ├─ content/ # @nuxt/content 源 │ ├─ posts/*.md │ └─ projects/*.md │ ├─ public/ # 静态资源(favicon / cursor / play 3D) │ ├─ play/ # studio 构建产物(npm run build:play 写入) │ └─ activity-data.json # prebuild 钩子生成 │ ├─ scripts/ # 构建辅助 │ ├─ build-activity-stats.mjs # 扫 git log 出热力图数据 │ └─ build-play.mjs # 编 studio 3D,拷到 public/play/ │ ├─ deploy/ # 部署相关 │ ├─ nginx/ # daisy-garden.conf · daisy-sidecar.conf │ └─ scripts/ # deploy.ps1(Windows 一键发布)+ setup-daisy-user.sh │ ├─ data/ # 运行时(gitignored) │ ├─ blog.db # sqlite 主库 │ └─ avatars/ # 用户上传头像 │ ├─ assets/css/tailwind.css # Tailwind 入口(含全局 prose 微调) ├─ tailwind.config.js # 色盘 · 字体栈 · 自定义动画 ├─ nuxt.config.ts # 模块 / runtimeConfig / Nitro 预渲染规则 └─ DEPLOYMENT.md # 完整部署手册 ``` ## 数据模型 `data/blog.db`(单文件)。所有表通过 `server/utils/db.ts` 自动迁移。 | 表 | 用途 | |---|---| | `users` | id / username / password_hash(scrypt salt:hash 双 hex)/ email / email_hash / website / created_at / last_login_at / **nickname** / **bio** / **avatar_url** | | `sessions` | UUID v4 cookie 的服务端备份 + 过期时间 | | `post_comments` | slug / parent_id(一级回复)/ user_id(匿名为 null)/ author 快照 / email_hash 快照 / content / ip_hash / is_deleted(软删) | | `comment_likes` | (comment_id, ip_hash) 唯一约束;CASCADE 删评论时一并清 | | `post_likes` | (slug, ip_hash) 唯一约束 | | `post_views` + `post_view_uniques` | 累计浏览 + 24h 去重 | > **快照 vs 实时**:评论作者名走快照(用户改昵称不影响旧评论的署名),头像 / email_hash 走实时 LEFT JOIN(改头像后旧评论自动同步)。 ## API 端点 | 模块 | 端点 | |---|---| | **认证** | `POST /api/auth/{register,login,logout}` · `GET /api/auth/me` | | **资料** | `PATCH /api/auth/profile` · `POST /api/auth/change-password` | | **头像** | `POST /api/auth/avatar`(multipart,含 magic byte 校验 + 旧文件清理)· `DELETE /api/auth/avatar` | | **头像服务** | `GET /api/avatars/[filename]`(读盘 + 长缓存) | | **评论** | `GET/POST /api/comments/[slug]`(GET 时 LEFT JOIN users 取实时头像) | | **点赞** | `GET/POST/DELETE /api/likes/post/[slug]` · `…/comment/[id]` | | **浏览** | `GET /api/views/[slug]` | | **管理** | `/api/admin/comments/*`(受 `NUXT_ADMIN_TOKEN` 保护) | | **杂项** | `GET /api/weather`(QWeather 代理)· `/api/geo` · `/api/stats` | > 写入端点(注册 / 评论 / 点赞 / 头像上传 / 资料修改)均经过 `server/utils/rate-limit.ts` 内存限流。 ## 环境变量 复制 `.env.example` 到 `.env` 后填入。运行时由 `nuxt.config.ts` 的 `runtimeConfig` 注入(`NUXT_XXX` → `xxx`)。 | 变量 | 默认 | 说明 | |---|---|---| | `NUXT_QWEATHER_KEY` | _空_ | QWeather API key(不填则天气接口返回错误) | | `NUXT_QWEATHER_API_HOST` | `devapi.qweather.com` | 2024+ 账号专属 host(如 `xxx.re.qweatherapi.com`) | | `NUXT_DB_PATH` | `data/blog.db` | sqlite 文件路径,生产建议指 ECS 持久卷 | | `NUXT_AVATARS_DIR` | `data/avatars` | 头像目录,同样建议持久卷 | | `NUXT_ADMIN_TOKEN` | _空_ | 空时禁用管理 DELETE 接口;生产用 `openssl rand -hex 32` | | `NUXT_PUBLIC_WEATHER_DEFAULT_LOCATION` | `121.47,31.23` | 默认天气位置(经度,纬度) | ## npm 脚本 | 命令 | 用途 | |---|---| | `npm run dev` | Nuxt 开发服 · `http://localhost:3000` | | `npm run build` | SSR 构建(Nitro 输出到 `.output/`) | | `npm run generate` | 静态生成(带 prebuild 钩子跑活动热力图) | | `npm run build:full` | studio 3D + Nuxt 一并打包 | | `npm run build:play` | 仅重建 `/play/` 3D 场景 | | `npm run preview` / `preview:dist` | 本地预览构建产物 | | `npm run stats:activity` | 单独刷新活动热力图数据 | | `npm run typecheck` | TypeScript 检查 | | `npm run deploy` / `deploy:fast` / `deploy:dryrun` | Windows → ECS 一键部署(PowerShell 脚本) | ## 部署 完整步骤见 [`DEPLOYMENT.md`](./DEPLOYMENT.md)。要点: - ECS 持久卷挂载到 `NUXT_DB_PATH` / `NUXT_AVATARS_DIR`,避免发布覆盖历史数据 - Nginx 反代 Nuxt(`3000`)+ 静态托管 `/play/`,配置在 `deploy/nginx/` - Let's Encrypt 通过 Certbot 自动续期 - 日常更新:本地 `npm run deploy`(构建 → rsync → 重启 PM2) ## 设计取舍备忘 - **头像 fallback 链**:自定义上传 → Gravatar(基于 email_hash) → 首字母色块 - **博主识别**:`users.id === 0`(第一个注册的用户),评论项渲染 🌼 徽章 - **`/play/` 不经 Nuxt 渲染**:`routeRules: { '/play/**': { prerender: false } }` + Nitro `prerender.ignore`,由 Nginx / 静态服务直出 - **字体本地化**:所有 webfont 走 `@fontsource/*` 与 `lxgw-wenkai-lite-webfont` npm 依赖,国内 ECS 首屏不依赖 jsDelivr