项目概览与进度
介绍自建全栈内容站点的架构选型、三阶段演进规划与当前交付状态,重点说明 V1 迭代的关键实现。
- 采用 Nuxt 4 SSR/SPA + NestJS 11 + MySQL 8/Redis 7 全栈架构,Docker Compose 单机部署
- 当前处于 Phase 2 · V1 阶段,10 个模块已交付 9 个,仅剩相册模块待开始
- 关键实现包括分类层级树、FULLTEXT ngram 中文检索、sharp 图片处理与访问统计聚合
- 通过设计令牌统一管理六套主题,XSS 防护覆盖服务端净化、前端转义与端到端验证
- 部署采用 nginx 网关统一入口,WebHook 驱动增量发布,应用容器通过 bridge 网络直连数据库
摘要
本站是一套自建的全栈内容站点,由前台(Nuxt 4 SSR)、管理后台(Nuxt 4 SPA)、REST API(NestJS 11)与 MySQL 8 / Redis 7 组成,通过 Docker Compose 部署在单台 Linux 云主机,并由代码托管平台 WebHook 驱动增量发布。
本文分两部分:一是架构与技术选型,二是三阶段演进与当前交付状态。
| 维度 | 现状 |
|---|---|
| 当前阶段 | Phase 2 · V1 迭代收尾(10 个模块已交付 9 个) |
| 上线状态 | 已上线:skyblue.fun(前台)+ admin.skyblue.fun(后台),HTTPS / 反向代理 / CI/CD 就绪 |
| 技术栈 | Nuxt 4.5 · Vue 3.5 · Element Plus 2.13 · NestJS 11 · TypeORM 0.3 · MySQL 8 · Redis 7 |
| 数据规模 | 43 张表、17 个后端模块、6 套主题、70+ 篇项目文档 |
| 下一阶段 | V1-7 相册、V2 实验模块(AI / 日志管理)转正 |
一、项目概况
站点围绕三类内容场景构建:文章、作品、关于页。功能边界明确——不引入多租户与插件机制,复杂度集中在内容模型、访问性能与工程可维护性上。
flowchart TD
U["访客 / 搜索引擎"] --> F["前台 SSR"]
A["管理后台"] --> B["NestJS API"]
F --> B
B --> DB[("MySQL 8")]
B --> R[("Redis 7")]
B --> S["uploads"]
三类场景对应三组数据模型:content_article 承载长文(Markdown、分类、标签、全文索引),portfolio_project 承载作品(技术栈、精选位),site_* 系列承载站点级配置(品牌、友链、访问统计、留言)。分类、标签、评论、上传等通用能力由三类内容共用,避免重复实现。
二、技术栈与架构
2.1 技术选型
| 层 | 技术 | 版本 | 选型依据 |
|---|---|---|---|
| 前台 | Nuxt 4(SSR) | 4.5 | 首屏直出,按路由生成 SEO 元信息 |
| 后台 | Nuxt 4(SPA) | 4.5 | 与前台隔离部署,复用同一套 Vue 生态与组件库 |
| UI | Element Plus | 2.13 | 面向中后台的表单、表格与弹窗组件 |
| 状态 | Pinia + 持久化插件 | 4.x | 登录态与主题偏好跨刷新保留 |
| API | NestJS | 11 | 模块化 + 守卫 / 拦截器 / 管道,按业务域切分 |
| ORM | TypeORM | 0.3 | 实体驱动建模,synchronize: false 手工管理表结构 |
| 数据 | MySQL 8 / Redis 7 | — | MySQL 承担事务与 FULLTEXTngram 检索;Redis 承担路由缓存与限流计数 |
2.2 仓库结构与模块划分
flowchart TD
R["monorepo / pnpm workspace"] --> F["apps/sky-frontend-nuxt<br/>SSR 前台"]
R --> A["apps/sky-admin-nuxt<br/>SPA 后台"]
R --> S["server/sky-server-nest<br/>REST API"]
R --> D["docs<br/>规划 · 规范 · 进度 · 待办"]
R --> O["deploy.sh / webhook<br/>部署与自动化"]
S --> M1["modules/content<br/>文章 · 分类 · 标签"]
S --> M2["modules/comment · message<br/>评论 · 留言"]
S --> M3["modules/visit · search<br/>统计 · 检索"]
S --> M4["modules/system · auth<br/>菜单 · 角色 · 认证"]
接口契约由后端统一定义,前台与后台各自维护 api/ 目录下的类型和调用封装。两端不共享运行时代码,但遵循同一套契约:前台可以独立调整渲染方式,后台可以独立发版。
2.3 请求链路
sequenceDiagram
autonumber
participant U as 浏览器
participant N as nginx 443
participant F as 前台 SSR
participant B as NestJS
participant M as MySQL / Redis
U->>N: GET /posts?view=timeline
N->>F: 反向代理至前台容器端口
F->>B: GET /sky/posts/timeline
Note over N,B: /sky/* 重写为 /api/*
B->>M: 查询(缓存优先)
M-->>B: 结果集
B-->>F: Result { code, data }
F-->>U: SSR HTML + 水合
设计上有两点:前端统一使用 /sky 相对前缀,调整后端地址只需修改网关配置;响应统一封装为 Result 结构(5 位字符错误码),前端错误处理集中在拦截器一处。
三、阶段规划与演进
flowchart LR
P1["Phase 1 · MVP<br/>基础设施与内容闭环"] --> P2["Phase 2 · V1<br/>功能增强"]
P2 --> P3["Phase 3 · V2<br/>能力扩展"]
| 阶段 | 时间区间 | 目标 | 状态 | 交付范围 |
|---|---|---|---|---|
| Phase 1 · MVP | 2026-09-17 ~ 09-23 | 建立可运行的完整站点 | 已完成 | 首页 / 博文 / 作品 / 关于 / 后台 / Docker 上线 |
| Phase 2 · V1 | 2026-09-22 ~ 10-21 | 完善核心业务链路 | 进行中(9/10) | 评论、博文增强、主题、SEO、文件系统、友链、检查、功能完善、访问统计 |
| Phase 3 · V2 | 2026-10-22 起 | 扩展平台能力 | 规划中 | EXP 实验模块、AI 模块、PWA、性能优化 |
%%{init: {"gantt": {"fontSize": 14, "sectionFontSize": 14, "barHeight": 22, "barGap": 6, "topPadding": 45, "leftPadding": 110, "gridLineStartPadding": 24, "numberSectionStyles": 3}, "themeCSS": ".taskText{fill:#f8fafc;stroke:#0f172a;stroke-width:3px;paint-order:stroke;font-weight:600}.taskTextOutsideRight,.taskTextOutsideLeft{fill:#f8fafc;stroke:#0f172a;stroke-width:3px;paint-order:stroke}"}}%%
gantt
title 阶段推进节奏(2026-09 起)
dateFormat YYYY-MM-DD
axisFormat %m/%d
tickInterval 1week
todayMarker off
section MVP
搭建 / 首页 / 风格 / 博文 / 上线 :done, p1, 2026-09-17, 2026-09-23
section V1
评论 / 博文增强 / SEO / 文件 / 友链 :done, p2a, 2026-09-22, 2026-10-20
搜索 / 统计 / 检查清理 / CI-CD :done, p2b, 2026-09-28, 2026-10-21
相册(V1-7) :p2c, 2026-10-21, 7d
section V2
实验模块 EXP-1 / EXP-3 :done, p3a, 2026-10-19, 2026-10-21
AI 原型 EXP-2 / PWA / 性能 :p3b, 2026-10-22, 21d
规划文档 SPEC-00 采用版本化维护(当前 v5.19),每次结构调整保留更新记录,便于回溯阶段划分的依据。
四、Phase 1 · MVP 交付
MVP 拆分为六个步骤,每步都有独立方案文档与验收产出。
| 步骤 | 内容 | 关键产出 |
|---|---|---|
| 第 1 步 | 工程搭建 | Monorepo、规范配置、可启动骨架 |
| 第 2 步 | 首页与设计体系 | 首页结构、基础组件库、响应式栅格 |
| 第 3 步 | UI 风格设计 | 六套主题、设计令牌、组件二次封装 |
| 第 4 步 | 博文系统 | 前后台联调闭环,支持写作与发布 |
| 第 5 步 | 上线部署 | Docker Compose、域名、HTTPS、反向代理 |
| 第 6 步 | 回归与复盘 | 回归清单、经验沉淀 |
flowchart TD
S1["1 工程搭建"] --> S2["2 首页与设计体系"]
S2 --> S3["3 UI 风格设计"]
S3 --> S4["4 博文系统"]
S4 --> S5["5 上线部署"]
S5 --> S6["6 回归与复盘"]
该阶段的主要工程产出是设计令牌:颜色、间距、圆角、字号统一收敛为 CSS 变量(--space-* 11 档基元 + --stack-* 语义层)。后续新增主题或调整版式只需修改令牌,不涉及页面级改动;V1 阶段的卡片间距统一即基于此完成全站校准。
五、Phase 2 · V1 迭代
5.1 模块交付状态
| 模块 | 内容 | 状态 | 进度 |
|---|---|---|---|
| V1-1 | 评论留言系统(楼中楼 / 先审后发 / 邮件通知) | 完成 | ██████████ 11/11 |
| V1-2 | 博文增强(时间线 / 标签状态 / 分类层级) | 完成 | ██████████ 3/3 |
| V1-3 | 主题调整(六主题 + 深浅色) | 完成 | ██████████ 收口 |
| V1-4 | 多主题 SEO(sitemap / robots / RSS / JSON-LD) | 完成 | ██████████ 5/5 |
| V1-5 | 文件系统与图片处理(webp / 三档 / 水印) | 完成 | ██████████ 收口 |
| V1-6 | 友链(申请审核 / 点击统计 / 死链检查) | 完成 | ██████████ 8/8 |
| V1-7 | 相册(后台 CRUD + 前台页面) | 待开始 | ░░░░░░░░░░ 0/3 |
| V1-8 | 上线检查与清理(mock 收敛 / 安全复核) | 完成 | ██████████ 2/2 |
| V1-9 | 功能完善(FULLTEXT 检索 / XSS / 邮件重试) | 完成 | ██████████ 3/3 |
| V1-10 | 访问统计(埋点 / 看板 / 聚合 / IP 掩码) | 完成 | ██████████ 3/3 |
5.2 关键实现
分类层级。content_category 具备 parent_id / level / path 字段,服务层在创建与移动节点时重算祖先链;成环检测采用「父级祖先链命中自身即拒绝」;删除前校验子分类与文章引用。查询侧先解析整棵子树再以 IN (...) 过滤,父级分类可命中全部子级文章,层级语义在检索层真正生效。
全文检索。早期实现为 title / excerpt 的 LIKE 匹配,中文场景命中率不足;V1-9 升级为 MySQL FULLTEXT ... WITH PARSER ngram,并提供独立接口 GET /api/search 与前台 /search 页面。
图片链路。服务端接入 sharp,统一转 webp 并生成 320 / 768 / 1600 三档,按场景叠加水印;存储层抽象 StorageDriver,本地目录与对象存储可切换;跨环境同步由脚本完成,服务器作为唯一运行时数据源。
访问统计。埋点上报 PV、UV 与浏览时长,原始记录写入 site_visit_log;每日 00:10 由 @Cron 将前一日数据聚合至汇总表(先删后插,幂等,支持手动补跑)。IP 处理提供两个开关:VISIT_IP_STORE 控制是否落库,VISIT_IP_MASK 控制是否仅保留网段;UV 哈希仍基于原始 IP,保证去重准确。
内容渲染管线:
flowchart TD
A["后台编辑器"] --> B["保存 / 发布"]
B --> C["DTO 校验"]
C --> D["markdown-it 渲染"]
D --> E["xss 白名单净化"]
E --> F[("content_article")]
F --> G["SSR 输出"]
XSS 防护覆盖三段:服务端渲染时白名单净化、前端兜底转义、以及「提交 → 审核 → 展示 → 清理」的端到端验证。
5.3 分类层级的前后台职责划分
flowchart TD
T["后台分类树<br/>父级选择 · 成环校验"] --> V["重算 level / path<br/>级联刷新后代"]
V --> DB[("content_category")]
DB --> Q["按父级解析子树"]
Q --> FE["前台列表筛选"]
FE --> D1["详情页分类标签"]
D1 -->|"?category=slug"| FE
2026-10-21 对该链路做过一次完整核对:后端与后台维护能力完整,缺口集中在前台消费端(URL 参数未被列表页读取、作品列表缺少分类筛选)。随后按「参数闭环 + 作品筛选」补齐;独立分类页与后台层级列经评估后未实施。
六、部署与自动化
6.1 运行拓扑
说明:宿主端口以占位符表示(
<*_PORT>),真实值见部署环境.env,不写入文档。
| 容器 | 端口映射 | 职责 |
|---|---|---|
mysql |
<DB_PORT> → 3306 |
业务库 app_db,43 张表 |
cache-redis |
<CACHE_PORT> → 6379 |
路由缓存、限流计数 |
gateway-nginx |
80 / 443 | 唯一公网入口,静态资源与反向代理 |
sky-backend |
<API_PORT> → 3000 |
REST API,含 Swagger |
sky-frontend |
<WEB_PORT> → 3000 |
SSR 前台,根域 |
sky-admin |
<ADMIN_PORT> → 80 |
SPA 后台,子域 |
应用容器通过自建 bridge 网络按容器名直连数据库与缓存,不依赖宿主机端口。MySQL、Redis 与 nginx 复用主机已有容器,本项目的编排仅管理三个应用容器。
6.2 自动部署流程
flowchart TD
A["git push origin master"] --> B["代码托管平台 WebHook"]
B --> C["nginx 443<br/>/hooks/deploy"]
C --> D["sky-webhook(内网端口)<br/>密钥与事件校验"]
D --> E["deploy.sh<br/>按改动范围构建"]
E --> F["docker compose up -d<br/>健康检查"]
变更范围与重建服务的对应关系:
| 变更路径 | 重建服务 |
|---|---|
server/** |
sky-backend |
apps/sky-frontend-nuxt/** |
sky-frontend |
apps/sky-admin-nuxt/** |
sky-admin |
仅docs/** |
跳过构建 |
约束有三条:公网仅暴露 443;密钥文件不入版本库;发布为增量构建,纯文档提交不触发重建。回滚通过回退镜像完成。
七、质量保障机制
flowchart TD
A["需求登记<br/>待办列表"] --> B["方案文档"]
B --> C["实现与自测"]
C --> D["代码实况核对"]
D --> E{"与文档一致"}
E -->|否| F["回写文档 / 补齐缺口"]
E -->|是| G["进度台账收口"]
F --> G
G --> A
具体机制:
- 错误码统一:5 位字符
ResultCode,业务错误具备稳定语义,前端无需依赖 HTTP 状态推断。 - 入参校验:DTO +
class-validator,字段白名单转换,非法参数在进入 Service 前拦截。 - 权限到按钮:菜单驱动动态路由,按钮级权限串(如
experiment:journal:save)落库,前端路由与后端守卫同源。 - 核对留证:进度表中的「已完成」尽量附带
文件:行号证据,避免文档与实现脱节。 - 脚本化验收:友链模块通过脚本执行 68 项断言,覆盖接口与数据一致性。
八、Phase 3 · V2 规划
V2 采用实验模块(EXP)先行策略:新能力先在沙盒中验证,成熟后转为正式模块,不占用主线编号。
flowchart TD
E1["EXP-1 占位<br/>菜单与路由链路"] --> E2["EXP-2 AI 原型<br/>摘要 · 问答 · 写作"]
E1 --> E3["EXP-3 日志管理<br/>任务 · 看板 · 统计"]
E2 --> R1["V2-1 AI 正式模块<br/>限流 · 计费 · 内容安全"]
E3 --> R2["能力沉淀<br/>按需转正"]
R1 --> R3["V2-2 PWA · V2-3 性能优化"]
| 编号 | 方向 | 状态 |
|---|---|---|
| EXP-1 | 试验模块占位(菜单与路由链路) | 已交付(后端接口保留 TODO) |
| EXP-2 | AI 功能原型(摘要 / 问答 / 写作助手) | 规划中 |
| EXP-3 | 日志管理系统 | 已交付(5 表 2 视图 + 完整接口) |
| V2-1 | AI 正式模块(承接 EXP-2) | 待办 |
| V2-2 | PWA(离线 / 安装) | 待办 |
| V2-3 | 性能优化(Core Web Vitals) | 待办 |
EXP-3 是沙盒转正的典型案例:最初作为实验模块中的第二项试验,验证完成后独立为顶级菜单 /work-log(任务面板 / 任务计划 / 日志配置 / 数据统计),页面组件按路由末段分流页签。
九、里程碑
| 日期 | 事件 |
|---|---|
| 2026-09-17 | 项目立项,确定六步交付路线 |
| 2026-09-23 | MVP 上线,上线后缺陷当日修复 |
| 2026-09-28 | V1 清单扩展至 10 项,搜索与统计从 V2 前移 |
| 2026-10-19 | 实验模块落地,日志管理系统启动 |
| 2026-10-20 | V1-2 / V1-9 收口,V1 仅剩相册 |
| 2026-10-21 | 移动端单层滚动统一;EXP-3 独立为/work-log |
十、复盘与计划
关键决策
- 先上线再迭代。MVP 第 5 步完成部署,后续功能基于真实访问反馈推进。
- 设计令牌先行。主题、间距、字号变量化,视觉调整以修改令牌为主。
- 文档与代码核对。进度表要求附带实证,降低文档超前于实现的风险。
- 沙盒机制。EXP 不占主线编号,验证成本可控,成熟后转正。
经验教训
- 文档超前于代码。曾多次出现文档标记完成而实现仅部分落地,后续通过强制核对收敛。
- 移动端滚动模型。桌面端「固定外壳 + 内层滚动」在触屏设备上会导致内层滚动到底后整页无法继续滚动,最终统一为小屏单层滚动。
- 检索方案评估不足。初期以 LIKE 支撑搜索,中文分词命中率不达预期,后续补充 FULLTEXT
ngram。
后续计划
- 完成 V1-7 相册(后台 CRUD + 前台
/albums),V1 阶段收尾。 - 推进 EXP-2 AI 原型:先完成摘要 / 问答 / 写作助手三项能力,再处理限流、计费与内容安全。
- PWA 与 Core Web Vitals:先采集基线,再优化图片与首屏关键路径。
数据口径:阶段与模块状态取自
SPEC-00-开工方案.md(v5.19)与PROG-02-V1迭代进度.md(2026-10-21);部署与拓扑取自仓库根README.md;

评论 0
还没有评论,快来抢沙发吧~