截图来自本分支的本地生产构建,使用现有课程数据;生产效果以上线版本为准。README 的居中介绍、技术徽章及页面预览形式参考「今日海大吃什么」,网站右侧采用站点概览与快速入口布局。
- 首页:最新点评、最新收录老师、最新收录课程,各展示 5 条;每组及页底都有完整目录入口。目录无历史创建时间,因此“最新”按现有收录顺序展示,不代表最近开课或入职。
- 点评:浏览课程和教师点评,正文直接完整展示,独立搜索标题与正文,支持分页。
- 课程:搜索名称或课程号,按学院、类型、授课教师、学分、属性和点评数量筛选。详情页优先显示课程名与课程号,再看课程信息和同学点评,点击“写点评”再展开表单;右侧展示教师、其他班级及同学院同学分的相似课程。
- 老师:独立搜索姓名,进入教师页查看授课信息与点评。
- 补充目录:普通用户补充尚未收录的课程号或教师,由管理员核实后公开;有效管理员可直接收录并保留审计。账号菜单和管理页均有目录审核入口,自己的提交页可看进度与理由。已有目录点评仍提交即公开。详见 补充审核。
- 顶部搜索:仅搜索课程或课程号;点评与老师使用各自页面的搜索框。
- 统一账号:注册与登录使用 SHOU-Auth,点击头像打开本站账号菜单,可查看自己的目录补充、管理内容或退出;选择“头像与账号设置”才前往统一账号中心。本站会话有效 8 小时,可独立退出。
- 内容管理:认证中心管理员可开启顶部“管理模式”,在点评搜索列表、课程和老师详情中原位删除/恢复点评、封禁/解封作者;完整管理面板支持内容、目标与作者筛选及审计分页。权限每次验证最多有效 1 小时,本站封禁保留旧点评并即时撤销本站会话。
- 分享体验:登录并设置用户名后可提交点评,默认显示“匿名用户”并隐藏头像,也可选择已验证的账号用户名与头像;署名从服务端账号资料取得。写入要求会话、CSRF 和 Cloudflare Turnstile;历史点评保留原文与存储归属。
- 显示主题:保留原深色主题,增加奶油、粉玫瑰与可可色浅色主题;顶部切换后记住偏好,刷新时在首屏绘制前应用。
- 加载失败:显示统一、无内部细节的提示,并可玩本地校园跑酷——戴眼镜的学生躲避教学楼、收集 GPA POINTS。空格、↑ 或轻点画面跳跃;积分与真实成绩无关。
| 层次 | 实际使用 |
|---|---|
| 页面与服务端 | Svelte 5、SvelteKit 3、TypeScript 6,SSR 与渐进增强表单 |
| 样式与组件 | Tailwind CSS 4、shadcn-svelte、Bits UI、Lucide Svelte |
| 构建与部署 | Vite 8、SvelteKit Cloudflare adapter 8、Wrangler 4、Cloudflare Workers |
| 数据与缓存 | Cloudflare D1 / SQLite、SQL 索引与计数触发器、Workers Cache API |
| 认证与点评 | SHOU-Auth OIDC / openid-client、D1 本站会话、CSRF、Cloudflare Turnstile |
| 小游戏 | 原生 Canvas 2D 与 TypeScript,无远程游戏服务或额外图片依赖 |
| 本地开发 | 原生 Windows / PowerShell 7,Pixi 管理 Node.js 26、pnpm 12 |
| 检查与测试 | svelte-check、Oxlint、Oxfmt、Node test runner、Miniflare/workerd 本地 D1 |
准确依赖版本见 package.json、pnpm-lock.yaml 与 pixi.lock。本项目没有 React、Astro 或 R2 依赖,也没有关注或星级评分功能。账号接入、环境变量与会话边界见 UNIFIED_AUTH.md。
以下是现有本地数据(1,909 门课程、3,286 个课段、5,597 条点评、970 位教师)在 Miniflare/workerd 的整页服务端加载实测。包括 COUNT、列表、授课教师及公共数据查询,而非只计算缓存部分。
| 页面第一页 | 缓存全冷:查询数 / 读取行 | 缓存命中:查询数 / 读取行 |
|---|---|---|
| 首页 | 4 / 32 | 0 / 0 |
| 课程目录 | 7 / 2,802 | 3 / 87 |
| 点评列表 | 2 / 50 | 2 / 50 |
| 老师列表 | 2 / 13 | 2 / 13 |
首页 32 行 = 最新点评 21 + 统计 1 + 课程 5 + 老师 5。原先无筛选 COUNT 的约 6,572 行扫描已替换为事务维护的单行统计读取,首页不再加载课程目录和筛选选项。
这些数字仍适用于游客,没有会话 Cookie 的请求不增加认证查询。已登录访问会额外执行一次通过索引关联的本站会话查询,同一请求只验证一次;个人账号与 CSRF 数据不进入公共缓存。
缓存属于服务器的数据中心,并不属于某个用户:新用户也可能命中已有缓存,老用户也可能遇到过期或不同地区的冷缓存。首页数据缓存 60 秒;课程筛选项缓存 6 小时。评论提交成功后清除当前数据中心的最新评论与展示统计,其他中心最多滞后一个 TTL。目录列表与精确分页总数不缓存。
课程、点评和姓名子串搜索仍有扫描成本。例如点评搜索“老师”本地为 5,655 行,不能将首页 32 行套用到搜索或深分页。关闭了悬停时的数据预加载,仅预加载代码,避免鼠标经过链接就触发查询。静态资源及小游戏不查询 D1。
完整前后 SQL、执行计划、搜索成本和一致性取舍见 D1_READ_BUDGET.md 与 整页测量记录。这不是生产账单保证。
管理模式另有本地测量:点评 COUNT 与第一页列表从 35,393 行降至 184 行,其中无筛选精确 COUNT 使用原有事务计数,只读 1 行。认证和审计分页另计;子串搜索、历史归属筛选与深分页仍有成本。此优化不新增索引或迁移,详见 管理读取预算。
pixi install
pixi run installPixi 从 conda-forge 创建锁定环境,pnpm 根据 lockfile 安装依赖。使用本地 D1;完整 schema 与历史数据说明见 SCHEMA.md。
现有工作区已导入数据并应用 0005。新检出需取得 shou-lxk-full-2026-10-02.sql.zip,导入到空本地数据库后再应用剩余迁移:
New-Item -ItemType Directory -Force .wrangler\shou-lxk-import-2026-10-02 | Out-Null
bz x shou-lxk-full-2026-10-02.sql.zip -o:.wrangler/shou-lxk-import-2026-10-02 -y
# 若 bz 不可用,可使用 Expand-Archive。
pixi run pnpm exec wrangler d1 execute DB --local --file .wrangler/shou-lxk-import-2026-10-02/shou-lxk-full-2026-10-02.sql
pixi run pnpm exec wrangler d1 migrations apply DB --local
pixi run dev该归档已包含 0001 至 0004 的迁移记录,不要重复执行它们。没有归档时,可在空库执行 schema.sql 建立空白演示库;不要再对其重放结构迁移。
本地提交测试可把 .dev.vars.example 复制为 .dev.vars,使用 Cloudflare 官方测试键;不要在生产使用测试键。生产的 TURNSTILE_SITE_KEY 是公开变量,TURNSTILE_SECRET_KEY 必须作为 Worker secret 保存。缺少配置或验证服务不可用时,提交验证失败关闭。
统一登录还需独立本地 OIDC client 与 secret,Auth 默认联调端口为 8788、LXK 为 5173。生产 callback 固定为 https://lxk.shoumc.com/auth/callback,HTTP 只在显式配置的 loopback 开发环境可用。缺少认证配置时仍可浏览,无法开始新登录;新点评始终要求有效本站会话,详见 统一认证。
pixi run check
pixi run lint
pixi run test
pixi run build
pixi run pnpm benchmark:d1 --database <本地SQLite文件路径>
pixi run pnpm benchmark:pages --database <本地SQLite文件路径>
pixi run pnpm benchmark:moderation --database <本地SQLite文件路径>可用 rg --files --hidden --no-ignore .wrangler/state -g '*.sqlite' 查找本地数据库。基准脚本以只读事务复制本地数据到临时 Miniflare D1,绝不连接远程数据库。报告输出到 .wrangler/read-budget/。测试覆盖排序、筛选、分页、计数事务、真实 Cache API、Turnstile 拒绝路径、错误脱敏及跑酷规则。
仓库不使用 Git 自动部署。读取优化需要 0005,统一账号需要 0006,本站管理需要 0007,中心资料、角色与发表身份需要 0008,目录补充审核需要 0009。备份、迁移成本和回退说明见 读取优化上线步骤、统一认证 与 管理员上线顺序。远程变更须由维护者明确决定。
pixi run pnpm exec wrangler d1 export DB --remote --output .wrangler/shou-courses-before-next-migration-<unique-time>.sql
pixi run pnpm exec wrangler d1 migrations apply DB --remote
pixi run build
pixi run pnpm exec wrangler deploy --config wrangler.jsonc --keep-vars --strict --var MAINTENANCE_MODE:false配置见 wrangler.jsonc。保留生产 Turnstile 变量和密钥,并提前以 Worker Secret 保存 OIDC_CLIENT_SECRET。若启用 Workers Builds,.node-version 指定 Node.js 26,并在构建变量中设置 PNPM_VERSION=12。
MAINTENANCE_MODE=true 时,服务端在加载数据与执行表单前返回不缓存的 503 维护页,暂停本网站的 D1 访问,不删除数据库或绑定。维护版可在迁移之前发布,但必须保持此开关开启。正常发布前应先成功备份、完成所需迁移,再显式传入 --var MAINTENANCE_MODE:false;--keep-vars 单独使用会保留维护状态。


