mirror of
https://github.com/andrey271192/PCAtelegram_web.git
synced 2026-09-20 11:55:32 +00:00
fix: keep routing edits during refresh
This commit is contained in:
@@ -532,6 +532,8 @@ const state = {
|
|||||||
userTrafficLoading: false,
|
userTrafficLoading: false,
|
||||||
backupSchedule: null,
|
backupSchedule: null,
|
||||||
routing: null,
|
routing: null,
|
||||||
|
routingDirty: false,
|
||||||
|
routingPreviewMap: null,
|
||||||
warp: null,
|
warp: null,
|
||||||
qrLink: "",
|
qrLink: "",
|
||||||
pendingUsers: new Set(),
|
pendingUsers: new Set(),
|
||||||
@@ -656,7 +658,10 @@ function applyI18n() {
|
|||||||
$("#languageSelect").value = state.lang;
|
$("#languageSelect").value = state.lang;
|
||||||
$("#settingsLanguage").textContent = state.lang === "ru" ? "Русский" : "English";
|
$("#settingsLanguage").textContent = state.lang === "ru" ? "Русский" : "English";
|
||||||
$("#settingsTheme").textContent = state.theme === "dark" ? t("darkTheme") : t("lightTheme");
|
$("#settingsTheme").textContent = state.theme === "dark" ? t("darkTheme") : t("lightTheme");
|
||||||
$("#visualTitle").textContent = t("visualTitle");
|
const visualPort = state.routingDirty
|
||||||
|
? (state.routingPreviewMap?.public_port || $("#visualRoutingPort")?.value || state.routing?.port || 443)
|
||||||
|
: (state.overview?.port_map?.public_port || state.routing?.port || 443);
|
||||||
|
$("#visualTitle").textContent = t("visualTitle").replace("{port}", visualPort);
|
||||||
$("#visualText").textContent = t("visualText");
|
$("#visualText").textContent = t("visualText");
|
||||||
updateTrafficControls();
|
updateTrafficControls();
|
||||||
updateUserTrafficControls();
|
updateUserTrafficControls();
|
||||||
@@ -921,7 +926,11 @@ function renderOverview() {
|
|||||||
$("#settingsBind").textContent = `${bind.host || "127.0.0.1"}:${bind.port || 1984}`;
|
$("#settingsBind").textContent = `${bind.host || "127.0.0.1"}:${bind.port || 1984}`;
|
||||||
$("#metricMode").textContent = cfg.mode || "--";
|
$("#metricMode").textContent = cfg.mode || "--";
|
||||||
renderSiteStatus();
|
renderSiteStatus();
|
||||||
|
if (state.routingDirty && state.routingPreviewMap) {
|
||||||
|
renderPortMap(state.routingPreviewMap);
|
||||||
|
} else if (!state.routingDirty) {
|
||||||
renderPortMap(data.port_map || data.port_443 || {});
|
renderPortMap(data.port_map || data.port_443 || {});
|
||||||
|
}
|
||||||
$("#metricUsers").textContent = data.users_count ?? 0;
|
$("#metricUsers").textContent = data.users_count ?? 0;
|
||||||
$("#metricProxyTraffic").textContent = fmtBytes(stats.proxy_bytes);
|
$("#metricProxyTraffic").textContent = fmtBytes(stats.proxy_bytes);
|
||||||
$("#metricProxyPackets").textContent = `${stats.proxy_pkts || 0} ${t("packets")}`;
|
$("#metricProxyPackets").textContent = `${stats.proxy_pkts || 0} ${t("packets")}`;
|
||||||
@@ -1458,12 +1467,29 @@ function routingControlPairs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setRoutingControlValues(routing = {}) {
|
function setRoutingControlValues(routing = {}) {
|
||||||
|
if (state.routingDirty) return;
|
||||||
routingControlPairs().forEach((item) => {
|
routingControlPairs().forEach((item) => {
|
||||||
|
if (document.activeElement === item.port || document.activeElement === item.mask) return;
|
||||||
item.port.value = routing.port || 443;
|
item.port.value = routing.port || 443;
|
||||||
item.mask.value = routing.mask_host || "google.com";
|
item.mask.value = routing.mask_host || "google.com";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function syncRoutingControls(source) {
|
||||||
|
const form = source?.closest?.("form");
|
||||||
|
const port = form?.querySelector('[name="port"]')?.value ?? "";
|
||||||
|
const mask = form?.querySelector('[name="mask_host"]')?.value ?? "";
|
||||||
|
routingControlPairs().forEach((item) => {
|
||||||
|
if (item.port !== source && document.activeElement !== item.port) item.port.value = port;
|
||||||
|
if (item.mask !== source && document.activeElement !== item.mask) item.mask.value = mask;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function markRoutingDirty(eventObj) {
|
||||||
|
state.routingDirty = true;
|
||||||
|
syncRoutingControls(eventObj.target);
|
||||||
|
}
|
||||||
|
|
||||||
function setRoutingNotes(routing = {}) {
|
function setRoutingNotes(routing = {}) {
|
||||||
const conflicts = routing.conflicts || [];
|
const conflicts = routing.conflicts || [];
|
||||||
const message = routingSummary(routing);
|
const message = routingSummary(routing);
|
||||||
@@ -1476,6 +1502,7 @@ function setRoutingNotes(routing = {}) {
|
|||||||
|
|
||||||
function renderRoutingSettings(payload = null) {
|
function renderRoutingSettings(payload = null) {
|
||||||
const routing = payload || state.routing || state.overview?.routing || {};
|
const routing = payload || state.routing || state.overview?.routing || {};
|
||||||
|
if (state.routingDirty && !payload) return;
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
setRoutingControlValues(routing);
|
setRoutingControlValues(routing);
|
||||||
}
|
}
|
||||||
@@ -1679,14 +1706,15 @@ async function checkRoutingPort(inputEl = $("#routingPort")) {
|
|||||||
try {
|
try {
|
||||||
const data = await api(`/api/routing?port=${encodeURIComponent(port)}`);
|
const data = await api(`/api/routing?port=${encodeURIComponent(port)}`);
|
||||||
renderRoutingSettings(data);
|
renderRoutingSettings(data);
|
||||||
renderPortMap({
|
state.routingPreviewMap = {
|
||||||
public_port: data.port,
|
public_port: data.port,
|
||||||
configured_port: state.routing?.port || state.overview?.routing?.port || data.port,
|
configured_port: state.routing?.port || state.overview?.routing?.port || data.port,
|
||||||
listeners: data.listeners || [],
|
listeners: data.listeners || [],
|
||||||
routes: [],
|
routes: [],
|
||||||
ok: data.ok,
|
ok: data.ok,
|
||||||
error: data.error,
|
error: data.error,
|
||||||
});
|
};
|
||||||
|
renderPortMap(state.routingPreviewMap);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$("#routingStatus").textContent = t("routingBusy");
|
$("#routingStatus").textContent = t("routingBusy");
|
||||||
$("#routingStatus").className = "status-pill health-error";
|
$("#routingStatus").className = "status-pill health-error";
|
||||||
@@ -1714,6 +1742,8 @@ async function saveRoutingSettings(eventObj) {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
});
|
});
|
||||||
|
state.routingDirty = false;
|
||||||
|
state.routingPreviewMap = null;
|
||||||
state.routing = data;
|
state.routing = data;
|
||||||
state.overview = await api("/api/overview");
|
state.overview = await api("/api/overview");
|
||||||
renderRoutingSettings();
|
renderRoutingSettings();
|
||||||
@@ -1997,8 +2027,12 @@ $("#repairStatsBtn").addEventListener("click", repairStats);
|
|||||||
$("#collectStatsBtn").addEventListener("click", collectStats);
|
$("#collectStatsBtn").addEventListener("click", collectStats);
|
||||||
$("#authSettingsForm").addEventListener("submit", updateAuthSettings);
|
$("#authSettingsForm").addEventListener("submit", updateAuthSettings);
|
||||||
$("#visualRoutingForm").addEventListener("submit", saveRoutingSettings);
|
$("#visualRoutingForm").addEventListener("submit", saveRoutingSettings);
|
||||||
|
$("#visualRoutingPort").addEventListener("input", markRoutingDirty);
|
||||||
|
$("#visualRoutingMaskHost").addEventListener("input", markRoutingDirty);
|
||||||
$("#visualRoutingPort").addEventListener("change", (eventObj) => checkRoutingPort(eventObj.target));
|
$("#visualRoutingPort").addEventListener("change", (eventObj) => checkRoutingPort(eventObj.target));
|
||||||
$("#routingSettingsForm").addEventListener("submit", saveRoutingSettings);
|
$("#routingSettingsForm").addEventListener("submit", saveRoutingSettings);
|
||||||
|
$("#routingPort").addEventListener("input", markRoutingDirty);
|
||||||
|
$("#routingMaskHost").addEventListener("input", markRoutingDirty);
|
||||||
$("#routingPort").addEventListener("change", (eventObj) => checkRoutingPort(eventObj.target));
|
$("#routingPort").addEventListener("change", (eventObj) => checkRoutingPort(eventObj.target));
|
||||||
$("#warpSettingsForm").addEventListener("submit", saveWarpSettings);
|
$("#warpSettingsForm").addEventListener("submit", saveWarpSettings);
|
||||||
$("#warpScope").addEventListener("change", renderWarpSettings);
|
$("#warpScope").addEventListener("change", renderWarpSettings);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
document.documentElement.dataset.theme = theme;
|
document.documentElement.dataset.theme = theme;
|
||||||
}());
|
}());
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="/styles.css?v=2.5.0-admin24">
|
<link rel="stylesheet" href="/styles.css?v=2.5.0-admin25">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="app-shell">
|
<div class="app-shell">
|
||||||
@@ -482,6 +482,6 @@
|
|||||||
<button id="qrCopyBtn" type="button" class="soft" data-i18n="copyLink">Copy link</button>
|
<button id="qrCopyBtn" type="button" class="soft" data-i18n="copyLink">Copy link</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/app.js?v=2.5.0-admin24" type="module"></script>
|
<script src="/app.js?v=2.5.0-admin25" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user