教育 SaaS 工具的多模块协同设计:拾趣课堂前端架构与产品体验实践
引言
前端教育工具开发有一个隐形难题:一个产品里通常有十几个并存的子工具,每个工具的交互密度、数据规模、登录要求都不同。本文以一个真实的教师课堂工具平台「拾趣课堂」为例,分享 Vue3 工具平台架构的具体取舍,包括如何让倒计时这种纯交互工具和灵兽积分这种重数据工具共存于同一个前端工程,如何在 SaaS 产品体验和 SEO 要求之间找到平衡。
技术栈:Vue 3.5 + TypeScript 5 + Vite 6 + Inertia.js 2 + Tailwind CSS 3 + shadcn-vue(底层 radix-vue)+ Laravel 12 后端。
一、模块边界:从扁平目录到分层结构
教育科技产品的目录结构最容易腐化。最初的扁平结构可能是:
pages/
├── Countdown.vue
├── Pick.vue
├── Seat.vue
├── Pet.vue
└── Mbti.vue
随着工具数量增加,每个工具内部的子组件、子页面、Composables 都会指数级增长。拾趣课堂采用按工具分目录的分层结构:
resources/js/
├── components/
│ ├── ui/ ← shadcn-vue 基础组件,禁止修改
│ ├── common/ ← 跨工具共享组件
│ └── tools/
│ ├── countdown/ ← 倒计时专属组件
│ ├── seat/ ← 排座专属组件
│ ├── pick/ ← 点名专属组件
│ └── pet/ ← 灵兽积分专属组件
├── composables/
├── layouts/
├── lib/
└── pages/
├── Landing/
├── Classroom/
└── Tools/
├── Countdown/
├── Seat/
├── Pick/
└── Pet/
前端教育产品架构的关键判断:哪些组件应该放进 common/,哪些应该放进工具专属目录?经验法则是:超过两个工具会用到的组件才放 common/,否则放工具目录里。过早抽象比重复更危险。
二、Inertia 2 在前端教育平台的适配性
很多人会问:为什么不上纯 SPA?
教师工具的访问路径决定了 Inertia 是更优解:
- 大量未登录工具页:倒计时、人格测试、资源库不需要登录就能用,纯 SPA 的鉴权空架子在这些页面是负担
- SEO 是一等公民:百度搜索"在线倒计时"、"班级积分"是主要获客路径,需要 SSR 提供完整 HTML
- 快速迭代:教师工具的产品需求碎片化,每个工具单独维护一套 API + Store + Component 成本太高
Inertia 2 相对 v1 的关键改进对教育 SaaS 体验提升明显:
| 特性 | 价值 |
|---|---|
Inertia::defer() + <Deferred> | 慢查询不阻塞首屏,骨架屏自然过渡 |
router.reload({ only: ['xxx'] }) | 排座面板局部刷新数据,不丢失拖拽状态 |
useForm() 内置 errors | 避免手动 catch 422 的重复代码 |
更稳定的 usePage() 类型推断 | TypeScript 体验显著改善 |
三、shadcn-vue 在教育产品的取舍
shadcn-vue 的底层是 radix-vue(不是 reka-ui,这点容易踩坑)。对教育 SaaS 工具的实际价值:
适合用 shadcn-vue 的场景:表单、对话框、Tooltip、下拉菜单、Toast。这些通用交互直接复用,节约大量样式调试时间。
不适合用 shadcn-vue 的场景:
- 倒计时的波浪液面表盘 —— 视觉强差异化的核心组件,自己写 SVG 动画
- 灵兽进化庆典覆盖层 —— 全屏舞台光效,shadcn 没有现成方案
- 排座面板的拖拽网格 —— 交互逻辑高度定制,hand-craft 更合适
- 盲盒点名矩阵 —— 视觉特效是产品差异化点
关键原则:shadcn-vue 用在"无聊但必须有"的部分,自定义 hand-craft 用在"差异化体验"的部分。混淆这两者会让产品体验平庸。
四、composables 的拆分粒度
前端教育产品架构里,composables 是最容易写烂的地方。拾趣课堂的拆分原则:
// 一个 composable 只做一件事
useCountdown() // 计时状态机
useAlertSound() // 音效反馈
useFullscreen() // 全屏控制
useKeyboardShortcut() // 快捷键
倒计时页面把这四个 composable 组合起来用,而不是写一个巨大的 useCountdownPage()。每个 composable 可以独立测试、独立替换。
灵兽积分系统的状态机更复杂,但同样按职责拆分:
usePetSummon() // 召唤选择族系
usePetAwaken() // 觉醒选择属性
usePetEvolution() // 进化庆典动画
usePetGraduate() // 毕业仪式
useScoreDraft() // 草稿批量提交
每个钩子的输入输出清晰、副作用可控。重构时只需要替换单个钩子。
五、SEO 与教育产品的特殊耦合
教育 SaaS 用户体验和 SEO 在多数场景下是协同的:
- 首屏渲染快 —— 同时利好用户体验和 Core Web Vitals
- 结构化内容 —— FAQ、How-to 既帮助用户理解也帮助富摘要
- 不堆砌交互 —— 让搜索引擎能解析的内容更多,用户也读得更轻松
具体实践:
- 所有工具落地页都有 SEO 说明区,与交互区域并列
- 工具内置 JSON-LD 的 SoftwareApplication / FAQ schema
- Inertia SSR 保证未登录页面 100% 可被爬虫解析
sitemap.xml自动包含 PubArticle 文章页
六、用户体验上的关键设计判断
教师工具的用户群有两个特点:使用场景碎片、设备五花八门(投影、一体机、个人电脑、手机临时查看)。这导致几个反直觉的体验决策:
6.1 工具页面默认撑满,文章页面默认居中
.github/copilot-instructions.md 里有一条规则:"老师在'看'的页面居中留白,老师在'用'的页面撑满屏幕"。课堂场景下投屏需要每一寸像素,留白是浪费。
6.2 全屏模式自动隐藏控件
倒计时全屏后,三秒无鼠标移动就隐藏所有按钮,只留下时间和波浪表盘。投屏画面更接近"真正的课堂工具",而不是"后台面板"。
6.3 动画用得克制
教育产品最容易踩的坑是动画过度。课堂上投屏画面如果一直在动,会分散学生注意力。拾趣课堂的所有动画都遵循「触发即结束」原则,不做循环动画,不做"装饰性"运动。
6.4 默认值优于配置项
排座工具如果让老师配置 20 个参数,没人会用。拾趣课堂的智能排座只暴露两个约束开关(近视靠前、男女交替)和两个核心模式(身高排序、随机排座),其他全部走合理默认值。
七、可借鉴的 SaaS 产品体验优化经验
- 未登录优先:能不要求登录的功能就别要求,登录窗口越靠后越好
- 场景化默认值:6 个倒计时预设直接对应课堂时长,老师不用思考
- 状态可视化:状态颜色联动比纯文字提示更适合远距离观看
- 撤回比确认重要:积分误操作的撤回入口比"确认提交"按钮的位置更显眼
- 快照而非覆盖:排座方案保存为多个快照,比覆盖式保存安全得多
总结
前端教育工具开发的核心命题不是用什么框架,而是如何让多个差异巨大的子工具在同一个工程里共存。拾趣课堂的实践给出三个可复用的判断:按工具分目录、shadcn-vue 用在通用部分而 hand-craft 用在差异化部分、composables 拆到一个钩子只做一件事的粒度。Vue3 + Inertia 2 + TypeScript + Tailwind 3 在这个组合里几乎是性价比最优解,值得做教育 SaaS 工具的团队参考。