Browse Source

docs: update README to match current project state

main
Mohan 1 month ago
parent
commit
f945ad701f
  1. 240
      readme.md

240
readme.md

@ -0,0 +1,240 @@
# 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` 双重前缀):
```ts
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. 快速开始(本地开发)
```bash
# 前置: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 代理请求后端:
```ts
// vite.config.ts
server: {
proxy: {
'/api': { target: 'http://localhost:9480', changeOrigin: true },
'/uploads': { target: 'http://localhost:9480', changeOrigin: true }
}
}
```
---
## 8. 关键注意事项(红线)
### 8.1 契约驱动纪律
1. **禁止手写 API 类型**,必须从 `openapi.yaml` 生成(`npm run api:generate`)。
2. 后端契约更新后,先 `chore(api-gen): regenerate from openapi.yaml` 再对接。
3. **禁止直接 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/*` 被守卫拦截跳登录页
Loading…
Cancel
Save