feat(calendar): 校历改用教务处页面的校历图片 - #77
Merged
Merged
Conversation
Fixes yan-xiaoo#74 one2020 的校历 JSON 接口(/EIP/schoolcalendar/terms.htm)目前固定返回 {"code": 200, "data": []},而客户端把 code==200 当作成功,于是校历页面出现 “提示查询成功、学期下拉与表格却是空的”。教务处已改为在 https://dean.xjtu.edu.cn/xxfw/xl.htm 上以图片形式发布各学年校历。 - jwxt/calendar.py 改为解析页面上的 <a href="图片"><img></a>,产出 CalendarImage(year, url)。学年优先取锚点 title(如“2015-2016学年校历”), 其次取图片文件名(如 2026-2027.jpg);教务处没有标注学年的图片保留为 year=None,不按顺序猜测。相对地址按页面地址补全,http:// 统一升级为 https。 删除已失效的 CalendarTerm / CalendarHoliday / get_terms 及 JSON 接口封装。 - app/SchoolCalendarInterface.py 改为校历图片查看器:学年下拉框 + 适应窗口 / 原始大小 / 缩小 / 放大 + 百分比,图片支持滚轮缩放与拖拽平移。 没有解析到图片时给出警告,而不是“查询成功”。 - 测试:test_calendar_api.py 改为覆盖新的页面解析(用真实页面结构的内联 fixture,覆盖 title 取学年、文件名取学年、未标注学年、相对地址补全、 http→https、重复地址去重、无图锚点跳过、HTTP 错误传播);test_calendar_week.py 随 CalendarTerm 一并删除;test_campus_pages.py 的校历用例改为覆盖图片选择器 与“空数据不再报成功”。 缩放与平移刻意做成 QLabel 子类自身的事件处理,而不是给 ScrollArea 的 viewport 装 eventFilter:qfluentwidgets 的 ScrollArea 内部也有事件过滤器,两者叠加会让 进程直接崩溃且没有 Python 异常。 未覆盖:教务处页面有 10 张图片没有标注学年(页面纯文本里没有任何学年标题, 只能按 title/文件名取),这些图片在下拉框中显示为“未标注学年”;页面里还混有 一个非校历图片(upload.png)也会作为一个未标注学年的条目出现。
按 review 反馈调整: - 教务处校历页面是公开的,去掉登录相关的部分:不再经过 jwxt 会话登录,也不再要求 账号。为此让 CampusPage.start_job 的 need_login=False 真正可用(此前该分支没有 账号时结果会被 _guarded 静默丢弃,所以是个死参数),并把重复的两份守卫收成一个 _stale()。 - 页面按学年倒序排列各张校历,因此用已知学年作锚点按顺序补齐没有标注学年的图片: 锚点之后每张依次减一年,遇到下一个已知学年时重新对齐;开头的若干张若仍未知,再从 后面第一个已知学年往前推。实测真实页面 14 张全部得到学年(2026-2027 … 2013-2014, 严格递减):两个已知锚点之间的 9 张正好补成 2024-2025…2016-2017,与两个锚点都 吻合。此前被当成"非校历图片"的 upload.png 因此确认是 2024-2025 的真校历。 - 图片交互改为与图书馆可视化选座(VisualSeatView)完全一致:QGraphicsView + ScrollHandDrag 拖拽平移 + AnchorUnderMouse 滚轮缩放 + 双击还原,去掉全部缩放按钮 与百分比标签。原实现手动改滚动条,所以拖动卡顿。 - 测试:新增学年推定的用例(锚点之间补齐、开头向前推、遇到已知学年重新对齐、严格 递减、完全没有锚点时为未标注);校历页的自动加载用例单独拆出,并显式覆盖"没有 账号也能自动加载"。
fyc09
marked this pull request as ready for review
September 21, 2026 07:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
变更说明
修复 #74。one2020 的校历 JSON 接口目前固定返回
{"code": 200, "data": []},而客户端把code == 200当作成功,于是校历页面出现「提示查询成功,学期下拉与表格却是空的」。实测确认(与代码完全相同的方式调用):
教务处已改为在
https://dean.xjtu.edu.cn/xxfw/xl.htm上以图片形式发布各学年校历(最新一学年即https://dean.xjtu.edu.cn/2026-2027.jpg,951 KB / 4581×2056,全分辨率足够放大)。修改内容
jwxt/calendar.py:解析页面上的<a href="图片"><img></a>,产出CalendarImage(year, url)。学年优先取锚点title(如"2015-2016学年校历"),其次取图片文件名(如2026-2027.jpg),其余按页面顺序推定 —— 页面按学年倒序排列:以已知学年作锚点,其后每张依次减一年,遇到下一个已知学年时重新对齐;开头的若干张若仍未知,再从后面第一个已知学年往前推。相对地址按页面地址补全,http://统一升级为https。删除已失效的CalendarTerm/CalendarHoliday/get_terms及 JSON 接口封装。app/SchoolCalendarInterface.py:改为校历图片查看器,不需要登录(教务处页面是公开的,不再经过 jwxt 会话登录、也不要求账号)。图片交互与图书馆可视化选座(VisualSeatView)保持一致:滚轮缩放、按住拖动平移、双击还原,没有额外的缩放按钮。app/components/CampusPage.py:让start_job(..., need_login=False)真正可用。此前该参数没有任何调用方,而且走这条路径时没有账号会让结果被_guarded静默丢弃(死参数);同时把重复两份的守卫收成一个_stale()。验证
PR Tests / CI Gate已通过。测试证据
真实页面(校园网直连):解析出 14 张,全部得到学年且严格递减:
页面 16 个图片锚点里只有 5 个自带学年,其余靠顺序推定。两个已知锚点(#2
2025-2026与 #122015-2016)之间的 9 张正好补成2024-2025 … 2016-2017,与两个锚点都吻合,可作为推定正确性的交叉验证。无账号端到端(
accounts.current = None,真实网络):本地分片:
ai 71 / qt-ui 121 / notification 28 / auth-session 67 / schedule 53全部 OK,check_test_contract通过(27 个产品测试模块),Existing bug regressions137 项通过。未运行的测试:
test/ci/test_pr_workflow.py::test_gate_accepts_only_all_success在本机失败(该用例用subprocess.run(["bash", ...])执行 CI gate 脚本,本机是 Git-Bash 而非 ubuntu runner),已确认在干净 main 上同样失败。校外访问
教务处站点在校外可以正常访问(已确认),因此不需要为公开抓取再补 WebVPN 路径;校历页也不再经过会话管理器。