# LPT 前端应用(lpt-fe) > Vue 3 + TypeScript + Vite 单页应用。 ## Git 提交规范 - 提交信息必须简短且使用中文,不要使用英文长句。 - 格式:`类型: 简述`,例如 `feat: 新增学习会话页面`、`fix: 修复路由守卫401跳转`、`docs: 补充组件说明`。 ## 技术栈 - 框架:Vue 3 + TypeScript + Vite 5 - UI 库:Element Plus 2.8 - HTTP:Axios(`withCredentials: true`,自动携带 Cookie `satoken`) - 思维导图:mind-elixir 5.13 - Markdown:marked 18.0 - 测试:Vitest + Playwright ## 项目结构 ```text lpt-fe/src/ ├── api/ → API 接口层 ├── components/ → 页面组件 ├── components/composables/ → 组合式函数 ├── router/ → 路由配置 ├── utils/ → 工具函数 ├── assets/ → 全局样式与资源 └── __tests__/ → 单元测试 ``` 核心组件:`Login.vue`、`Welcome.vue`、`Study.vue`、`StartTask.vue`、`Review.vue`、`ReviewDetail.vue`、`ReviewRecall.vue`、`TaskForm.vue`、`MindMapViewer.vue`、`MarkdownRenderer.vue`。 ## 路由表 | 路径 | 组件 | 说明 | |------|------|------| | `/login` | Login.vue | 登录页(无需认证) | | `/welcome` | Welcome.vue | 首页 | | `/study` | Study.vue | 学习任务列表 | | `/start-task/:taskNum` | StartTask.vue | 学习会话 | | `/add-task` | TaskForm.vue | 创建任务 | | `/update-task/:taskId` | TaskForm.vue | 更新任务 | | `/review` | Review.vue | 复习总览 | | `/review/detail/:type/:id` | ReviewDetail.vue | 复习详情 | | `/review/recall/:taskNum` | ReviewRecall.vue | 回忆复习 | ## 认证与请求 - Axios `withCredentials: true`,Cookie `satoken` 自动携带。 - 401 处理:HTTP 层和业务层双重检测,清理 `localStorage.isLoggedIn` 后跳转 `/login`。 - `validateResponse`:`code !== 200` 时 reject。 - Vite 代理:`/api` → `http://localhost:5157`,自动重写去掉 `/api` 前缀。 ## Markdown 学习材料 - 编辑:textarea 输入,支持 `[文字](url)` 和裸 URL。 - 预览:`renderMarkdown(raw)` 同步函数,使用 `__LINK_N__` 占位符防止嵌套 HTML。 - 保存:`convertMaterialUrls()` 异步拉取标题,替换裸 URL 为 `[标题](url)`。 - `getUrlTitle(url)`:调用 `/utils/fetch-title`,带内存缓存和请求去重。 ## 应用场景 - TaskForm 编辑页使用 `el-dialog` 弹窗管理应用场景。 - Study 详情页使用 `getUrlTitle` 展示应用场景链接标题。 ## 样式与交互约定 - 链接使用绿色系 `var(--green-600)`,虚线下划线,hover 变实线。 - 区块分隔使用 `.detail-block`:`border-top` + `padding-top`,首个除外。 - 小字提示使用 12px `var(--text-secondary)`。 - `Study.vue` 任务清单每页 20 条。 - `StartTask.vue` 编辑任务时先 GET 详情,合并后再 PUT,避免覆盖其他字段。 - `MindMapViewer.vue` 支持只读、编辑、selectable、colorByCompare 模式;selectable 模式下点击节点 emit `node-select`。 - ReviewRecall 中 `standardExpanded` 展开后节点可点击,用于选择复习起点。 ## 前端代码标准 ### 按钮规范 - 页面主操作 / 卡片 CTA:`size="large"`,如 Study 开始任务、TaskForm 保存、Welcome 快速入口。 - 区块工具栏 / 页内操作:默认尺寸,如 Review 刷新、ReviewRecall 面板操作、历史记录。 - 表格/列表行内操作:`size="small" text`,如 查看记录、回忆复习、编辑、删除。 - 弹窗 footer:默认尺寸;确认按钮 `type="success"`,取消按钮默认;危险操作统一 `type="danger"`。 - 正向/保存语义统一 `success`,次级编辑语义可用 `primary`,不要在同一功能上混用。 - 窄屏(`max-width: 768px`)操作区按钮纵向全宽,全局规则位于 `src/assets/main.css` 的 `.action-row / .edit-actions / .fragment-edit-actions`。 ### 移动端适配 - 断点约定:按钮/弹窗使用 768px,卡片与汇总布局使用 900px。 - 弹窗:窄屏宽度 `calc(100% - 24px)`,body 允许纵向滚动,footer 按钮等宽;全局规则位于 `main.css` 的 `@media (max-width: 768px)`,新增弹窗不需要再逐页适配。 - 多按钮弹窗(如 Welcome 回忆卡片)在窄屏纵向堆叠。 - 列表页优先使用卡片列表而非 `el-table`,桌面与移动端视觉统一,参考 `Review.vue` 的 `.task-list`。 - 文案不缩写:使用完整字段名,如 `学习报告数量`、`学习残片数量`,不使用 `报告数`、`残片数`。 ### 代码整洁 - Markdown 渲染统一使用 `src/utils/markdown.ts` 的 `renderMarkdown`,禁止在组件内复制实现。 - 应用场景状态常量统一使用 `src/utils/taskApplication.ts` 的 `applicationStatusOptions`。 - 不保留无消费者代码:未使用的 import、prop、事件、API 封装、CSS class、组件文件与依赖应及时删除。 - 组件公开 props/events 只在有实际消费者时保留,例如 MindMapViewer 通过 `toOutline()` 导出编辑内容,不依赖无人监听的 change 事件。 - Vite 模板遗留文件(示例组件、icon、logo)不进入业务代码。 ### 提交前检查 - 运行 `npx vue-tsc --noEmit`、`npm run test`、`npm run build`。 - 提交信息按 Git 提交规范使用中文短句;样式类改动用 `style:`,清理类用 `refactor:` / `chore:`。 ## 开发配置 - 开发端口:5158 - 代理:`/api` → `http://localhost:5157` - 环境变量:`.env.development` / `.env.production` / `.env.uat` ## 启动命令 ```bash npm install npm run dev npm run build npm run test npm run test:e2e npx vue-tsc --noEmit ``` 编译检查也可以使用: ```bash npx vite build npx vue-tsc --noEmit ``` ## Docker - 多阶段构建:`node:20-alpine` 编译 → `nginx:alpine` 运行。 - 暴露端口:80。 - 构建参数:`BUILD_MODE`,默认 production。 ## 关联项目 | 项目 | 路径 | 端口 | 说明 | |------|------|------|------| | lpt-be | `../lpt-be/` | 5157 | Spring Boot 后端,前端通过 `/api` 代理调用 | | lpt-ai | `../lpt-ai/` | 5199 | AI 服务,前端不直接调用 | ## 调用关系 ```text 浏览器 → lpt-fe (5158) ──/api──→ lpt-be (5157) ──HTTP──→ lpt-ai (5199) │ └── MySQL (8109) ```