Skip to content

加固校园卡会话、接口边界、流水分页与账户隔离 - #63

Open
yeliqin666 wants to merge 9 commits into
yan-xiaoo:mainfrom
yeliqin666:feat/campus-card
Open

加固校园卡会话、接口边界、流水分页与账户隔离#63
yeliqin666 wants to merge 9 commits into
yan-xiaoo:mainfrom
yeliqin666:feat/campus-card

Conversation

@yeliqin666

@yeliqin666 yeliqin666 commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

变更背景

本 PR 加固校园卡功能,处理原实现中已确认的会话状态、接口边界、流水分页和账户切换问题。原 PR 可以在简单场景下显示校园卡信息,但在真实使用中存在以下风险:

  • 会话把内部状态写入 X-Card-* 伪请求头,中文姓名等内容可能造成请求头编码问题。
  • 从快照恢复后,令牌可能恢复了,但姓名、学号和卡账户资料没有重新加载。
  • 接口返回异常 JSON、业务失败或不完整分页时,可能被当成空数据并继续显示“查询成功”。
  • 金额方向没有明确区分收入、支出和未知类型。
  • 切换账户、连续刷新或使用反向日期时,旧结果可能覆盖当前页面,非法查询也可能启动后台任务。

本次修改直接基于原校园卡实现,优先复用现有会话、请求、账户管理、后台任务和页面保护机制,不引入平行的认证、分页或渲染框架。

主要修改

一、同步上游并保留并发保护

  • 将原校园卡分支同步到最新上游 main
  • 保留上游已有的任务代际保护、账户 UUID 校验和错误回调保护。
  • 仅在校园卡相关入口和实现范围内继续修复,不回退其他模块的并发安全改动。

二、清理校园卡会话状态和请求头

  • 校园卡请求只发送服务实际需要的 Synjones-AuthsynAccessSource
  • 删除 X-Card-Access-TokenX-Card-AccountX-Card-SnoX-Card-Name 等内部伪请求头。
  • 删除为伪请求头引入的全局 http_safe_headers() 过滤逻辑。
  • 保留校园卡专用移动端用户代理,不改变其他站点会话的默认行为。
  • 登录成功后加载姓名、学号和卡账户;快照恢复令牌后首次验证登录态时也会重新加载这些资料。
  • 用户资料接口返回异常、非对象数据、错误业务码或缺少必要字段时,明确返回可读错误,不伪装成登录成功。
  • 对 JSON 401、其他设备登录和未登录提示保留自动重新登录路径。

三、加固校园卡接口和流水分页

  • 统一校验 HTTP 状态、JSON 对象、业务码、data 对象和列表字段。
  • 兼容整数 200 与字符串 "200",但业务码缺失不再被视为成功。
  • 卡片数据为空、字段类型错误、流水记录格式错误时抛出明确的 ServerError
  • 金额内部使用整数分保存,界面展示时再转换为两位小数,避免浮点数参与财务状态计算。
  • 收入类型(充值、圈存、退款、补助)显示为正数,消费类型显示为负数;服务端已经带负号的金额保持原符号;未知类型保留服务端原始符号。
  • 根据服务端总数和分页大小计算最大请求页数,防止接口异常导致无限请求。
  • 检测空页、重复页、总数变化、返回记录超过总数、页数上限仍不完整等情况,残缺流水不会被标记为查询成功。
  • 清除 card/ 和应用代码中遗留的 X-Card-* 回退逻辑。

四、加固页面账户隔离和日期校验

  • 继续复用 CampusPage.start_job() 以及上游已有的任务代际和账户 UUID guard。
  • 通过真实 currentAccountChanged 信号清空余额摘要和流水表格,并重置自动加载状态。
  • 切换账户后,旧账户的结果和错误不会渲染到当前页面。
  • 同一账户连续刷新时,较早任务的结果不会覆盖较晚任务。
  • 当前查询失败时保留上一次成功结果和日期选择,不把页面改成虚假的零值,也不显示成功提示。
  • 开始日期晚于结束日期时,在启动后台任务前给出中文提示并直接返回。

测试与验证

定向和共享回归测试

  • 校园卡接口、分页、金额方向和页面测试:18 项通过。
  • 校园卡页面、任务代际、账户切换和注册共享测试:33 项通过。
  • 登录与会话相关测试:61 项通过,其中 2 项因本地没有真实凭据按既有规则跳过。

完整测试域

  • 人工智能测试:71 项通过。
  • Qt 桌面界面测试:101 项通过。
  • 通知与爬虫测试:28 项通过。
  • 登录与会话测试:61 项通过,其中 2 项跳过。
  • 校历与课程安排测试:45 项通过。
  • 测试合同检查:39 项通过。
  • 测试清单检查:27 个产品测试模块全部且仅归属于 5 个测试域。
  • Python 字节码编译检查通过,git diff --check 通过。

测试合同

  • 将新增的 test.card.test_campus_card 登记到 Qt/UI 测试域。
  • 将新增的 test.app.test_http_headers 登记到登录与会话测试域。
  • 同步更新测试模块总数和开发文档测试部分的实测用例数。
  • 未修改 CI 并发数、矩阵成员或工作流行为。

变更范围

  • 本 PR 只处理校园卡功能,不包含 PR feat: 学籍档案、体测查询、校历与交晓智入口 #57 的代码或文档。
  • 未修改 .github 下的工作流和 CI 并发配置。
  • docs/development/testing.md 的测试清单和实测用例数外,没有修改其他文档。
  • 未提交 Token、Cookie、姓名、学号、卡号、账户号、流水或个人财务数据。
  • 设计稿、计划文件和协作通信记录均未进入 PR。

验收状态

  • 自动化定向测试、共享测试和完整测试域通过。
  • 原 PR 分支已同步最新上游并更新到本次候选提交。
  • PR diff 已限制在校园卡代码、对应测试和测试清单文档部分。
  • 真实账户验收:维护者已在本地应用中确认余额摘要、未结算金额、近三个月流水、账户切换和反向日期提示正常;验收记录只保留脱敏后的行为结果。

Copilot AI lite review requested due to automatic review settings August 18, 2026 05:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@JimmyWang0417

JimmyWang0417 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Approved!

这个Feature的设计方向我认可。非常感谢你的贡献,请严格按照项目测试流程执行,保证相关测试全部通过,之后可以进行合并。

@JimmyWang0417 JimmyWang0417 self-assigned this Aug 18, 2026
@JimmyWang0417
JimmyWang0417 self-requested a review August 18, 2026 07:36

@JimmyWang0417 JimmyWang0417 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复查后建议先修复以下问题再合并:

  1. [P1] 流水被静默截断
    app/CampusCardInterface.py:53 固定只请求第 1 页、80 条。默认查询 90 天时很容易超过 80 笔;界面却显示服务端 total,会出现“共 100 笔但表格只有 80 条”。请循环分页取完,或实现显式分页/加载更多。

  2. [P1] 切换账户后仍显示上一账户的财务数据
    app/CampusCardInterface.py:37_auto_loaded 不会因 currentAccountChanged 重置,页面也没有清空余额和流水。如果查询过程中切换账户,旧任务结果还可能覆盖当前页面。请在账户切换时取消当前任务、清空数据、重置自动加载,并通过账户 UUID 丢弃过期结果。

  3. [P2] 流水接口业务失败会显示“查询成功”
    card/campus_card.py:87 没有像 get_card_info() 一样检查 payload["code"]。例如返回 {"code": 500, "message": "查询失败"} 时,当前实现会得到 (0, []),随后 UI 弹出“查询成功”。请校验业务状态并抛出 ServerError

验证情况:代码编译通过;head 与 base 的现有测试结果相同,118 项中 116 通过,2 项均为既有 schedule/lesson 失败,暂未发现本 PR 引入的现有测试回归。不过本 PR 没有新增测试,Test plan 的 3 项手测均未勾选,GitHub 也没有 check run。建议补充分页、业务错误和账户切换相关测试,并完成手测后重新请求 review。

Comment thread app/CampusCardInterface.py Outdated
Comment thread card/campus_card.py Outdated
Comment thread app/CampusCardInterface.py
yeliqin666 and others added 2 commits August 19, 2026 08:07
超过一页的流水不再静默截断;业务失败不再显示查询成功;切账户会清空余额和表格。

Co-authored-by: Cursor <cursoragent@cursor.com>
姓名写入 X-Card-Name 后 urllib 按 latin-1 编码直接崩;流水 401「其他设备」以前也不会触发重登。

Co-authored-by: Cursor <cursoragent@cursor.com>
@yeliqin666

Copy link
Copy Markdown
Contributor Author

已更正修复

@JimmyWang0417
JimmyWang0417 self-requested a review August 19, 2026 01:29
Keep campus card in the sidebar and school course in the toolbox.

Co-authored-by: Cursor <cursoragent@cursor.com>
# Conflicts:
#	app/HomeInterface.py
#	app/main_window.py
#	auth/constant.py
@JimmyWang0417 JimmyWang0417 changed the title feat: 校园卡余额与流水 加固校园卡会话、接口边界、流水分页与账户隔离 Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants