update
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
let toastTimer = 0;
|
||||
let settingsHydrated = false;
|
||||
let activeView = "live";
|
||||
let bootstrapResetComplete = false;
|
||||
|
||||
function buildShell() {
|
||||
const sidebar = $(".v2-sidebar");
|
||||
@@ -101,18 +102,24 @@
|
||||
<div class="v2-calibration-seat-scene">
|
||||
<div class="v2-calibration-floor-grid"></div>
|
||||
<div id="calibrationSeatViewer" class="seat-model-host calibration-cartoon-viewer">
|
||||
<canvas id="calibrationSeatCanvas" aria-label="自标定卡通风格三维座椅,可拖动旋转并滚轮缩放"></canvas>
|
||||
<canvas id="calibrationSeatCanvas" aria-label="自标定三维座椅,拖动空白处旋转视角,拖动轴标签或座椅部件调节四轴"></canvas>
|
||||
<div id="seatModelLoading" class="model-loading">
|
||||
<span class="model-spinner"></span>
|
||||
<strong>正在构建座椅数字孪生</strong>
|
||||
<small>CALIBRATION · CARTOON TWIN</small>
|
||||
</div>
|
||||
<div class="orbit-hint">拖动旋转 · 滚轮缩放 · 双击复位</div>
|
||||
<div class="orbit-hint">拖动空白处旋转 · 拖动轴标签或座椅部件调轴 · 滚轮缩放 · 双击复位</div>
|
||||
</div>
|
||||
<div class="v2-axis-tag tag-back">靠背 <b id="calibrationTagBack">0.0°</b></div>
|
||||
<div class="v2-axis-tag tag-base">前后 <b id="calibrationTagLong">0.00 cm</b></div>
|
||||
<div class="v2-axis-tag tag-leg">腿托 <b id="calibrationTagLeg">0.0°</b></div>
|
||||
<div class="v2-axis-tag tag-height">高度 <b id="calibrationTagHeight">0.00 cm</b></div>
|
||||
<svg class="v2-calibration-label-lines" id="calibrationSeatLabelLines" aria-hidden="true">
|
||||
<line data-seat-label-line="backrest"></line>
|
||||
<line data-seat-label-line="longitudinal"></line>
|
||||
<line data-seat-label-line="legrest"></line>
|
||||
<line data-seat-label-line="height"></line>
|
||||
</svg>
|
||||
<div class="v2-axis-tag tag-back" data-seat-axis-label="backrest" role="slider" tabindex="0" aria-label="拖动调节靠背" aria-valuemin="0" aria-valuemax="1000" aria-valuenow="0" aria-disabled="true"><i></i><span>靠背 <b id="calibrationTagBack">0.0°</b></span></div>
|
||||
<div class="v2-axis-tag tag-base" data-seat-axis-label="longitudinal" role="slider" tabindex="0" aria-label="拖动调节前后位置" aria-valuemin="0" aria-valuemax="1000" aria-valuenow="0" aria-disabled="true"><i></i><span>前后 <b id="calibrationTagLong">0.00 cm</b></span></div>
|
||||
<div class="v2-axis-tag tag-leg" data-seat-axis-label="legrest" role="slider" tabindex="0" aria-label="拖动调节腿托" aria-valuemin="0" aria-valuemax="1000" aria-valuenow="0" aria-disabled="true"><i></i><span>腿托 <b id="calibrationTagLeg">0.0°</b></span></div>
|
||||
<div class="v2-axis-tag tag-height" data-seat-axis-label="height" role="slider" tabindex="0" aria-label="拖动调节高度" aria-valuemin="0" aria-valuemax="1000" aria-valuenow="0" aria-disabled="true"><i></i><span>高度 <b id="calibrationTagHeight">0.00 cm</b></span></div>
|
||||
</div>
|
||||
<div class="v2-calibration-operation">
|
||||
<i></i><div><small>当前任务</small><strong id="calibrationOperationLabel">等待设备检测</strong></div><span>JOB <b id="calibrationJobId">—</b></span>
|
||||
@@ -234,6 +241,7 @@
|
||||
const data = await response.json().catch(() => ({}));
|
||||
if (!response.ok) throw new Error(data.message || data.error || `HTTP ${response.status}`);
|
||||
render(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
async function run(action, success = "") {
|
||||
@@ -300,6 +308,15 @@
|
||||
renderWorkflow(state.operation.phase);
|
||||
renderAxes(state.axes, controller.job_active, transport.state === "online");
|
||||
renderSeat(state.axes);
|
||||
const seatViewer = $("#calibrationSeatViewer");
|
||||
const axisControlEnabled = transport.state === "online" && !controller.job_active;
|
||||
if (seatViewer) {
|
||||
seatViewer.dataset.axisControlEnabled = String(axisControlEnabled);
|
||||
}
|
||||
$$('[data-seat-axis-label]').forEach((label) => {
|
||||
label.dataset.controlEnabled = String(axisControlEnabled);
|
||||
label.setAttribute("aria-disabled", String(!axisControlEnabled));
|
||||
});
|
||||
renderVideo(state.video);
|
||||
$("#calibrationStartAll").disabled =
|
||||
transport.state !== "online" || controller.job_active;
|
||||
@@ -411,6 +428,47 @@
|
||||
$("#calibrationTagLeg").textContent = `${legrest.physical_value.toFixed(1)}°`;
|
||||
$("#calibrationTagBack").textContent = `${backrest.physical_value.toFixed(1)}°`;
|
||||
$("#calibrationTagHeight").textContent = `${height.physical_value.toFixed(2)} cm`;
|
||||
[
|
||||
["longitudinal", longitudinal],
|
||||
["legrest", legrest],
|
||||
["backrest", backrest],
|
||||
["height", height],
|
||||
].forEach(([name, axis]) => {
|
||||
const label = $(`[data-seat-axis-label="${name}"]`);
|
||||
if (!label) return;
|
||||
label.setAttribute("aria-valuenow", String(Math.round(axis.permille)));
|
||||
label.setAttribute("aria-valuetext", formatPhysical(axis, axis.permille));
|
||||
});
|
||||
}
|
||||
|
||||
function previewSeatAxis(event) {
|
||||
if (!currentState?.axes?.length) return;
|
||||
const viewer = $("#calibrationSeatViewer");
|
||||
if (viewer?.dataset.axisControlEnabled !== "true") return;
|
||||
const axisId = Number(event.detail?.axis);
|
||||
const permille = Math.max(0, Math.min(1000, Number(event.detail?.permille)));
|
||||
if (!Number.isInteger(axisId) || !Number.isFinite(permille)) return;
|
||||
const axes = currentState.axes.map((axis) => ({ ...axis }));
|
||||
const axis = axes.find((item) => item.id === axisId);
|
||||
if (!axis) return;
|
||||
axis.permille = permille;
|
||||
axis.physical_value = axis.physical_range * permille / 1000;
|
||||
const card = $(`.v2-calibration-axis-card[data-axis="${axisId}"]`);
|
||||
if (card) {
|
||||
const slider = $('input[type="range"]', card);
|
||||
slider.value = String(permille);
|
||||
$(".v2-calibration-axis-reading strong", card).textContent = formatPhysical(axis, permille);
|
||||
}
|
||||
renderSeat(axes);
|
||||
}
|
||||
|
||||
function commitSeatAxis(event) {
|
||||
const viewer = $("#calibrationSeatViewer");
|
||||
if (viewer?.dataset.axisControlEnabled !== "true") return;
|
||||
const axis = Number(event.detail?.axis);
|
||||
const permille = Math.max(0, Math.min(1000, Math.round(Number(event.detail?.permille))));
|
||||
if (!Number.isInteger(axis) || !Number.isFinite(permille)) return;
|
||||
run(() => api("/move", { axis, permille }));
|
||||
}
|
||||
|
||||
function renderVideo(video) {
|
||||
@@ -542,7 +600,13 @@
|
||||
closeEvents();
|
||||
return;
|
||||
}
|
||||
fetchState().catch((error) => toast(`自标定服务连接失败:${error.message}`, true));
|
||||
fetchState().then(async (state) => {
|
||||
if (bootstrapResetComplete) return;
|
||||
bootstrapResetComplete = true;
|
||||
if (state.transport?.mode === "simulation") {
|
||||
await api("/session/reset");
|
||||
}
|
||||
}).catch((error) => toast(`自标定服务连接失败:${error.message}`, true));
|
||||
connectEvents();
|
||||
}
|
||||
|
||||
@@ -583,6 +647,8 @@
|
||||
});
|
||||
window.addEventListener("cognitive-agent:module-change", activate);
|
||||
window.addEventListener("cognitive-agent:demo-role-change", activate);
|
||||
window.addEventListener("calibration-seat-axis-preview", previewSeatAxis);
|
||||
window.addEventListener("calibration-seat-axis-commit", commitSeatAxis);
|
||||
window.addEventListener("beforeunload", closeEvents);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user