原 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(永远返回第一个端口,从不等连接结果)。
191 lines
7.2 KiB
HTML
191 lines
7.2 KiB
HTML
<!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/ https://e-hentai.org/g/4239249/b325120778/ 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>
|