Skip to content

Repository files navigation

TinyStudy

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 dev

npm run setup 是交互式安装向导,会依次:

  1. 选择 SQLite 或 PostgreSQL;
  2. 填写数据库连接(SQLite 自动完成);
  3. 设置超级管理员账号、显示名称和密码;
  4. 自动生成 JWT 安全密钥;
  5. 生成 Prisma Client、初始化表、写入默认 RBAC 权限;
  6. 创建超级管理员钱包。

SQLite 初始化优先使用 Prisma;在受限环境中若 Prisma Schema Engine 不可用且系统已安装 sqlite3,安装器会自动使用仓库内的 prisma/sqlite/init.sql 完成等价初始化。

安装向导默认使用 API 端口 3001,并会自动同步给前端开发代理。安装结束后请在项目根目录运行 npm run dev,并确认终端同时出现 Web 和 API 的启动地址。如果端口被占用,开发服务会直接停止并显示原因,不会再出现只有登录页能打开的假启动状态。

打开:

局域网内其他电脑可以使用运行 TinyStudy 电脑的局域网 IP:

前端:http://192.168.x.x:5173
接口:http://192.168.x.x:3001

前后端均监听所有网卡,开发环境默认允许来自本机和私有局域网地址的访问。请同时确认操作系统防火墙允许 TCP 51733001 端口。

账号注册入口有意关闭。所有教师与学生账号都由超级管理员创建。

登录显示 Not Found

如果项目从旧版本迁移而来,请使用新版源码重新执行:

npm run setup
npm run dev

新版安装向导会清理可能覆盖前端配置的旧构建文件,并让登录请求自动连接到安装时选择的 API 端口。还可以在浏览器访问以下地址检查服务:

http://localhost:5173/api/health

正常时会返回包含 "ok": true 的 JSON。如果无法访问,请检查 npm run dev 的终端中 API 是否成功启动,以及 .env 中的 PORTAPI_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

SQLite / PostgreSQL 切换

配置在 .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

AI 配置

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 支持 FLASHCARDSINGLE_CHOICETRUE_FALSE

卡片的 rewardCoins 是首次答对奖励。系统会按学生与卡片分别记录历史答对次数:首次发放 100%,第二次 50%,第三次 25%,之后继续减半。金币余额和账本支持小数;卡片购买价、礼物价格与钻石仍使用整数。

HTML 礼物格式

上传 ZIP,根目录必须包含:

gift.zip
├── index.html
├── assets/
│   ├── model.glb
│   └── texture.png
└── app.js

可包含 Canvas、Three.js、CSS 和本地资源。服务端会拒绝路径穿越,学生端使用受限 iframe 预览。HTML 礼物若引用第三方 CDN,需要生产服务器的网络策略允许该域名;更推荐把依赖打包进 ZIP。

构建与 PM2 部署

npm run build
npm run pm2:start

生产时 Fastify 同时提供:

  • /api/* API
  • /assets/* 礼物静态资源
  • React SPA

单机一键部署:

./scripts/deploy.sh

PM2 日志位于 logs/。配置变更后:

npm run pm2:restart

Docker 部署

先复制并修改配置:

cp .env.example .env

SQLite:

docker compose up -d --build

PostgreSQL:

docker compose --profile postgres up -d --build

PostgreSQL 模式下把应用 .env 的数据库地址主机改为 postgres

数据迁移与备份

超级管理员进入“迁移与审计”:

  • 导出:生成包含身份、RBAC、钱包、内容、学习、礼物元数据和日志的版本化 JSON;
  • 导入:校验 tinystudy-backup 格式和超级管理员后,按依赖顺序完整恢复;
  • 礼物文件:同步复制 storage/gifts/,并保持相对目录不变。

生产备份应同时保存:

tinystudy-backup-*.json
storage/gifts/

密码仅以 bcrypt 哈希迁移,明文密码和 AI/JWT 密钥不会出现在导出中。

推荐的首次验收流程

  1. 安装时创建超级管理员;
  2. 管理员创建教师“张三”和学生“李四”,给李四 5 金币;
  3. 管理员创建图片鲨鱼礼物和 HTML 互动礼物;
  4. 张三创建 10 道题的卡片集,售价 5 金币,每题奖励 1 金币;
  5. 李四购买并完成卡片集,观察逐题金币动画和最终奖励;
  6. 管理员继续发放金币至 100,李四在礼物中心兑换礼物;
  7. 李四在礼物房勾选礼物并转换钻石;
  8. 管理员查看钱包流水和审计日志。

启动 API 后也可运行自动化冒烟验收:

node scripts/smoke.mjs
node scripts/feature-smoke.mjs

smoke.mjs 会创建一次性教师/学生数据,完成购买、答题奖励和钱包账本校验;feature-smoke.mjs 会额外验证字段级错误提示、账号编辑/删除、礼物删除以及带选项卡片的练习流程。两个脚本仅建议在开发数据库使用。

安全上线清单

  • 使用 HTTPS 和反向代理;
  • 设置长度至少 32 位的不同 JWT 密钥;
  • 限制 ALLOWED_ORIGINS
  • 使用 PostgreSQL 进行多实例部署;
  • storage/ 挂载到持久卷并纳入备份;
  • 定期轮换 AI API Key;
  • 不要把 .env、数据库文件、备份或 storage/ 提交到 Git;
  • iframe 权限按具体 HTML 礼物需要最小化开放。

更多设计说明见 docs/ARCHITECTURE.md

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages