TinyStudy 是一个简易、完整的学习卡片 Web SaaS:超级管理员统一创建账号并管理奖励经济,教师创建或 AI 生成卡片集,学生购买卡片集、答题赚金币、兑换礼物,再把礼物转换为钻石。
UI 方向融合 Quizlet 的学习效率、Notion 的信息清晰度和 Duolingo 的即时激励,尤其优化了学生答题时的金币爆发动画、礼物预览和完成反馈。
- 默认超级管理员安装与登录
- 创建、编辑、删除教师/学生/管理员账号,支持修改登录名、显示名称、密码、角色和状态
- 超级管理员可直接使用全部教师功能,包括卡片集、学习结果和 AI 创作
- RBAC 角色/权限数据模型与服务端权限守卫
- 增加、减少或直接设置任意用户的金币与钻石,完整钱包账本
- 图片礼物和 HTML ZIP 礼物上传
- HTML 礼物 iframe 预览、全屏预览、库存、金币售价、钻石价值和礼物删除
- 表单按具体字段返回中文校验提示,不再只显示笼统的格式错误
- 审计日志、系统配置
- 系统业务数据 JSON 导出/合并导入
- 创建、编辑、发布卡片集
- 已保存或已发布卡片集仍可修改标签、展示色、市场售价和可见范围
- 支持公开市场或指定学生名单,并可随时调整分配
- 手动创建卡片并逐题设置奖励金币
- 已保存或已发布的单张卡片仍可编辑和删除,历史作答记录继续保留
- 固定 JSON 数组导入
- AI 生成卡片、测试题、知识点解释
- 分配卡片集给学生
- 查看学生正确率、奖励和学习记录
- 按每次学习会话展开错题明细,定位卡片序号、题目、学生答案、正确答案与解析
- 浏览市场、使用金币购买卡片集
- 查看已购买或教师分配的卡片集
- 单选、判断、文字作答和翻看答案四种学习交互;旧数据只要含选项也会自动显示选项
- 答对后实时金币结算和爆金币动画;同一学生再次答对同一卡片时,奖励按 50% 逐次衰减(例如 1、0.5、0.25)
- 学习完成页与奖励反馈
- 礼物中心兑换、图片/HTML 礼物预览
- 未兑换礼物使用神秘礼物盒展示,兑换后才在礼物房揭晓内容
- 礼物房多选礼物转换钻石,转换完成后礼物立即从礼物房移除
- 钱包余额与完整流水
- 前端:React 19、Vite、Tailwind CSS、shadcn/ui 风格组件、Zustand、React Router
- 后端:Node.js 22 ESM、Fastify、JWT、Zod
- 数据:Prisma ORM,SQLite / PostgreSQL 双配置
- API:OpenAPI 3 + Swagger UI
- 进程:PM2
- 部署:Docker Compose 或单机部署脚本
TinyStudy/
├── apps/
│ ├── web/ # React SPA
│ └── api/ # Fastify API
├── prisma/
│ ├── sqlite/schema.prisma
│ └── postgresql/schema.prisma
├── scripts/
│ ├── setup.mjs # 类 WordPress 安装向导
│ ├── db-command.mjs # 数据库类型路由
│ └── deploy.sh # 单机一键部署
├── storage/ # 礼物静态资源
├── docs/ARCHITECTURE.md # 产品与技术架构
├── ecosystem.config.cjs
├── docker-compose.yml
└── .env.example
- Node.js 22+
- npm 10+
- SQLite 无需额外安装
- PostgreSQL 部署需要 PostgreSQL 14+,或使用 Docker Compose 内置服务
npm install
npm run setup
npm run devnpm run setup 是交互式安装向导,会依次:
- 选择 SQLite 或 PostgreSQL;
- 填写数据库连接(SQLite 自动完成);
- 设置超级管理员账号、显示名称和密码;
- 自动生成 JWT 安全密钥;
- 生成 Prisma Client、初始化表、写入默认 RBAC 权限;
- 创建超级管理员钱包。
SQLite 初始化优先使用 Prisma;在受限环境中若 Prisma Schema Engine 不可用且系统已安装 sqlite3,安装器会自动使用仓库内的 prisma/sqlite/init.sql 完成等价初始化。
安装向导默认使用 API 端口 3001,并会自动同步给前端开发代理。安装结束后请在项目根目录运行 npm run dev,并确认终端同时出现 Web 和 API 的启动地址。如果端口被占用,开发服务会直接停止并显示原因,不会再出现只有登录页能打开的假启动状态。
打开:
- Web:http://localhost:5173
- API:http://localhost:3001
- Swagger:http://localhost:3001/docs
- OpenAPI JSON:http://localhost:3001/openapi.json
局域网内其他电脑可以使用运行 TinyStudy 电脑的局域网 IP:
前端:http://192.168.x.x:5173
接口:http://192.168.x.x:3001
前后端均监听所有网卡,开发环境默认允许来自本机和私有局域网地址的访问。请同时确认操作系统防火墙允许 TCP 5173 和 3001 端口。
账号注册入口有意关闭。所有教师与学生账号都由超级管理员创建。
如果项目从旧版本迁移而来,请使用新版源码重新执行:
npm run setup
npm run dev新版安装向导会清理可能覆盖前端配置的旧构建文件,并让登录请求自动连接到安装时选择的 API 端口。还可以在浏览器访问以下地址检查服务:
http://localhost:5173/api/health
正常时会返回包含 "ok": true 的 JSON。如果无法访问,请检查 npm run dev 的终端中 API 是否成功启动,以及 .env 中的 PORT 或 API_URL 是否被其他程序占用。默认 API 地址是 http://127.0.0.1:3001。
CI 或自动部署可使用环境变量:
DB_PROVIDER=sqlite \
DATABASE_URL="file:/absolute/path/to/prisma/dev.db" \
SUPER_ADMIN_USERNAME=admin \
SUPER_ADMIN_PASSWORD='Your-Strong-Password' \
npm run setup -- --non-interactive配置在 .env:
# SQLite
DB_PROVIDER=sqlite
DATABASE_URL=file:/absolute/path/to/TinyStudy/prisma/dev.db# PostgreSQL
DB_PROVIDER=postgresql
DATABASE_URL=postgresql://tinystudy:password@127.0.0.1:5432/tinystudy?schema=public切换后执行:
npm run db:generate
npm run db:push生产系统已有数据时,请先在管理端导出备份。不要对重要生产库使用 db push --accept-data-loss。
TinyStudy 使用 OpenAI-compatible chat/completions 接口。编辑 .env:
AI_ENABLED=true
AI_BASE_URL=https://api.openai.com/v1
AI_API_KEY=your-api-key
AI_MODEL=gpt-4.1-mini
AI_TIMEOUT_MS=45000所有 AI 响应必须是 JSON 数组,并在服务端做结构校验。不合法输出不会进入卡片集。
卡片导入格式:
[
{
"front": "shark",
"back": "鲨鱼",
"questionType": "SINGLE_CHOICE",
"options": ["鲨鱼", "海豚", "鲸鱼", "章鱼"],
"correctAnswer": "鲨鱼",
"explanation": "Shark 指鲨鱼。",
"rewardCoins": 1
}
]questionType 支持 FLASHCARD、SINGLE_CHOICE、TRUE_FALSE。
卡片的 rewardCoins 是首次答对奖励。系统会按学生与卡片分别记录历史答对次数:首次发放 100%,第二次 50%,第三次 25%,之后继续减半。金币余额和账本支持小数;卡片购买价、礼物价格与钻石仍使用整数。
上传 ZIP,根目录必须包含:
gift.zip
├── index.html
├── assets/
│ ├── model.glb
│ └── texture.png
└── app.js
可包含 Canvas、Three.js、CSS 和本地资源。服务端会拒绝路径穿越,学生端使用受限 iframe 预览。HTML 礼物若引用第三方 CDN,需要生产服务器的网络策略允许该域名;更推荐把依赖打包进 ZIP。
npm run build
npm run pm2:start生产时 Fastify 同时提供:
/api/*API/assets/*礼物静态资源- React SPA
单机一键部署:
./scripts/deploy.shPM2 日志位于 logs/。配置变更后:
npm run pm2:restart先复制并修改配置:
cp .env.example .envSQLite:
docker compose up -d --buildPostgreSQL:
docker compose --profile postgres up -d --buildPostgreSQL 模式下把应用 .env 的数据库地址主机改为 postgres。
超级管理员进入“迁移与审计”:
- 导出:生成包含身份、RBAC、钱包、内容、学习、礼物元数据和日志的版本化 JSON;
- 导入:校验
tinystudy-backup格式和超级管理员后,按依赖顺序完整恢复; - 礼物文件:同步复制
storage/gifts/,并保持相对目录不变。
生产备份应同时保存:
tinystudy-backup-*.json
storage/gifts/
密码仅以 bcrypt 哈希迁移,明文密码和 AI/JWT 密钥不会出现在导出中。
- 安装时创建超级管理员;
- 管理员创建教师“张三”和学生“李四”,给李四 5 金币;
- 管理员创建图片鲨鱼礼物和 HTML 互动礼物;
- 张三创建 10 道题的卡片集,售价 5 金币,每题奖励 1 金币;
- 李四购买并完成卡片集,观察逐题金币动画和最终奖励;
- 管理员继续发放金币至 100,李四在礼物中心兑换礼物;
- 李四在礼物房勾选礼物并转换钻石;
- 管理员查看钱包流水和审计日志。
启动 API 后也可运行自动化冒烟验收:
node scripts/smoke.mjs
node scripts/feature-smoke.mjssmoke.mjs 会创建一次性教师/学生数据,完成购买、答题奖励和钱包账本校验;feature-smoke.mjs 会额外验证字段级错误提示、账号编辑/删除、礼物删除以及带选项卡片的练习流程。两个脚本仅建议在开发数据库使用。
- 使用 HTTPS 和反向代理;
- 设置长度至少 32 位的不同 JWT 密钥;
- 限制
ALLOWED_ORIGINS; - 使用 PostgreSQL 进行多实例部署;
- 将
storage/挂载到持久卷并纳入备份; - 定期轮换 AI API Key;
- 不要把
.env、数据库文件、备份或storage/提交到 Git; - iframe 权限按具体 HTML 礼物需要最小化开放。
更多设计说明见 docs/ARCHITECTURE.md。