205 lines
9.4 KiB
HTML
205 lines
9.4 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="styles.css">
|
||
</head>
|
||
<body data-theme="dark">
|
||
|
||
<div class="toast-container" id="toastContainer"></div>
|
||
|
||
<div class="modal-overlay" id="settingsModal">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<h3>设置</h3>
|
||
<button class="modal-close" onclick="closeSettings()">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="form-group">
|
||
<div class="toggle-row">
|
||
<span class="toggle-label">Trace 日志</span>
|
||
<label class="toggle"><input type="checkbox" id="setTraceEnabled"><span class="toggle-slider"></span></label>
|
||
</div>
|
||
<div class="form-hint">开启后会在 logs/ 目录生成 douyu_trace_*.log,文件较大</div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label class="form-label">Trace 正文上限(字节)</label>
|
||
<input class="form-input" type="number" id="setTraceMaxBody" min="0" step="1024" placeholder="0=不限">
|
||
<div class="form-hint">0 表示不限</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label">日志显示等级</label>
|
||
<select class="form-select" id="setLogLevel">
|
||
<option value="debug">Debug</option>
|
||
<option value="info">Info</option>
|
||
<option value="warn">Warn</option>
|
||
<option value="error">Error</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label class="form-label">抢购并发数</label>
|
||
<input class="form-input" type="number" id="setConcurrency" min="1" max="200" step="10">
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label">单号重试次数</label>
|
||
<input class="form-input" type="number" id="setAttempts" min="1" max="10" step="1">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-ghost" onclick="closeSettings()">取消</button>
|
||
<button class="btn btn-primary" onclick="saveSettings()">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="app-shell">
|
||
<aside class="left">
|
||
<div class="brand">
|
||
<div>
|
||
<h1>斗鱼抢购</h1>
|
||
<div class="brand-sub">实时库存 · 多账号 · 定时触发</div>
|
||
</div>
|
||
<span class="stat-pill" id="versionTag">v--</span>
|
||
</div>
|
||
<div class="left-header">
|
||
<div class="product-actions">
|
||
<button class="btn btn-primary" id="btnLoadProducts" onclick="loadProducts(true)">刷新商品</button>
|
||
</div>
|
||
<div class="product-search">
|
||
<span class="search-icon">⌕</span>
|
||
<input id="productSearch" type="search" placeholder="搜索商品名 / ID / 积分 / 库存" autocomplete="off" oninput="setProductSearch(this.value)">
|
||
<button class="search-clear" id="btnClearProductSearch" type="button" onclick="clearProductSearch()" title="清空">×</button>
|
||
</div>
|
||
<div class="selected-product-card" id="selectedProductCard">
|
||
<div class="selected-product-label">当前商品</div>
|
||
<div class="selected-product-name" id="selectedProductName">未选</div>
|
||
<div class="selected-product-meta" id="selectedProductMeta"></div>
|
||
</div>
|
||
<div class="product-meta" id="productMeta">库存未刷新</div>
|
||
</div>
|
||
<div class="left-list" id="prodList">
|
||
<div class="empty-state">点击「刷新商品」获取列表</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="right">
|
||
<header class="console-head">
|
||
<div class="headline">
|
||
<div>
|
||
<div class="headline-title">抢购控制台</div>
|
||
<div class="headline-meta" id="runStateText">等待操作</div>
|
||
</div>
|
||
<span id="cdBadge" class="countdown-badge" style="display:none"></span>
|
||
</div>
|
||
<div class="top-actions">
|
||
<button class="btn btn-ghost icon-btn" onclick="openSettings()" title="设置" aria-label="设置">⚙</button>
|
||
<button class="btn btn-ghost icon-btn theme-toggle" id="btnTheme" onclick="toggleTheme()" title="切换主题" aria-label="切换主题">☾</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="status-grid">
|
||
<div class="metric">
|
||
<span class="metric-label">服务器</span>
|
||
<span class="metric-value server" id="svrTime">--</span>
|
||
</div>
|
||
<div class="metric">
|
||
<span class="metric-label">账号</span>
|
||
<span class="metric-value"><span id="selectedCnt">0</span>/<span id="accCnt">0</span></span>
|
||
</div>
|
||
<div class="metric">
|
||
<span class="metric-label">成功</span>
|
||
<span class="metric-value success-num" id="successCnt">0</span>
|
||
</div>
|
||
<div class="metric">
|
||
<span class="metric-label">异常</span>
|
||
<span class="metric-value fail-num" id="failCnt">0</span>
|
||
</div>
|
||
<div class="metric">
|
||
<span class="metric-label">待处理</span>
|
||
<span class="metric-value" id="pendingCnt">0</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-strip">
|
||
<div class="action-group">
|
||
<button class="btn btn-danger" onclick="startNow()">立即抢购</button>
|
||
<button class="btn btn-success" id="btnSchedule" onclick="startSchedule()">开启定时</button>
|
||
<button class="btn btn-cancel" id="btnCancel" onclick="cancelSchedule()" style="display:none">停止定时</button>
|
||
<button class="btn" onclick="reloadAccounts()">加载账号</button>
|
||
<button class="btn" onclick="queryAllScore()">查询积分</button>
|
||
</div>
|
||
<div class="schedule-bar">
|
||
<div class="schedule-item">
|
||
<label>目标</label>
|
||
<input type="time" id="targetTime" value="18:00:00" step="1">
|
||
</div>
|
||
<div class="schedule-item">
|
||
<label>提前</label>
|
||
<input type="number" id="advance" value="300" min="0" max="5000" step="100">
|
||
<span style="color:var(--muted);font-size:11.5px">ms</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<section class="workspace">
|
||
<div class="panel">
|
||
<div class="panel-head">
|
||
<div>
|
||
<span class="panel-title">账号作战表</span>
|
||
<span class="panel-sub" id="accountPanelSub">0 个账号</span>
|
||
</div>
|
||
<label class="stat-pill"><input type="checkbox" id="chkAll" onchange="toggleAll()"> 全选</label>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th class="select-cell"></th>
|
||
<th>账号</th>
|
||
<th>凭据</th>
|
||
<th>商品</th>
|
||
<th>积分</th>
|
||
<th class="status-col">状态</th>
|
||
<th>最后结果</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="accTable"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<aside class="side-stack">
|
||
<div class="panel log-wrap">
|
||
<div class="log-header">
|
||
<div class="log-tabs">
|
||
<button class="log-tab active" data-log-tab="logBody" onclick="switchLogTab('logBody')">实时日志</button>
|
||
<button class="log-tab" data-log-tab="resultBody" onclick="switchLogTab('resultBody')">抢购结果</button>
|
||
<button class="log-tab" data-log-tab="statsBody" onclick="switchLogTab('statsBody')">统计</button>
|
||
</div>
|
||
<button class="btn btn-compact" onclick="clearLog()">清空</button>
|
||
</div>
|
||
<div class="log-panel log-body active" id="logBody">
|
||
<div class="log-i">[系统] 就绪,等待操作...</div>
|
||
</div>
|
||
<div class="log-panel" id="resultBody">
|
||
<div class="result-empty">暂无抢购结果</div>
|
||
</div>
|
||
<div class="log-panel" id="statsBody">
|
||
<div class="result-empty">暂无统计数据</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|