一个针对 PTA(pintia.cn) 的浏览器扩展:在「活跃题目集」「所有题目集」列表页按课程分组与筛选,并给卡片加上课程徽章与截止倒计时,解决不同课程题目集混在一起、难以浏览的问题。
主要能力:
- 课程分组 / 筛选与跨页聚合——复用 PTA 自己的列表接口,筛选条常驻吸顶并区分课程开放状态;
- 答题状态与进度——卡片显示
已完成/未完成/未答题胶囊与已作答 N/M,口径为「有提交就算」; - 题目关闭提醒——两条通道,任一开启即生效:浏览器通知(v0.10,默认开、零配置、纯本地,截止前 3 天 / 1 天各弹一次,点击直达题目集)与邮件提醒(可选,v0.6,配自建轻量后端,浏览器没开也能收到);
- 自动答题(实验,v0.9,默认关)——用你自己的 LLM 账号作答判断 / 单选 / 填空 / 编程题;
- 另有「新标签页打开题目集」(默认开)等小开关。
当前版本 v0.11.3:编程题的 LLM 调用改为流式转发(OpenCode Go 经后台端口),45 秒没有响应头或没有数据即判定卡住、总生成上限 300 秒,卡死最多重试一次,不再把一次网关卡顿放大成每题 4–6 分钟;等首块期间后台每 20 秒保活一次(并记录「仍在等待 / 流已建立」进度),worker 不再在 30 秒空闲时被回收;推理模型会显示「模型思考中… 已收到 N 字符推理」,请求行带模型名;每次尝试、首块与每 15 秒的生成进度都进日志;切题等待改为恒定 5 秒(1–5 秒随机实测仍会触发 PTA 限流)。v0.11.2 的编程题含图照常作答、语言限额误判、离开确认卡死与 1–5 秒切题,v0.11.1 的 OpenCode Go 后台转发与限流冷却,v0.11.0 的弹窗重做(视觉与交互对齐 PTA、提醒 / 课程规则 / 导入导出子页面)与 v0.10 的浏览器通知通道详见逐版本历史《路线图》,文档索引见文末。
better-pta-problems/
├── src/ # 扩展源码(构建入口)
│ ├── shared/ # 内容脚本与弹窗共用:设置定义与迁移、提醒通道判定、通知档位判定、PTA URL 形状、时间、小工具
│ ├── content/ # 内容脚本:课程识别与归并、跨页聚合、答题进度、视图渲染、原生卡片装饰、提醒上报
│ ├── background/ # 后台 service worker:浏览器通知(alarms 扫描 + notifications)与邮件(→ 用户自建后端)
│ └── popup/ # 工具栏弹窗(主页面=开关列表 + 三个入口行;提醒 / 课程规则 / 配置导入导出各为右滑子页面)
├── extension/ # 构建产物 + 静态资源(发版 zip 里的 extension/ 子文件夹来源,可直接加载)
│ ├── manifest.json # MV3 清单
│ ├── background.js # ← 由 src/background/ 构建
│ ├── content/
│ │ ├── core.js # ← 由 src/content/ 构建(勿直接编辑)
│ │ └── styles.css # 注入样式(PTA 令牌,明暗跟随页面主题)
│ ├── popup/ # ← popup.js 由 src/popup/ 构建
│ └── icons/ # 扩展图标
├── test/ # node:test 单元测试(识别/归并/整组分页/时间文案/设置迁移/数据源记账/答题进度口径/通知档位)
├── preview.html # 设计预览页(复刻 PTA DOM + mock 接口 + 实际运行 core.js 产物)
├── package.json # 构建(esbuild)与测试脚本
├── server/ # 邮件提醒通道的后端(Node + node:sqlite + Nodemailer,部署见其 README)
├── docs/ # 设计文档与使用指南(索引见文末《文档》)
│ ├── 安装教程.md
│ ├── 核心结论.md
│ ├── 课程识别策略.md
│ ├── 布局设计.md
│ ├── 自动答题.md
│ ├── 自动答题初探.md
│ ├── 提醒.md
│ ├── 路线图.md
│ └── 发版流程.md
└── tools/ # 构建脚本、发行包打包(zip.mjs / package.mjs)、图标生成、本地预览服务器
普通用户:到 Releases 下载最新的 better-pta-problems-v*.zip,解压到一个固定位置,双击里面的 安装教程.html 跟着做即可。压缩包解压后是一个目录,里面是扩展本体 extension/ 与《安装教程》——在 chrome://extensions(Edge 为 edge://extensions)打开开发者模式,点「加载已解压的扩展程序」,选解压目录里的 extension 子文件夹。升级时把新包里的 extension 覆盖到同一位置、回扩展页在卡片上点「刷新」(↻),设置不会丢。完整说明见《安装教程》(同一份正文打包时渲染成压缩包里的 安装教程.html)。
从仓库源码(开发者):chrome://extensions → 开发者模式 →「加载已解压的扩展程序」→ 选仓库里的 extension/ 目录(构建产物已随仓库提交,克隆后无需先构建)。
本地预览:浏览器直接打开 preview.html(mock 了数据与接口,实际运行 core.js,可验证聚合/筛选/折叠/模式切换)。
源码在 src/,用 esbuild 打包成单文件写回 extension/ 的原有路径——manifest.json、preview.html 与发版流程因此都不用改,产物也提交进仓库,克隆后可直接加载。
npm install
npm run build # 一次性构建(改完 src/ 必须跑一次)
npm run dev # 监听源码变化自动重建
npm run package # 组装发行 zip(extension/ + 安装教程)到 dist/
npm test # node:test 单测:识别/归并/整组分页/时间文案/设置迁移/数据源记账/答题进度口径/通知档位/发行包- 改代码改
src/下的文件;extension/里的content/core.js、background.js、popup/popup.js是产物(首行有「构建产物」标记),不要直接编辑。 - 发行包由 tools/package.mjs 组装:
extension/+ 由docs/安装教程.md渲染出的安装教程.html(教程正文只维护 Markdown 一份,打包时渲染;zip 由 tools/zip.mjs 写,显式带 UTF-8 文件名标志位)。 - CI(check.yml)在每次推送/PR 跑单测、校验产物与源码一致、并给发行包做一次打包冒烟,出问题会直接失败。
- 发版(维护者)见《发版流程》。
- PTA 改版:接口路径、
.pc-list、分页条类名(paginationWrapper_*)等若变化,表现为聚合退化为当前页分组或静默不注入,页面本身不受影响;控制台有警告。 - 聚合请求按路由记录:PTA 标签切换是 SPA(同一文档),扩展把页面发出的列表请求按路径分别记录(v0.3.1 修复:此前取"全局最新请求",快速切换标签"所有→活跃→没加载完就切回"会把活跃页的请求错当所有页的数据源,导致串页)。换页时筛选状态自动重置为全部。
- 聚合失败自动恢复(v0.5.3):切换路由会中止在途的旧聚合请求(不产生报错);请求失败(网络抖动等)30 秒后自动重试,期间暂用上次聚合结果,从未成功过才退回当前页数据——插件视图可能短暂变少,页面本身不受影响。
- 排序语义:组序 = 聚合数据(即用户在 PTA 选的排序)中各组首次出现的位置;组内保持该排序。
- "已开考"徽章启发式:关联考试 + 已开始 + (开放中或 7 天内关闭)时显示;极老考试集与 PTA 展示可能有细微出入。卡片自带 PTA 精确倒计时("距离关闭还有…")时不再叠加插件的倒计时。
- 答题进度的适用范围(v0.8):只对考试型(PTA 返回了
examIdByProblemSetId关联)且已开始、未关闭的题目集显示——非考试型题目集 PTA 不提供进度接口(它自己的概览页也只显示"未答题/答题中"),已关闭的题目集不再取数(补做不了,也避免为几十个历史题目集逐个打接口)。进度按 2 分钟缓存,刚答完题切回列表页可能最多滞后 2 分钟。 - 暗色模式:设置弹窗跟随系统(暗色取 PTA
.dark的实际取值);注入的列表页 UI 与悬浮答题面板跟随 PTA 自己的主题开关(实测它的dark类挂在<body>上,所以是页面主题说了算,不是系统)。 - 提醒的同步时机:打开 PTA 任意页面约 2 秒后自动上报一次;「进行中」页的聚合刷新可在会话中途捕获教师改期;配置变更即时推送。两个通道各自独立开关(v0.7.1 起不再依赖「启用增强」,关掉页面增强也能收提醒)。
- 浏览器通知只在浏览器运行时才会响(v0.10):完全退出期间不弹,重新打开浏览器后会补判一轮(只要还没到截止时间,错过的档位会补上);系统通知被关(专注助手等)时也不会弹,弹窗入口行会红字提示「系统通知已关」。要覆盖关机时段请用邮件通道。
| 文档 | 内容 |
|---|---|
| 安装教程 | 面向普通用户:解压后怎么装进浏览器、怎么升级、常见问题(打包时渲染成压缩包里的 安装教程.html) |
| 核心结论 | 可行性依据、数据来源与接口细节、徽章推导、SPA 稳定性设计、备选方案对比、风险缓解、验证记录 |
| 课程识别策略 | 六层识别管线、归并算法与阈值、真实数据验证 |
| 布局设计 | 视图状态机(全部=分组/平铺、课程筛选=平铺)、卡片元素、吸顶筛选条、本地预览 |
| 自动答题 | 使用步骤、模型服务与 API Key 配置、跳过与中止、含图题与编程题的真实提交语义 |
| 自动答题初探 | exam-submissions 保存协议、题型页 DOM 表单形状、LLM 自动答题的实现与限制 |
| 提醒 | 两条提醒通道(浏览器通知 / 邮件)的开关与配置步骤、提醒范围、边界与「已完成的不再提醒」 |
| 路线图 | 已完成版本(逐版本登记)、计划中的 v1.0 |
| 发版流程 | 维护者:tag 自动发版、发行包结构、本地打包与校验、tag 重发 |