# 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` - 底部引入 `` ### 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` - 侧边栏或底部引入 `` ### 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 图片语法 `![alt](url)` ## 代码规范(违反 = 拒收) | # | 规则 | |---|------| | 1 | **禁止手写 API 类型**,必须从 openapi.yaml 生成 | | 2 | **禁止直接 import axios**,统一用 `src/api/client.ts` | | 3 | 组件必须用 `