fix: keep V2X intersection code out of login UI

This commit is contained in:
2026-08-24 14:47:25 +08:00
parent 1c2d091ad2
commit bb2a1449ac
3 changed files with 9 additions and 8 deletions

View File

@@ -24,6 +24,8 @@ Add a non-sensitive `v2xPreview` object to the area configuration:
`apiBaseUrl` and `wsBaseUrl` should normally be relative, same-origin paths.
The deployment server proxies them to the V2X REST and WebSocket services. Do
not commit a private upstream address, an account, a token, or an AMap key.
`crossCode` is deployment configuration for the selected intersection. It is
never shown or editable in the browser login panel.
The browser sends `POST {apiBaseUrl}/facilities/api/sys/login` with `userName`
and an MD5-hashed password, matching the source V2X dashboard. It holds the

View File

@@ -21,7 +21,7 @@
metrics: null,
vehicleSource: "waiting",
};
const ui = buildUi(state, settings);
const ui = buildUi(state);
function setStatus(message) {
state.status = message;
@@ -99,12 +99,11 @@
}
async function loadLiveData() {
const crossCode = ui.crossCode.value.trim();
const crossCode = state.crossCode;
if (!crossCode) {
setStatus("Enter a V2X intersection code.");
setStatus("V2X intersection code is not configured.");
return;
}
state.crossCode = crossCode;
clearEntities();
state.vehicleSource = "waiting";
setStatus("Loading live V2X intersection data...");
@@ -195,12 +194,12 @@
return { state, load: loadLiveData, signOut, dispose: () => { disconnect(); clearEntities(); state.vehicleSource = "waiting"; ui.root.remove(); } };
}
function buildUi(state, settings) {
function buildUi(state) {
const root = document.createElement("aside");
root.id = "v2xPanel";
root.innerHTML = `<div class="v2x-heading"><strong>Live V2X Data</strong><span>Native: WGS84/ENU | V2X: GCJ-02</span></div>
<form id="v2xLoginForm"><label>Username<input name="userName" autocomplete="username" required></label><label>Password<input name="password" type="password" autocomplete="current-password" required></label><button type="submit">Sign in</button></form>
<div id="v2xLiveControls" hidden><label>Intersection code<input name="crossCode" value="${escapeAttribute(settings.crossCode || "")}" required></label><div><button type="button" data-action="reload">Refresh</button><button type="button" data-action="signout">Sign out</button></div></div>
<div id="v2xLiveControls" hidden><div><button type="button" data-action="reload">Refresh</button><button type="button" data-action="signout">Sign out</button></div></div>
<output id="v2xStatus"></output>`;
document.body.appendChild(root);
return {
@@ -209,7 +208,6 @@
live: root.querySelector("#v2xLiveControls"),
userName: root.querySelector("[name=userName]"),
password: root.querySelector("[name=password]"),
crossCode: root.querySelector("[name=crossCode]"),
reload: root.querySelector("[data-action=reload]"),
signOut: root.querySelector("[data-action=signout]"),
status: root.querySelector("#v2xStatus"),
@@ -329,7 +327,6 @@
resolved.searchParams.set("authorization", token);
return resolved.href;
}
function escapeAttribute(value) { return String(value).replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;"); }
function transformLat(x, y) { let value = -100 + 2 * x + 3 * y + .2 * y * y + .1 * x * y + .2 * Math.sqrt(Math.abs(x)); value += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3; value += (20 * Math.sin(y * PI) + 40 * Math.sin(y / 3 * PI)) * 2 / 3; value += (160 * Math.sin(y / 12 * PI) + 320 * Math.sin(y * PI / 30)) * 2 / 3; return value; }
function transformLon(x, y) { let value = 300 + x + 2 * y + .1 * x * x + .1 * x * y + .1 * Math.sqrt(Math.abs(x)); value += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3; value += (20 * Math.sin(x * PI) + 40 * Math.sin(x / 3 * PI)) * 2 / 3; value += (150 * Math.sin(x / 12 * PI) + 300 * Math.sin(x / 30 * PI)) * 2 / 3; return value; }

View File

@@ -281,6 +281,8 @@ assert.match(v2xRuntime, /GCJ-02 -> WGS84 once/);
assert.match(v2xRuntime, /\/network\/ws\/network\/signal/);
assert.match(v2xRuntime, /\/network\/ws\/network\/obuPosition/);
assert.match(v2xRuntime, /\/network\/ws\/network\/targetPosition/);
assert.doesNotMatch(v2xRuntime, /Intersection code<input/);
assert.match(v2xRuntime, /V2X intersection code is not configured/);
assert.match(v2xRuntime, /gcj02ToWgs84/);
assert.match(previewRuntime, /createLiveVehicleState\(\)/);
assert.doesNotMatch(previewRuntime, /const cruise = addVehicleCruises\(/);