kaikai_test/public/index.html

269 lines
14 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">
<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>