e6515fe278
- 重启标记不再污染新一轮运行:hydrate_runs() 标记「已中断」后立即落库,runtime.set_state() 在切入 discovering/studying 时清掉上一轮的 error/progress/finished_at - 服务重启后卡片「课程日志」能读到 SQLite 历史:前端兜底条件不再拿 status 是否为空做判断(重启后 status 恒为 interrupted) - 删除账号连带清日志:account_delete() 按账号 id + 用户名清 run_state/run_log/login_log,删除接口同时清内存里两个 key - 新增 uv.lock 依赖锁定;pyproject 走阿里云 PyPI 镜像,Dockerfile 支持 PIP_INDEX_URL 构建参数 - 文档移入 docs/,.gitignore 忽略 *.egg-info/(uv run 可编辑安装产物)
62 lines
3.9 KiB
Markdown
62 lines
3.9 KiB
Markdown
# TODO
|
||
|
||
## 待评估:接入广东公需课平台(jsxx.gds.edu.cn)
|
||
|
||
**状态**:已接入,见 `src/study_tool/platforms/gdgxk.py` 与 `OPTIMIZATION.md`;登录 / 课程列表 / 进度心跳已实测,待用未学完课程确认。
|
||
|
||
### 背景
|
||
|
||
参考脚本:`2026广东公需课·全自动完美版(后台保活+10分钟刷新).js`(油猴 v1.3,`@match https://jsxx.gds.edu.cn/*`)。
|
||
|
||
它做的事:悬浮面板 + 后台保活 + 10 分钟整页刷新 + 视频题目题库命中(约 200 条)+ 未命中时 12 轮
|
||
暴力试错 + 考核页按课程 id 硬编码两套 30 题答案自动勾选(不代交卷)。
|
||
|
||
注意:这是**广东专业技术人员继续教育公需课**,跟本项目的 dgjy(东莞教师培训)不是一套系统,
|
||
连登录入口都不同。
|
||
|
||
### 结论:不能直接融合
|
||
|
||
| 维度 | 该脚本 | 本项目 | 能不能用 |
|
||
| --- | --- | --- | --- |
|
||
| 站点 | jsxx.gds.edu.cn | jspx / study.dgjy.net | 无交集 |
|
||
| 实现层 | 页面 DOM 点击、layui/mylayer 弹层 | 服务端接口 + Playwright 真播 | 不同层 |
|
||
| 答案 | 硬编码题库 + 按课程 id 两套答案 | 大模型现算 | 数据不可复用 |
|
||
| 保活 | setInterval、伪造 mousemove、整页 reload | 服务端跑逻辑,浏览器只播视频 | reload 会打断播放 |
|
||
| 兜底 | 12 轮暴力试错 | LLM + 交卷前人工核对 | 平台限次,会烧光重考机会 |
|
||
|
||
### 真要接入时的顺序
|
||
|
||
1. **抓包取证**(阻塞项,必须有公需课账号)
|
||
- 登录链路:账号密码还是统一身份认证?落哪些 cookie / token
|
||
- 课程列表与课时树接口
|
||
- 课时上报接口:视频进度怎么记账,是否要心跳
|
||
- 考试接口:取卷、交卷、重考次数(对应 dgjy 的 `surplusExamCount` 那一套)
|
||
- 视频是不是直链,需不需要 Playwright 真播到结尾
|
||
2. **适配层分派**:`app.py` 现在 `login()` / `discover()` / `detect_platform()` / `StudyClient`
|
||
全是 dgjy 专用,得按平台分支;`accounts` 表加平台标识,控制台卡片显示平台
|
||
3. **答题**:本地题库命中优先、LLM 兜底(题库得自己攒 dgjy 的,脚本那 200 条是公需课内容,搬不过来)
|
||
4. **UI**:课程卡片区分平台;公需课的「考核」页结构跟 dgjy 完全不同,不能复用测验弹窗
|
||
|
||
### 明确不照抄的部分
|
||
|
||
- 暴力试错答题:dgjy 平台一般只给 3 次重考,试错直接废掉机会
|
||
- 10 分钟整页刷新:打断正在播放的视频,进度白费
|
||
- 按课程 id 硬编码答案:换课程批次即失效,脚本注释自己写了「已反转,解决反了问题」,说明是试错出来的
|
||
- `.layui-layer` / `.mylayer-wrap` / `#studySelectAct .next` / `#topicList .m-topic-item` 这些选择器
|
||
- 用 `innerText` 包含「正确」判断已答弹层:题干带「正确」二字就会被误点
|
||
- 把「下一节」按钮 `pointer-events:none` 锁死:平台一改版就失效
|
||
|
||
### 可以借鉴的
|
||
|
||
- 题库命中优先、LLM 兜底(省 token、命中时更准)
|
||
- 强制播完才放开「下一节」—— 项目已有等价实现(播到 `ended` + `completeTime` 校验)
|
||
|
||
## 待办:日志 key 与 ddddocr 报错提示
|
||
|
||
- **登录日志的 key 用错维度**:`routes/accounts.py` 的 `_log_login()` 拿**用户名(手机号)**当 key 写 run_log,而卡片「课程日志」读的是**账号 id**,两边对不上——登录行只有登录记录页(`login_log` 表)能看到。要么统一成账号 id,要么卡片同时聚合两个 key。
|
||
- **ddddocr 的报错提示会误导**:`platforms/gdgxk.py` 把任何导入失败都写成「需要先装 ddddocr(pip install ddddocr)」,`uv sync` 在应用运行期间改写包造成的 `DLL load failed` 也会被说成「没装」。应区分 ImportError 与 OSError(DLL),并把真实异常写进 `runtime.log`。
|
||
|
||
## 已完成
|
||
|
||
- 「首次进入课程弹『未加入课堂』」已修复,实测确认见 `OPTIMIZATION.md`。
|