Name Last Update
.claude Loading commit data...
.cursor/commands Loading commit data...
.github/prompts Loading commit data...
.specify Loading commit data...
.trae/skills/vue-best-practices Loading commit data...
build Loading commit data...
mcp Loading commit data...
public Loading commit data...
specs Loading commit data...
src Loading commit data...
.env Loading commit data...
.env.development Loading commit data...
.env.production Loading commit data...
.eslintrc-auto-import.json Loading commit data...
.gitignore Loading commit data...
CLAUDE.md Loading commit data...
ISSUES_TO_FIX.md Loading commit data...
README.md Loading commit data...
VUE_CODE_STYLE_GUIDE.md Loading commit data...
index.html Loading commit data...
jsconfig.json Loading commit data...
package-lock.json Loading commit data...
package.json Loading commit data...
pnpm-lock.yaml Loading commit data...
postcss.config.js Loading commit data...
tailwind.config.js Loading commit data...
vite.config.js Loading commit data...
yarn.lock Loading commit data...

美乐爱觉项目

测试环境网站 https://oa-dev.onwall.cn/f/mlaj

业务系统架构

1. 用户与认证 (User & Auth)

  • 核心流程:支持手机号+验证码/密码登录,注册流程。
  • 微信集成
    • 环境检测:wxInfo().isWeiXin 检测微信浏览器。
    • 授权登录:基于 OAuth 2.0,通过 getAuthInfoAPI 获取 OpenID/UserInfo,支持静默/显式授权。
    • 分享配置:通过 JS-SDK 配置自定义分享标题、描述和图片。
  • 个人中心:管理个人资料(头像/昵称/手机/密码)、消息通知、帮助中心。
  • 状态管理contexts/auth.js 维护全局 currentUser,使用 localStorage 持久化,Axios 拦截器自动注入 Token。

2. 课程系统 (Courses)

  • 展示与浏览:首页推荐、课程列表(热门/精选/搜索)、课程详情页(介绍/目录/评价)。
  • 购买流程
    • 购物车:contexts/cart.js 支持单品/多品模式,本地持久化。
    • 结算:收银台页面 (/checkout),集成微信支付 (api/wx/pay.js)。
    • 环境校验:付费课程强制在微信环境内购买。
  • 学习体验
    • 学习页:展示课程目录与学习进度。
    • 内容预览:集成 Video.js 播放视频,PDF.js 预览文档,Office Web Viewer 预览 Word/Excel/PPT。
    • 记录追踪:useStudyRecordTracker 自动追踪学习时长与进度。

3. 打卡与作业系统 (Check-in & Tasks)

  • 学生端
    • 作业日历IndexCheckInPage 展示每日打卡状态,支持按月切换。
    • 统一打卡页 (/checkin/detail):
    • 支持类型:文本、图片、视频、音频、计数打卡(如感恩日记)。
    • 核心逻辑:useCheckin 封装上传(七牛云+Hash秒传)、校验、提交逻辑。
    • 交互:支持补卡、编辑已提交内容、选择打卡对象(计数模式)。
    • 互动社区:打卡动态流,支持点赞、评论、查看他人作品。
  • 教师端 (/teacher):
    • 作业管理:发布新作业,查看作业列表与详情(完成率/出勤率统计)。
    • 班级管理:查看班级学员列表,进入学员详情页。
    • 审批流程:审核学生提交的打卡内容,支持通过/驳回。

4. 活动系统 (Activities)

  • 功能:活动列表展示、活动详情、在线报名表单 (/activities/:id/signup)。
  • 记录:用户可查看“我的活动”历史记录。

5. 召回系统 (Recall)

  • 目标:面向老用户的营销与促活流程。
  • 流程
    1. 登录/身份验证(支持身份证查询历史)。
    2. 引导页与信息补全。
    3. 时光机旅程 (Timeline):展示用户在平台的历史里程碑。
    4. 活动历史回顾与积分汇总。
    5. 专属海报:生成个性化分享海报。
    6. 导流:引导至 AI 星球或最新课程。

6. 积分与订单

  • 订单:查看订单状态(待支付/已支付/退款),支持取消订单。
  • 积分:查看积分余额与变动明细,积分可用于抵扣或兑换(视具体业务规则)。

核心技术栈与实现

状态管理

  • Context API:项目主要使用 Vue 3 provide/inject 模式进行全局状态管理。
    • auth.js:用户认证、登录态、Token 管理。
    • cart.js:购物车逻辑、商品增删改、结算流程。
  • 持久化:关键状态同步至 localStorage,页面刷新不丢失。

文件处理

  • 七牛云上传
    • 前端计算文件 Hash (browser-md5-file / qiniuFileHash)。
    • 申请上传 Token(支持 Hash 秒传检测)。
    • 直传七牛云对象存储。
    • 回填业务服务器保存元数据。
  • 文档预览
    • PDF: @sunsetglow/vue-pdf-viewer
    • Office: @vue-office/docx, @vue-office/excel, @vue-office/pptx
    • Video: @videojs-player/vue (Video.js 7.x)

路由与权限

  • 路由守卫 (guards.js):
    • checkAuth:基于白名单或 meta.requiresAuth 拦截未登录访问。
    • startWxAuth:按需触发微信授权流程(非自动触发,避免死循环)。

目录结构说明

src/
├── api/              # API 接口层
│   ├── auth.js       # 认证
│   ├── checkin.js    # 打卡/作业
│   ├── course.js     # 课程
│   ├── teacher.js    # 教师端
│   ├── recall_users.js # 召回系统
│   └── ...
├── components/       # UI 组件
│   ├── ui/           # 通用组件 (VideoPlayer, CheckInDialog, SearchBar)
│   ├── checkin/      # 打卡业务组件
│   ├── teacher/      # 教师端组件
│   └── ...
├── composables/      # 逻辑复用 (useCheckin, useAuth, useStudyRecordTracker)
├── contexts/         # 全局状态 (auth, cart)
├── router/           # 路由配置
│   ├── checkin.js    # 打卡路由
│   ├── teacher.js    # 教师路由
│   └── ...
├── views/            # 页面视图
│   ├── auth/         # 登录/注册
│   ├── checkin/      # 打卡相关页面 (Index, Detail, Upload)
│   ├── courses/      # 课程相关页面
│   ├── teacher/      # 教师端页面 (Task, Student, Class)
│   ├── recall/       # 召回系统页面
│   ├── profile/      # 个人中心
│   └── ...
└── ...

功能更新记录 (Recent Changes)

  • 打卡详情页重构 (/checkin/detail)

    • 统一了文本、媒体上传和计数打卡的入口。
    • 实现了基于 useCheckin 的通用提交流程。
    • 优化了附件预览和编辑回填逻辑。
  • 教师端功能完善

    • 新增作业管理、作业主页(统计与日历视图)、学员作业记录页面。
  • 基础体验优化

    • 登录逻辑调整:仅在点击微信图标时触发授权。
    • 搜索栏优化:支持 iOS 软键盘搜索键。
    • 课程详情页:增加动态 Open Graph 标签,优化分享体验。

功能更新记录

  • 教师端新增作业管理页面:路径 /teacher/tasks,标题“作业管理”。
    • 列表展示:作业名称、开始时间、截止时间。
    • 当前数据来源为Mock,后续可替换为真实接口数据。
  • 教师端新增作业主页:路径 /teacher/tasks/:id,标题“作业主页”。
    • 头部:作业名称、介绍文案、细项信息(周期、频次、时间段、附件类型)。
    • 统计:出勤率与任务完成率(参考 myClassPage.vue 统计样式,数据Mock)。
    • 日历:使用 van-calendar 单选模式,选择日期后展示当日学生完成情况。
    • 学生完成情况:参考图片2样式,勾选代表已完成,未勾选代表未完成(数据Mock)。
  • 教师端新增学员作业记录页面:路径 /teacher/student-record,标题“学员作业记录”。
    • 在作业主页的学生列表点击卡片可跳转至该页面(当前版本为固定示例页面)。
    • 列表展示:作业帖子、图片/视频/音频、点赞与点评弹窗(与 studentPage.vue 的作业记录样式一致)。
    • 接口参数固定:user_id=817017group_id=816653(后续可替换为动态参数)。
  • 学习详情页标签指示条修复:/src/views/profile/StudyCoursePage.vue
    • 现象:首次进入且存在“打卡互动”时,底部绿色指示条定位错误。
    • 修复:新增标签容器 refResizeObserver,按栏目数量对容器进行等分,指示条宽度与位移按分段和索引计算,异步加载第三个栏目时不再错位。
  • 登录逻辑调整:仅在登录页微信图标点击时触发授权

    • 变更文件:/src/views/auth/LoginPage.vue/src/router/guards.js/src/router/index.js
    • 路由守卫:移除自动微信授权检查,新增 startWxAuth 供手动触发。
    • 登录页:微信图标绑定点击事件,非微信环境提示“请在微信内打开”。
    • 使用方式:进入登录页,点击微信图标进行授权登录。
  • 课程详情页动态 Open Graph 元标签

    • 行为:进入课程详情页时,在 <head> 中插入 4 个 meta 标签:og:title(课程 title)、og:description(课程 subtitle)、og:image(课程 cover)、og:url(当前页面 URL);这些 meta 必须插在 <title> 标签的前面;离开页面时移除。
    • CDN 规则:若图片域名为 cdn.ipadbiz.cn,自动追加 ?imageMogr2/thumbnail/200x/strip/quality/70
    • 位置:/src/views/courses/CourseDetailPage.vue,在 onMounted 插入,onUnmounted 清理。
    • 函数:build_og_image_url(src)set_og_meta(payload)remove_og_meta()
  • 课程详情页咨询弹窗(Mock)

    • 入口:详情页顶部快捷操作中的“咨询”按钮。
    • 展示:底部弹出层,仅底部关闭按钮;展示联系人列表,可点击名称或号码直接拨打(tel:)。
    • 联系人:支持多个联系人,展示姓名与号码;电话号码使用绿色高亮;联系人与号码字体大小一致。
    • 位置:/src/views/courses/CourseDetailPage.vue,“咨询弹窗”模板与交互逻辑(open_consult_dialogclose_consult_dialogconsult_contactscall_phone(phone))。
  • 购买流程环境校验

    • 行为:仅对非免费课程在详情页点击“购买”时进行校验;生产环境下必须为微信内置浏览器(wxInfo().isWeiXin)。
    • 免费课程:跳过微信环境校验,允许直接进入结算流程。
    • 非微信环境(付费课):提示“请在微信内打开进行购买”,不进入结算。
    • 位置:/src/views/courses/CourseDetailPage.vuehandlePurchase 中,使用 wxInfo 进行环境判断。
  • 微信授权自动触发(微信环境内)

    • 行为:在微信内置浏览器环境下点击“购买”时,若检测到未完成微信授权(openid_has=false),系统将自动发起一次微信授权流程并中止本次购买;授权完成后再次点击可进入结算。
    • 开发环境:不触发微信授权流程(保留现有调试行为)。
    • 位置:/src/views/courses/CourseDetailPage.vuehandlePurchase 中,调用 getAuthInfoAPI() 探测并使用 startWxAuth() 触发授权。
  • 401拦截策略优化(公开页面不再跳登录)

    • 行为:接口返回 code=401 时,不再对公开页面(如课程详情 /courses/:id)进行登录重定向;仅当当前路由确实需要登录权限时才跳转至登录页。
    • 原理:响应拦截器调用路由守卫 checkAuth 判断当前路由是否为受限页面,受限则清理登录信息并附带 redirect 重定向至登录页;公开页面保持当前页,由业务自行处理401。
    • 位置:/src/utils/axios.js,在响应拦截器中按需处理重定向。
  • 搜索栏回车搜索兼容性提升

    • 行为:将输入框类型改为 search,并可选开启 form @submit.prevent 机制以提升 iOS 设备软键盘“搜索”键触发稳定性;同时保留 @keyup.enter 回车触发搜索。
    • 路由行为:
    • 课程页(isCoursePage=true):回车或搜索键触发后跳转至 /courses-list 并携带 keyword 参数。
    • 列表页:仅更新当前路由的查询参数 keyword
    • 位置:/src/components/ui/SearchBar.vue,新增 useFormSubmit 可选参数(默认开启)。
  • 课程列表页搜索触发修复

    • 现象:进入列表页后,输入关键字并更新为 /courses-list?keyword=xxx 时未触发搜索。
    • 原因:父组件 handleSearch 对“相同关键字”进行了拦截,导致路由参数变化不执行请求。
    • 修复:移除拦截逻辑;无论关键字是否变化均触发搜索(防抖控制频率)。
    • 位置:/src/views/courses/CourseListPage.vuehandleSearch
  • 分享海报弹窗(通用组件)

    • 入口:课程详情页底部操作栏“分享”按钮。
    • 组件:/src/components/ui/SharePoster.vue(支持复用),v-model:show 控制显隐,course 传入课程信息,qr_url 可指定二维码内容地址(默认取当前页面 URL)。
    • 布局:上部封面图;下部信息区左侧二维码,右侧课程标题、副标题、精简介绍与日期范围。
    • 样式:优先使用 TailwindCSS 布局;组件内部使用 Less 做层级嵌套的样式补充。
    • 图片规则:当封面图域名为 cdn.ipadbiz.cn 时,自动追加 ?imageMogr2/thumbnail/200x/strip/quality/70 压缩参数。
    • 接入位置:/src/views/courses/CourseDetailPage.vue,导入并渲染 <SharePoster v-model:show="show_share_poster" :course="course" />
    • Canvas 合成:弹窗打开时使用 Canvas 直接合成海报(封面图、二维码、文案),生成 dataURL 并以 <img> 展示,用户可直接长按图片保存到手机(无需额外按钮)。
    • 依赖:pnpm add qrcode(在 Canvas 内本地生成二维码,避免跨域图片导致画布污染)。
    • 跨域:通过 crossorigin="anonymous" 加载封面,并追加时间戳防缓存;若封面跨域不允许,则显示降级卡片,仍可长按截图保存。
    • 文案:使用中文字体并自动换行限制行数,末行超出追加省略号。
  • 打卡弹窗统一为通用组件 CheckInDialog

    • 目的:统一 CourseDetailPage、StudyCoursePage、StudyDetailPage 三处页面的打卡弹窗与交互,避免重复逻辑。
    • 组件:/src/components/ui/CheckInDialog.vuev-model:show 控制显隐;支持外部传入任务列表。
    • Props:
    • items_today:今日打卡任务数组(外部传入)。
    • items_history:历史打卡任务数组(外部传入)。
    • 数据结构:每项需包含 idtitle(name)task_typecheckin/upload)、is_gray
    • 使用位置:
    • /src/views/courses/CourseDetailPage.vue
    • /src/views/profile/StudyCoursePage.vue
    • /src/views/study/StudyDetailPage.vue
    • 清理:上述页面已移除旧弹窗的冗余状态与方法(如 default_listshowTaskListshowTimeoutTaskListselectedCheckIn 等),统一由组件内部处理。
  • 打卡列表组件 CheckInList(复用)

    • 目的:抽取首页与弹窗内重复的“打卡类型列表 + 提交按钮”UI与交互逻辑,提升复用性与维护性。
    • 位置:/src/components/ui/CheckInList.vue,样式补充:/src/components/ui/CheckInList.less(使用 Less 层级嵌套)。
    • Props:
    • items:打卡任务数组,元素包含 idnametask_typecheckin/upload)、is_gray
    • dense:是否使用更紧凑的栅格与间距。
    • scroll:是否启用滚动容器(最大高度 13rem)。
    • Emits:
    • submit-success:提交成功后触发,由父组件决定后续行为(轻提示、关闭弹窗等)。
    • 行为:
    • 点击置灰的 checkin 项时提示“您已经完成了今天的打卡”。
    • 点击 upload 类型时跳转到 /checkin/index?id=xxx 上传页面。
    • 选择 checkin 类型后显示提交按钮,点击后调用接口提交;成功后抛出 submit-success 并重置选中项。
    • 使用位置:
    • 首页:/src/views/HomePage.vue(替换原重复 UI,监听 submit-success 显示“打卡成功”)。
    • 弹窗:/src/components/ui/CheckInDialog.vue(以 active_list 作为数据源,监听 submit-success 转发为 check-in-success 并延时关闭)。
  • 打卡详情页(统一提交/编辑页)CheckinDetailPage

    • 路径:/checkin/detail,页面文件:/src/views/checkin/CheckinDetailPage.vue
    • 目标:统一“提交作业/打卡”的入口,覆盖文本/图片/视频/音频上传,以及计数打卡;同时承接“编辑已提交动态”的入口。
    • 路由参数约定(query):
    • 新增提交:task_id(大作业ID)、subtask_id(可选,默认选中小作业)、date(YYYY-MM-DD,用于补卡与月份计算)、is_patch(是否补卡:'1'/'0')、task_type(当前作业类型,常见为 upload/count)。
    • 编辑提交:额外携带 status=editpost_id(打卡动态ID)、type(原 file_type,实际以详情接口回填为准)。
    • 初始化数据:
    • 大作业详情:调用 getTaskDetailAPI({ i: task_id, month }) 获取作业描述、默认附件类型、完成状态等。
    • 小作业列表:调用 getSubtaskListAPI({ task_id, date }) 获取小作业列表并生成 Picker 选项(包含 note/field_list/person_type/attachment_type/is_makeup 等)。
    • 编辑回填:通过 useCheckin().initEditDatagetUploadTaskInfoAPI({ i: post_id }) 回填 note/file_type/files/subtask_id/gratitude_count 等。
    • 附件类型与上传限制:
    • normalizeAttachmentTypeConfig 解析后端 attachment_type 配置,生成 attachmentTypeOptions,并通过 setMaxFileSizeMbMap 写入不同类型的最大上传大小。
    • 计数打卡(task_type=count)下过滤掉 text 类型;非计数模式下当 activeType 不在选项中时自动重置为第一个可用类型。
    • 提交流程(核心封装在 useCheckin):
    • 上传:beforeRead/afterRead 先校验数量/大小/类型,再走七牛上传(hash 去重 → token → upload → saveFile),成功回填 meta_id/url/status
    • 提交:onSubmit 新增走 addUploadTaskAPI,编辑走 editUploadTaskInfoAPI;成功后写 sessionStorage.checkin_refresh_flag/checkin_refresh_id 供列表页局部刷新,并 router.back() 返回。
    • 页面层校验:文本打卡至少 10 字;计数打卡必须选择对象且次数 > 0;非文本类型必须有文件。
    • 计数打卡交互:
    • 通过 reuseGratitudeFormAPI({ subtask_id }) 获取可选对象列表 targetList 与最近使用 last_used_list,进入页面会自动勾选最近使用项。
    • 选中对象首次会弹窗确认(标记 has_confirmed),支持新增/编辑;删除对象调用 gratitudeDeleteAPI(当前页面内未引入该 API,需补齐后才可生效)。
    • 预览能力:
    • 上传组件点击预览时,根据扩展名识别:音频使用 AudioPlayer 底部弹窗;视频使用 VideoPlayer 居中弹窗(封面 → 点击播放 → 关闭时重置进度);图片使用 van-image-preview