You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
11 KiB
11 KiB
Mach-CMS 前端项目 README(readme-front)
仓库:
mach-cms-frontend| 责任方:Agent2 状态:开发中 | 当前契约:OpenAPI v0.3.1(以openapi.yaml为准)
1. 项目简介
Mach-CMS 前端是 CMS 的 Vue 3 + TypeScript 单页应用,独立仓库,消费后端 mach-cms-backend 的 REST API,包含前台(文章浏览/搜索/评论/点赞)与管理后台(文章/标签/评论/用户管理)两大部分,整体采用宋韵风格(SongUI) UI 主题,内置暗色模式。
前端遵循契约驱动开发(CDD):所有 API 类型与客户端代码由 openapi.yaml 经 OpenAPI Generator 生成,禁止手写类型。
2. 技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| Vue | 3.5+ | 框架(<script setup lang="ts">) |
| TypeScript | 5.6+ | 严格模式 |
| Vite | 5.4+ | 构建工具 |
| Vue Router | 4.5+ | 路由 + 权限守卫 |
| Pinia | 2.3+ | 状态管理(认证等) |
| Axios | 1.7+ | HTTP 客户端(统一拦截器) |
| OpenAPI Generator | 7.6.0 | 从 YAML 生成 TS 类型 + API 客户端(typescript-axios) |
| Quill.js | 2.0+ | 富文本编辑器(文章编辑) |
| github-markdown-css | 5.9+ | 文章详情页 GitHub 风格渲染 |
| DOMPurify | 3.2+ | HTML 过滤,防 XSS |
| marked / marked-highlight | 18.x / 2.2 | Markdown 渲染(旧文章兼容)+ 代码高亮 |
| highlight.js | 11.1+ | 代码块语法高亮 |
| lxgw-wenkai-webfont | 1.7+ | 霞鹜文楷 Web 字体 |
| SongUI(内置组件) | — | 宋韵设计契约组件(src/components/Song* + song-theme.css) |
| Playwright | 1.62+ | 验收测试(scripts/acceptance/,devDependency) |
3. 项目结构
mach-cms-frontend/
├── openapitools.json # OpenAPI Generator 配置
├── openapi.yaml # API 契约(唯一事实来源)
├── vite.config.ts # dev proxy / 构建优化
├── scripts/acceptance/ # Playwright 验收测试脚本
└── src/
├── main.ts
├── App.vue
├── api/
│ └── client.ts # Axios 实例 + 拦截器 + 全部 API 客户端导出(唯一入口)
├── stores/
│ └── auth.ts # Pinia 认证 store
├── router/
│ └── index.ts # 路由 + 守卫(requiresAuth / requiresAdmin)+ SEO
├── generated/
│ └── api/ # ⚠️ 生成代码,禁止手改(单文件输出)
│ ├── api.ts # 所有 API 类与 TS 类型(合并单文件)
│ ├── base.ts / configuration.ts / common.ts / index.ts
│ └── ...
├── composables/
│ ├── useApi.ts # 泛型请求封装(loading / error / 分页)
│ └── useTheme.ts # 明暗主题切换(localStorage 持久化)
├── utils/
│ ├── markdown.ts # marked + 代码高亮 + DOMPurify 渲染
│ ├── readingTime.ts # 阅读时间估计
│ └── seo.ts # document.title + OpenGraph meta
├── styles/
│ ├── song-theme.css # SongUI 设计令牌(天青昼 / 黛墨夜)
│ └── markdown-override.css # 文章渲染样式覆盖
├── assets/
│ └── markdown-override.css
├── views/ # 页面组件
│ ├── HomeView.vue # 首页
│ ├── LoginView.vue # 登录
│ ├── RegisterView.vue # 注册
│ ├── ArticleDetailView.vue # 文章详情(评论区、Star)
│ ├── SearchView.vue # 搜索(标签推荐 + 热门文章)
│ ├── NotFoundView.vue # 404
│ └── admin/
│ ├── AdminLayout.vue # 管理后台布局(顶部置顶 bar)
│ ├── ArticleListView.vue # 文章管理表格(图标操作)
│ ├── ArticleEditorView.vue # 文章编辑(Quill.js + 自动保存)
│ ├── TagListView.vue # 标签管理
│ ├── CommentReviewView.vue # 评论审核(待审核列表)
│ └── UserListView.vue # 用户管理(角色/状态)
└── components/ # 通用组件
├── ArticleCard.vue
├── ArticleMetaBar.vue
├── CommentSection.vue
├── Pagination.vue
├── QuillEditor.vue
├── TagCloud.vue
└── Song*(SongButton / SongCard / SongInput / SongTag) # SongUI 基础组件
注:OpenAPI Generator 的
typescript-axios为单文件输出(所有类型合并到api.ts),类名为单数(如CommentApi而非CommentsApi),属生成器正常行为,禁止手动改类名。
4. API 客户端(src/api/client.ts)
全部实例化于 client.ts,basePath 固定为 ''(配合 Vite 代理,避免 /api/api 双重前缀):
export const publicApi = new PublicApi(config, '', axiosInstance)
export const authApi = new AuthApi(config, '', axiosInstance)
export const articleApi = new ArticleApi(config, '', axiosInstance)
export const articleAdminApi = new ArticleAdminApi(config, '', axiosInstance)
export const tagApi = new TagApi(config, '', axiosInstance)
export const tagAdminApi = new TagAdminApi(config, '', axiosInstance)
export const mediaApi = new MediaApi(config, '', axiosInstance)
export const searchApi = new SearchApi(config, '', axiosInstance)
export const commentApi = new CommentApi(config, '', axiosInstance)
export const commentAdminApi = new CommentAdminApi(config, '', axiosInstance)
export const userApi = new UserApi(config, '', axiosInstance)
5. 路由一览(src/router/index.ts)
| 路径 | 组件 | 守卫 |
|---|---|---|
/ |
HomeView | — |
/post/:slug |
ArticleDetailView | — |
/search |
SearchView | — |
/login / /register |
LoginView / RegisterView | guestOnly |
/admin |
AdminLayout(重定向 /admin/articles) |
requiresAuth |
/admin/articles |
ArticleListView | requiresAuth |
/admin/articles/new /admin/articles/edit/:id |
ArticleEditorView | requiresAuth |
/admin/tags |
TagListView | requiresAuth |
/admin/users |
UserListView | requiresAdmin |
/admin/comments |
CommentReviewView | requiresAdmin |
/:pathMatch(.*)* |
NotFoundView | — |
6. 核心功能
| 区域 | 功能 |
|---|---|
| 前台 | 文章列表 / 详情 / 全文搜索 / 标签云 / 热门文章 / 阅读时间估计 |
| 评论区 | 发表评论(免登录,提交后 PENDING 待审核)、登录态自动填充昵称邮箱(只读)、时间线样式、折叠表单 |
| Star 点赞 | 文章 / 评论点赞,未登录点击提示并跳登录页 |
| 认证 | 登录 / 注册 / 登出,Access 过期静默刷新(401 自动 refresh) |
| 管理后台 | 文章 CRUD + 发布/归档(图标操作)、标签管理、评论审核(通过/驳回/删除)、用户管理(角色/状态)、媒体上传 |
| 编辑器 | Quill 富文本 + 60s 自动保存 + 离线检测;草稿按 id 加载 |
| SEO | OpenGraph meta 注入、document.title 随路由更新 |
| 体验 | 宋韵主题、暗色模式、水波纹装饰、GitHub 风格文章渲染、404 页面 |
7. 快速开始(本地开发)
# 前置:Node.js 20+,后端已启动
npm install
# 生成 API 客户端(每次 openapi.yaml 更新后执行)
npm run api:generate
# 开发启动(默认端口 5173)
npm run dev
# 构建(vue-tsc 类型检查 + vite build)
npm run build
# 验收测试(Playwright,需先 npm run build 或 dev)
node scripts/acceptance/acc_*.cjs
开发环境通过 Vite 代理请求后端:
// vite.config.ts
server: {
proxy: {
'/api': { target: 'http://localhost:9480', changeOrigin: true },
'/uploads': { target: 'http://localhost:9480', changeOrigin: true }
}
}
8. 关键注意事项(红线)
8.1 契约驱动纪律
- 禁止手写 API 类型,必须从
openapi.yaml生成(npm run api:generate)。 - 后端契约更新后,先
chore(api-gen): regenerate from openapi.yaml再对接。 - 禁止直接 import axios,统一走
src/api/client.ts导出的实例。
8.2 basePath 纪律(易错点)
生成代码默认带 /api 前缀,叠加 Vite 代理会变成 /api/api/xxx。每次重新生成代码后,检查 client.ts 中 API 实例化的 basePath 必须为 ''(见第 4 节)。
8.3 代码规范
| # | 规则 |
|---|---|
| 1 | 组件统一 <script setup lang="ts"> |
| 2 | 异步操作必须 try/catch,错误统一 Toast/Notification 提示 |
| 3 | 路由参数用 useRoute(),类型安全 |
| 4 | 图片上传用 FormData,Content-Type 由浏览器自动设置 |
| 5 | 所有 API 调用带 loading 状态(禁用按钮 / 骨架屏 / spinner) |
| 6 | 渲染用户内容(评论、文章)必须经 DOMPurify 过滤,防 XSS |
| 7 | 文章内容渲染用 github-markdown-css 的 .markdown-body 类 |
| 8 | 标题字体用 Noto Serif SC(思源宋体)回退系统宋体 |
| 9 | 颜色使用 SongUI 设计令牌(--song-* 变量),对比度 ≥ 4.5:1 |
8.4 Git 规范
- 直接基于
main开发,commit 后 30 秒内立即 push。 - 格式:
type(scope): subject(Conventional Commits)。 - 前端 scope:
page/component/store/api/router/type/asset/config/contract。 - 提交前必须
npm run build通过,少量多次(单 commit 单意图,文件 ≤ 10)。 - 提交顺序:
feat(contract)(架构方)→ 后端实现 →chore(api-gen)→feat(page/component)。
9. 与后端联调
- 契约对账:以 Swagger UI(
http://localhost:9480/swagger-ui.html)为准,前后端各自对照openapi.yaml自查。 - 开发代理:本地前端 →
localhost:9480;生产经 Nginx:9434反代/api/。 - 认证流程:登录成功后将 access/refresh Token 存入 localStorage,请求拦截器自动携带
Authorization: Bearer。 - 401 处理:响应拦截器自动用 refreshToken 换新 accessToken 并重放请求;刷新失败清除 Token 并跳转登录页。
- 未登录访问后台:路由守卫跳转
/login;非管理员访问/admin/users、/admin/comments被拦截回/admin/articles。
10. 验收自查
npm run api:generate成功,生成src/generated/api/npm run dev无 TS 类型错误,npm run build通过- 能调通
/api/public/health - 登录 Token 正确入库(localStorage),401 自动刷新
- 文章列表 / 详情 / 搜索 / 标签云 / 评论区 / Star 全部可用
- 后台文章管理(图标操作)、标签管理、评论审核、用户管理可用
- 未登录访问
/admin/*被守卫拦截跳登录页