mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 07:24:55 +08:00
422 lines
17 KiB
HTML
422 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">
|
|
<title>bat-api Dashboard - BlueArchiveToolkit</title>
|
|
<link rel="stylesheet" href="styles.css">
|
|
</head>
|
|
<body>
|
|
<div class="shell">
|
|
<aside class="sidebar">
|
|
<div class="brand">
|
|
<div class="brand-mark" aria-hidden="true">BA</div>
|
|
<div>
|
|
<div class="brand-title">bat-api Dashboard</div>
|
|
<div class="brand-subtitle">BlueArchiveToolkit</div>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav" aria-label="dashboard navigation">
|
|
<button class="nav-item is-active" type="button" data-view="dashboard">总览</button>
|
|
<button class="nav-item" type="button" data-view="resources">资源</button>
|
|
<button class="nav-item" type="button" data-view="schedules">调度</button>
|
|
<button class="nav-item" type="button" data-view="translation">翻译</button>
|
|
<button class="nav-item" type="button" data-view="tasks">任务</button>
|
|
<button class="nav-item" type="button" data-view="logs">日志</button>
|
|
<button class="nav-item" type="button" data-view="settings">设置</button>
|
|
</nav>
|
|
|
|
<div class="connection-box">
|
|
<span class="state-dot" id="connectionDot"></span>
|
|
<div>
|
|
<div class="connection-title" id="connectionTitle">未连接</div>
|
|
<div class="connection-subtitle" id="connectionSubtitle">等待刷新</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<main class="main">
|
|
<header class="topbar">
|
|
<div>
|
|
<h1 id="viewTitle">总览</h1>
|
|
<p id="viewSubtitle">读取 bat-api 与 Rust daemon 的当前状态。</p>
|
|
</div>
|
|
<div class="topbar-actions">
|
|
<label class="inline-check">
|
|
<input id="autoRefreshInput" type="checkbox" checked>
|
|
自动刷新
|
|
</label>
|
|
<button class="btn btn-primary" id="refreshAllBtn" type="button">刷新</button>
|
|
</div>
|
|
</header>
|
|
|
|
<section class="view is-active" id="view-dashboard" data-title="总览" data-subtitle="读取 bat-api 与 Rust daemon 的当前状态。">
|
|
<div class="status-grid">
|
|
<div class="metric">
|
|
<div class="metric-label">bat-api</div>
|
|
<div class="metric-value" id="metricHealth">unknown</div>
|
|
<div class="metric-note" id="metricHealthNote">-</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-label">Rust RPC</div>
|
|
<div class="metric-value" id="metricRpc">unknown</div>
|
|
<div class="metric-note" id="metricRpcNote">-</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-label">资源完整度</div>
|
|
<div class="metric-value" id="metricResources">-</div>
|
|
<div class="metric-note" id="metricResourcesNote">-</div>
|
|
</div>
|
|
<div class="metric">
|
|
<div class="metric-label">汉化状态</div>
|
|
<div class="metric-value" id="metricLocalized">unknown</div>
|
|
<div class="metric-note" id="metricLocalizedNote">需要 admin token</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid two-col">
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>当前 release</h2>
|
|
<p id="releaseSummary">尚未读取</p>
|
|
</div>
|
|
</div>
|
|
<dl class="kv-list" id="releaseDetails"></dl>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>最近任务</h2>
|
|
<p id="taskSummary">需要 admin token</p>
|
|
</div>
|
|
<button class="btn btn-small" type="button" data-jump="tasks">打开任务</button>
|
|
</div>
|
|
<div class="list" id="dashboardTaskList"></div>
|
|
</section>
|
|
</div>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>资源样本</h2>
|
|
<p id="resourceSampleSummary">读取 /v1/resources</p>
|
|
</div>
|
|
<button class="btn btn-small" type="button" data-jump="resources">查看资源</button>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>路径</th>
|
|
<th>大小</th>
|
|
<th>状态</th>
|
|
<th>BLAKE3</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="dashboardResourceRows"></tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
|
|
<section class="view" id="view-resources" data-title="资源" data-subtitle="查看当前发布 release 的资源清单,并触发同步、校验或修复。">
|
|
<section class="panel">
|
|
<div class="panel-head split">
|
|
<div>
|
|
<h2>资源清单</h2>
|
|
<p id="resourceListSummary">-</p>
|
|
</div>
|
|
<div class="row-actions">
|
|
<button class="btn" type="button" data-control="sync">同步</button>
|
|
<button class="btn" type="button" data-control="verify">校验</button>
|
|
<button class="btn btn-danger" type="button" data-control="repair">修复</button>
|
|
</div>
|
|
</div>
|
|
<div class="filter-row">
|
|
<input id="resourceFilterInput" type="search" placeholder="过滤已加载路径">
|
|
<select id="resourceLimitInput">
|
|
<option value="20">20</option>
|
|
<option value="50" selected>50</option>
|
|
<option value="100">100</option>
|
|
<option value="200">200</option>
|
|
</select>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>路径</th>
|
|
<th>大小</th>
|
|
<th>状态</th>
|
|
<th>BLAKE3</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="resourceRows"></tbody>
|
|
</table>
|
|
</div>
|
|
<div class="pager">
|
|
<span id="resourcePagerText">-</span>
|
|
<div>
|
|
<button class="btn btn-small" id="resourcePrevBtn" type="button">上一页</button>
|
|
<button class="btn btn-small" id="resourceNextBtn" type="button">下一页</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
|
|
<section class="view" id="view-schedules" data-title="调度" data-subtitle="管理 Rust 持久化 schedule,覆盖资源拉取、解析、翻译和发布任务。">
|
|
<div class="grid two-col">
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>计划列表</h2>
|
|
<p id="scheduleSummary">需要 admin token</p>
|
|
</div>
|
|
<button class="btn btn-small" id="scheduleRefreshBtn" type="button">刷新</button>
|
|
</div>
|
|
<div class="filter-row">
|
|
<input id="scheduleIdFilter" type="search" placeholder="id">
|
|
<input id="scheduleGroupFilter" type="search" placeholder="group: res / parse / i18n">
|
|
<select id="scheduleEnabledFilter">
|
|
<option value="">全部</option>
|
|
<option value="true">启用</option>
|
|
<option value="false">停用</option>
|
|
</select>
|
|
</div>
|
|
<div class="list" id="scheduleList"></div>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>新增或更新</h2>
|
|
<p>schedule.add / schedule.update</p>
|
|
</div>
|
|
</div>
|
|
<form class="form" id="scheduleForm">
|
|
<label>ID <input id="scheduleIdInput" autocomplete="off"></label>
|
|
<label>Group <input id="scheduleGroupInput" placeholder="res"></label>
|
|
<label>Command <input id="scheduleActionInput" placeholder="res sync"></label>
|
|
<label>Args <textarea id="scheduleArgsInput" rows="3" placeholder="每行一个参数"></textarea></label>
|
|
<div class="form-grid">
|
|
<label>Delay seconds <input id="scheduleDelayInput" type="number" min="0"></label>
|
|
<label>Every seconds <input id="scheduleEveryInput" type="number" min="1"></label>
|
|
<label>Count <input id="scheduleCountInput" type="number" min="1"></label>
|
|
<label>Next run unix <input id="scheduleNextRunInput" type="number" min="0"></label>
|
|
</div>
|
|
<label class="inline-check"><input id="scheduleEnabledInput" type="checkbox" checked>启用</label>
|
|
<div class="row-actions">
|
|
<button class="btn btn-primary" id="scheduleAddBtn" type="button">新增</button>
|
|
<button class="btn" id="scheduleUpdateBtn" type="button">更新</button>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view" id="view-translation" data-title="翻译" data-subtitle="查看翻译任务、触发 provider worker、编辑人工校对结果并发布汉化资源。">
|
|
<div class="grid two-col">
|
|
<section class="panel">
|
|
<div class="panel-head split">
|
|
<div>
|
|
<h2>翻译任务</h2>
|
|
<p id="translationTaskSummary">需要 admin token</p>
|
|
</div>
|
|
<button class="btn btn-small" id="translationRefreshBtn" type="button">刷新</button>
|
|
</div>
|
|
<div class="filter-row">
|
|
<select id="translationStatusFilter">
|
|
<option value="">全部状态</option>
|
|
<option value="queued">queued</option>
|
|
<option value="running">running</option>
|
|
<option value="failed">failed</option>
|
|
<option value="completed">completed</option>
|
|
<option value="skipped">skipped</option>
|
|
</select>
|
|
<input id="translationDestinationFilter" type="search" placeholder="destination">
|
|
<input id="translationTaskFilter" type="search" placeholder="task_id">
|
|
</div>
|
|
<div class="table-wrap compact">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>任务</th>
|
|
<th>资源</th>
|
|
<th>状态</th>
|
|
<th>结果</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="translationTaskRows"></tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>Provider worker</h2>
|
|
<p>translation.worker.run</p>
|
|
</div>
|
|
</div>
|
|
<form class="form">
|
|
<div class="form-grid">
|
|
<label>Provider
|
|
<select id="workerProviderInput">
|
|
<option value="mock">mock</option>
|
|
<option value="crowdin">crowdin</option>
|
|
</select>
|
|
</label>
|
|
<label>Concurrency <input id="workerConcurrencyInput" type="number" min="1" max="256" value="8"></label>
|
|
<label>Max attempts <input id="workerMaxAttemptsInput" type="number" min="1" value="3"></label>
|
|
<label>Lease seconds <input id="workerLeaseInput" type="number" min="1" value="300"></label>
|
|
<label>Backoff seconds <input id="workerBackoffInput" type="number" min="0" value="5"></label>
|
|
<label>Max tasks <input id="workerMaxTasksInput" type="number" min="1"></label>
|
|
</div>
|
|
<label>Worker ID <input id="workerIdInput" placeholder="dashboard-worker"></label>
|
|
<label>Fixture path <input id="workerFixtureInput" placeholder="/tmp/mock-provider.json"></label>
|
|
<button class="btn btn-primary" id="workerRunBtn" type="button">启动 worker</button>
|
|
</form>
|
|
</section>
|
|
</div>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head split">
|
|
<div>
|
|
<h2>人工校对</h2>
|
|
<p id="translationDetailSummary">选择一个翻译任务</p>
|
|
</div>
|
|
<div class="row-actions">
|
|
<button class="btn" id="proofreadBtn" type="button">标记人工校对中</button>
|
|
<button class="btn btn-primary" id="manualSaveBtn" type="button">保存校对结果</button>
|
|
</div>
|
|
</div>
|
|
<div class="form manual-meta">
|
|
<label>Provider run ID <input id="manualProviderRunInput" placeholder="留空时由 Rust 生成"></label>
|
|
</div>
|
|
<div class="unit-editor" id="unitEditor"></div>
|
|
</section>
|
|
|
|
<div class="grid two-col">
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>汉化发布</h2>
|
|
<p id="localizedSummary">需要 admin token</p>
|
|
</div>
|
|
</div>
|
|
<div class="form">
|
|
<label>Localized release ID <input id="localizedReleaseInput" placeholder="可选"></label>
|
|
<label class="inline-check"><input id="localizedForceInput" type="checkbox">强制发布</label>
|
|
<div class="row-actions">
|
|
<button class="btn btn-primary" id="localizedPublishBtn" type="button">从 worker 结果发布</button>
|
|
<button class="btn btn-danger" id="localizedRollbackBtn" type="button">回滚</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>交接视图</h2>
|
|
<p id="handoffSummary">translation.handoff</p>
|
|
</div>
|
|
</div>
|
|
<dl class="kv-list" id="handoffDetails"></dl>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view" id="view-tasks" data-title="任务" data-subtitle="轮询 Rust daemon 持久化任务,查看状态、日志并发起取消。">
|
|
<section class="panel">
|
|
<div class="panel-head split">
|
|
<div>
|
|
<h2>任务列表</h2>
|
|
<p id="daemonTaskSummary">需要 admin token</p>
|
|
</div>
|
|
<button class="btn btn-small" id="daemonTaskRefreshBtn" type="button">刷新</button>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Task ID</th>
|
|
<th>Kind</th>
|
|
<th>Status</th>
|
|
<th>Stage</th>
|
|
<th>Updated</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="daemonTaskRows"></tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head split">
|
|
<div>
|
|
<h2>任务详情</h2>
|
|
<p id="daemonTaskDetailSummary">选择一个任务</p>
|
|
</div>
|
|
<button class="btn btn-danger" id="daemonTaskCancelBtn" type="button">取消任务</button>
|
|
</div>
|
|
<dl class="kv-list" id="daemonTaskDetails"></dl>
|
|
<pre class="log-box" id="daemonTaskLogBox"></pre>
|
|
</section>
|
|
</section>
|
|
|
|
<section class="view" id="view-logs" data-title="日志" data-subtitle="读取 Rust daemon 诊断和最近日志。">
|
|
<div class="grid two-col">
|
|
<section class="panel">
|
|
<div class="panel-head split">
|
|
<div>
|
|
<h2>诊断</h2>
|
|
<p id="doctorSummary">需要 admin token</p>
|
|
</div>
|
|
<button class="btn btn-small" id="doctorRefreshBtn" type="button">刷新</button>
|
|
</div>
|
|
<div class="list" id="doctorChecks"></div>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head split">
|
|
<div>
|
|
<h2>Daemon log</h2>
|
|
<p id="logSummary">需要 admin token</p>
|
|
</div>
|
|
<label class="inline-label">Tail <input id="logTailInput" type="number" min="1" max="2000" value="200"></label>
|
|
</div>
|
|
<pre class="log-box" id="daemonLogBox"></pre>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view" id="view-settings" data-title="设置" data-subtitle="配置 dashboard 调用 bat-api 的地址和 admin token。">
|
|
<section class="panel settings-panel">
|
|
<div class="panel-head">
|
|
<div>
|
|
<h2>连接</h2>
|
|
<p>默认使用当前页面同源 bat-api。</p>
|
|
</div>
|
|
</div>
|
|
<form class="form">
|
|
<label>Base URL <input id="baseUrlInput" autocomplete="off"></label>
|
|
<label>Admin token <input id="tokenInput" type="password" autocomplete="off"></label>
|
|
<label class="inline-check"><input id="rememberTokenInput" type="checkbox">在本浏览器保存 token</label>
|
|
<div class="row-actions">
|
|
<button class="btn btn-primary" id="saveSettingsBtn" type="button">保存并刷新</button>
|
|
<button class="btn" id="forgetSettingsBtn" type="button">清除</button>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
|
|
<div class="toast-region" id="toastRegion" aria-live="polite"></div>
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|