Repository navigation
Practice Data
ChangYo edited this page Oct 26, 2026
·
3 revisions
这页把校园工具里最容易出错的三个通用问题抽出来:文件怎么下、时间怎么算、缓存怎么不骗人。平台特有的细节放各平台页。
相关:Canvas、Mail、Classroom-Video、交大云盘。
| 类型 | 例子 | 关键点 |
|---|---|---|
| 直接返回文件流 | 邮箱附件、Pan | 流式写盘,别整包读内存 |
| 302 到对象存储 | Canvas 文件 | 第一段带 Token,第二段不带;签名 URL 是凭据 |
| 签名直链 | 课堂视频 MP4 | 免 Cookie、支持 Range、会过期;每次现取 |
- 先拿元数据(大小、MIME、文件名),再下载。
- 下载到临时文件,校验后
rename;失败清理。 - 校验大小;有条件校验 hash。
- 大文件流式写;不要
arrayBuffer()整个 1GB。 - 并发限速;429/403 退避。
- 文件名:过滤
<>:"/\|?*、控制字符、Windows 保留名;限制长度;防路径穿越。 - 同名冲突:跳过/覆盖/加序号,策略要明确。
- 断点续传:
Range+If-Range;服务端不支持就重下。 - 签名 URL 不落日志、不存库、不发模型。
| 情况 | 处理 |
|---|---|
| 302 缺失 Location | 报错;不要猜 |
| 重定向到非预期域 | 拒绝;防 SSRF/钓鱼 |
| 403(对象存储) | 签名过期/权限错;重新取签名,不要重试旧 URL |
| 416 | Range 越界;检查文件大小 |
| 200 但大小不符 | 截断/代理错误;重试 |
| 429 | 退避;读 Retry-After
|
| 格式 | 来源 | 注意 |
|---|---|---|
| Unix 秒 | Open API、InfoPlus、数据资源 API | 单位为秒,不是毫秒 |
| Unix 毫秒 | 课堂视频转写 bg/ed
|
除 1000 得秒 |
| ISO 8601 | Canvas due_at、邮件日期 |
带 Z 就是 UTC |
- 校园业务默认
Asia/Shanghai。 - 服务器返回的
Z时间是 UTC;展示时转本地。 - 计算「第 N 周」时,先把学期开始日归一到周一,再按本地日历算;不要用 UTC 日期直接加。
- 中国没有夏令时,但不要假设所有用户都在 +8;如果做跨时区,显式带 TZID。
- 学期代码各平台不同:i.sjtu 用
xnm+xqm=3/12/16;Open API 用2026-2027-1。 - 周次表达式可能是中文(
1-16周(单));解析后展开成具体周。 - 没有学期开始日期时,不要生成具体日期;显示「第 N 周」或让用户手填。
- DDL 用
due_at的 UTC 时刻;不要二次加减 8 小时。
- 这个接口有稳定的变更游标吗?
- 没有游标时,用什么字段判断变化?
- 同步失败/返回空时,缓存该保留还是清空?
| 平台 | 增量依据 | 注意 |
|---|---|---|
| Canvas |
updated_at、文件 id |
没有稳定 change cursor;定期全量校核 |
| 邮箱 |
UIDVALIDITY + UID
|
UIDVALIDITY 变了必须清空重同步 |
| 水源 |
last_posted_at、more_topics_url
|
没有 change cursor;按页对比 |
| 课堂视频 | 场次 id + 状态字段 | 转写/PPT 异步;未就绪下次重拉 |
| 教务 | 学期 + 课程 id | 全量替换该学期;失败保留旧数据 |
- 失败不清空:网络错误、空响应、解析失败都保留旧缓存,标错误。
- 区分「删除」与「没拿到」:只有服务端明确返回「不存在/已删除」才删本地。
- 墓碑:需要删除同步时,记录 tombstone,不要靠「本次没返回」推断删除。
- TTL:结构/分类等低频数据可以缓存几分钟;个人数据不要缓存太久。
- 可重建:缓存应能从源重建;不要把唯一副本放缓存。
- 迁移:缓存 key 加版本;结构变了就重建,不要读旧格式。
列表接口为了体积会裁字段,不能把列表项当详情:
- 选课社区列表的
rating.distribution恒为[0,0,0,0,0],详情才有真实分布。 - 第二课堂列表没有
in_signed_up,报名状态只在详情。 - 传承的班级端点
materials恒为null,资料要走/material。
[实测 2026-10-26]
来源:
- Canvas 作业
description、页面body、讨论message。 - 水源
cooked(服务端消毒过,但仍要清洗)。 - 邮件
text/html。 - 教务/新闻网页。
处理:
- 用白名单 sanitizer;去掉
<script>、事件属性、javascript:URL、iframe(除非明确需要)。 - 相对链接补全 base;图片走代理/鉴权,不要直连外域。
- 邮件远程图片默认不加载(跟踪像素)。
- 代码块/数学公式按需渲染;不要执行任意 HTML。
- 保留原文链接,方便核对。
| 类型 | 例子 | 注意 |
|---|---|---|
| 数字 id | Canvas course/file/assignment | 稳定;但跨实例可能冲突 |
| GUID | Open API/InfoPlus | 字符串;不要转数字 |
bsid/code
|
教学班/课程 | 可能带学期/班号;不要当全局唯一 |
jxb_id |
i.sjtu 教学班 | 课表主键候选 |
teclId |
课堂视频教学班 | 与课程代码映射 |
activity_id |
第二课堂热门列表 | 与普通列表的 id 不同名 |
| base64 | 第二课堂详情页 URL | 不是接口 id,需解码或换成数字 id |
UID |
IMAP | 只在同一 UIDVALIDITY 内稳定 |
topic_id/post_id
|
水源 | 数字;topic 是核心实体 |
原则:用服务端提供的稳定 id,不要用显示名/标题做键。显示名会改,标题会重名。
同一个实体在不同接口里可能换主键名:第二课堂列表用 id,热门用 activity_id,网页 URL 又用 base64。解析前先确认当前端点的键名,不要写一个通用 getId()。[实测 2026-10-26]
- 下载链路区分了「带 Token 的第一段」和「不带 Token 的第二段」。
- 文件名安全,冲突策略明确。
- 大文件流式,内存有上限。
- 时间格式(秒/毫秒/ISO)明确,时区明确。
- 周次/学期开始缺失时有降级。
- 同步失败不清空缓存。
- UIDVALIDITY/updated_at 等游标用对。
- HTML 清洗,远程资源不默认加载。
- ID 稳定,不用标题做键。
- Canvas 302/S3/大小/分页:
[实测 2026-09-10] - 邮箱 UIDVALIDITY/窗口:
[实测 2026-09,Dela mail] - 课堂视频签名/Range/异步:
[实测 2026-10-06] - 水源
cooked/分页/标签:[实测 2026-09-15] - 节次/周次:
[实测 2026-09,Dela schedule] - 列表裁剪字段、第二课堂主键名:
[实测 2026-10-26]
- 2026-10-25:首版。抽取文件、时间、缓存、HTML、ID 的通用规则。
- 2026-10-26:补「列表字段可能不全」与第二课堂主键差异。
本 Wiki 记录的是开发实践,不是学校官方承诺。每个结论都标注证据与日期;校园平台会调整字段、权限和登录方式,动手前请按页面里的「最后验证」复核。发现过期内容请提 Issue 或直接改。