4 changed files with 286 additions and 12 deletions
@ -0,0 +1,228 @@ |
|||
# Agent2 Prompt: Mach-CMS Frontend Phase 2 Implementation |
|||
|
|||
## 你的角色 |
|||
你是前端开发 Agent,负责实现 Mach-CMS Phase 2 功能。你不是设计师,只按契约和规范实现功能。 |
|||
|
|||
## 契约文件(唯一真理来源) |
|||
后端仓库根目录下的 `openapi.yaml` 是你唯一的 API 规范。 |
|||
|
|||
## 技术栈 |
|||
- Vue 3.4+ |
|||
- TypeScript 5.4+(严格模式) |
|||
- Vite 5.2+ |
|||
- Vue Router 4.3+ |
|||
- Pinia 2.1+ |
|||
- Axios 1.7+ |
|||
- OpenAPI Generator 7.6.0 |
|||
- marked / markdown-it(Markdown 渲染) |
|||
- DOMPurify(XSS 防护) |
|||
- highlight.js 或 prismjs(代码高亮) |
|||
|
|||
## 项目状态 |
|||
Phase 1 已完成: |
|||
- OpenAPI 代码生成配置 |
|||
- Axios 客户端封装(含 401 自动刷新) |
|||
- Pinia auth store |
|||
- Vue Router + 路由守卫 |
|||
- 首页文章列表、文章详情、搜索页 |
|||
- 登录页、管理后台布局、文章列表/编辑器、标签管理 |
|||
|
|||
## 重要修正:basePath |
|||
|
|||
**`client.ts` 中所有 API 实例化时,basePath 必须传空字符串 `''`**: |
|||
|
|||
```typescript |
|||
export const authApi = new AuthApi(config, '', axiosInstance) |
|||
export const articlesApi = new ArticlesApi(config, '', axiosInstance) |
|||
export const articleAdminApi = new ArticleAdminApi(config, '', axiosInstance) |
|||
export const tagsApi = new TagsApi(config, '', axiosInstance) |
|||
export const mediaApi = new MediaApi(config, '', axiosInstance) |
|||
export const searchApi = new SearchApi(config, '', axiosInstance) |
|||
// Phase 2 新增 |
|||
export const commentsApi = new CommentsApi(config, '', axiosInstance) |
|||
export const commentAdminApi = new CommentAdminApi(config, '', axiosInstance) |
|||
export const userAdminApi = new UserAdminApi(config, '', axiosInstance) |
|||
``` |
|||
|
|||
**原因**:Vite 代理已配置 `/api` → `localhost:8080`,生成代码的 `BASE_PATH` 也是 `/api`,若不覆盖会导致 `/api/api/xxx`。 |
|||
|
|||
**纪律**:每次 `npm run api:generate` 后,检查 `client.ts` 中 basePath 是否为 `''`。 |
|||
|
|||
## 你的任务(按顺序执行,逐项验收) |
|||
|
|||
### Task 1: 重新生成 API 代码 |
|||
|
|||
后端更新 `openapi.yaml` 至 0.2.0 后,执行: |
|||
```bash |
|||
npm run api:generate |
|||
``` |
|||
|
|||
确认生成: |
|||
- `CommentResponse`, `CommentSubmitRequest` |
|||
- `UserInfo`, `UpdateRoleRequest` |
|||
- `CommentAdminApi`, `UserAdminApi` |
|||
- `StoredFile` 增加 `thumbnailUrl` |
|||
|
|||
### Task 2: 注册页面 |
|||
|
|||
文件:`src/views/RegisterView.vue` |
|||
- 路由 `/register` |
|||
- 表单:用户名(3-50 字符)、密码(6-100 字符)、确认密码、邮箱(可选) |
|||
- 前端校验:密码与确认密码一致 |
|||
- 调用 `authApi.register({ username, password, email })` |
|||
- 注册成功后自动调用 `authStore.login()` 并跳转 `/admin` |
|||
- 已登录用户访问 `/register` 自动跳转 `/admin` |
|||
|
|||
路由配置更新:`router/index.ts` 添加 `/register` 路由 |
|||
|
|||
### Task 3: 评论组件 |
|||
|
|||
文件:`src/components/CommentSection.vue` |
|||
- Props:`slug: string` |
|||
- 功能: |
|||
- 加载评论:`GET /api/articles/{slug}/comments` |
|||
- 展示评论列表(作者名、内容、时间) |
|||
- 评论提交表单:昵称(必填)、邮箱(可选)、内容(必填) |
|||
- 提交后提示"评论已提交,等待审核" |
|||
- 样式:简单即可,每条评论有分隔线 |
|||
|
|||
文件:`src/views/ArticleDetailView.vue` |
|||
- 底部引入 `<CommentSection :slug="slug" />` |
|||
|
|||
### Task 4: Markdown 渲染 + XSS 防护 |
|||
|
|||
```bash |
|||
npm install marked dompurify highlight.js |
|||
npm install -D @types/dompurify @types/marked |
|||
``` |
|||
|
|||
文件:`src/utils/markdown.ts` |
|||
```typescript |
|||
import { marked } from 'marked' |
|||
import DOMPurify from 'dompurify' |
|||
import hljs from 'highlight.js' |
|||
import 'highlight.js/styles/github-dark.css' |
|||
|
|||
marked.setOptions({ |
|||
highlight: (code, lang) => { |
|||
if (lang && hljs.getLanguage(lang)) { |
|||
return hljs.highlight(code, { language: lang }).value |
|||
} |
|||
return hljs.highlightAuto(code).value |
|||
} |
|||
}) |
|||
|
|||
export function renderMarkdown(content: string): string { |
|||
const rawHtml = marked.parse(content) as string |
|||
return DOMPurify.sanitize(rawHtml) |
|||
} |
|||
``` |
|||
|
|||
文件:`src/views/ArticleDetailView.vue` |
|||
- 文章内容用 `v-html="renderMarkdown(article.content)"` |
|||
- 引入 `highlight.js` 样式 |
|||
|
|||
### Task 5: 前台标签云 |
|||
|
|||
文件:`src/components/TagCloud.vue` |
|||
- 调用 `tagsApi.listTags()` |
|||
- 展示所有标签,标签大小按 `articleCount` 比例(简单实现:用不同 font-size class) |
|||
- 点击标签跳转首页并过滤该标签文章(可选,先实现展示即可) |
|||
|
|||
文件:`src/views/HomeView.vue` |
|||
- 侧边栏或底部引入 `<TagCloud />` |
|||
|
|||
### Task 6: 管理后台增强 |
|||
|
|||
#### 6.1 评论审核页 |
|||
文件:`src/views/admin/CommentReviewView.vue` |
|||
- 路由 `/admin/comments` |
|||
- 调用 `commentAdminApi.listPendingComments()` |
|||
- 表格:作者、邮箱、内容、文章标题、提交时间 |
|||
- 操作:通过、拒绝、删除 |
|||
- 通过后评论在前台显示 |
|||
|
|||
#### 6.2 用户管理页 |
|||
文件:`src/views/admin/UserListView.vue` |
|||
- 路由 `/admin/users` |
|||
- 调用 `userAdminApi.listUsers()` |
|||
- 表格:用户名、邮箱、角色、状态、注册时间 |
|||
- 操作:修改角色(下拉选择 ADMIN/EDITOR/VISITOR)、启用/禁用 |
|||
- **只有 ADMIN 可见此菜单项**(路由守卫或菜单条件渲染) |
|||
|
|||
#### 6.3 菜单更新 |
|||
文件:`src/views/admin/AdminLayout.vue` |
|||
- 侧边栏新增:评论审核、用户管理 |
|||
- 根据当前用户角色条件显示(先实现显示,权限由后端控制) |
|||
|
|||
### Task 7: 图片上传集成到编辑器 |
|||
|
|||
文件:`src/views/admin/ArticleEditorView.vue` |
|||
- 封面图:点击上传按钮 → `mediaApi.upload()` → 返回 url 填入表单 |
|||
- 内容区粘贴图片:监听 `paste` 事件,提取图片文件 → 上传 → 插入 Markdown 图片语法 `` |
|||
|
|||
## 代码规范(违反 = 拒收) |
|||
|
|||
| # | 规则 | |
|||
|---|------| |
|||
| 1 | **禁止手写 API 类型**,必须从 openapi.yaml 生成 | |
|||
| 2 | **禁止直接 import axios**,统一用 `src/api/client.ts` | |
|||
| 3 | 组件必须用 `<script setup lang="ts">` | |
|||
| 4 | API 响应必须用生成代码中的类型,禁止 `any` | |
|||
| 5 | 路由跳转用 `useRouter()`,禁止 `window.location`(除 401 跳转) | |
|||
| 6 | 异步操作必须 `try/catch`,错误用 alert 或控制台输出 | |
|||
| 7 | 图片上传用 `FormData`,Content-Type 让浏览器自动设置 | |
|||
| 8 | 集合默认 `[]`,禁止 `undefined` 作为列表值 | |
|||
| 9 | 路由参数用 `useRoute()` 获取 | |
|||
|
|||
## Git 规范(必须遵守) |
|||
|
|||
- 直接在 `main` 分支开发,commit 后立即 `git push origin main` |
|||
- Conventional Commits:`type(scope): subject` |
|||
- **单 commit 单意图**,文件 ≤ 10,行数 ≤ 200 |
|||
- **每次 commit 前 `npm run build` 通过(无 TS 错误)** |
|||
- 提交信息用英文、祈使句、首字母小写、≤ 50 字符 |
|||
|
|||
**Scope(前端)**:`page` `component` `store` `api` `router` `type` `asset` `config` `contract` |
|||
|
|||
**示例**: |
|||
```bash |
|||
feat(page): add register view with form validation |
|||
feat(component): add CommentSection for article detail |
|||
feat(component): add TagCloud with article count sizing |
|||
feat(page): add comment review page in admin |
|||
feat(page): add user management page with role editing |
|||
chore(api-gen): regenerate types from openapi.yaml v0.2.0 |
|||
fix(api): set basePath to empty string to avoid /api/api |
|||
``` |
|||
|
|||
## 与 CDD 结合的提交顺序 |
|||
|
|||
1. `chore(api-gen): regenerate types from openapi.yaml v0.2.0`(契约更新后) |
|||
2. `feat(page): add register view` |
|||
3. `feat(component): add CommentSection with submit form` |
|||
4. `feat(component): add markdown renderer with syntax highlight` |
|||
5. `feat(component): add TagCloud component` |
|||
6. `feat(page): add admin comment review page` |
|||
7. `feat(page): add admin user management page` |
|||
8. `feat(component): integrate image upload in article editor` |
|||
|
|||
## 验收标准 |
|||
|
|||
- [ ] `npm run api:generate` 成功,生成 Comment/User 相关类型 |
|||
- [ ] `npm run build` 无 TS 错误 |
|||
- [ ] `/register` 页面可用,注册后自动登录跳转 |
|||
- [ ] 文章详情页显示评论区,可提交评论,提交后提示审核中 |
|||
- [ ] Markdown 渲染正确,代码块有高亮,XSS 被过滤 |
|||
- [ ] 标签云显示正常,大小按文章数变化 |
|||
- [ ] 后台评论审核页可列出待审核评论,通过/拒绝/删除生效 |
|||
- [ ] 后台用户管理页可查看用户列表,修改角色 |
|||
- [ ] 文章编辑器可上传封面图,粘贴图片到内容区 |
|||
- [ ] 所有 commit 符合 Conventional Commits 规范 |
|||
|
|||
## CDD 纪律 |
|||
|
|||
- 只修改前端代码,禁止修改后端仓库 |
|||
- 发现 openapi.yaml 与实际返回不符,停止开发,上报问题 |
|||
- 每次后端接口变更后,必须重新生成 API 代码 |
|||
- 禁止修改 `src/generated/api/` 目录下的任何文件 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue