TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Kids Playground
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗一年级孩子的学习打卡 + 积分 + 礼物兑换系统。
/kid/[孩子的slug],手机浏览器打开即可,查看今日任务、打卡、兑换礼物。/admin,需要密码登录,管理任务模板、临时任务、积分、礼物、打卡记录、兑换记录。技术栈:Next.js (App Router) + Prisma 7 + Neon Postgres(Serverless Postgres)+ Vercel 部署。
以下三个都是免费额度,用邮箱或 GitHub 账号注册即可:
postgresql://用户名:密码@xxx.neon.tech/数据库名?sslmode=require 的连接串,这就是下面要用的 DATABASE_URL。项目根目录已经有一个 .env 文件(由 prisma init 自动生成),打开它,确保包含下面两个变量(没有就手动加上):
DATABASE_URL="上一步从 Neon 复制的连接串"
SESSION_SECRET="随便一串足够长的随机字符串,用 `openssl rand -hex 32` 生成"
.env 已经在 .gitignore 里,不会被提交到 git,可以放心写真实密钥。
账号密码不再放在环境变量里——第一次打开网站会引导你创建家长账号(这个账号自动成为 超级管理员,能在「账号总览」里查看和代管其它账号),密码用 PBKDF2 哈希后存数据库。
SESSION_SECRET换掉会让所有人的登录状态失效(需要重新登录),别随便改。
系统默认只有你一个账号。想让朋友注册,用超管账号打开 /admin/tenants,
点「生成一个邀请码」,把生成的码(形如 K7QM-3XPT-9WRD)发给对方。
/signup 会重定向回登录页。这是刻意的默认值:
不会因为忘了配置就变成对全网开放注册。邀请码存在数据库里而不是环境变量里,所以点一下就能换,不用重新部署。 每个账号是完全独立的租户,看不到别人家的孩子和数据。
登录和注册目前都没有做限流,一次性 + 12 位随机码(≈2^60)是现阶段防爆破的主要手段。
所有价格最初都是照着「每天 25 阳光」定的。你在「任务模板」加一门课,日薪就变了, 而礼物、精灵球、植物的价格不会自己跟上——这是最容易被忽略、又实实在在影响激励效果的一件事。
后台的 「经济体检」 页把这件事摊开:
系统自动发的那些数额不用管——满勤奖、刷新费、图鉴里程碑、重复返还都已经改成按日薪算, 改任务模板会自动跟上(日薪 25 时的数值和写死的时代分毫不差)。
跑 npm run check:economy 可以把上面这些规则全自检一遍。
图鉴库有前三世代 386 只,但不是一次全放出来:从关都(1–151)开始, 集齐当前地区 80% 就自动开放下一个(城都 → 丰缘),孩子会看到「新地区开放了」。
一次全开的话,按模拟重度玩家 21 个月就集齐了,之后扔球期望回报远低于球价, 没有任何理由再抓。分批之后能撑到六年以上。
立绘不存在仓库里,由应用代理转发:浏览器请求 /pokemon-art/<id>,服务端去
PokeAPI 托管在 GitHub 上的官方立绘取图再转出来。
为什么要绕这一层:raw.githubusercontent.com 在国内访问不了,直接外链的话
孩子和朋友那边图片全是裂的。走自己的域名就没这个问题——应用域名本来就必须可达。
万一哪天连服务器也取不到 GitHub,换个镜像只改一个环境变量:
# 可选,不配就用 GitHub 上的官方源
POKEMON_ART_BASE="https://fastly.jsdelivr.net/gh/PokeAPI/sprites@master/sprites/pokemon/other/official-artwork"
npm install
npm run db:migrate # 在 Neon 数据库里建表(首次运行会让你输入一个迁移名字,随便填比如 init)
npm run db:seed # 创建一个示例孩子档案 + 示例任务模板 + 示例礼物
db:seed 跑完后,终端会打印出示例孩子的打卡链接,形如 /kid/doudou-demo,先用这个示例链接跑通全流程,正式使用前记得去家长后台把示例数据换成真实的。
如果执行 Prisma 相关命令时报 TLS/证书相关的错误,可以在命令前加上
NODE_OPTIONS="--use-system-ca"试试(部分公司网络环境下 Node 默认的证书库和系统证书库不一致导致的)。
npm run dev
打开 http://localhost:3000:
/setup 引导你创建家长账号(邮箱 + 密码,至少 8 位)。建完之后注册入口自动关闭,
别人再打开只能看到登录页。建号时会自动把已存在的孩子档案认领到这个账号下。/login,登录后按角色分流:家长 → /admin,孩子设备 → /kid。孩子的平板怎么设置:在平板上打开网站 → 登录时勾选「这是孩子的设备」 → 登录后会落到 /kid,
把这个地址「添加到主屏幕」。这台设备的会话有效期一年,且只能打开孩子端、进不了家长后台,
所以孩子没法自己批准自己的任务。你自己的手机/电脑登录时不勾这个框,拿到的是完整权限。
/login。/kid/[slug](隐身窗口模拟孩子视角),确认任务出现,点击"完成",积分从 0 变成 10。把代码推到 GitHub(新建一个私有仓库):
git init
git add .
git commit -m "init"
git branch -M main
git remote add origin <你的仓库地址>
git push -u origin main
去 Vercel 网站 "Add New… → Project",选择刚才的 GitHub 仓库导入。
在 Vercel 项目的 Environment Variables 里配置三个变量(和本地 .env 里的一样):
DATABASE_URL、SESSION_SECRET。
点 Deploy,等构建完成后会拿到一个 https://xxx.vercel.app 的线上地址。
线上环境同样跑一遍 1.4 的走查清单(可以新建一个明确标记"测试"的任务/礼物,走完后在后台删除或停用)。
⚠️
*.vercel.app这个默认域名在国内打不开,而这个应用是给国内的孩子用的。 想真正用起来必须配自定义域名 + Cloudflare 代理,见下一节。
*.vercel.app 打不开有两层原因,实测确认过(2026-09):
| 测的什么 | 结果 |
|---|---|
国内手机流量打开 https://<自定义域名>,A 记录直接指向 Vercel 76.76.21.21 | ❌ 连不上(Safari「打不开该页面」,不是证书错误也不是 DNS 错误) |
国内手机流量打开 https://www.cloudflare.com | ✅ 正常 |
也就是说不只是 vercel.app 这个域名被墙,Vercel 的 anycast IP 本身从国内就连不上——
换个自己的域名直连 Vercel 一样没用。而 Cloudflare 的边缘节点是通的,
所以要让 Cloudflare 挡在前面代理回源:
访客 ──HTTPS──> Cloudflare 边缘 ──HTTPS──> Vercel(源站)
访客看到的是 这一段不校验证书
Cloudflare 的证书 (见下面的 SSL 模式)
配置步骤:
vercel domains add <域名> <项目名>A @ 76.76.21.21 🟠 Proxied
CNAME www cname.vercel-dns.com 🟠 Proxied
xxx.ns.cloudflare.com)。
阿里云提示需要 24–48 小时生效,是注册局层面的下发延迟,急不得Full第 6 步的 Full 不能想当然换成别的,三个选项各有坑:
| 模式 | Cloudflare→Vercel | 后果 |
|---|---|---|
| Flexible | 明文 HTTP | ❌ Vercel 把 HTTP 跳 HTTPS、Cloudflare 再转回 HTTP → 无限重定向 |
| Full | HTTPS,不校验证书 | ✅ 初始用这个 |
| Full (strict) | HTTPS,严格校验 | ⚠️ 一开始会死锁 |
死锁是这么来的:Full (strict) 要求源站先有有效证书,而 Vercel 签证书走 HTTP-01
质询、需要 Let's Encrypt 穿过 Cloudflare 访问到它——两边互相等。
先用 Full 打破循环,等 Vercel 证书签好之后再升到 Full (strict)。
怎么知道证书签好了(这是升 Full (strict) 唯一的前提):
npx vercel certs ls
# id cns expiration renew age
# cert_xxxxxxxxxxxxxxxxxxxxxxxx 你的域名 in 89d yes 20h
列出来了就可以去 Cloudflare → SSL/TLS → Overview 改成 Full (strict)。
不升也能用,但 Cloudflare 到 Vercel 那一段不校验证书,中间被劫持时发现不了。
另外
vercel domains inspect <域名>会把 Nameservers 那两行标成 ✘ (它期望你把 NS 指到ns1/ns2.vercel-dns.com)。这是预期的—— 我们就是要用 Cloudflare 的 NS 才能让它挡在前面代理,这个 ✘ 可以无视。
实测结果(2026-09-15,7234327.xyz):阿里云改 NS 后不到 24 小时生效,
国内手机流量能正常打开,Vercel 也自动签发了 Let's Encrypt 证书。
关于公司内网:如果你的公司网关按 TLD 封锁(实测 Roche 就封了整个 .xyz,
而且是 DNS 劫持 + TLS SNI 双层拦截),那么无论托管在哪、前面挂不挂 CDN,
在公司网络里都打不开。这种情况只能换一个没被封的 TLD(比如 .com)。
/admin,进入"任务模板",把示例任务停用,换成孩子真实的每日任务。https://你的域名/kid/xxx),
点一下在新标签页打开,也可以整条复制。地址是按你当前访问后台用的域名拼的——
从自定义域名进后台,复制出去的就是自定义域名。
(也可以直接用 db:seed 生成的示例孩子改名字继续用,不需要重新建。)npm run dev # 本地开发
npm run build # 生产构建(Vercel 部署时会自动跑)
npm run db:migrate # 修改 prisma/schema.prisma 之后同步数据库结构
npm run db:seed # 重新跑一遍示例数据(对已有孩子不会重复插入)
npm run db:studio # 打开 Prisma Studio 可视化查看/修改数据库数据
npm run check:economy # 经济自检:日薪、派生金额、四条不变量、校准幂等、图鉴解锁
npm run check:isolation # 多租户隔离自检:拿 A 的身份去动 B 的数据,逐条断言必须失败
npm run check:pinyin # 扫描孩子端全部文案的拼音,重点核对多音字
npm run check:layout # 孩子端每一页都锁在一屏内、且底部导航不会被内容裁掉
childId,加个孩子选择器即可)。