Files
ClassHelper/docs/app/homeworks.md
T
LoveChengke 19c2aa07b2 feat(docs,scripts,build): 用 docfx 搭文档站并发布到 GitHub Pages,版本号收口成脚本迭代
文档站(`docs/` 就是 docfx 项目,发布在 https://lovechengke.github.io/ClassHelper/):

- 四章 + 常见问题 + 完整参考,共 44 页:快速上手(8 页)/ 应用帮助(10 页)/
  管理运维(6 页)/ 开发文档(11 页)。信息架构照 ClassIsland 文档站来:
  顶栏分章、左侧章节导航、右侧本页目录、上一页 / 下一页、站内搜索、深色主题跟随系统;
- 自定义模板覆盖(`templates/classhelper/`):把 docfx modern 模板那套英文 UI 文案
  (In this article / Improve this doc / Next…)换成中文,补 GitHub 入口与版本徽标,
  并加一层只调排版与配色的 `public/main.css`(不动 DOM 结构);
- 站点顶栏的版本徽标取自根 `package.json`(`docs/build.mjs` 用 `--metadata` 注入),
  不在文档里写第二份 —— 否则一定漂;
- 404 页单独生成:GitHub Pages 的项目页挂在 `/<仓库名>/` 子路径下,而浏览器是按**被请求的路径**
  解析页面里的相对链接的,所以 `<base>` 必须钉到站点根,由 `build.mjs`(本地 `./`)与
  workflow(CI 传 `/<仓库名>/`)分别注入;
- 构建前清空 `_site`:docfx 只覆盖不清理,删掉或改名的页面会以旧文件留在目录里,
  而 Pages 上传的是整个目录。

版本迭代(**每一次 releases,不是每一次提交**):

- 新增 `scripts/version.mjs`。这个仓库里同一个版本号散在 **10 个文件**里(5 份 `package.json`、
  `deploy/package.runtime.json`、两个 compose 的镜像 tag、插件 `manifest.yml`、以及插件 C# 里的
  `PluginVersion` 常量),手工改必然漏一处,而漏掉的那处**不会报错**,只在某个不常走的分支上
  表现为"版本号对不上"。现在收口成两条命令:`pnpm version:check`(逐处比对,不一致 exit 1)
  与 `pnpm version:bump patch|minor|major`(一次改写全部 10 处,任何一处匹配不到或匹配到多处
  就直接失败退出,不做尽力而为的部分改写);
- `AGENTS.md` 新增 §4.4「版本迭代(每一次 releases,不是每一次提交)」:写清版本号落在哪 10 处、
  完整发布命令序列(体检 → 验收 → `dist:all` → 哈希清单 → 推 master → `gh release create` →
  Linux 包由 CI 合并哈希行),以及"已发布的版本号不要复用"的理由。

其它:

- `.github/workflows/docs.yml`:推 master(`docs/**` / `package.json` / workflow 自身有变)即构建并
  部署到 Pages;构建带 `--check`,把 docfx 的警告当错误 —— 最常见的警告是"某个 `.md` 没被任何
  `toc.yml` 引用",那种页面有内容但没有侧边栏,属于必须修掉的疏漏;
- docs 目录重组后的引用同步:`production` / `mysql` / `linux-deploy` / `winisland-design-tokens`
  移到新位置后,AGENTS.md、`deploy/`、`scripts/`、客户端源码注释里的路径引用一并更新;
- 文档站只发布 `docs/` 这一棵树,页面里指向树外的相对链接(`../AGENTS.md` 等)改成 GitHub 绝对 URL,
  否则上线全是 404;
- 图标派生清单补上文档站模板里的 `logo.png` 与 `favicon.png`(`pnpm icons` 一并生成,
  仍然只有一个图形源 `build/classhelper.{png,ico}`);
- `docs/_site` 进 `.gitignore` / `.prettierignore` 与 ESLint ignores;
- 根脚本补 `version:check` / `version:bump` / `docs:build` / `docs:serve` / `docs:check`。
2026-10-06 16:27:44 +08:00

93 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 作业
description: 作业按所属日期归类、看板与全屏看板、教室机器录入作业、未交名单与附件。
---
# 作业
## 按「所属日期」归类,不是按录入时间
每份作业有一个**所属日期**(`Homework.assignDate`,形如 `2026-10-06` 的本地日期,不带时区)。
按天查看、日期高亮、客户端的「只看今天」都看它。
> 用录入时间(`createdAt`)当"哪一天的作业"是错的:它是 UTC,晚上 8 点留的作业会被算到第二天。
> 系统里统一用「本地日期」,新增按天查询的接口也一样走 `?date=YYYY-MM-DD`。
所以老师可以给今天、明天、甚至补录上周某一天 —— 客户端按日期查得到。
## 两端各自能做什么
| 能力 | Web 管理端(老师) | 桌面客户端(教室机器) |
| ------------------ | ---------------------------------------- | ----------------------------------------------- |
| 按天查看 | 工具栏日期选择器;有作业的日期下面带圆点 | 日期选择器 + 前 / 后一天,支持 `?date=` 深链 |
| 发布 / 编辑 / 删除 | ✅(教师 / 管理员) | ✅ **录入**(班级账号也能发,归属到该班班主任) |
| 看板模式 | — | ✅ 默认视图 |
| 全屏看板 | — | ✅ |
| 完成情况 | ✅ 按名单统计完成人数 | ❌ **客户端不显示"已完成 / 待完成"** |
| 未交名单 | ✅ 作业详情抽屉里可看可改 | ✅ |
> 客户端刻意不显示完成状态:完成与否是**老师端与通知中心**的概念;
> 教室机器上只做"看作业 + 录作业"两件事。服务端的完成数据与统计接口都还在,Web 端照旧可用。
## 看板模式
客户端作业页默认按**科目**分卡片,每张卡列出该科的所有作业。工具栏可以:
- **看板 / 列表** 切换视图(列表模式有一列"作业要求"全文);
- **只看今天** 开关(默认开);
- **显示时间** 开关;
- **字号**滑块(11–28px 即时生效)。
这些偏好存在客户端配置里,重启后仍生效。
卡片里同时渲染**标题 + 作业要求全文**(不截断)。
### 全屏看板
点卡片或「全屏看板」进入。全屏下的排版不是简单地放大:
1. 按"可用宽 × 可用高"枚举 1..N 列,取**单卡面积最大、宽高比最接近 1.15** 的方案;
2. 再按「内容高度 / 可用高度」整体 `transform: scale()` 缩到刚好铺满 —— 所以**不用上下翻页**;
3. 标题栏中间绝对居中显示当天日期时间(受「显示时间」开关控制,每分钟刷新)。
> 字号仍由工具栏的滑块决定,缩放只负责"放得下"。工具栏上会显示当前缩放比例。
## 教室机器录入作业
教室里那台机器用**班级账号**登录,可以直接发作业。两个细节:
- 服务端拿到的是班级账号的会话(`sub` 是班级 id),写 `createdBy` 前会换成该班班主任,
否则会撞外键。
- **本机刚录入的那条不会弹到灵动岛上**——自己通知自己没意义。这条判断是在发请求**之前**
按内容登记指纹做的(服务端是先广播后回响应,等拿到 id 再登记就晚了)。
录入时可以点**快捷短语**(默认 `P` / `大本` / `小本` / `卷子` / `背诵` / `默写` / `听写` / `预习` /
`订正` / `读书`),点一下追加到标题或内容。短语可以在客户端「设置 → 通用」里增删,存在本机。
## 未交名单
在作业列表或详情里点「未交名单」→ 勾选**没交作业**的同学 → 保存。
其余同学会被自动标记为已完成(接口是 `PATCH /api/homeworks/:id/submissions`)。
Web 端作业详情抽屉里同样可看可改。
> 名单来自班级的学生名单 —— 名单不全,这项就不准。见[班级、学生与教师](classes.md)。
## 附件
作业可以带一个附件链接。**只接受 `http(s)://` 或站内相对路径**,其他 scheme(`javascript:`、
`data:text/html` 等)服务端会直接拒;Web 端渲染前还会再兜一层。
放行这些 scheme 等于给了一条存储型 XSS。
## 实时推送
发布 / 修改 / 删除作业会分别广播:
| 事件 | 客户端反应 |
| ------------------ | ------------------------------------- |
| `homework:new` | 作业列表刷新 + 灵动岛弹「新作业」胶囊 |
| `homework:updated` | 刷新;带 `deleted: true` 表示删除 |
| `homework:status` | 完成状态变化时刷新统计 |
课表、作业、通知、成绩都是同一个套路:写库 → 按班级房间广播 → 客户端更新内存状态并写回 IndexedDB。