269 lines
14 KiB
HTML
269 lines
14 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>节目热度采集</title>
|
||
<link rel="stylesheet" href="/styles.css">
|
||
<link rel="stylesheet" href="/rankings.css">
|
||
</head>
|
||
<body>
|
||
<nav class="app-nav" aria-label="桌面 App 导航">
|
||
<a class="app-nav-brand" href="#desktop-dashboard">节目热度采集</a>
|
||
<span id="app-version-badge" class="app-version-badge">桌面开发版</span>
|
||
<div class="app-nav-links">
|
||
<a href="#desktop-dashboard">工作台</a>
|
||
<a href="#collect-form">采集</a>
|
||
<a href="#temporary-query-panel">临时查询</a>
|
||
<a href="#program-list">历史库</a>
|
||
</div>
|
||
<div class="app-nav-meta">
|
||
<span>本地端口</span>
|
||
<strong id="app-status-port">--</strong>
|
||
</div>
|
||
</nav>
|
||
<main class="shell">
|
||
<header class="topbar">
|
||
<div class="brand-block">
|
||
<div class="brand-copy">
|
||
<h1>节目热度采集</h1>
|
||
<p id="subtitle">腾讯视频、优酷、爱奇艺、芒果TV</p>
|
||
</div>
|
||
<div class="top-actions">
|
||
<button id="collect-history-button" class="top-collect-all" type="button">采集全部历史节目</button>
|
||
<button id="retry-pending-button" class="top-collect-all secondary" type="button">复查无数据</button>
|
||
</div>
|
||
</div>
|
||
<form id="collect-form" class="searchbar">
|
||
<input id="program-name" name="name" type="search" placeholder="输入节目名" autocomplete="off" required>
|
||
<button id="collect-button" type="submit">采集一次</button>
|
||
<a id="export-link" class="button ghost" href="#" aria-disabled="true">导出 CSV</a>
|
||
<a id="export-all-link" class="button ghost" href="/api/export-all">导出全部</a>
|
||
<div class="url-grid" aria-label="节目页地址">
|
||
<input id="url-tencent" name="tencent" type="url" placeholder="腾讯视频 URL">
|
||
<input id="url-youku" name="youku" type="url" placeholder="优酷 URL">
|
||
<input id="url-iqiyi" name="iqiyi" type="url" placeholder="爱奇艺 URL">
|
||
<input id="url-mgtv" name="mgtv" type="url" placeholder="芒果TV URL">
|
||
</div>
|
||
<div id="link-candidates" class="link-candidates" aria-live="polite"></div>
|
||
<div class="collect-platforms" aria-label="本次采集平台">
|
||
<span>本次采集</span>
|
||
<label><input type="checkbox" value="tencent" checked>腾讯视频</label>
|
||
<label><input type="checkbox" value="youku" checked>优酷</label>
|
||
<label><input type="checkbox" value="iqiyi" checked>爱奇艺</label>
|
||
<label><input type="checkbox" value="mgtv" checked>芒果TV</label>
|
||
<button id="collect-platform-all" class="mini-button" type="button">全选</button>
|
||
</div>
|
||
<div class="library-row">
|
||
<input id="alias-input" type="text" placeholder="别名,多个用逗号分隔">
|
||
<button id="save-library-button" class="button ghost" type="button">保存链接库</button>
|
||
<span id="library-status" class="inline-status"></span>
|
||
</div>
|
||
<details class="network-help">
|
||
<summary>手机不在同一 WiFi 怎么用</summary>
|
||
<div class="help-grid">
|
||
<span>最快:让手机连接电脑开的热点,再打开手机访问地址。</span>
|
||
<span>稳定:电脑和手机都装 Tailscale,用 Tailscale 分配的电脑地址访问。</span>
|
||
<span>临时外网:用内网穿透工具转发 3000 端口,只发给可信的人。</span>
|
||
</div>
|
||
</details>
|
||
</form>
|
||
</header>
|
||
|
||
<section class="statusline" aria-live="polite">
|
||
<span id="status-dot" class="dot idle"></span>
|
||
<span id="status-text">等待输入节目名</span>
|
||
</section>
|
||
|
||
<section id="task-queue-panel" class="task-queue-panel idle" aria-label="采集任务队列">
|
||
<div class="task-queue-head">
|
||
<div>
|
||
<div class="panel-title">任务队列</div>
|
||
<div id="task-current" class="task-current">暂无运行中的采集任务</div>
|
||
</div>
|
||
<div id="task-ratio" class="task-ratio">0/0</div>
|
||
</div>
|
||
<div class="task-progress-track" aria-hidden="true">
|
||
<div id="task-progress-fill" class="task-progress-fill"></div>
|
||
</div>
|
||
<div class="task-counters">
|
||
<span>有效 <strong id="task-ok-count">0</strong></span>
|
||
<span>未找到/无指标 <strong id="task-missing-count">0</strong></span>
|
||
<span>风控/错误 <strong id="task-error-count">0</strong></span>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="mobile-sync-panel" class="mobile-sync-panel">
|
||
<div class="panel-head">
|
||
<div>
|
||
<div class="panel-title">手机同步待处理</div>
|
||
<div class="panel-note">手机端同步过来的节目先放这里,不会自动写入历史数据。</div>
|
||
</div>
|
||
</div>
|
||
<div id="mobile-sync-list" class="mobile-sync-list empty">暂无手机同步记录</div>
|
||
</section>
|
||
|
||
<section id="duty-panel" class="duty-panel">
|
||
<div class="panel-head">
|
||
<div>
|
||
<div class="panel-title">半自动值班</div>
|
||
<div class="panel-note">减少每天重复操作:复查无数据、采集历史、导出 CSV、备份数据。</div>
|
||
</div>
|
||
<button id="duty-run-now" class="mini-button" type="button">立即执行一次</button>
|
||
</div>
|
||
<div class="duty-grid">
|
||
<label><input id="duty-auto-retry" type="checkbox"> 每天复查无数据</label>
|
||
<label><input id="duty-auto-collect" type="checkbox"> 每天采集历史节目</label>
|
||
<label><input id="duty-auto-export" type="checkbox"> 完成后导出 CSV 并备份</label>
|
||
<label class="duty-time">执行时间 <input id="duty-run-time" type="time" value="09:30"></label>
|
||
<button id="duty-save-settings" class="mini-button" type="button">保存值班设置</button>
|
||
</div>
|
||
<div id="duty-status" class="duty-status">尚未执行值班任务</div>
|
||
</section>
|
||
|
||
<section class="workspace">
|
||
<aside class="side">
|
||
<div class="side-title">
|
||
<span>历史节目</span>
|
||
<div class="history-actions">
|
||
<button id="history-collect-selected" class="collect-history-button" type="button">采集选中</button>
|
||
<button id="history-bulk-button" class="collect-history-button" type="button">批量选择</button>
|
||
</div>
|
||
</div>
|
||
<div id="history-bulk-bar" class="history-bulk-bar" hidden>
|
||
<button id="history-delete-selected" type="button">删除选中</button>
|
||
<button id="history-cancel-bulk" type="button">取消</button>
|
||
</div>
|
||
<div id="program-list" class="program-list"></div>
|
||
</aside>
|
||
|
||
<section class="table-panel">
|
||
<div class="table-tools">
|
||
<div id="table-title" class="table-title">还没有采集结果</div>
|
||
<div class="table-actions">
|
||
<button id="run-bulk-button" class="mini-button" type="button">批量删除列</button>
|
||
<div id="run-count" class="run-count">0 次</div>
|
||
</div>
|
||
</div>
|
||
<div id="run-bulk-bar" class="run-bulk-bar" hidden>
|
||
<button id="run-delete-selected" type="button">删除选中列</button>
|
||
<button id="run-cancel-bulk" type="button">取消</button>
|
||
</div>
|
||
<div class="platform-filters" aria-label="筛选视频网站">
|
||
<button class="filter-chip active" type="button" data-platform-filter="tencent">腾讯视频</button>
|
||
<button class="filter-chip active" type="button" data-platform-filter="youku">优酷</button>
|
||
<button class="filter-chip active" type="button" data-platform-filter="iqiyi">爱奇艺</button>
|
||
<button class="filter-chip active" type="button" data-platform-filter="mgtv">芒果TV</button>
|
||
<button class="filter-chip reset" type="button" data-platform-filter="all">全部</button>
|
||
</div>
|
||
<div class="run-collapse-tools">
|
||
<span id="run-collapse-note" class="run-collapse-note"></span>
|
||
<button id="run-collapse-toggle" class="mini-button" type="button" hidden>展开旧列</button>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table id="hotness-table">
|
||
<thead></thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
<section class="chart-panel">
|
||
<div class="panel-head">
|
||
<div class="panel-title">趋势图</div>
|
||
<div class="panel-note">每个平台独立刻度</div>
|
||
</div>
|
||
<div id="trend-charts" class="trend-grid"></div>
|
||
</section>
|
||
|
||
<section id="desktop-dashboard" class="desktop-dashboard" aria-label="今日工作台">
|
||
<div class="dashboard-card dashboard-card-main">
|
||
<div class="dashboard-label">历史节目</div>
|
||
<div id="dashboard-program-count" class="dashboard-value">0</div>
|
||
<div class="dashboard-note">已建立采集档案</div>
|
||
</div>
|
||
<div class="dashboard-card">
|
||
<div class="dashboard-label">最近采集</div>
|
||
<div id="dashboard-last-capture" class="dashboard-value compact">--</div>
|
||
<div class="dashboard-note">来自历史库更新时间</div>
|
||
</div>
|
||
<div class="dashboard-card">
|
||
<div class="dashboard-label">当前节目待复查</div>
|
||
<div id="dashboard-pending-count" class="dashboard-value">--</div>
|
||
<div class="dashboard-note">未匹配、无指标、风控或错误</div>
|
||
</div>
|
||
<div class="dashboard-card dashboard-actions-card">
|
||
<div class="dashboard-label">快捷入口</div>
|
||
<div class="dashboard-actions">
|
||
<a class="dashboard-action" href="#temporary-query-panel">临时查询</a>
|
||
<a class="dashboard-action" href="#program-list">历史节目</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="compare-panel">
|
||
<div class="panel-head">
|
||
<div class="panel-title">节目对比</div>
|
||
<div class="compare-controls">
|
||
<select id="compare-platform" aria-label="对比平台">
|
||
<option value="tencent">腾讯视频</option>
|
||
<option value="youku">优酷</option>
|
||
<option value="iqiyi">爱奇艺</option>
|
||
<option value="mgtv">芒果TV</option>
|
||
</select>
|
||
<select id="compare-range" aria-label="对比日期范围">
|
||
<option value="today">当天</option>
|
||
<option value="3d">近三天</option>
|
||
<option value="7d">近七天</option>
|
||
<option value="all" selected>全部</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div id="compare-list" class="compare-list"></div>
|
||
<div id="compare-chart" class="compare-chart empty">选择节目后显示对比</div>
|
||
<div id="compare-table" class="compare-table"></div>
|
||
</section>
|
||
<section id="ranking-radar" class="ranking-panel"></section>
|
||
</section>
|
||
</section>
|
||
|
||
<section id="temporary-query-panel" class="temporary-query-panel">
|
||
<div class="panel-head">
|
||
<div>
|
||
<div class="panel-title">临时查询</div>
|
||
<div class="panel-note">只查这一次,不写入历史;可单独导出 CSV</div>
|
||
</div>
|
||
<div class="temporary-actions">
|
||
<label class="file-button">
|
||
导入列表
|
||
<input id="temporary-file-input" type="file" accept=".txt,.csv,.xlsx,text/plain,text/csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,image/*">
|
||
</label>
|
||
<label><input id="temporary-save-links" type="checkbox">保存成功链接</label>
|
||
<button id="temporary-query-button" class="mini-button" type="button">一键查询</button>
|
||
<button id="temporary-export-button" class="mini-button" type="button" disabled>导出临时 CSV</button>
|
||
</div>
|
||
</div>
|
||
<textarea id="temporary-query-text" rows="4" placeholder="粘贴节目列表,每行一个节目名"></textarea>
|
||
<div id="temporary-query-result" class="temporary-result empty">暂无临时查询结果</div>
|
||
</section>
|
||
</main>
|
||
<footer class="app-status-dock" aria-live="polite">
|
||
<span class="dock-label">状态</span>
|
||
<span id="app-status-text">等待操作</span>
|
||
<span class="dock-separator"></span>
|
||
<span id="app-build-label">桌面开发版</span>
|
||
<span class="dock-separator"></span>
|
||
<span>端口 <strong id="app-status-port-dock">--</strong></span>
|
||
</footer>
|
||
<dialog id="detail-dialog" class="detail-dialog">
|
||
<form method="dialog">
|
||
<div class="dialog-head">
|
||
<strong id="detail-title">采集详情</strong>
|
||
<button class="close-button" value="close" aria-label="关闭">×</button>
|
||
</div>
|
||
<div id="detail-body" class="detail-body"></div>
|
||
</form>
|
||
</dialog>
|
||
<script src="/app.js" type="module"></script>
|
||
<script src="/rankings.js" type="module"></script>
|
||
</body>
|
||
</html>
|