355 lines
17 KiB
HTML
355 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>闲鱼采集助手</title>
|
|
<link rel="stylesheet" href="style.css?v=19">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<!-- Header -->
|
|
<header class="header">
|
|
<div class="header-left">
|
|
<button class="brand-button" onclick="showHome()" title="返回首页"><h1>🐟 闲鱼采集助手</h1></button>
|
|
<span class="status-dot" id="ws-status"></span>
|
|
</div>
|
|
<div class="header-right">
|
|
<button class="btn theme-toggle" id="theme-toggle" onclick="toggleTheme()" title="切换深色/浅色主题">
|
|
<span class="theme-icon" id="theme-icon">🌙</span><span id="theme-label">深色</span>
|
|
</button>
|
|
<button class="btn btn-home-main" onclick="showHome()">首页</button>
|
|
<button class="btn" onclick="showClearCacheModal()">清除缓存</button>
|
|
<button class="btn" onclick="showNotifyModal()">通知设置</button>
|
|
<button class="btn" onclick="showLoginModal()">账号登录 / Cookie</button>
|
|
<button class="btn btn-primary" onclick="showCreateModal()">+ 新建任务</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="main-layout">
|
|
<!-- Sidebar: Task List -->
|
|
<aside class="sidebar" id="sidebar">
|
|
<div class="sidebar-header">任务列表</div>
|
|
<div id="task-list" class="task-list"></div>
|
|
</aside>
|
|
|
|
<!-- Main Content -->
|
|
<main class="content" id="main-content">
|
|
<div class="home-dashboard" id="empty-state">
|
|
<section class="hero-card">
|
|
<div>
|
|
<div class="hero-eyebrow">Hermes 主控 · 闲鱼采集助手</div>
|
|
<h2>把闲鱼搜索变成可复用的商品雷达</h2>
|
|
<p>创建任务后自动采集、粗筛、细筛,再由 Hermes 做推荐/谨慎/排除分析。默认只分析,不联系卖家。</p>
|
|
<div class="hero-actions">
|
|
<button class="btn btn-primary" onclick="showCreateModal()">+ 新建采集任务</button>
|
|
<button class="btn" onclick="showLoginModal()">检测登录状态</button>
|
|
<button class="btn" onclick="showClearCacheModal()">整理缓存</button>
|
|
</div>
|
|
</div>
|
|
<div class="hero-orb">
|
|
<span>🐟</span>
|
|
<strong>AI</strong>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="overview-grid" id="home-overview"></section>
|
|
|
|
<section class="home-split">
|
|
<div class="home-panel">
|
|
<div class="home-panel-head">
|
|
<div>
|
|
<h3>最近任务</h3>
|
|
<p>快速回到已有任务,继续采集或查看分析。</p>
|
|
</div>
|
|
<button class="btn btn-sm" onclick="showCreateModal()">创建</button>
|
|
</div>
|
|
<div class="home-task-list" id="home-task-list"></div>
|
|
</div>
|
|
<div class="home-panel">
|
|
<div class="home-panel-head">
|
|
<div>
|
|
<h3>推荐工作流</h3>
|
|
<p>按这个顺序使用,页面不会空等。</p>
|
|
</div>
|
|
</div>
|
|
<div class="workflow-list">
|
|
<button class="workflow-step workflow-step-clickable" type="button" onclick="showLoginModal()"><span>1</span><div><b>账号登录</b><small>扫码后 Cookie 自动复用 · 点击打开</small></div></button>
|
|
<button class="workflow-step workflow-step-clickable" type="button" onclick="showCreateModal()"><span>2</span><div><b>新建任务</b><small>关键词、价格、地区、个人卖家 · 点击创建</small></div></button>
|
|
<button class="workflow-step workflow-step-clickable" type="button" onclick="openHomeCard('fine')"><span>3</span><div><b>采集 + 预筛</b><small>只保留值得进一步看的候选 · 点击查看</small></div></button>
|
|
<button class="workflow-step workflow-step-clickable" type="button" onclick="openHomeCard('recommend')"><span>4</span><div><b>Hermes 分析</b><small>推荐/谨慎/排除,必要时通知 · 点击查看</small></div></button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<!-- Task Detail (hidden initially) -->
|
|
<div id="task-detail" class="task-detail" style="display:none">
|
|
<!-- Pipeline -->
|
|
<div class="pipeline" id="pipeline"></div>
|
|
|
|
<!-- Tab Bar -->
|
|
<div class="tab-bar">
|
|
<button class="tab active" data-tab="products" onclick="switchTab('products')">商品列表</button>
|
|
<button class="tab" data-tab="analysis" onclick="switchTab('analysis')">Hermes 分析</button>
|
|
<button class="tab" data-tab="logs" onclick="switchTab('logs')">运行日志</button>
|
|
</div>
|
|
|
|
<!-- Products Tab -->
|
|
<div class="tab-content active" id="tab-products">
|
|
<div class="product-stats" id="product-stats"></div>
|
|
<div class="product-table-wrap">
|
|
<table class="product-table" id="product-table">
|
|
<thead>
|
|
<tr>
|
|
<th>图片</th><th>标题</th><th>价格</th><th>地区</th><th>阶段</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="product-tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Analysis Tab -->
|
|
<div class="tab-content" id="tab-analysis">
|
|
<div id="analysis-panel" class="analysis-panel"></div>
|
|
</div>
|
|
|
|
<!-- Logs Tab -->
|
|
<div class="tab-content" id="tab-logs">
|
|
<div class="log-panel" id="log-panel"></div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clear Cache Modal -->
|
|
<div class="modal-overlay" id="clear-cache-modal-overlay" onclick="hideClearCacheModal()">
|
|
<div class="modal clear-cache-modal" onclick="event.stopPropagation()">
|
|
<div class="modal-header">
|
|
<h2>清除采集缓存</h2>
|
|
<button class="modal-close" onclick="hideClearCacheModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="cache-warning">
|
|
这里清理的是任务内已采集商品、粗筛/细筛结果和 Hermes 分析缓存;不会删除任务配置,也不会清理登录 Cookie。
|
|
</div>
|
|
<div class="form-group">
|
|
<label>作用范围</label>
|
|
<select id="cache-task-scope" onchange="renderClearCachePreview()">
|
|
<option value="active">当前选中任务</option>
|
|
<option value="all">全部任务</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>清理方式</label>
|
|
<select id="cache-clear-mode" onchange="renderClearCachePreview()">
|
|
<option value="hermes-recommend">只保留 Hermes 推荐结果</option>
|
|
<option value="hermes-pass">保留 Hermes 通过的优质结果(推荐/谨慎且达到最低分)</option>
|
|
<option value="all">全部清除</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group" id="cache-min-score-row">
|
|
<label>优质结果最低分</label>
|
|
<input id="cache-min-score" type="number" min="0" max="100" value="75" oninput="renderClearCachePreview()">
|
|
</div>
|
|
<div class="cache-preview" id="cache-preview"></div>
|
|
<pre class="login-log" id="cache-log"></pre>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="hideClearCacheModal()">取消</button>
|
|
<button class="btn btn-danger" onclick="clearCacheFromModal()">确认清理</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notification Modal -->
|
|
<div class="modal-overlay" id="notify-modal-overlay" onclick="hideNotifyModal()">
|
|
<div class="modal notify-modal" onclick="event.stopPropagation()">
|
|
<div class="modal-header">
|
|
<h2>通知设置</h2>
|
|
<button class="modal-close" onclick="hideNotifyModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-row">
|
|
<div class="form-group checkbox-group">
|
|
<label><input id="n-enabled" type="checkbox"> 启用分析完成通知</label>
|
|
</div>
|
|
<div class="form-group checkbox-group">
|
|
<label><input id="n-good-only" type="checkbox"> 仅有合适结果时通知</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>通知最低分</label>
|
|
<input id="n-min-score" type="number" min="0" max="100" value="75">
|
|
</div>
|
|
</div>
|
|
<div class="notify-help">
|
|
推荐:Hermes 平台消息会直接调用本机 Hermes send_message,可选择飞书/微信/QQ 等目标;Bark、PushPlus 和自定义 Webhook 仍保留为备用。
|
|
</div>
|
|
<div id="notify-channels"></div>
|
|
<div class="persona-actions" style="margin-top:12px">
|
|
<button type="button" class="btn btn-sm" onclick="addNotifyChannel('hermes-send-message')">+ Hermes平台消息</button>
|
|
<button type="button" class="btn btn-sm" onclick="addNotifyChannel('bark')">+ Bark</button>
|
|
<button type="button" class="btn btn-sm" onclick="addNotifyChannel('pushplus')">+ PushPlus</button>
|
|
<button type="button" class="btn btn-sm" onclick="addNotifyChannel('webhook')">+ 自定义Webhook</button>
|
|
</div>
|
|
<pre class="login-log" id="notify-log"></pre>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="hideNotifyModal()">取消</button>
|
|
<button class="btn" onclick="testNotifyConfigFromForm()">发送测试通知</button>
|
|
<button class="btn btn-primary" onclick="saveNotifyConfigFromForm()">保存通知设置</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Login Modal -->
|
|
<div class="modal-overlay" id="login-modal-overlay" onclick="hideLoginModal()">
|
|
<div class="modal login-modal" onclick="event.stopPropagation()">
|
|
<div class="modal-header">
|
|
<h2>闲鱼账号登录 / Cookie 持久化</h2>
|
|
<button class="modal-close" onclick="hideLoginModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="login-status-card" id="login-status-card">
|
|
<div class="login-status-title">状态检测中...</div>
|
|
<div class="login-account-row" id="login-account-row" style="display:none">
|
|
<img id="login-avatar" class="login-avatar" alt="账号头像">
|
|
<div>
|
|
<div class="login-account-name" id="login-account-name"></div>
|
|
<div class="login-account-sub" id="login-account-sub"></div>
|
|
</div>
|
|
</div>
|
|
<div class="login-status-meta" id="login-status-meta"></div>
|
|
</div>
|
|
<div class="login-qr-panel" id="login-qr-panel" style="display:none">
|
|
<div class="login-qr-header">
|
|
<div>
|
|
<div class="login-qr-title">扫码登录</div>
|
|
<div class="login-qr-sub">点击“获取登录二维码”后,在这里直接扫码;二维码过期就重新获取。</div>
|
|
</div>
|
|
<button class="btn btn-sm" onclick="clearLoginQr()">清空</button>
|
|
</div>
|
|
<div class="login-qr-wrap">
|
|
<img id="login-qr-img" class="login-qr-img" alt="闲鱼登录二维码/登录面板截图">
|
|
</div>
|
|
</div>
|
|
<div class="login-actions">
|
|
<button class="btn btn-primary" onclick="fetchLoginQr()">获取/刷新登录二维码</button>
|
|
<button class="btn" onclick="checkLoginStatus()">刷新账号状态</button>
|
|
</div>
|
|
<div class="login-help">
|
|
<p>1. 点击“获取/刷新登录二维码”后,后台会从闲鱼 Web 登录入口生成二维码/登录面板截图,可直接在本页面扫码。</p>
|
|
<p>2. 扫码完成后点击“刷新账号状态”,本页会展示当前账号昵称、头像、Cookie 数和登录墙状态。</p>
|
|
<p>3. Cookie 会自动保存在项目的 <code>browser-data/</code> 目录,后续采集任务复用这个登录态。</p>
|
|
<p>4. 如果二维码过期或页面显示登录墙,重新获取二维码后再扫码。</p>
|
|
</div>
|
|
<pre class="login-log" id="login-log"></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create Task Modal -->
|
|
<div class="modal-overlay" id="modal-overlay" onclick="hideCreateModal()">
|
|
<div class="modal" onclick="event.stopPropagation()">
|
|
<div class="modal-header">
|
|
<h2 id="task-modal-title">新建采集任务</h2>
|
|
<button class="modal-close" onclick="hideCreateModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label>任务名称</label>
|
|
<input id="f-name" type="text" placeholder="例如:找一台M4 MacBook Air">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>搜索关键词 <span class="hint">(多个用逗号分隔)</span></label>
|
|
<input id="f-queries" type="text" placeholder="例如:MacBook Air M4, macbook air m4 13寸">
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>最低价</label>
|
|
<input id="f-price-min" type="number" placeholder="不限">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>最高价</label>
|
|
<input id="f-price-max" type="number" placeholder="不限">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>最大页数</label>
|
|
<input id="f-pages" type="number" value="3" min="1" max="20">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>单次最大商品数</label>
|
|
<input id="f-max-items" type="number" value="60" min="1" max="500">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>地区 <span class="hint">(省份或城市名)</span></label>
|
|
<input id="f-region" type="text" placeholder="例如:四川、成都、广东 深圳">
|
|
</div>
|
|
<div class="form-group checkbox-group">
|
|
<label><input id="f-personal" type="checkbox"> 仅个人闲置</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>需求描述 <span class="hint">(用于本地预筛和后续 Hermes 分析,自然语言描述你想买什么样的)</span></label>
|
|
<textarea id="f-requirements" rows="3" placeholder="例如:只要成色9新以上的,电池健康90%以上,价格4500以内优先,最好有原装配件和发票。不要华强北翻新机。"></textarea>
|
|
</div>
|
|
<div class="form-group task-optimize-card">
|
|
<label>AI 优化生成 <span class="hint">(根据当前商品/预算/需求生成关键词和筛选条件)</span></label>
|
|
<div class="persona-actions">
|
|
<button type="button" class="btn btn-sm btn-primary" onclick="optimizeTaskForm()">AI 优化当前表单</button>
|
|
<span class="hint" id="optimize-status"></span>
|
|
</div>
|
|
</div>
|
|
<details class="advanced-section" open>
|
|
<summary class="advanced-toggle">定时任务</summary>
|
|
<div class="form-row" style="margin-top:12px">
|
|
<div class="form-group checkbox-group">
|
|
<label><input id="f-schedule-enabled" type="checkbox"> 启用后台定时采集</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>间隔分钟</label>
|
|
<input id="f-schedule-interval" type="number" value="0" min="0" placeholder="例如:60">
|
|
</div>
|
|
</div>
|
|
<div class="hint">定时触发时会清空本轮旧结果重新采集;仍然只采集+预筛,不联系卖家。</div>
|
|
</details>
|
|
|
|
<!-- 高级设置折叠区 -->
|
|
<details class="advanced-section">
|
|
<summary class="advanced-toggle">高级设置 — 本地预筛提示词</summary>
|
|
|
|
<div class="form-group" style="margin-top:12px">
|
|
<label>粗筛提示 <span class="hint">(本地根据标题预筛时参考)</span></label>
|
|
<textarea id="f-coarse-prompt" rows="4" class="persona-editor"></textarea>
|
|
<div class="persona-actions">
|
|
<button type="button" class="btn btn-sm" onclick="resetCoarsePrompt()">恢复默认</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>细筛提示 <span class="hint">(详情采集后给 Hermes 分析参考)</span></label>
|
|
<textarea id="f-fine-prompt" rows="4" class="persona-editor"></textarea>
|
|
<div class="persona-actions">
|
|
<button type="button" class="btn btn-sm" onclick="resetFinePrompt()">恢复默认</button>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="hideCreateModal()">取消</button>
|
|
<button class="btn" id="save-only-btn" onclick="saveTask(false)">仅保存任务</button>
|
|
<button class="btn btn-primary" id="save-run-btn" onclick="saveTask(true)">保存并采集</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<script src="app.js?v=19"></script>
|
|
</body>
|
|
</html>
|