在 version.h 中将固件版本由 0.3.71 递增至 0.3.72。 移除 BUILD_TIME 的手动填写项,现由构建系统自动生成。 更新电机 OTA relay 逻辑,缩短状态检查的宽限期。 增强电机 OTA 上传与 relay 流程中的错误处理和日志记录。 为固件上传引入 SHA-256 校验,确保固件完整性。 调整前端命令值提交逻辑,改善用户体验。 更新 HTML 与 JavaScript 文件,以反映 OTA 流程及 UI 的变更。 新增 build_info 文件,用于管理构建时间的自动生成。
348 lines
21 KiB
HTML
348 lines
21 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>电机控制台 — Motor CAN FD Console</title>
|
||
<link rel="stylesheet" href="css/motor.css?v=20260727b">
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ═══════════ TOOLBAR ═══════════ -->
|
||
<header class="toolbar">
|
||
<div class="toolbar-brand">
|
||
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" aria-hidden="true">
|
||
<rect x="1" y="1" width="24" height="24" rx="6" stroke="var(--primary)" stroke-width="1.5" opacity=".6"/>
|
||
<circle cx="13" cy="13" r="5.5" stroke="var(--primary)" stroke-width="1.8"/>
|
||
<path d="M13 4v3.5M13 18.5V22M4 13h3.5M18.5 13H22" stroke="var(--primary)" stroke-width="1.5" stroke-linecap="round"/>
|
||
<circle cx="13" cy="13" r="1.8" fill="var(--primary)"/>
|
||
</svg>
|
||
<span>电机控制台</span>
|
||
<span class="sub">Motor CAN FD</span>
|
||
</div>
|
||
<div class="toolbar-sep"></div>
|
||
<div class="conn-group" title="与 OTA 主页共用设备 IP,本页不提供连接配置">
|
||
<span class="led" id="connLed"></span>
|
||
<span class="conn-ip-label" id="ipLabel">IP --</span>
|
||
<span style="font-size:.72rem;color:var(--fg-dim);font-family:var(--font-mono)" id="devStatus">探测中…</span>
|
||
</div>
|
||
<div class="toolbar-sep"></div>
|
||
<div class="conn-group">
|
||
<label for="chSelect" style="font-size:.72rem;color:var(--fg-muted);font-family:var(--font-mono);letter-spacing:.06em">通道</label>
|
||
<select class="ch-select" id="chSelect">
|
||
<option value="0">CH0</option>
|
||
<option value="1">CH1</option>
|
||
<option value="2">CH2</option>
|
||
</select>
|
||
</div>
|
||
<div class="toolbar-sep"></div>
|
||
<div class="conn-group" title="电机状态轮询间隔(ms)。GD32 0xC5 推送周期 250ms:设 ≤250 按 250ms 锁相;设更大则按 N×250ms 抽稀(例如 1000≈每 4 次推送拉一次)">
|
||
<label for="refreshRate" class="refresh-hint">刷新速度</label>
|
||
<input type="number" id="refreshRate" class="refresh-input" value="250" min="250" max="5000" step="50" aria-label="电机状态刷新间隔(毫秒)" />
|
||
<span class="refresh-hint">ms</span>
|
||
</div>
|
||
<div class="toolbar-right">
|
||
<a class="btn btn-sm" href="index.html" title="返回 OTA 主页配置连接">返回 OTA 控制台</a>
|
||
<span class="node-badge" id="nodeBadge">NODE -</span>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="net-banner" id="netBanner">
|
||
<span class="led led-err led-pulse" style="width:7px;height:7px"></span>
|
||
<span id="netBannerText">未连接 — 使用主页共享 IP 自动探测中… 请先在 OTA 主页配置并测试连接</span>
|
||
</div>
|
||
|
||
<!-- ═══════════ MAIN 3-ZONE GRID ═══════════ -->
|
||
<main class="main-grid">
|
||
|
||
<!-- LEFT: NODE OVERVIEW -->
|
||
<aside class="panel nodes-panel">
|
||
<div class="panel-head">
|
||
<span class="panel-title">节点总览</span>
|
||
<span style="margin-left:auto;font-size:.68rem;color:var(--fg-dim);font-family:var(--font-mono)" id="nodeSummary">0/9 在线 · CAN FD</span>
|
||
</div>
|
||
<div class="panel-body">
|
||
<!-- 独立 BOOT 状态:总线检测到 0x103 心跳时显示,不归属任何 Nx
|
||
显示/隐藏只靠 .boot-badge / .boot-badge.show,禁止内联 display -->
|
||
<div id="bootBadge" class="boot-badge" aria-hidden="true">
|
||
<span class="boot-dot" aria-hidden="true"></span>
|
||
<span class="boot-txt">电机在 BOOT</span>
|
||
<span class="boot-sub" id="bootBadgeSub">0x103</span>
|
||
</div>
|
||
<div class="node-list" id="nodeList" role="listbox" aria-label="电机节点列表 N1-N9(离线可选)">
|
||
<!-- N1–N9 由 JS 固定渲染,离线也可选中刷写 -->
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- CENTER: CONTROL -->
|
||
<section class="panel center-panel">
|
||
<div class="panel-head">
|
||
<span class="panel-title">CMD 控制</span>
|
||
<span style="font-size:.68rem;color:var(--fg-dim);font-family:var(--font-mono);margin-left:auto" id="cmdIdLabel">ID 0x000-0200 · DLC 32</span>
|
||
</div>
|
||
<div class="cmd-section">
|
||
<div class="cmd-grid">
|
||
<div class="field">
|
||
<span class="field-label">Control_Mode <span class="field-unit">控制模式</span></span>
|
||
<select id="modeSelect" aria-label="控制模式">
|
||
<option value="0">0 — Disable 关闭</option>
|
||
<option value="1">1 — Angle 位置控制</option>
|
||
<option value="2">2 — Velocity 速度控制</option>
|
||
<option value="3" selected>3 — Velocity_Angle 速度+位置</option>
|
||
<option value="4">4 — MIT Mode</option>
|
||
<option value="5">5 — Current 电流/力矩</option>
|
||
<option value="6">6 — 开环速度</option>
|
||
<option value="7">7 — 开环速度 (2)</option>
|
||
</select>
|
||
<span class="mode-desc" id="modeDesc">速度+位置环联合控制,目标速度与目标角度同时生效</span>
|
||
</div>
|
||
<div class="field">
|
||
<span class="field-label">Limit_Voltage <span class="field-unit">V · 0~65.535</span></span>
|
||
<input type="number" id="inVoltage" value="24.000" step="0.5" min="0" max="65.535" aria-label="电压限制" />
|
||
</div>
|
||
<div class="field" id="fldCurrent">
|
||
<span class="field-label">Target_Current <span class="field-unit">mA</span></span>
|
||
<input type="number" id="inCurrent" value="0" step="100" aria-label="目标电流" />
|
||
</div>
|
||
<div class="field" id="fldVelocity">
|
||
<span class="field-label">Target_Velocity <span class="field-unit">deg/s</span></span>
|
||
<input type="number" id="inVelocity" value="360" step="10" aria-label="目标速度" />
|
||
</div>
|
||
<div class="field" id="fldAngle">
|
||
<span class="field-label">Target_Angle <span class="field-unit">deg</span></span>
|
||
<input type="number" id="inAngle" value="180.0" step="1" aria-label="目标角度" />
|
||
</div>
|
||
</div>
|
||
<div class="field" style="margin-top:var(--sp-4)">
|
||
<span class="field-label">PID 增益 <span class="field-unit">P × 3 环</span></span>
|
||
<div class="pid-group">
|
||
<div class="field"><span class="field-label" style="font-size:.62rem">电流环 P</span><input type="number" id="pidCurP" value="100" step="1" /></div>
|
||
<div class="field"><span class="field-label" style="font-size:.62rem">速度环 P</span><input type="number" id="pidVelP" value="100" step="1" /></div>
|
||
<div class="field"><span class="field-label" style="font-size:.62rem">角度环 P</span><input type="number" id="pidAngP" value="100" step="1" /></div>
|
||
</div>
|
||
</div>
|
||
<div class="cmd-actions">
|
||
<button class="btn btn-primary" id="sendCmdBtn">
|
||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true"><path d="M1.5 7h9M8 3.5L11.5 7 8 10.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
发送 CMD
|
||
</button>
|
||
<button class="btn" id="sendRepeatBtn">周期发送</button>
|
||
<label class="repeat-period" title="周期发送间隔(最小 80ms)">
|
||
<input type="number" id="repeatPeriod" value="100" min="80" max="10000" step="10" />
|
||
<span>ms</span>
|
||
</label>
|
||
<span class="send-hint" id="sendHint">POST /can/send_batch · CH0</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TABS -->
|
||
<nav class="tabs-bar" aria-label="辅助功能">
|
||
<button class="tab-btn active" data-tab="config">配置操作</button>
|
||
<button class="tab-btn" data-tab="version">版本信息</button>
|
||
<button class="tab-btn" data-tab="nodeid">节点 ID</button>
|
||
<button class="tab-btn" data-tab="ota">电机 OTA</button>
|
||
</nav>
|
||
<div class="tab-content">
|
||
<!-- CONFIG TAB -->
|
||
<div class="tab-page active" id="tab-config">
|
||
<div class="config-grid">
|
||
<button class="config-btn danger-action" data-action="motReset">
|
||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true"><path d="M4 11a7 7 0 1 1 2 4.9M4 16v-5h5" stroke="var(--danger)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
<span class="cb-name">电机复位</span><span class="cb-sig">motReset · bit0</span>
|
||
</button>
|
||
<button class="config-btn" data-action="saveConfig">
|
||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true"><path d="M5 3h9l4 4v12H5V3z" stroke="var(--primary)" stroke-width="1.6" stroke-linejoin="round"/><path d="M8 3v5h6V3M8 18v-5h7v5" stroke="var(--primary)" stroke-width="1.4"/></svg>
|
||
<span class="cb-name">保存配置</span><span class="cb-sig">saveConfig · bit2</span>
|
||
</button>
|
||
<button class="config-btn" data-action="angleReset">
|
||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true"><circle cx="11" cy="11" r="7.5" stroke="var(--primary)" stroke-width="1.6"/><path d="M11 6v5l3.5 2" stroke="var(--primary)" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||
<span class="cb-name">角度置零</span><span class="cb-sig">angle_reset · bit3</span>
|
||
</button>
|
||
<button class="config-btn" data-action="sleep">
|
||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true"><path d="M17 13.5A7 7 0 0 1 8.5 5a7 7 0 1 0 8.5 8.5z" stroke="var(--warn)" stroke-width="1.6" stroke-linejoin="round"/></svg>
|
||
<span class="cb-name">休眠</span><span class="cb-sig">SLEEP · bit56</span>
|
||
</button>
|
||
</div>
|
||
<p style="margin-top:var(--sp-4);font-size:.72rem;color:var(--fg-dim);line-height:1.6">
|
||
CMD_CONFIG (0x000<span class="cfgNodeNibble">-</span>0301) · DLC 24 · 每个操作发送单帧脉冲信号,操作前需确认
|
||
</p>
|
||
</div>
|
||
<!-- VERSION TAB -->
|
||
<div class="tab-page" id="tab-version">
|
||
<button class="btn btn-sm" id="queryVerBtn">
|
||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" aria-hidden="true"><circle cx="6.5" cy="6.5" r="5" stroke="currentColor" stroke-width="1.3"/><path d="M6.5 4.2v.1M6.5 6v3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||
查询版本 (GET_VERSION)
|
||
</button>
|
||
<div class="version-grid" style="margin-top:var(--sp-4)" id="versionGrid">
|
||
<div class="ver-card"><div class="ver-type">软件版本</div><div class="ver-date ver-empty" id="verSoft">--</div></div>
|
||
<div class="ver-card"><div class="ver-type">硬件版本</div><div class="ver-date ver-empty" id="verHard">--</div></div>
|
||
<div class="ver-card"><div class="ver-type">Bootloader</div><div class="ver-date ver-empty" id="verBoot">--</div></div>
|
||
</div>
|
||
<p style="margin-top:var(--sp-3);font-size:.72rem;color:var(--fg-dim)">请求/回报共用 0x000<span class="cfgNodeNibble">-</span>00FF(同 ID)· DLC 24 · major.minor.patch.build ×3 (soft/hard/boot,DBC v0.71) · GD32 解析后 0xC6 同步</p>
|
||
</div>
|
||
<!-- NODE ID TAB -->
|
||
<div class="tab-page" id="tab-nodeid">
|
||
<div class="nodeid-row">
|
||
<div class="field" style="min-width:140px">
|
||
<span class="field-label">目标 Node ID</span>
|
||
<input type="number" id="nodeIdInput" min="1" max="9" value="3" />
|
||
</div>
|
||
<button class="btn btn-primary btn-sm" id="setNodeIdBtn">设置 ID (0xN0400)</button>
|
||
<button class="btn btn-sm" id="getNodeIdBtn">读取 ID (0xN0401)</button>
|
||
</div>
|
||
<div class="nodeid-result" id="nodeIdResult">连接设备后读取节点 ID</div>
|
||
<p style="margin-top:var(--sp-3);font-size:.72rem;color:var(--fg-dim);line-height:1.6">
|
||
SET_NODE_ID (0x000N0400 DLC2) / GET_NODE_ID (0x000N0401 DLC2)。写入后 CAN ID 前缀变为 0x000Nxxxx。
|
||
</p>
|
||
</div>
|
||
<!-- OTA TAB -->
|
||
<div class="tab-page" id="tab-ota">
|
||
<div class="ota-stages" id="otaStages" aria-label="OTA阶段">
|
||
<div class="ota-stage" data-stage="upload"><span class="st-dot">1</span>上传固件</div>
|
||
<div class="ota-stage" data-stage="boot"><span class="st-dot">2</span>进入BOOT</div>
|
||
<div class="ota-stage" data-stage="handshake"><span class="st-dot">3</span>转发握手</div>
|
||
<div class="ota-stage" data-stage="erase"><span class="st-dot">4</span>擦除Flash</div>
|
||
<div class="ota-stage" data-stage="transfer"><span class="st-dot">5</span>数据传输</div>
|
||
<div class="ota-stage" data-stage="app"><span class="st-dot">6</span>完成</div>
|
||
</div>
|
||
<div class="ota-file-row">
|
||
<button class="btn btn-sm" id="otaFileBtn">选择固件 (.bin)</button>
|
||
<input type="file" id="otaFileInput" accept=".bin" hidden />
|
||
<span class="ota-file-name" id="otaFileName">未选择固件</span>
|
||
<button class="btn btn-primary btn-sm" id="otaStartBtn">开始 OTA</button>
|
||
<button class="btn btn-danger btn-sm" id="otaCancelBtn" disabled>取消</button>
|
||
</div>
|
||
<div class="ota-progress-wrap">
|
||
<div class="ota-progress-bar"><div class="ota-progress-fill" id="otaProgressFill"></div></div>
|
||
<div class="ota-stats">
|
||
<span>包 <span class="hl" id="otaPktNum">0</span> / <span id="otaPktTotal">0</span></span>
|
||
<span>速率 <span class="hl" id="otaSpeed">—</span></span>
|
||
<span>状态 <span id="otaCrc">—</span></span>
|
||
</div>
|
||
</div>
|
||
<div class="ota-log-toolbar">
|
||
<button id="otaLogCopyBtn" title="复制全部日志">复制</button>
|
||
<button id="otaLogClearBtn" title="清空日志">清空</button>
|
||
</div>
|
||
<div class="ota-log" id="otaLog" aria-live="polite">
|
||
<div class="log-info">[就绪] 电机 Bootloader OTA · 先上传固件到 ESP32 → 发 0x000N0000 进 BOOT → 触发转发 → GD32 本地 relay(AES-128 + CAN stop-and-wait)</div>
|
||
<div>[信息] 选固件 → 上传并比对 flash SHA-256(失败重传≤2次)→ 发进BOOT命令 → 触发 /motor/ota/relay → GD32 完成握手/加密/传输 · 每包 48 B · 48 KB 上限</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- RIGHT: STATUS FEEDBACK -->
|
||
<section class="panel status-panel">
|
||
<div class="panel-head">
|
||
<span class="panel-title">STATUS 实时反馈</span>
|
||
<span style="font-size:.68rem;color:var(--fg-dim);font-family:var(--font-mono);margin-left:auto" id="statusIdLabel">0x000-0100 · 1 Hz</span>
|
||
</div>
|
||
<div class="panel-body">
|
||
<div class="offline-overlay show" id="offlineOverlay">
|
||
<svg class="off-icon" width="40" height="40" viewBox="0 0 40 40" fill="none" aria-hidden="true"><circle cx="20" cy="20" r="16" stroke="var(--fg-dim)" stroke-width="1.5" stroke-dasharray="4 4"/><path d="M14 26l12-12M26 26L14 14" stroke="var(--fg-dim)" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||
<span style="font-size:.85rem" id="offlineTitle">节点离线 — 未收到 STATUS 帧</span>
|
||
<span style="font-size:.72rem" id="offlineSub">检查电机供电与 CAN 总线连接</span>
|
||
</div>
|
||
<div class="status-live hide" id="statusLive">
|
||
<div class="big-readings">
|
||
<div class="big-reading" data-signal="angle" title="点击展开/收起角度波形">
|
||
<div class="br-val" id="rtAngle">--</div>
|
||
<div class="br-unit">deg</div>
|
||
<div class="br-lbl">RT_Angle <span class="br-toggle">▾ 波形</span></div>
|
||
<div class="br-scope"><canvas id="miniAngle" aria-label="角度波形" role="img"></canvas></div>
|
||
</div>
|
||
<div class="big-reading" data-signal="velocity" title="点击展开/收起速度波形">
|
||
<div class="br-val" id="rtVelocity">--</div>
|
||
<div class="br-unit">deg/s</div>
|
||
<div class="br-lbl">RT_Velocity <span class="br-toggle">▾ 波形</span></div>
|
||
<div class="br-scope"><canvas id="miniVelocity" aria-label="速度波形" role="img"></canvas></div>
|
||
</div>
|
||
<div class="big-reading" data-signal="current" title="点击展开/收起电流波形">
|
||
<div class="br-val" id="rtCurrent">--</div>
|
||
<div class="br-unit">mA</div>
|
||
<div class="br-lbl">RT_Current <span class="br-toggle">▾ 波形</span></div>
|
||
<div class="br-scope"><canvas id="miniCurrent" aria-label="电流波形" role="img"></canvas></div>
|
||
</div>
|
||
</div>
|
||
<div class="status-row">
|
||
<div class="temp-block" data-signal="mcuTemp" title="点击展开/收起 MCU 温度曲线">
|
||
<div class="temp-head"><span class="temp-name">MCU_Temp<span class="temp-toggle">▾ 曲线</span></span><span class="temp-val" id="mcuTemp">-- °C</span></div>
|
||
<div class="temp-bar"><div class="temp-fill" id="mcuTempBar" style="width:0%"></div></div>
|
||
<div class="br-scope"><canvas id="miniMcuTemp" aria-label="MCU温度曲线" role="img"></canvas></div>
|
||
</div>
|
||
<div class="temp-block" data-signal="motTemp" title="点击展开/收起电机温度曲线">
|
||
<div class="temp-head"><span class="temp-name">Motor_Temp<span class="temp-toggle">▾ 曲线</span></span><span class="temp-val" id="motTemp">-- °C</span></div>
|
||
<div class="temp-bar"><div class="temp-fill" id="motTempBar" style="width:0%"></div></div>
|
||
<div class="br-scope"><canvas id="miniMotTemp" aria-label="电机温度曲线" role="img"></canvas></div>
|
||
</div>
|
||
</div>
|
||
<div class="phase-currents">
|
||
<div class="pc-head">
|
||
<span class="pc-title">三相电流 U / V / W</span>
|
||
<div class="pc-live-vals">
|
||
<span class="pc-chip" style="--ch-color:var(--primary)">U <b id="valU">+0</b> mA</span>
|
||
<span class="pc-chip" style="--ch-color:var(--ok)">V <b id="valV">+0</b> mA</span>
|
||
<span class="pc-chip" style="--ch-color:var(--warn)">W <b id="valW">+0</b> mA</span>
|
||
</div>
|
||
</div>
|
||
<div class="scope-wrap">
|
||
<canvas id="scopeCanvas" aria-label="三相电流实时波形" role="img"></canvas>
|
||
<div class="scope-grid-labels"><span>+5A</span><span>0</span><span>-5A</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="misc-grid">
|
||
<div class="misc-item"><span class="mi-lbl">Power_Voltage</span><span class="mi-val" id="pwrVolt">-- V</span></div>
|
||
<div class="misc-item"><span class="mi-lbl">test_float</span><span class="mi-val" id="testFloat">--</span></div>
|
||
<div class="misc-item"><span class="mi-lbl">test_U16</span><span class="mi-val" id="testU16">--</span></div>
|
||
<div class="cpu-ring-wrap" style="grid-column:2;grid-row:2">
|
||
<div class="cpu-ring">
|
||
<svg width="52" height="52" viewBox="0 0 52 52" role="img" aria-label="CPU占用率">
|
||
<circle class="ring-bg" cx="26" cy="26" r="21"/>
|
||
<circle class="ring-fg" id="cpuRingFg" cx="26" cy="26" r="21" stroke-dasharray="131.9" stroke-dashoffset="131.9"/>
|
||
</svg>
|
||
<span class="cpu-pct" id="cpuPct">--%</span>
|
||
</div>
|
||
<div class="cpu-info"><span class="mi-lbl">CPU_Usage</span><span class="mi-sub" id="cpuSub">-- </span></div>
|
||
</div>
|
||
</div>
|
||
<div class="flag-lights">
|
||
<div class="flag-item" id="flagItemMot"><span class="flag-led" id="flagMot"></span>motStatus 使能<span class="flag-state" id="flagMotState">—</span></div>
|
||
<div class="flag-item" id="flagItemMag"><span class="flag-led" id="flagMag"></span>magStatus 磁编码<span class="flag-state" id="flagMagState">—</span></div>
|
||
<div class="flag-item" id="flagItemThermal"><span class="flag-led" id="flagThermal"></span>thermal 过温<span class="flag-state" id="flagThermalState">—</span></div>
|
||
<div class="flag-item" id="flagItemEeprom"><span class="flag-led" id="flagEeprom"></span>EEPROM 存储<span class="flag-state" id="flagEepromState">—</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<!-- ═══════════ STATUS BAR ═══════════ -->
|
||
<footer class="statusbar">
|
||
<div class="sb-item"><span class="led" id="sbLed" style="width:7px;height:7px"></span> <span id="sbCh">CH0</span> <span class="sb-val" id="sbRx">RX --</span></div>
|
||
<div class="sb-sep"></div>
|
||
<div class="sb-item">TX <span class="sb-val" id="sbTx">--</span></div>
|
||
<div class="sb-sep"></div>
|
||
<div class="sb-item">ERR <span class="sb-val" id="sbErr">--</span> · TEC <span id="sbTec">--</span> / REC <span id="sbRec">--</span></div>
|
||
<div class="sb-sep"></div>
|
||
<div class="sb-item">BUS <span class="sb-val" id="sbBus">--</span></div>
|
||
<span class="sb-last-send" id="sbLastSend">尚未发送</span>
|
||
</footer>
|
||
|
||
<!-- TOAST & MODAL -->
|
||
<div class="toast-container" id="toastContainer" aria-live="polite"></div>
|
||
<div class="modal-mask" id="modalMask" role="dialog" aria-modal="true">
|
||
<div class="modal-box">
|
||
<div class="modal-title" id="modalTitle">确认操作</div>
|
||
<div class="modal-desc" id="modalDesc"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn" id="modalCancel">取消</button>
|
||
<button class="btn btn-primary" id="modalConfirm">确认执行</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script type="module" src="js/motor/main.js?v=20260727l"></script>
|
||
</body>
|
||
</html> |