TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
家庭学习打卡阳光系统
Translation pending
EducationTypeScript · PythonGitHub @carrotjoshOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Kids Playground
Translation pending
Taken from the repository README
Loading the full README.
Read the full 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,加个孩子选择器即可)。