同步移动端工程、设备控制改进与发布资料

This commit is contained in:
2026-09-26 19:21:12 +08:00
parent 912ba432cf
commit 98eadc5c8b
137 changed files with 9274 additions and 85 deletions
@@ -41,6 +41,7 @@
<p id="last-message" class="last-message" aria-live="polite">控制台已就绪</p>
</div>
<div class="topbar-statuses" aria-label="设备实时状态">
<span id="topbar-mobile" class="resource-indicator" role="status" aria-live="polite">手机未连接</span>
<button id="topbar-current-content" class="current-content-indicator" type="button" aria-haspopup="dialog" aria-controls="current-display-dialog" aria-live="polite" aria-atomic="true">
当前画面:正在读取…
</button>
@@ -3618,6 +3618,18 @@
"source": "index.html::#workspace-templates > div:nth-of-type(1) > div:nth-of-type(1) > p:nth-of-type(1)::text[0]",
"text": "内容"
},
"copy.9977eafad4a6d6e9": {
"kind": "html_text",
"placeholders": [],
"render": {
"selector": "#topbar-mobile",
"text_index": 0,
"type": "static_text"
},
"scope": "global",
"source": "index.html::#topbar-mobile::text[0]",
"text": "手机未连接"
},
"copy.9a395662799ecd7a": {
"kind": "html_text",
"placeholders": [],
@@ -16,6 +16,7 @@ import {
} from "../current-display-playback.js";
const statusEls = {
mobile: document.getElementById("topbar-mobile"),
orientation: document.getElementById("status-orientation"),
brightness: document.getElementById("status-brightness"),
currentContent: document.getElementById("topbar-current-content"),
@@ -760,9 +761,22 @@ export async function refreshDeviceStorage() {
}
}
let lastMobileSession = null;
export async function refreshStatus({ source = "manual" } = {}) {
try {
const data = await apiJson("/api/status");
const mobile = data.mobile;
if (statusEls.mobile) {
statusEls.mobile.textContent = mobile?.connected
? `手机:${mobile.client_name || "已连接"}`
: (mobile?.available === false ? "手机蓝牙暂不可用" : "手机未连接");
const session = `${data.service?.instance_id || ""}:${mobile?.generation || 0}`;
if (mobile?.connected && lastMobileSession !== null && session !== lastMobileSession) {
announce(`${mobile.client_name || "手机"}已连接`);
}
lastMobileSession = session;
}
syncCurrentDisplayDialogStatus(data);
statusEls.orientation.textContent = `${data.state.orientation}°`;
showDeviceBrightness(data.state);
@@ -263,6 +263,20 @@ function applyOtaStatus(status) {
otaProgressGroup.hidden = true;
setOtaFeedback("");
}
if (job?.phase !== "failed") {
const recovery = status?.kernel_recovery;
if (recovery?.state === "pending") {
setOtaFeedback("应用更新完成;正在进行一次候选内核恢复重启…", "pending");
} else if (recovery?.state === "succeeded") {
setOtaFeedback("候选内核与 CPU 调频策略已恢复。", "ready");
} else if (recovery?.state === "failed") {
setOtaFeedback(`内核恢复失败:${recovery.reason || "请查看设备诊断"}`, "error");
} else if (recovery?.state === "requires_package") {
setOtaFeedback("应用已更新;内核材料缺失或损坏,需要专用修复包。", "error");
} else if (recovery?.state === "ready") {
setOtaFeedback("当前设备运行原内核,性能模式不可用;下次 OTA 将尝试轻量恢复。", "error");
}
}
}
}
@@ -281,7 +295,7 @@ async function pollOtaUntilFinished() {
const status = await fetchOtaStatus();
if (disconnected) setOtaFeedback("设备服务已恢复,正在确认更新结果…", "pending");
applyOtaStatus(status);
if (!status.active) return;
if (!status.active && status.kernel_recovery?.state !== "pending") return;
} catch {
disconnected = true;
setOtaFeedback("设备正在切换软件版本,等待服务恢复…", "pending");
@@ -297,7 +311,7 @@ async function loadOtaStatus() {
try {
const status = await fetchOtaStatus();
applyOtaStatus(status);
if (status.active) pollOtaUntilFinished();
if (status.active || status.kernel_recovery?.state === "pending") pollOtaUntilFinished();
} catch (error) {
otaCurrentVersion.textContent = "读取失败";
otaFeatureUpdatedAt.textContent = "读取失败";