docs: 添加项目文档和本地设置文件
添加 CLAUDE.md 项目文档,包含项目概述、开发命令、目录结构、核心架构模式等重要信息 添加 .claude/settings.local.json 配置文件,设置权限控制
Showing
2 changed files
with
317 additions
and
0 deletions
.claude/settings.local.json
0 → 100644
CLAUDE.md
0 → 100644
| 1 | +# CLAUDE.md | ||
| 2 | + | ||
| 3 | +此文件为 Claude Code (claude.ai/code) 在此代码库中工作时提供指导。 | ||
| 4 | + | ||
| 5 | +## 项目概述 | ||
| 6 | + | ||
| 7 | +**美乐爱觉 (mlaj)** - 基于 Vue 3 的教育平台,深度集成微信生态,服务于教师和学生。 | ||
| 8 | + | ||
| 9 | +- **框架**: Vue 3 (Composition API + `<script setup>`) | ||
| 10 | +- **构建工具**: Vite 6.2.0 | ||
| 11 | +- **包管理器**: pnpm (项目使用 `.nvm` 管理 Node.js 18.19.1) | ||
| 12 | +- **UI 框架**: Vant 4.9.22 (移动端优先) | ||
| 13 | +- **样式**: TailwindCSS + Less (分层) | ||
| 14 | +- **状态管理**: Context API (`/src/contexts/`) + localStorage | ||
| 15 | +- **路由**: Vue Router 4.5.0,支持懒加载和路由守卫 | ||
| 16 | +- **HTTP**: Axios 1.8.4,集中式拦截器 | ||
| 17 | + | ||
| 18 | +## 常用开发命令 | ||
| 19 | + | ||
| 20 | +### 核心开发 | ||
| 21 | +```bash | ||
| 22 | +pnpm dev # 启动开发服务器 (使用 Node.js 18.19.1) | ||
| 23 | +pnpm build # 生产环境构建 | ||
| 24 | +pnpm preview # 本地预览生产构建 | ||
| 25 | +pnpm test # 使用 Vitest 运行测试 | ||
| 26 | +``` | ||
| 27 | + | ||
| 28 | +### 部署 | ||
| 29 | +```bash | ||
| 30 | +pnpm dev_upload # 部署到开发服务器 | ||
| 31 | +pnpm behalo_upload # 部署到 behalo 环境 | ||
| 32 | +pnpm oa_upload # 部署到 OA 服务器 | ||
| 33 | +``` | ||
| 34 | + | ||
| 35 | +### 开发流程 | ||
| 36 | +- 每个部署命令都会:构建、归档(tar.gz)、通过 scp 上传、在服务器上解压、清理归档文件。 | ||
| 37 | + | ||
| 38 | +## 目录结构 | ||
| 39 | + | ||
| 40 | +``` | ||
| 41 | +src/ | ||
| 42 | +├── api/ # API 接口层 - 按领域模块化 | ||
| 43 | +│ ├── auth.js # 认证相关接口 | ||
| 44 | +│ ├── course.js # 课程相关接口 | ||
| 45 | +│ ├── teacher.js # 教师端接口 | ||
| 46 | +│ └── ... | ||
| 47 | +├── assets/ # 静态资源 (图片、CSS、模拟数据) | ||
| 48 | +├── components/ # 可复用的 Vue 组件 | ||
| 49 | +│ ├── ui/ # 通用 UI 组件 (VideoPlayer, AudioPlayer, CheckInDialog 等) | ||
| 50 | +│ ├── checkin/ # 打卡相关组件 | ||
| 51 | +│ ├── courses/ # 课程相关组件 | ||
| 52 | +│ └── studyDetail/ # 学习详情页组件 | ||
| 53 | +├── composables/ # Vue 组合式函数,用于逻辑复用 (useStudyComments, useStudyRecordTracker 等) | ||
| 54 | +├── contexts/ # 全局状态提供者 (auth, cart) | ||
| 55 | +├── common/ # 共享常量和工具 | ||
| 56 | +├── router/ # Vue Router 配置 | ||
| 57 | +│ ├── index.js # 路由实例与守卫 | ||
| 58 | +│ ├── routes.js # 路由定义(懒加载) | ||
| 59 | +│ └── guards.js # 认证守卫辅助函数 | ||
| 60 | +├── utils/ # 工具函数 | ||
| 61 | +│ ├── axios.js # Axios 实例与拦截器 (认证头、401 处理) | ||
| 62 | +│ ├── tools.js # 通用工具 (wxInfo, 文件处理等) | ||
| 63 | +│ └── auth_user_info.js # 用户信息存储辅助函数 | ||
| 64 | +└── views/ # 页面组件,按功能组织 | ||
| 65 | + ├── auth/ # 登录/认证页面 | ||
| 66 | + ├── courses/ # 课程浏览、详情、购买 | ||
| 67 | + ├── profile/ # 用户资料、设置、课程历史 | ||
| 68 | + ├── recall/ # 提醒/回忆系统 | ||
| 69 | + ├── study/ # 学习资料和内容 | ||
| 70 | + └── teacher/ # 教师端仪表板、任务、班级管理 | ||
| 71 | +``` | ||
| 72 | + | ||
| 73 | +## 路径别名 | ||
| 74 | + | ||
| 75 | +在 `vite.config.js` 和 `jsconfig.json` 中配置: | ||
| 76 | +- `@/` → `src/` | ||
| 77 | +- `@components/` → `src/components/` | ||
| 78 | +- `@composables/` → `src/composables/` | ||
| 79 | +- `@utils/` → `src/utils/` | ||
| 80 | +- `@api/` → `src/api/` | ||
| 81 | +- `@images/` → `src/assets/images/` | ||
| 82 | +- `@css/` → `src/assets/css/` | ||
| 83 | +- `@mock/` → `src/assets/mock/` | ||
| 84 | +- `common/` → `src/common/` | ||
| 85 | +- `@root/` → 项目根目录 | ||
| 86 | + | ||
| 87 | +## 核心架构模式 | ||
| 88 | + | ||
| 89 | +### API 接口层架构 | ||
| 90 | + | ||
| 91 | +**位置**: `/src/api/` | ||
| 92 | + | ||
| 93 | +所有接口遵循统一的响应结构: | ||
| 94 | +```javascript | ||
| 95 | +{ | ||
| 96 | + code: 1, // 1 = 成功,其他 = 失败 | ||
| 97 | + data: any, // 响应数据 | ||
| 98 | + msg: string // 消息(成功时为空,失败时为错误信息) | ||
| 99 | +} | ||
| 100 | +``` | ||
| 101 | + | ||
| 102 | +**重要**: 检查成功时使用 `if (res.code === 1)` 而不是 `if (res.code)`,避免将 401/403 误判为成功。 | ||
| 103 | + | ||
| 104 | +**认证头** 通过 axios 拦截器自动添加 (`/src/utils/axios.js`): | ||
| 105 | +- 每次请求读取 `localStorage.user_info` | ||
| 106 | +- 设置 `User-Id` 和 `User-Token` 请求头 | ||
| 107 | +- 401 响应处理:仅当当前路由需要认证时才重定向到登录页 (见 guards.js 中的 `checkAuth`) | ||
| 108 | + | ||
| 109 | +### 组件分层 | ||
| 110 | + | ||
| 111 | +**视图页面** (`/src/views/`): 页面级组件,负责编排: | ||
| 112 | +- 通过 API 获取数据 | ||
| 113 | +- 通过 refs/composables 管理状态 | ||
| 114 | +- 路由和导航 | ||
| 115 | +- 集成更小的组件 | ||
| 116 | + | ||
| 117 | +**UI 组件** (`/src/components/ui/`): 可复用、无状态或自包含: | ||
| 118 | +- VideoPlayer, AudioPlayer, CheckInDialog, SharePoster, SearchBar 等 | ||
| 119 | +- 应尽可能避免直接调用 API | ||
| 120 | +- 通过 emit 事件向父组件传递操作 | ||
| 121 | + | ||
| 122 | +**组合式函数** (`/src/composables/`): 可复用逻辑: | ||
| 123 | +- `useStudyComments`: 评论获取、提交、分页 | ||
| 124 | +- `useStudyRecordTracker`: 学习时长追踪和分析 | ||
| 125 | +- `useCheckin`: 打卡流程和提交 | ||
| 126 | +- 返回响应式 refs 和函数,内部处理副作用 | ||
| 127 | + | ||
| 128 | +### 路由与认证 | ||
| 129 | + | ||
| 130 | +**路由** 使用懒加载进行代码分割: | ||
| 131 | +```javascript | ||
| 132 | +{ | ||
| 133 | + path: '/courses/:id', | ||
| 134 | + component: () => import('@/views/courses/CourseDetailPage.vue') | ||
| 135 | +} | ||
| 136 | +``` | ||
| 137 | + | ||
| 138 | +**认证守卫** (`/src/router/guards.js`): | ||
| 139 | +- `checkAuth(route)` - 返回 `true` 或重定向对象 | ||
| 140 | +- 不再自动触发微信认证;仅通过登录页手动触发 | ||
| 141 | +- 路由可标记 `meta: { requireAuth: false }` 以公开访问 | ||
| 142 | + | ||
| 143 | +### 样式策略 | ||
| 144 | + | ||
| 145 | +**TailwindCSS** 是主要样式方案: | ||
| 146 | +- 用于布局、间距、排版、颜色 | ||
| 147 | +- 自定义颜色定义在 `tailwind.config.js` 中 (primary: #4caf50) | ||
| 148 | + | ||
| 149 | +**Less** 用于组件特定样式: | ||
| 150 | +- 组件边界内的嵌套选择器 | ||
| 151 | +- 使用 `<style lang="less" scoped>` 限制作用域到组件 | ||
| 152 | +- 使用 `:deep()` 修改 Vant/VideoJS 内部样式 | ||
| 153 | + | ||
| 154 | +**自动导入**: | ||
| 155 | +- Vant 组件自动导入(无需手动导入) | ||
| 156 | +- Vue 组合式函数自动导入 (ref, computed, onMounted 等) | ||
| 157 | + | ||
| 158 | +### 状态管理模式 | ||
| 159 | + | ||
| 160 | +**用户认证状态**: | ||
| 161 | +- 运行时: `contexts/auth.js` → `currentUser` ref | ||
| 162 | +- 持久化: `localStorage.currentUser` 和 `localStorage.user_info` | ||
| 163 | +- Axios 请求头: 从 localStorage 派生(在拦截器中) | ||
| 164 | +- 辅助函数: `getUserInfoFromStorage()`, `removeUserInfoFromStorage()` | ||
| 165 | + | ||
| 166 | +**购物车/订单状态**: | ||
| 167 | +- 运行时: `contexts/cart.js` | ||
| 168 | +- 通过 provide/inject 在页面间保持 | ||
| 169 | + | ||
| 170 | +### 微信集成 | ||
| 171 | + | ||
| 172 | +**微信 JS SDK** 初始化在 `App.vue` 中: | ||
| 173 | +- 仅在浏览器环境中 | ||
| 174 | +- 通过 `wxInfo()` 工具检测环境 | ||
| 175 | +- `wxInfo().isWeiXin` - 在微信浏览器中运行 | ||
| 176 | +- `wxInfo().isPc` - 在 PC 上运行 | ||
| 177 | + | ||
| 178 | +**微信认证流程**: | ||
| 179 | +1. 用户在登录页点击微信图标 | ||
| 180 | +2. 重定向到微信 OAuth | ||
| 181 | +3. 回调 → `getUserIsLoginAPI()` → 写入用户信息到存储 | ||
| 182 | +4. 重定向到原页面或首页 | ||
| 183 | + | ||
| 184 | +**微信支付**: | ||
| 185 | +- 集成在结账流程中 | ||
| 186 | +- 生产环境: 需要微信浏览器环境 (`wxInfo().isWeiXin`) | ||
| 187 | +- 免费课程: 跳过环境验证 | ||
| 188 | + | ||
| 189 | +### 文件预览系统 | ||
| 190 | + | ||
| 191 | +**PDF 预览**: | ||
| 192 | +- 组件: `@sunsetglow/vue-pdf-viewer` | ||
| 193 | +- 专用路由: `/pdfPreview` 用于浏览器内预览 | ||
| 194 | + | ||
| 195 | +**Office 文档** (Word, Excel, PPT): | ||
| 196 | +- `@vue-office/docx`, `@vue-office/excel`, `@vue-office/pptx` | ||
| 197 | +- 弹窗预览组件,带错误处理 | ||
| 198 | + | ||
| 199 | +**图片**: | ||
| 200 | +- 使用 Vant 的 `van-image-preview` | ||
| 201 | + | ||
| 202 | +**视频播放器**: | ||
| 203 | +- 基于 `@videojs-player/vue` (Video.js 7.21.7 的封装) | ||
| 204 | +- 自定义 `VideoPlayer.vue` 组件添加错误处理、自动重试和播放速率控制 | ||
| 205 | + | ||
| 206 | +## 重要注意事项 | ||
| 207 | + | ||
| 208 | +### 视频播放器问题 | ||
| 209 | + | ||
| 210 | +**VideoPlayer 使用 `v-show` vs `v-if`**: | ||
| 211 | +- Video.js 在 `v-show` (display: none) 下无法正常工作 | ||
| 212 | +- 使用 `v-if` 确保视频元素在初始化前完全挂载 | ||
| 213 | +- 参考 `StudyDetailPage.vue` 中的正确模式:设置 `isPlaying = true`,然后 `setTimeout` 再调用 `play()` | ||
| 214 | + | ||
| 215 | +### 401 响应处理 | ||
| 216 | + | ||
| 217 | +`src/utils/axios.js` 中的 axios 响应拦截器: | ||
| 218 | +- 仅当 `checkAuth(to)` 返回重定向时才跳转到登录页 | ||
| 219 | +- 公开页面(如课程详情)即使在 401 时也保持当前页 | ||
| 220 | +- 页面组件应为自己的用户操作处理 401 | ||
| 221 | + | ||
| 222 | +### API 响应安全性 | ||
| 223 | + | ||
| 224 | +始终检查 `res.code === 1`(而不仅仅是 `res.code`): | ||
| 225 | +```javascript | ||
| 226 | +// 正确 | ||
| 227 | +const { code, data } = await getCourseDetailAPI({ i: courseId }) | ||
| 228 | +if (code === 1) { ... } | ||
| 229 | + | ||
| 230 | +// 错误 - 将 401/403 当作成功 | ||
| 231 | +if (code) { ... } | ||
| 232 | +``` | ||
| 233 | + | ||
| 234 | +### 组件自动导入 | ||
| 235 | + | ||
| 236 | +Vant 组件通过 `unplugin-vue-components` 自动导入: | ||
| 237 | +- **不要导入** `import { Button } from 'vant'` | ||
| 238 | +- 直接使用 `<van-button>` | ||
| 239 | +- 参见 `src/components.d.ts` 查看所有可用组件 | ||
| 240 | + | ||
| 241 | +### 打卡系统 | ||
| 242 | + | ||
| 243 | +**统一组件**: `CheckInDialog.vue` 处理所有打卡流程: | ||
| 244 | +- 接收 `items_today` 和 `items_history` props | ||
| 245 | +- 每项包含 `id`, `name`, `task_type` ('checkin'/'upload'), `is_gray` | ||
| 246 | +- 完成时触发 `check-in-success` 事件 | ||
| 247 | + | ||
| 248 | +**可复用列表组件**: `CheckInList.vue` | ||
| 249 | +- 用于首页和 CheckInDialog | ||
| 250 | +- 对话框使用紧凑模式,页面使用正常模式 | ||
| 251 | +- `submit-success` 事件向上冒泡 | ||
| 252 | + | ||
| 253 | +### 环境配置 | ||
| 254 | + | ||
| 255 | +使用 `.env.development`, `.env.production` 等: | ||
| 256 | +- `VITE_PORT` - 开发服务器端口 | ||
| 257 | +- `VITE_BASE` - 基础路径 | ||
| 258 | +- `VITE_PROXY_PREFIX` - API 代理前缀 | ||
| 259 | +- `VITE_PROXY_TARGET` - 后端 API 目标 | ||
| 260 | +- `VITE_OUTDIR` - 构建输出目录 | ||
| 261 | + | ||
| 262 | +### Speckit 框架命令 | ||
| 263 | + | ||
| 264 | +位于 `.cursor/commands/`: | ||
| 265 | +- `/speckit.specify` - 从需求生成规范 | ||
| 266 | +- `/speckit.plan` - 创建实现计划 | ||
| 267 | +- `/speckit.tasks` - 生成任务分解 | ||
| 268 | +- `/speckit.analyze` - 跨文件一致性分析 | ||
| 269 | +- `/speckit.implement` - 执行实现计划 | ||
| 270 | +- `/speckit.checklist` - 验证检查清单 | ||
| 271 | +- `/speckit.clarify` - 需求澄清 | ||
| 272 | +- `/speckit.constitution` - 项目原则和约束 | ||
| 273 | + | ||
| 274 | +### 代码风格说明 (来自 VUE_CODE_STYLE_GUIDE.md) | ||
| 275 | + | ||
| 276 | +**当前实践**: | ||
| 277 | +- 新组件使用 `<script setup>` 和 Composition API | ||
| 278 | +- API 函数应始终返回 `{ code, data, msg }` - 永不返回 `false` | ||
| 279 | +- 尽可能将逻辑提取到 composables (`/src/composables/useXxx.js`) | ||
| 280 | +- 本地状态使用 refs,派生状态使用 computed | ||
| 281 | +- 除非必要避免 JSX;大多数页面使用 Vue 模板 | ||
| 282 | + | ||
| 283 | +**已知不一致性** (需注意): | ||
| 284 | +- 文件中混合使用分号/无分号 | ||
| 285 | +- 混合使用 2 空格/4 空格缩进 | ||
| 286 | +- 混合使用 function/箭头函数 | ||
| 287 | +- 混合使用中文/英文注释 | ||
| 288 | + | ||
| 289 | +## 特殊功能 | ||
| 290 | + | ||
| 291 | +### 分享海报生成 | ||
| 292 | +- 基于 Canvas 的海报生成,带二维码 (`qrcode` 包) | ||
| 293 | +- 自动优化 `cdn.ipadbiz.cn` URL 的图片 | ||
| 294 | +- 使用 `crossorigin="anonymous"` 处理跨域 Canvas 污染 | ||
| 295 | +- 组件: `SharePoster.vue` (可复用) | ||
| 296 | + | ||
| 297 | +### 动态 Open Graph 元标签 | ||
| 298 | +- 课程详情页动态添加 `og:title`, `og:description`, `og:image`, `og:url` | ||
| 299 | +- 页面卸载时移除标签以避免冲突 | ||
| 300 | + | ||
| 301 | +### 标签指示器动画 | ||
| 302 | +- 基于 ResizeObserver 的指示器定位 | ||
| 303 | +- 处理异步加载第三列而不错位 | ||
| 304 | +- 参考 `StudyCoursePage.vue` 的实现 | ||
| 305 | + | ||
| 306 | +## 测试 | ||
| 307 | + | ||
| 308 | +- **测试运行器**: Vitest | ||
| 309 | +- **命令**: `pnpm test` | ||
| 310 | +- 测试文件位于 `/test/` (当前可能测试覆盖较少) |
-
Please register or login to post a comment