feat(油猴): 行内推送按钮 + 已推送画廊标灰

需求两条:
  1) 列表页的复选框改成按钮,点一下直接推送到工具
  2) 推送过但没点进去的画廊,标题也要变灰(像浏览过的),
     这样刷新后还认得出哪些推过

一、行内推送按钮

复选框 + 底部「批量推送」两步走太啰嗦,列表页每行改成「📤 推送」
胶囊按钮,点一下直接调 /add。按钮三态:
  📤 推送  ->  ⏳ 推送中(禁用)  ->  ✓ 已推送(变绿)
底部悬浮条保留,改为「全部推送」+「重置状态」+ 本页计数。

二、标灰::visited 伪造不了,只能自己记

E-Hentai 的灰色来自自带样式
  a:visited .glink, a:active .glink { color:#8F6063 }
但 :visited 是浏览器**受保护**伪类:脚本查 matches(':visited')
永远返回 false,加 class 也触发不了站点的原生规则。

所以改成自己记一份「推送过」的清单,再照抄站点的色值手动染色,
观感与原生 :visited 一致(hover 恢复站点的 #8F4701)。

三、清单存哪:工具端为主,浏览器端为辅

新增 internal/core/pushed.go —— PushedStore 独立于 Store,
单独存 %APPDATA%\EH Downloader\pushed.json。

为什么单独一个文件:state.json 里的 tasks 是「当前要下载的东西」,
用户点「清除已完成」就删掉了;但「这个画廊我推送过」是历史事实,
删了任务不该忘掉。所以推送历史与任务列表解耦。

新增桥口 GET /pushed 返回推送历史(与 GET /tasks 语义不同:
后者是当前任务列表,会被清除)。

油猴脚本侧:
  - localStorage(ehdl_pushed_gids)先渲染,刷新后立刻可见,
    工具不在线也能用
  - 工具在线时用 /pushed 校正一次(localStorage 可能被清,
    工具才是权威),以工具为准整体覆盖
  - GET /tasks 保留给需要看当前任务列表的场合

四、附带:state.json 事故的恢复工具

tools/recoverstate —— 修复被写坏的 state.json:
  1) token 先从下载目录的 .ehdl.json 清单里找
  2) 找不到的用 E-Hentai 的 ?next=<gid> 定位法去站点抓
     (该 URL 会返回以 gid 开头的 25 条列表,正则取 token,
     offset 0..5 轮着试)
  3) 抓不到的说明画廊在站点上已被删除

-dry 预演不写盘,写盘前先备份原文件。

配套回归测试:
  - internal/core/pushed_test.go   推送历史读写、任务删除后仍保留
  - internal/core/recover_e2e_test.go  恢复出的任务能真下载(71/71 页)
  - internal/eh/recover_verify_test.go 恢复出的 token 能解析画廊
  - app_test.go                    点「清除已完成」后灰标不消失
  - internal/core/bridge_test.go   /tasks 与 /pushed 的 token 校验

后两者需要能连 e-hentai.org,设 EH_TEST_PROXY 才跑。
This commit is contained in:
2026-10-25 00:16:03 +08:00
parent 1d7d261490
commit 2d3c322e34
15 changed files with 1738 additions and 68 deletions
+16 -1
View File
@@ -51,7 +51,7 @@ Linux:`wails build -platform linux/amd64`
- **批量下载** —— 一行一个链接,粘进去就走
- **断点续传** —— 以文件系统为准,中途断网/关窗口/删状态文件都不影响续传
- **油猴联动** —— 浏览时推送画廊,列表页勾选后批量推送
- **油猴联动** —— 浏览时推送画廊,列表页每行一个「推送」按钮,点一下直接进工具;推送过的画廊标题会自动标灰
- **目录模板** —— 按作者 / 社团 / 分类 / 标签自动归档
- **任务清理** —— 只删列表项,本地文件一个都不动
- **代理支持** —— HTTP / SOCKS5,首次启动自动探测本机代理
@@ -313,12 +313,27 @@ App 启动时在 `127.0.0.1:37777` 起 HTTP 服务(**只绑回环**):
| `GET /ping` | 探活,返回 `{ok:true}` |
| `POST /add` | 推送单个,需带 `X-EHDL-Token: ehdl-local-9f2a4c7e` |
| `POST /add-batch` | 批量推送,`{items:[...]}`,一次最多 500 个 |
| `GET /tasks` | 当前任务列表(gid/token/title/status),同样需带 token |
| `GET /pushed` | **推送历史**(推过的画廊),任务删了也还在 |
| `GET /info` | 版本与端口 |
安全措施:**固定 token + Origin 白名单**(只放行 e-hentai.org / exhentai.org)。
> 油猴脚本用 `GM_xmlhttpRequest` 而不是 `fetch`,直接绕开 CORS。
### 已推送的画廊标灰
E-Hentai 给「访问过的画廊」上灰色用的是原生 `:visited` 伪类(`a:visited .glink{color:#8F6063}`)。
这个伪类受浏览器保护,脚本伪造不了,所以油猴脚本自己记了一份推送清单:
- **推送历史存在 `pushed.json`**(和 `state.json` 同目录,`%APPDATA%\EH Downloader\`)——
独立于任务列表,所以点「清除已完成」把任务删了,**灰标依然保留**
- 浏览器端再存一份 localStorage(`ehdl_pushed_gids`),刷新后立刻显示,不用等网络
- 工具在线时用 `GET /pushed` 校正一次(localStorage 可能被清,工具才是权威)
- 染色用的是 E-Hentai 自己的色值 `#8F6063`,观感和原生 `:visited` 一致
清理方式:删掉 `pushed.json`,或在设置里清空推送历史。
## 已知限制
- **只支持 E-Hentai**,不支持 ExHentai(需账号 cookie,本工具不含登录)。