Skip to content

静态博客与提示词管理后台重构设计 ​

日期:2026-09-22 适用工作树:codex/blog-backend-admin

1. 背景与目标 ​

现有实现把个人 VitePress 静态博客扩展成了数据库驱动 CMS:文章、分类、标签、站点配置、GitHub 项目、媒体、发布快照和导出都在后台形成了第二份数据源。这与项目实际维护方式不符,也产生了数据库到 Markdown/JSON 的同步、发布和回滚复杂度。

本次重构采用与主流静态内容站一致的核心模式:Markdown、JSON 和静态资源是公开博客的唯一内容源,VitePress 在构建阶段生成页面,线上不通过 Spring Boot 实时读取文章正文。

后台不再承担博客 CMS 职责。后台改为最小的 React + Spring Boot 管理系统,保留单管理员认证、MySQL 和 MinIO,并在本轮实现私有的“提示词 + 一张生成图片”上传管理功能。

2. 总体架构 ​

2.1 公开博客 ​

text
Markdown / JSON / docs/public 资源
              ↓
VitePress 与现有构建脚本
              ↓
静态 HTML / CSS / JavaScript
              ↓
现有静态发布流程

公开博客不依赖 Spring Boot 获取文章、分类、标签、站点配置或 GitHub 项目数据。版本历史和回滚由 Git 负责。

2.2 管理系统 ​

text
React 管理前端
      ↓ 同源 /api
Spring Boot 最小后端
      ├── 单管理员认证与会话 → MySQL
      ├── 提示词元数据 → MySQL
      └── 提示词生成图片 → MinIO 私有桶

管理系统与公开博客之间不设置发布快照、数据库导出、自动部署或回滚链路。本轮上传的提示词记录仅在登录后的管理后台可见。

3. 保留范围 ​

3.1 静态博客 ​

  • 现有 VitePress 页面、Markdown、JSON 和 docs/public 资源。
  • 搜索索引、RSS、飞书同步、GitHub 项目更新和图片处理脚本。
  • docs/public/github-projects.json 及 npm run add-github-project。
  • 当前静态提示词档案及其公开页面,不迁移到新后台。

3.2 后端 ​

  • Spring Boot 工程骨架。
  • 单管理员登录、退出、本人修改密码。
  • 会话验证、CSRF、BCrypt 密码哈希和登录失败锁定。
  • 统一 API 响应、安全异常处理和必要基础配置。
  • MySQL、MinIO 连接和 Docker 编排。
  • 新增提示词上传管理 API。

3.3 管理前端 ​

  • 管理前端继续保留,但从 Vue/Element Plus 重建为 React。
  • 技术栈:React、TypeScript、Vite、React Router、Axios、Ant Design。
  • 不引入 Redux;登录状态使用轻量 Context 或等价最小方案。
  • 页面包括登录、提示词列表、新建、详情和本人修改密码。

4. 删除范围 ​

4.1 业务功能 ​

  • 数据库版文章管理、草稿、发布、归档和修订历史。
  • 分类管理与标签管理。
  • 站点配置管理。
  • GitHub 项目后台管理。
  • Dashboard。
  • 文章媒体库与原通用上传业务。
  • 发布快照、文章公开版本、后台数据导出。
  • 后台自动部署、发布队列和回滚规划。
  • 多管理员列表、创建、启用、禁用和代重置密码。
  • 数据库业务操作日志。

4.2 代码和文档 ​

  • 上述业务对应的 Controller、Service、Repository、Mapper、请求/响应模型和测试。
  • 现有 Vue 页面、路由、状态代码和 Element Plus 依赖。
  • scripts/export-backend-snapshot.mjs 及专用测试。
  • 旧 CMS 阶段报告、完成报告和 Vue 开发计划。
  • 与废弃 CMS 业务相关的数据库迁移和表。

MinIO 容器、存储卷和已有对象不得删除。

5. 认证设计 ​

5.1 保留能力 ​

  • 单管理员登录与退出。
  • 当前管理员修改本人密码。
  • BCrypt 密码哈希。
  • 服务端会话。
  • CSRF 防护。
  • 登录失败阈值与临时锁定。
  • 修改密码后使旧认证状态失效或要求重新登录。

5.2 删除能力 ​

  • 多管理员管理 API。
  • 管理员角色、权限组和复杂 RBAC。
  • 数据库业务审计日志。

首个管理员通过安全的本地环境配置引导创建。前端不得把密码或长期认证令牌保存到 localStorage。

6. 提示词管理数据模型 ​

一条提示词严格对应一张生成图片。记录创建后不可编辑;上传错误时永久删除并重新创建。

提示词记录包含:

  • id:UUID。
  • prompt_text:提示词正文,使用长文本类型。
  • prompt_hash:规范化提示词的稳定哈希,唯一。
  • object_key:MinIO 私有对象键。
  • mime_type:从真实文件内容识别的格式。
  • width、height:图片像素尺寸。
  • file_size:字节数。
  • image_sha256:图片内容哈希,仅记录,不设置唯一约束。
  • delete_state:用于可重试永久删除流程。
  • created_at:创建时间。

不保存以下字段:

  • 来源链接与来源标题。
  • 提示词标题。
  • 生成模型。
  • 用户手工填写的尺寸或质量。
  • 签名预览 URL。

7. 提示词与图片规则 ​

7.1 提示词 ​

  • 去除首尾空白后不能为空。
  • 最大 50,000 个字符。
  • 保留正文内部换行和空白。
  • 规范化仅包括统一换行为 \n 并去除首尾空白;不得折叠或改写正文内部空白。
  • 对规范化后的完整正文计算哈希。
  • 完全相同的提示词禁止重复创建,返回 HTTP 409。

7.2 图片 ​

  • 每次只上传一张图片,不支持批量上传。
  • 允许 PNG、JPEG 和 WebP。
  • 根据文件头和解码结果识别真实格式,不信任文件扩展名。
  • 单张最大 10 MB。
  • 宽度和高度分别不超过 8192 像素。
  • 总像素不超过 4000 万。
  • 不自动压缩或改写原图。
  • 同一图片允许用于不同提示词;图片哈希不参与去重。

8. MinIO 设计 ​

  • 使用专用私有桶 prompt-results。
  • 禁止匿名访问。
  • 对象键由后端生成,不使用用户原始文件名作为路径。
  • 后台预览由后端生成 15 分钟有效的签名 URL。
  • 签名 URL 不写入数据库。
  • 现有 MinIO 卷和对象保持不动。

9. API 设计 ​

所有提示词接口仅允许已登录管理员访问,并要求写请求通过 CSRF 校验。

  • POST /api/admin/prompts:multipart 创建一条提示词并上传一张图片。
  • GET /api/admin/prompts:分页列表,支持提示词关键词搜索。
  • GET /api/admin/prompts/{id}:查看完整记录及临时预览地址。
  • DELETE /api/admin/prompts/{id}:永久删除记录与 MinIO 图片。

列表规则:

  • 服务端分页。
  • 默认每页 20 条,可选择每页 50 条。
  • 按创建时间倒序。
  • 搜索使用 MySQL 简单正文模糊匹配。
  • 不支持分类、标签、高级筛选、批量导入、修改或匿名公开 API。

10. React 管理界面 ​

10.1 设计原则与视觉系统 ​

管理端采用轻量、内容优先的专业工具风格,不套用营销落地页布局,不使用重型侧边栏、玻璃拟态、大面积渐变或装饰性动效。界面只提供当前单管理员与提示词管理所需的导航和操作。

视觉令牌:

  • 主色:#2563EB。
  • 页面背景:#F8FAFC。
  • 内容表面:#FFFFFF。
  • 主文字:#0F172A。
  • 次要文字:#475569。
  • 边框:#E2E8F0。
  • 危险操作:#DC2626。
  • 当前只实现浅色主题;所有业务组件使用语义化主题令牌,不在组件内散落原始颜色值。
  • 字体优先使用本机 Noto Sans SC、PingFang SC、Microsoft YaHei 与系统无衬线字体,不依赖 Google Fonts 网络加载。
  • 间距使用 4/8 像素节奏,正文移动端不小于 16 像素。
  • 图标统一使用 Phosphor 线性图标,不使用 emoji 充当结构或操作图标。

10.2 导航与路由 ​

管理端采用顶部导航,不为当前少量功能引入侧边栏。顶部显示产品名“提示词管理”、当前“提示词”入口和账号菜单;当前入口必须有明确的文字与视觉选中状态。退出放在账号菜单中,并与普通导航操作分开。

  • /login:管理员登录。
  • /prompts:提示词分页列表和关键词搜索。
  • /prompts/new:填写提示词、选择图片、本地预览并上传。
  • /prompts/:id:查看完整提示词、图片和技术信息。
  • /account/password:修改本人密码。

登录成功后直接进入 /prompts,不保留空 Dashboard。

路由切换后将键盘与读屏焦点移到主内容标题。由详情页返回列表时恢复原搜索条件、页码和滚动位置。会话过期后跳转登录页,并在重新登录后返回原目标页面。

10.3 登录与账号 ​

  • 登录页使用居中的单列卡片,桌面端最大宽度约 420 像素,移动端保留页面边距。
  • 用户名和密码始终显示可关联的文字标签,不使用占位符代替标签。
  • 密码输入支持系统密码管理器、自动填充、粘贴与显示/隐藏切换。
  • 字段错误就近展示,并通过 aria-describedby 关联;提交错误使用 role="alert" 通知读屏软件。
  • 提交期间按钮禁用并显示加载状态,防止重复提交。
  • 修改密码页沿用相同表单规则;成功后按认证策略重新登录。

10.4 提示词列表 ​

  • 顶部工具区提供关键词搜索与唯一主操作“上传提示词”。搜索提交、清空与加载状态必须可见。
  • 内容使用图片卡片网格:桌面 3 列、平板 2 列、手机 1 列。
  • 卡片展示图片缩略图、提示词摘要、宽高、文件大小和创建时间;卡片主体进入详情页。
  • 删除入口始终可见或可由明确的更多操作按钮访问,不依赖鼠标悬停才出现。
  • 图片容器预留稳定比例空间以避免布局跳动;首屏外图片延迟加载。
  • 分页位于列表底部,默认 20 条,可切换 50 条;页码变化后焦点与滚动行为可预测。
  • 空列表、无搜索结果、加载失败分别提供明确说明与下一步操作。

10.5 新建提示词 ​

  • 桌面端使用左右分栏:左侧表单,右侧图片预览;移动端改为上下排列,提示词优先、图片预览随后。
  • 表单只包含提示词正文和单张图片,不包含标题、来源、模型、尺寸或质量输入。
  • 提示词输入展示固定标签、50,000 字符计数与规范化说明。
  • 图片区域同时提供拖放和普通文件选择按钮;拖放不是唯一上传方式。
  • 选择文件后立即显示本地预览以及真实可获得的文件名、大小和图片尺寸,但最终格式与尺寸以后端校验结果为准。
  • 页面只有一个主提交按钮。提交期间锁定重复操作并显示进度反馈。
  • 上传失败后保留提示词正文、本地图片预览和浏览器仍可保留的文件选择状态,错误信息说明原因和修复方式。
  • 多字段失败时,在页面顶部显示可聚焦的错误摘要,并保留字段旁的内联错误;摘要项可跳转到对应字段。

10.6 提示词详情与删除 ​

  • 桌面端以大图和完整提示词双栏展示,移动端上下排列。
  • 展示图片、完整提示词、宽高、文件大小、MIME 类型、图片哈希和创建时间。
  • 提供“复制提示词”操作并给出非抢焦点的成功反馈。
  • 永久删除放在与普通操作分离的危险区域,使用危险色和文字共同表达风险。
  • 删除前弹出二次确认,明确说明提示词与 MinIO 图片都会永久删除且不可恢复。
  • 确认弹窗打开后焦点进入弹窗并被约束在其中;取消是默认安全操作,关闭后焦点回到触发按钮。

10.7 响应式、动效与可访问性 ​

  • 验证宽度至少覆盖 375、768、1024 和 1440 像素,不允许移动端横向滚动。
  • 移动端输入控件高度和主要点击目标不小于 44 像素,交互目标之间保留至少 8 像素间距。
  • 所有功能必须可用键盘完成,焦点顺序与视觉顺序一致;交互控件显示至少 2 像素清晰焦点环。
  • 正文和背景的正常文本对比度不低于 4.5:1;状态不得只依靠颜色表达。
  • 有意义的图片提供描述性替代文本;装饰性图标从辅助技术中隐藏,独立图标按钮提供可访问名称。
  • 过渡仅用于反馈状态变化,时长约 120–200 毫秒,只动画 transform 与 opacity;不使用 GSAP、滚动揭示或装饰性入场编排。
  • 尊重 prefers-reduced-motion,减少或关闭非必要过渡。
  • Toast 使用 aria-live="polite" 且不抢焦点;错误必须同时包含原因和恢复办法。

11. 一致性与错误处理 ​

11.1 创建 ​

text
认证和 CSRF
→ 校验提示词与唯一性
→ 校验图片内容、格式、大小和分辨率
→ 生成 UUID 与对象键
→ 上传 MinIO
→ 写入 MySQL

若 MinIO 上传成功但数据库写入失败,后端立即补偿删除已上传对象。

11.2 永久删除 ​

text
数据库标记待删除
→ 删除 MinIO 对象
→ 删除数据库记录

删除必须幂等且可重试。MinIO 暂时失败时不得让数据库记录直接消失;已经进入删除流程的记录不出现在普通列表中。

11.3 HTTP 错误 ​

  • 400:提示词或图片校验失败。
  • 401:未登录或会话失效。
  • 403:CSRF 或权限校验失败。
  • 404:记录不存在。
  • 409:提示词重复或账号状态冲突。
  • 503:MinIO 暂时不可用。
  • 500:未预期服务端异常,响应不得泄露堆栈或密钥。

12. 数据库迁移与隔离环境 ​

后台尚未正式发布,因此不追加永久保留旧 CMS 历史的删除迁移。重写迁移为最小认证和提示词结构,并重建明确的隔离测试数据库 coding_blog_qa。

允许清除 coding_blog_qa 中现有测试数据。不得操作其他 MySQL 容器或数据库。管理员通过引导流程重新创建。

13. 测试与验收 ​

13.1 后端 ​

  • 登录、退出、修改密码、会话失效和 CSRF。
  • 提示词为空、超长和重复冲突。
  • PNG、JPEG、WebP 正常上传。
  • 伪造格式、超 10 MB、超宽高或超总像素图片被拒绝。
  • 相同图片可配不同提示词上传。
  • 分页、创建时间倒序和关键词搜索。
  • 15 分钟签名预览。
  • 永久删除、幂等重试和 MinIO 失败路径。
  • 数据库写入失败后的 MinIO 补偿清理。

13.2 React 前端 ​

  • 未登录路由保护。
  • 登录、退出和修改密码。
  • 创建表单校验和本地图片预览。
  • 上传失败后保留用户输入。
  • 分页、搜索、详情和永久删除确认。
  • 返回列表时恢复搜索、页码和滚动位置。
  • 登录和上传表单的标签、错误关联、错误摘要与焦点管理。
  • 删除确认弹窗的键盘操作、焦点约束和焦点恢复。
  • 375、768、1024 和 1440 像素宽度下的关键布局。
  • prefers-reduced-motion 下不执行非必要过渡。

13.3 整体 ​

  • 重建 coding_blog_qa。
  • 初始化私有桶 prompt-results。
  • 后端全量测试通过。
  • React 测试与生产构建通过。
  • 静态博客原有测试与构建不受影响。
  • 浏览器真实验证登录、上传、查看、搜索、删除和修改密码。

仓库中与本次无关的既有测试失败必须单独列明,不得误报为本次回归。

14. 明确不在本轮范围 ​

  • 公开提示词 API 或公开页面接入。
  • 将新数据写入现有 gpt-image-prompts.json。
  • 导入现有静态提示词档案。
  • 一条提示词对应多张图片。
  • 编辑提示词或替换图片。
  • 批量上传、CSV 或 ZIP 导入。
  • 提示词标题、来源、模型、分类或标签。
  • 图片内容去重。
  • 后台博客文章、分类、标签和配置管理。
  • 自动部署、发布快照、导出和回滚。

15. 成功标准 ​

重构完成后,公开博客仍由 Markdown/JSON 静态构建;废弃 CMS 功能及其数据表不再存在;管理员可通过 React 后台安全登录,将一条不重复的提示词和一张合规图片保存到 MySQL 与私有 MinIO,并能分页搜索、查看和永久删除记录。

Last updated:

最后更新2026-09-22
觉得有帮助?把这个链接转给正在求职的朋友 · 用 Ctrl + K 全站搜索其它题