hookehuyr

docs: 添加项目文档和本地设置文件

添加 CLAUDE.md 项目文档,包含项目概述、开发命令、目录结构、核心架构模式等重要信息
添加 .claude/settings.local.json 配置文件,设置权限控制
{
"permissions": {
"allow": [
"Bash(tree:*)"
]
}
}
# CLAUDE.md
此文件为 Claude Code (claude.ai/code) 在此代码库中工作时提供指导。
## 项目概述
**美乐爱觉 (mlaj)** - 基于 Vue 3 的教育平台,深度集成微信生态,服务于教师和学生。
- **框架**: Vue 3 (Composition API + `<script setup>`)
- **构建工具**: Vite 6.2.0
- **包管理器**: pnpm (项目使用 `.nvm` 管理 Node.js 18.19.1)
- **UI 框架**: Vant 4.9.22 (移动端优先)
- **样式**: TailwindCSS + Less (分层)
- **状态管理**: Context API (`/src/contexts/`) + localStorage
- **路由**: Vue Router 4.5.0,支持懒加载和路由守卫
- **HTTP**: Axios 1.8.4,集中式拦截器
## 常用开发命令
### 核心开发
```bash
pnpm dev # 启动开发服务器 (使用 Node.js 18.19.1)
pnpm build # 生产环境构建
pnpm preview # 本地预览生产构建
pnpm test # 使用 Vitest 运行测试
```
### 部署
```bash
pnpm dev_upload # 部署到开发服务器
pnpm behalo_upload # 部署到 behalo 环境
pnpm oa_upload # 部署到 OA 服务器
```
### 开发流程
- 每个部署命令都会:构建、归档(tar.gz)、通过 scp 上传、在服务器上解压、清理归档文件。
## 目录结构
```
src/
├── api/ # API 接口层 - 按领域模块化
│ ├── auth.js # 认证相关接口
│ ├── course.js # 课程相关接口
│ ├── teacher.js # 教师端接口
│ └── ...
├── assets/ # 静态资源 (图片、CSS、模拟数据)
├── components/ # 可复用的 Vue 组件
│ ├── ui/ # 通用 UI 组件 (VideoPlayer, AudioPlayer, CheckInDialog 等)
│ ├── checkin/ # 打卡相关组件
│ ├── courses/ # 课程相关组件
│ └── studyDetail/ # 学习详情页组件
├── composables/ # Vue 组合式函数,用于逻辑复用 (useStudyComments, useStudyRecordTracker 等)
├── contexts/ # 全局状态提供者 (auth, cart)
├── common/ # 共享常量和工具
├── router/ # Vue Router 配置
│ ├── index.js # 路由实例与守卫
│ ├── routes.js # 路由定义(懒加载)
│ └── guards.js # 认证守卫辅助函数
├── utils/ # 工具函数
│ ├── axios.js # Axios 实例与拦截器 (认证头、401 处理)
│ ├── tools.js # 通用工具 (wxInfo, 文件处理等)
│ └── auth_user_info.js # 用户信息存储辅助函数
└── views/ # 页面组件,按功能组织
├── auth/ # 登录/认证页面
├── courses/ # 课程浏览、详情、购买
├── profile/ # 用户资料、设置、课程历史
├── recall/ # 提醒/回忆系统
├── study/ # 学习资料和内容
└── teacher/ # 教师端仪表板、任务、班级管理
```
## 路径别名
`vite.config.js``jsconfig.json` 中配置:
- `@/``src/`
- `@components/``src/components/`
- `@composables/``src/composables/`
- `@utils/``src/utils/`
- `@api/``src/api/`
- `@images/``src/assets/images/`
- `@css/``src/assets/css/`
- `@mock/``src/assets/mock/`
- `common/``src/common/`
- `@root/` → 项目根目录
## 核心架构模式
### API 接口层架构
**位置**: `/src/api/`
所有接口遵循统一的响应结构:
```javascript
{
code: 1, // 1 = 成功,其他 = 失败
data: any, // 响应数据
msg: string // 消息(成功时为空,失败时为错误信息)
}
```
**重要**: 检查成功时使用 `if (res.code === 1)` 而不是 `if (res.code)`,避免将 401/403 误判为成功。
**认证头** 通过 axios 拦截器自动添加 (`/src/utils/axios.js`):
- 每次请求读取 `localStorage.user_info`
- 设置 `User-Id``User-Token` 请求头
- 401 响应处理:仅当当前路由需要认证时才重定向到登录页 (见 guards.js 中的 `checkAuth`)
### 组件分层
**视图页面** (`/src/views/`): 页面级组件,负责编排:
- 通过 API 获取数据
- 通过 refs/composables 管理状态
- 路由和导航
- 集成更小的组件
**UI 组件** (`/src/components/ui/`): 可复用、无状态或自包含:
- VideoPlayer, AudioPlayer, CheckInDialog, SharePoster, SearchBar 等
- 应尽可能避免直接调用 API
- 通过 emit 事件向父组件传递操作
**组合式函数** (`/src/composables/`): 可复用逻辑:
- `useStudyComments`: 评论获取、提交、分页
- `useStudyRecordTracker`: 学习时长追踪和分析
- `useCheckin`: 打卡流程和提交
- 返回响应式 refs 和函数,内部处理副作用
### 路由与认证
**路由** 使用懒加载进行代码分割:
```javascript
{
path: '/courses/:id',
component: () => import('@/views/courses/CourseDetailPage.vue')
}
```
**认证守卫** (`/src/router/guards.js`):
- `checkAuth(route)` - 返回 `true` 或重定向对象
- 不再自动触发微信认证;仅通过登录页手动触发
- 路由可标记 `meta: { requireAuth: false }` 以公开访问
### 样式策略
**TailwindCSS** 是主要样式方案:
- 用于布局、间距、排版、颜色
- 自定义颜色定义在 `tailwind.config.js` 中 (primary: #4caf50)
**Less** 用于组件特定样式:
- 组件边界内的嵌套选择器
- 使用 `<style lang="less" scoped>` 限制作用域到组件
- 使用 `:deep()` 修改 Vant/VideoJS 内部样式
**自动导入**:
- Vant 组件自动导入(无需手动导入)
- Vue 组合式函数自动导入 (ref, computed, onMounted 等)
### 状态管理模式
**用户认证状态**:
- 运行时: `contexts/auth.js``currentUser` ref
- 持久化: `localStorage.currentUser``localStorage.user_info`
- Axios 请求头: 从 localStorage 派生(在拦截器中)
- 辅助函数: `getUserInfoFromStorage()`, `removeUserInfoFromStorage()`
**购物车/订单状态**:
- 运行时: `contexts/cart.js`
- 通过 provide/inject 在页面间保持
### 微信集成
**微信 JS SDK** 初始化在 `App.vue` 中:
- 仅在浏览器环境中
- 通过 `wxInfo()` 工具检测环境
- `wxInfo().isWeiXin` - 在微信浏览器中运行
- `wxInfo().isPc` - 在 PC 上运行
**微信认证流程**:
1. 用户在登录页点击微信图标
2. 重定向到微信 OAuth
3. 回调 → `getUserIsLoginAPI()` → 写入用户信息到存储
4. 重定向到原页面或首页
**微信支付**:
- 集成在结账流程中
- 生产环境: 需要微信浏览器环境 (`wxInfo().isWeiXin`)
- 免费课程: 跳过环境验证
### 文件预览系统
**PDF 预览**:
- 组件: `@sunsetglow/vue-pdf-viewer`
- 专用路由: `/pdfPreview` 用于浏览器内预览
**Office 文档** (Word, Excel, PPT):
- `@vue-office/docx`, `@vue-office/excel`, `@vue-office/pptx`
- 弹窗预览组件,带错误处理
**图片**:
- 使用 Vant 的 `van-image-preview`
**视频播放器**:
- 基于 `@videojs-player/vue` (Video.js 7.21.7 的封装)
- 自定义 `VideoPlayer.vue` 组件添加错误处理、自动重试和播放速率控制
## 重要注意事项
### 视频播放器问题
**VideoPlayer 使用 `v-show` vs `v-if`**:
- Video.js 在 `v-show` (display: none) 下无法正常工作
- 使用 `v-if` 确保视频元素在初始化前完全挂载
- 参考 `StudyDetailPage.vue` 中的正确模式:设置 `isPlaying = true`,然后 `setTimeout` 再调用 `play()`
### 401 响应处理
`src/utils/axios.js` 中的 axios 响应拦截器:
- 仅当 `checkAuth(to)` 返回重定向时才跳转到登录页
- 公开页面(如课程详情)即使在 401 时也保持当前页
- 页面组件应为自己的用户操作处理 401
### API 响应安全性
始终检查 `res.code === 1`(而不仅仅是 `res.code`):
```javascript
// 正确
const { code, data } = await getCourseDetailAPI({ i: courseId })
if (code === 1) { ... }
// 错误 - 将 401/403 当作成功
if (code) { ... }
```
### 组件自动导入
Vant 组件通过 `unplugin-vue-components` 自动导入:
- **不要导入** `import { Button } from 'vant'`
- 直接使用 `<van-button>`
- 参见 `src/components.d.ts` 查看所有可用组件
### 打卡系统
**统一组件**: `CheckInDialog.vue` 处理所有打卡流程:
- 接收 `items_today``items_history` props
- 每项包含 `id`, `name`, `task_type` ('checkin'/'upload'), `is_gray`
- 完成时触发 `check-in-success` 事件
**可复用列表组件**: `CheckInList.vue`
- 用于首页和 CheckInDialog
- 对话框使用紧凑模式,页面使用正常模式
- `submit-success` 事件向上冒泡
### 环境配置
使用 `.env.development`, `.env.production` 等:
- `VITE_PORT` - 开发服务器端口
- `VITE_BASE` - 基础路径
- `VITE_PROXY_PREFIX` - API 代理前缀
- `VITE_PROXY_TARGET` - 后端 API 目标
- `VITE_OUTDIR` - 构建输出目录
### Speckit 框架命令
位于 `.cursor/commands/`:
- `/speckit.specify` - 从需求生成规范
- `/speckit.plan` - 创建实现计划
- `/speckit.tasks` - 生成任务分解
- `/speckit.analyze` - 跨文件一致性分析
- `/speckit.implement` - 执行实现计划
- `/speckit.checklist` - 验证检查清单
- `/speckit.clarify` - 需求澄清
- `/speckit.constitution` - 项目原则和约束
### 代码风格说明 (来自 VUE_CODE_STYLE_GUIDE.md)
**当前实践**:
- 新组件使用 `<script setup>` 和 Composition API
- API 函数应始终返回 `{ code, data, msg }` - 永不返回 `false`
- 尽可能将逻辑提取到 composables (`/src/composables/useXxx.js`)
- 本地状态使用 refs,派生状态使用 computed
- 除非必要避免 JSX;大多数页面使用 Vue 模板
**已知不一致性** (需注意):
- 文件中混合使用分号/无分号
- 混合使用 2 空格/4 空格缩进
- 混合使用 function/箭头函数
- 混合使用中文/英文注释
## 特殊功能
### 分享海报生成
- 基于 Canvas 的海报生成,带二维码 (`qrcode` 包)
- 自动优化 `cdn.ipadbiz.cn` URL 的图片
- 使用 `crossorigin="anonymous"` 处理跨域 Canvas 污染
- 组件: `SharePoster.vue` (可复用)
### 动态 Open Graph 元标签
- 课程详情页动态添加 `og:title`, `og:description`, `og:image`, `og:url`
- 页面卸载时移除标签以避免冲突
### 标签指示器动画
- 基于 ResizeObserver 的指示器定位
- 处理异步加载第三列而不错位
- 参考 `StudyCoursePage.vue` 的实现
## 测试
- **测试运行器**: Vitest
- **命令**: `pnpm test`
- 测试文件位于 `/test/` (当前可能测试覆盖较少)