以前只用了「邦国领土」这一类接口,控制台也只能看到一行「已启用/未启用」, 大量服务端公开信息拿得到却看不到。现在按官方文档 https://open.bgjq.top/api-docs.html 补齐。 新增 - SimpApiClient 从 7 个接口补到 16 个:/info/players、/info/unions/{key}/members、 /tech、/contributions、/info/buffs、/info/diplomacy、/info/bans、/info/logs、 /info/announcements - SimpApiV2Client(新):/players、/players/{name}/equipment、/time、/dragon。 文档明确 API 与 API-V2 是两套独立、互不通用的密钥体系,因此单独实例与配置 (apiV2Enabled / apiV2Key,或环境变量 SIMP_API_V2_KEY);V2 配额很小 (末影龙 1 次/分钟),一律按需查询、不做轮询 - 控制台「查看 API 数据」弹层,五个页签: 概览(两套密钥状态/请求数/缓存/健康检查)· 邦国(27 个,点开看成员/科技/捐献/领土统计) · 玩家(1600+ 可搜索,点开看详情与所属邦国)· 全服(加成/外交/封禁/日志/公告) · 实时 V2(在线玩家/游戏时间/末影龙/装备) - /api/simp/* 一整套只读代理接口,统一处理「未配 Key / 上游错误」并给出可读提示 修复(解析字段名以实测响应为准) - 捐献:响应只有 player_uuid 没有玩家名 -> 先用成员表补全、查不到再退到全服玩家表; 时间字段是 contributed_at;补充 reason(用途)列;amount 可为负(邦国支出) - 公告:message 是 Minecraft 聊天组件 JSON 字符串 -> 新增 componentToText() 压平为纯文本 - 封禁:实际字段 banned_player_name / banned_by_player_name / banned_at / unbanned - 日志:实际字段 username / action / timestamp - 玩家表:上下线时间是 last_join_time / last_quit_time - 王城坐标:服务端可能返回 null,原来 Number(null) 会算成 0, 伪装成「王城在世界原点 (0,0)」;现在显式判空返回 null 变更 - 快捷发送去掉 /spawn 与 /list,只留 /u return、/u claimmode、/u restore confirm 测试 326 -> 336,全部通过。
362 行
16 KiB
HTML
362 行
16 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||
<meta name="theme-color" content="#0d1117">
|
||
<title>AutoStore Bot 控制台</title>
|
||
<link rel="stylesheet" href="style.css">
|
||
</head>
|
||
<body>
|
||
<header class="topbar">
|
||
<div class="brand">
|
||
<span class="logo">AS</span>
|
||
<div class="brand-text">
|
||
<h1>AutoStore Bot</h1>
|
||
<p>多机器人自动扩地 · mineflayer · Grim 合规 · 大地图</p>
|
||
</div>
|
||
</div>
|
||
<div class="topbar-right">
|
||
<label class="field-inline">
|
||
<span class="field-label">当前机器人</span>
|
||
<select id="botSelect" class="input input-sm"></select>
|
||
</label>
|
||
<div class="badges">
|
||
<span id="connBadge" class="badge badge-offline">未连接</span>
|
||
<span id="taskBadge" class="badge badge-idle">空闲</span>
|
||
<span id="authBadge" class="badge badge-idle" title="控制台登录状态">未登录</span>
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<button id="btnStart" class="btn btn-primary">开始扩地</button>
|
||
<button id="btnStop" class="btn btn-danger">停止</button>
|
||
<button id="btnReconnect" class="btn">重连</button>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<nav class="mobile-nav" id="mobileNav">
|
||
<button class="mobile-nav-item active" data-scroll="panelStatus">状态</button>
|
||
<button class="mobile-nav-item" data-scroll="panelMap">地图</button>
|
||
<button class="mobile-nav-item" data-scroll="panelLogs">日志</button>
|
||
<button class="mobile-nav-item" data-scroll="panelConfig">配置</button>
|
||
</nav>
|
||
|
||
<main class="layout">
|
||
<!-- ==================== 左栏:状态面板 ==================== -->
|
||
<section class="column col-left" id="panelStatus">
|
||
<div class="card">
|
||
<div class="card-head">
|
||
<h2>机器人(<span id="botCount">0</span>)</h2>
|
||
<div class="row row-compact">
|
||
<button id="btnStartAll" class="btn btn-sm">全部开始</button>
|
||
<button id="btnStopAll" class="btn btn-sm">全部停止</button>
|
||
</div>
|
||
</div>
|
||
<div id="botList" class="bot-list"></div>
|
||
<details class="add-bot">
|
||
<summary>+ 添加玩家</summary>
|
||
<div class="field">
|
||
<input id="newBotName" class="input" type="text" placeholder="玩家名(1-16 位字母/数字/下划线)" maxlength="16">
|
||
</div>
|
||
<div class="field">
|
||
<input id="newBotPass" class="input" type="password" placeholder="服务器密码(可留空)" autocomplete="new-password">
|
||
</div>
|
||
<div class="field">
|
||
<input id="newBotLabel" class="input" type="text" placeholder="备注(可留空)">
|
||
</div>
|
||
<button id="btnAddBot" class="btn btn-sm btn-primary btn-block">添加</button>
|
||
<p class="hint">密码只保存在服务器本地凭据文件(权限 0600),不会进仓库、也不会出现在任何接口响应里。.env 里配置的账号需改 .env 才能移除。</p>
|
||
</details>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>连接</h2>
|
||
<dl class="kv">
|
||
<dt>服务器</dt><dd id="kServer">-</dd>
|
||
<dt>玩家名</dt><dd id="kUsername">-</dd>
|
||
<dt>版本</dt><dd id="kVersion">-</dd>
|
||
<dt>坐标</dt><dd id="kPos">-</dd>
|
||
<dt>所在区块</dt><dd id="kChunk">-</dd>
|
||
<dt>生命 / 饥饿</dt><dd id="kHealth">-</dd>
|
||
<dt>状态</dt><dd id="kBotState">-</dd>
|
||
<dt>登录验证</dt><dd id="kLogin">-</dd>
|
||
<dt>重连次数</dt><dd id="kReconnect">0</dd>
|
||
</dl>
|
||
<div class="row">
|
||
<label class="chk"><input type="checkbox" id="chkEnabled"> 启用该机器人</label>
|
||
<label class="chk"><input type="checkbox" id="chkAutoStart"> 启动后自动扩地</label>
|
||
<button id="btnSaveBotSetting" class="btn btn-sm">保存</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>任务</h2>
|
||
<dl class="kv">
|
||
<dt>状态机</dt><dd id="kTaskState">IDLE</dd>
|
||
<dt>描述</dt><dd id="kTaskStatus">未启动</dd>
|
||
<dt>开拓邦国</dt><dd id="kTaskStateName">-</dd>
|
||
<dt>当前目标</dt><dd id="kTarget">-</dd>
|
||
<dt>队列</dt><dd id="kQueue">0</dd>
|
||
<dt>已完成</dt><dd id="kCompleted">0</dd>
|
||
<dt>重试</dt><dd id="kRetry">0</dd>
|
||
<dt>开垦进度</dt><dd id="kProgress">0%</dd>
|
||
<dt>连续寻路超时</dt><dd id="kTimeout">0s</dd>
|
||
<dt>开垦时段</dt><dd id="kClaimTime">-</dd>
|
||
</dl>
|
||
<div class="progress"><div id="progressBar" class="progress-fill"></div></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-head">
|
||
<h2>定时消息</h2>
|
||
<button id="btnAddSchedule" class="btn btn-sm">+ 新增</button>
|
||
</div>
|
||
<div id="scheduleList" class="schedule-list"></div>
|
||
<div id="scheduleEditor" class="schedule-editor hidden">
|
||
<div class="field">
|
||
<label>内容(以 / 开头按游戏指令发送)</label>
|
||
<input id="schedContent" class="input" type="text" placeholder="/u restore confirm">
|
||
</div>
|
||
<div class="field-row">
|
||
<div class="field">
|
||
<label>间隔(秒)</label>
|
||
<input id="schedInterval" class="input" type="number" min="5" value="300">
|
||
</div>
|
||
<div class="field">
|
||
<label>备注</label>
|
||
<input id="schedLabel" class="input" type="text" placeholder="恢复民心">
|
||
</div>
|
||
</div>
|
||
<div class="row row-compact">
|
||
<button id="btnSaveSchedule" class="btn btn-sm btn-primary">保存</button>
|
||
<button id="btnCancelSchedule" class="btn btn-sm">取消</button>
|
||
</div>
|
||
<p class="hint">只会在机器人已连接且通过登录验证时发送;未就绪的周期会跳过,不会补发。</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>领土数据源</h2>
|
||
<dl class="kv">
|
||
<dt>markers.json</dt><dd id="kMarkersUrl" class="mono small">-</dd>
|
||
<dt>最近成功</dt><dd id="kLastFetch">-</dd>
|
||
<dt>错误</dt><dd id="kDataError">-</dd>
|
||
<dt>邦国数</dt><dd id="kStateCount">0</dd>
|
||
<dt>已占领区块</dt><dd id="kClaimed">0</dd>
|
||
<dt>会话占领</dt><dd id="kSession">0</dd>
|
||
<dt>己方飞地</dt><dd id="kFlying">0</dd>
|
||
<dt>SimpCore API</dt><dd id="kApi">未启用</dd>
|
||
</dl>
|
||
<div class="row row-compact">
|
||
<button id="btnRefreshMap" class="btn btn-sm">刷新地图</button>
|
||
<button id="btnFetchAll" class="btn btn-sm">拉取全服领土</button>
|
||
<button id="btnOpenSimp" class="btn btn-sm btn-primary">查看 API 数据</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Grim 合规</h2>
|
||
<dl class="kv">
|
||
<dt>合规层</dt><dd id="kGrimEnabled">-</dd>
|
||
<dt>旋转限速</dt><dd id="kGrimRot">-</dd>
|
||
<dt>朝向已同步</dt><dd id="kGrimSettled">-</dd>
|
||
<dt>攻击距离</dt><dd id="kGrimReach">-</dd>
|
||
<dt>攻击冷却</dt><dd id="kGrimCooldown">-</dd>
|
||
<dt>协议补包</dt><dd id="kGrimPackets">-</dd>
|
||
<dt>已拦下动作</dt><dd id="kGrimBlocked">0</dd>
|
||
<dt>物理自检</dt><dd id="kGrimAudit">-</dd>
|
||
</dl>
|
||
<ul id="grimIssues" class="issues"></ul>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ==================== 中栏:地图与日志 ==================== -->
|
||
<section class="column col-center" id="panelMap">
|
||
<div class="card card-map">
|
||
<div class="card-head card-head-wrap">
|
||
<div class="tabs tabs-inline" id="mapTabs">
|
||
<button class="tab active" data-view="big">大地图</button>
|
||
<button class="tab" data-view="territory">领土地图</button>
|
||
</div>
|
||
<div class="row row-compact" id="bigMapControls">
|
||
<label class="field-inline">
|
||
<span class="field-label">图幅</span>
|
||
<select id="bigMapRange" class="input input-sm">
|
||
<option value="512">±512 格</option>
|
||
<option value="1024">±1024 格</option>
|
||
<option value="2048">±2048 格</option>
|
||
<option value="4096" selected>±4096 格</option>
|
||
<option value="8192">±8192 格</option>
|
||
<option value="20480">全世界</option>
|
||
</select>
|
||
</label>
|
||
<label class="chk"><input type="checkbox" id="chkTerritory" checked> 领土标记</label>
|
||
<label class="chk"><input type="checkbox" id="chkBotLabels" checked> 名字</label>
|
||
<button id="btnCrawlAround" class="btn btn-sm btn-primary">爬取周边</button>
|
||
<button id="btnMapCenterBots" class="btn btn-sm">回到机器人</button>
|
||
</div>
|
||
<div class="row row-compact hidden" id="territoryMapControls">
|
||
<label class="chk"><input type="checkbox" id="chkFull" checked> 全部邦国</label>
|
||
<label class="chk"><input type="checkbox" id="chkFlying" checked> 飞地</label>
|
||
<label class="chk"><input type="checkbox" id="chkGrid" checked> 网格</label>
|
||
<button id="btnMapCenter" class="btn btn-sm">回到机器人</button>
|
||
<button id="btnMapFit" class="btn btn-sm">看己方全境</button>
|
||
</div>
|
||
</div>
|
||
<canvas id="mapCanvas"></canvas>
|
||
<div class="map-legend">
|
||
<span id="legendBig">
|
||
<i class="sw sw-self"></i>己方领土
|
||
<i class="sw sw-session"></i>本次占领
|
||
<i class="sw sw-capital"></i>王城
|
||
<i class="sw sw-bot"></i>机器人
|
||
</span>
|
||
<span id="legendTerritory" class="hidden">
|
||
<i class="sw sw-self"></i>己方领土
|
||
<i class="sw sw-session"></i>本次占领
|
||
<i class="sw sw-flying"></i>飞地(疏漏)
|
||
<i class="sw sw-target"></i>当前目标
|
||
<i class="sw sw-player"></i>机器人
|
||
<i class="sw sw-capital"></i>王城
|
||
</span>
|
||
<span id="mapInfo" class="mono small"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card card-log" id="panelLogs">
|
||
<div class="card-head card-head-wrap">
|
||
<div class="tabs tabs-inline" id="logTabs">
|
||
<button class="tab active" data-pane="log">运行日志</button>
|
||
<button class="tab" data-pane="chat">公屏聊天</button>
|
||
<button class="tab" data-pane="exp">开拓日志</button>
|
||
</div>
|
||
<div class="row row-compact" id="logControls">
|
||
<label class="chk"><input type="checkbox" id="chkAutoScroll" checked> 自动滚动</label>
|
||
<button id="btnClearLog" class="btn btn-sm">清屏</button>
|
||
<button id="btnExportLog" class="btn btn-sm">导出</button>
|
||
</div>
|
||
<div class="row row-compact hidden" id="chatControls">
|
||
<label class="chk"><input type="checkbox" id="chkChatAutoScroll" checked> 自动滚动</label>
|
||
<label class="chk"><input type="checkbox" id="chkChatAllBots"> 全部机器人</label>
|
||
<button id="btnClearChat" class="btn btn-sm">清屏</button>
|
||
<button id="btnExportChat" class="btn btn-sm">导出</button>
|
||
</div>
|
||
<div class="row row-compact hidden" id="expControls">
|
||
<label class="field-inline">
|
||
<span class="field-label">机器人</span>
|
||
<select id="expFilterBot" class="input input-sm"><option value="">全部</option></select>
|
||
</label>
|
||
<label class="chk"><input type="checkbox" id="chkExpAutoScroll" checked> 自动滚动</label>
|
||
<button id="btnExportExp" class="btn btn-sm">导出 CSV</button>
|
||
<button id="btnClearExp" class="btn btn-sm">清屏</button>
|
||
</div>
|
||
</div>
|
||
<div id="logView" class="log-view"></div>
|
||
<div id="chatView" class="log-view hidden"></div>
|
||
<div id="expView" class="log-view log-table hidden">
|
||
<table class="exp-table">
|
||
<thead>
|
||
<tr><th>时间</th><th>机器人</th><th>邦国</th><th>区块</th><th>方块坐标</th><th>来源</th></tr>
|
||
</thead>
|
||
<tbody id="expBody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ==================== 右栏:配置与控制 ==================== -->
|
||
<section class="column col-right" id="panelConfig">
|
||
<div class="card">
|
||
<div class="card-head">
|
||
<h2>控制台</h2>
|
||
<span class="mono small" id="consoleTarget">-</span>
|
||
</div>
|
||
<p class="hint" id="consoleHint">以 / 开头按游戏指令发送,否则按公屏消息发送。登录验证通过后才允许发送。</p>
|
||
<div class="row row-compact">
|
||
<input id="cmdInput" class="input input-grow" type="text" placeholder="输入内容或 /指令,回车发送">
|
||
<button id="btnSendCmd" class="btn btn-sm btn-primary">发送</button>
|
||
</div>
|
||
<div class="row row-compact">
|
||
<span class="field-label">快捷发送</span>
|
||
<button class="btn btn-sm" data-cmd="/u return">/u return</button>
|
||
<button class="btn btn-sm" data-cmd="/u claimmode">/u claimmode</button>
|
||
<button class="btn btn-sm" data-cmd="/u restore confirm">/u restore confirm</button>
|
||
</div>
|
||
<div class="row row-compact">
|
||
<span class="field-label">移动测试</span>
|
||
<button class="btn btn-sm" data-move="forward">前</button>
|
||
<button class="btn btn-sm" data-move="back">后</button>
|
||
<button class="btn btn-sm" data-move="left">左</button>
|
||
<button class="btn btn-sm" data-move="right">右</button>
|
||
<button class="btn btn-sm" data-move="jump">跳</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card card-config">
|
||
<div class="card-head">
|
||
<h2>配置</h2>
|
||
<div class="row row-compact">
|
||
<button id="btnSaveConfig" class="btn btn-sm btn-primary">保存</button>
|
||
<button id="btnReloadConfig" class="btn btn-sm">重新载入</button>
|
||
</div>
|
||
</div>
|
||
<label class="chk config-scope">
|
||
<input type="checkbox" id="chkBotOverride">
|
||
仅对当前机器人生效(不勾选则写入全局默认配置)
|
||
</label>
|
||
<div class="tabs" id="configTabs">
|
||
<button class="tab active" data-tab="strategy">策略</button>
|
||
<button class="tab" data-tab="timing">超时</button>
|
||
<button class="tab" data-tab="pathing">寻路</button>
|
||
<button class="tab" data-tab="survival">生存</button>
|
||
<button class="tab" data-tab="data">数据</button>
|
||
<button class="tab" data-tab="bigmap">大地图</button>
|
||
<button class="tab" data-tab="grim">Grim</button>
|
||
<button class="tab" data-tab="server">服务器</button>
|
||
</div>
|
||
<div id="configBody" class="config-body"></div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<!-- SimpCore 开放 API 数据浏览:数据量大且限流严格,做成按需打开的弹层而不是常驻面板 -->
|
||
<div id="simpOverlay" class="overlay hidden">
|
||
<div class="overlay-box overlay-box-lg">
|
||
<div class="card-head">
|
||
<h2>SimpCore 开放 API</h2>
|
||
<div class="row row-compact">
|
||
<span id="simpStatus" class="mono small"></span>
|
||
<button id="btnCloseSimp" class="btn btn-sm">关闭</button>
|
||
</div>
|
||
</div>
|
||
<div class="tabs" id="simpTabs">
|
||
<button class="tab active" data-simp="overview">概览</button>
|
||
<button class="tab" data-simp="unions">邦国</button>
|
||
<button class="tab" data-simp="players">玩家</button>
|
||
<button class="tab" data-simp="global">全服</button>
|
||
<button class="tab" data-simp="v2">实时 V2</button>
|
||
</div>
|
||
<div id="simpBody" class="simp-body"></div>
|
||
<div id="simpV2Result" class="simp-detail hidden"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 登录遮罩:控制台配置了 WEB_TOKEN / WEB_PASSWORD 时显示 -->
|
||
<div id="loginOverlay" class="overlay hidden">
|
||
<div class="overlay-box">
|
||
<h2>控制台登录</h2>
|
||
<p class="hint">验证通过后才允许操作各机器人的控制台、聊天框与扩地任务。</p>
|
||
<input id="loginPassword" class="input" type="password" placeholder="控制台密码 / 令牌" autocomplete="current-password">
|
||
<div class="row">
|
||
<button id="btnLogin" class="btn btn-primary btn-grow">登录</button>
|
||
<button id="btnLogout" class="btn">退出登录</button>
|
||
</div>
|
||
<p id="loginError" class="hint error-text"></p>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="toast" class="toast"></div>
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|