Files
eh-downloader/frontend/index.html
T
toor 0f927147cd feat: EH Downloader 用 Go + Wails v2 重写
原 Electron 版在这台 Windows 机器上无法启动(0x80000003 崩在 V8 初始化),
整个业务逻辑用 Go 重写,前端界面与协议结论完全保留。

- internal/eh: 协议核心,画廊页分页 -> /s/ -> hath 直链 -> 下载
- internal/core: 并发引擎 / 状态存储 / 目录模板 / 油猴桥口
- app.go: Wails 绑定层,替代 Electron IPC
- frontend/js/api.js: 适配层,renderer.js 一行未改
- 37 个测试,含 httptest 模拟 EH 的端到端链路验证

相比 Electron 版:90MB -> 12.4MB,180MB 内存 -> 27MB,构建 90s -> 2s。

顺带修掉原版代理探测的 bug(永远返回第一个端口,从不等连接结果)。
2026-10-08 23:28:16 +08:00

191 lines
7.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>EH Downloader</title>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="app">
<header class="bar">
<div class="brand">
<span class="logo">🐳</span>
<div>
<h1>EH Downloader</h1>
<p class="sub">E-Hentai 画廊批量下载 · 2026 版协议 · Wails</p>
</div>
</div>
<div class="actions">
<button id="btn-import" class="btn">导入链接</button>
<button id="btn-start" class="btn primary">开始下载</button>
<button id="btn-stop" class="btn danger" disabled>停止</button>
<button id="btn-clear" class="btn" title="只清除已完成的任务列表项,已下载的文件不会删除">清除已完成</button>
<button id="btn-delsel" class="btn danger" disabled title="删除勾选的任务。已下载的文件不会删除。">删除选中</button>
<button id="btn-clearall" class="btn danger" title="清空整个任务列表。本地已下载的文件不会删除。">删除全部</button>
<button id="btn-settings" class="btn icon" title="设置">⚙</button>
</div>
</header>
<div class="stats" id="stats">
<div class="stat"><b id="s-total">0</b><span>全部</span></div>
<div class="stat queued"><b id="s-queued">0</b><span>等待</span></div>
<div class="stat running"><b id="s-running">0</b><span>进行</span></div>
<div class="stat done"><b id="s-done">0</b><span>完成</span></div>
<div class="stat failed"><b id="s-failed">0</b><span>失败</span></div>
<div class="stat progress-wrap">
<div class="pbar"><i id="s-bar"></i></div>
<span id="s-text">—</span>
</div>
</div>
<main class="main">
<table class="tasks" id="tasks">
<thead>
<tr>
<th class="c-sel"><input type="checkbox" id="sel-all" /></th>
<th class="c-gid">GID</th>
<th class="c-title">标题</th>
<th class="c-prog">进度</th>
<th class="c-stat">状态</th>
<th class="c-act">操作</th>
</tr>
</thead>
<tbody id="tbody"></tbody>
</table>
<div class="empty" id="empty">
<div class="empty-inner">
<p class="big">还没有任务</p>
<p>点「导入链接」,粘贴一个 txt 文件或直接粘 <code>https://e-hentai.org/g/123456/abcdef1234/</code></p>
<p class="dim">一行一个画廊,也支持竖线/逗号分隔。一行粘多个也行。</p>
</div>
</div>
</main>
<section class="logpane" id="logpane">
<div class="log-head" id="log-head">
<span class="caret">▸</span>
<span>日志</span>
<span class="log-count" id="log-count"></span>
<div class="spacer"></div>
<button class="mini" id="btn-clearlog">清空</button>
<button class="mini" id="btn-togglelog">展开</button>
</div>
<div class="log-body" id="log-body"></div>
</section>
</div>
<!-- 导入 -->
<div class="modal" id="modal-import" hidden>
<div class="sheet">
<h2>导入画廊链接</h2>
<p class="hint">支持完整链接 <code>https://e-hentai.org/g/{gid}/{token}/</code>(推荐),或裸 gid。每行一个。</p>
<textarea id="import-text" placeholder="https://e-hentai.org/g/4239250/58703925db/&#10;https://e-hentai.org/g/4239249/b325120778/&#10;4239248"></textarea>
<div class="row">
<input type="file" id="import-file" accept=".txt,text/plain" />
</div>
<div class="sheet-foot">
<span class="msg" id="import-msg"></span>
<button class="btn" id="btn-import-cancel">取消</button>
<button class="btn primary" id="btn-import-ok">导入</button>
</div>
</div>
</div>
<!-- 通用确认 -->
<div class="modal" id="modal-confirm" hidden>
<div class="sheet narrow">
<h2 id="cf-title">确认</h2>
<p class="hint" id="cf-body"></p>
<div class="sheet-foot">
<span class="msg" id="cf-msg"></span>
<button class="btn" id="cf-cancel">取消</button>
<button class="btn danger" id="cf-ok">确认</button>
</div>
</div>
</div>
<!-- 设置 -->
<div class="modal" id="modal-settings" hidden>
<div class="sheet">
<h2>设置</h2>
<label class="field">
<span>下载目录</span>
<div class="row">
<input type="text" id="set-dir" />
<button class="btn" id="btn-pickdir">选择…</button>
</div>
</label>
<label class="field">
<span>目录结构模板</span>
<div class="row">
<input type="text" id="set-dirtpl" placeholder="{title}" />
</div>
<div class="presets" id="dir-presets"></div>
<small id="dir-preview"></small>
<small>占位符:<code>{title} {gid} {artist} {group} {series} {category} {lang} {tag1} {tags:3}</code><br>
换模板不会重下已完成的图 —— 引擎会先去老的「标题目录」里找。</small>
</label>
<label class="field">
<span>代理模式</span>
<select id="set-proxymode">
<option value="off">不使用代理(直连)</option>
<option value="http">HTTP / HTTPS 代理</option>
<option value="socks5">SOCKS5 代理</option>
</select>
</label>
<label class="field">
<span>代理地址</span>
<input type="text" id="set-proxy" placeholder="http://127.0.0.1:7890 或 socks5://127.0.0.1:1080" />
<small>EH 在国内直连基本不通,通常需要走本机代理。Sparkle/mihomo 默认端口是 7890。</small>
</label>
<label class="field">
<span>下载分辨率</span>
<select id="set-xres">
<option value="auto">站点默认(压缩 webp)</option>
<option value="org">原始分辨率(xres=org)</option>
<option value="1280">长边限制 1280</option>
<option value="1920">长边限制 1920</option>
</select>
<small>EH 浏览器里给的是压缩过的 webp;「原始分辨率」会改写 URL 里的 xres=org,但并非所有画廊都支持。</small>
</label>
<label class="field">
<span>并发数:<b id="set-conc-v">3</b></span>
<input type="range" id="set-conc" min="1" max="8" step="1" value="3" />
<small>每个画廊要发 2N+1 次请求,建议 2~4。调太高容易被限流。</small>
</label>
<label class="field">
<span>请求超时:<b id="set-to-v">30</b> 秒</span>
<input type="range" id="set-to" min="10" max="120" step="5" value="30" />
</label>
<label class="field">
<span>油猴推送端口</span>
<input type="text" id="set-bridgeport" placeholder="37777" />
<small>本地桥口端口,供油猴脚本推送画廊用。改这里的话,油猴脚本里的 PORT 也要同步改。<br>
启动日志里有「本地桥口已就绪 http://127.0.0.1:端口」那行,可用来确认实际生效端口。</small>
</label>
<div class="sheet-foot">
<span class="msg" id="set-msg"></span>
<button class="btn" id="btn-settings-cancel">取消</button>
<button class="btn primary" id="btn-settings-ok">保存</button>
</div>
</div>
</div>
<script src="wailsjs/go/main/App.js"></script>
<script src="wailsjs/runtime/runtime.js"></script>
<script src="js/api.js"></script>
<script src="js/renderer.js"></script>
</body>
</html>