工作台切换客户端时不再整页刷新,避免左侧 sim/live 分组闪回平铺。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+74
-6
@@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="desk-list" id="desk-list">
|
<ul class="desk-list" id="desk-list">
|
||||||
{% for inst in instances %}
|
{% for inst in instances %}
|
||||||
<li class="desk-list-item{% if current and current.id == inst.id %} active{% endif %}" data-id="{{ inst.id }}" title="{{ inst.name }}">
|
<li class="desk-list-item{% if current and current.id == inst.id %} active{% endif %}" data-id="{{ inst.id }}" data-name="{{ inst.name }}" data-base-url="{{ inst.base_url }}" title="{{ inst.name }}">
|
||||||
<a href="/desk?id={{ inst.id }}">
|
<a href="/desk?id={{ inst.id }}">
|
||||||
<span class="desk-list-name">{{ inst.name }}</span>
|
<span class="desk-list-name">{{ inst.name }}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -23,12 +23,12 @@
|
|||||||
{% if current and open_url %}
|
{% if current and open_url %}
|
||||||
<div class="desk-toolbar">
|
<div class="desk-toolbar">
|
||||||
<button type="button" class="desk-side-toggle desk-side-toggle--bar" id="desk-side-toggle-bar" title="展开客户端列表" aria-label="展开客户端列表">›</button>
|
<button type="button" class="desk-side-toggle desk-side-toggle--bar" id="desk-side-toggle-bar" title="展开客户端列表" aria-label="展开客户端列表">›</button>
|
||||||
<strong>{{ current.name }}</strong>
|
<strong id="desk-current-name">{{ current.name }}</strong>
|
||||||
<span class="muted">{{ current.base_url }}</span>
|
<span class="muted" id="desk-current-url">{{ current.base_url }}</span>
|
||||||
<a class="btn" href="{{ open_url }}" target="_blank" rel="noopener">新标签打开</a>
|
<a class="btn" id="desk-open-blank" href="{{ open_url }}" target="_blank" rel="noopener">新标签打开</a>
|
||||||
<a class="btn" href="/">回总览</a>
|
<a class="btn" href="/">回总览</a>
|
||||||
</div>
|
</div>
|
||||||
<iframe class="desk-frame" src="{{ open_url }}" title="{{ current.name }}"></iframe>
|
<iframe class="desk-frame" id="desk-frame" src="{{ open_url }}" title="{{ current.name }}"></iframe>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="desk-toolbar">
|
<div class="desk-toolbar">
|
||||||
<button type="button" class="desk-side-toggle desk-side-toggle--bar" id="desk-side-toggle-bar" title="展开客户端列表" aria-label="展开客户端列表">›</button>
|
<button type="button" class="desk-side-toggle desk-side-toggle--bar" id="desk-side-toggle-bar" title="展开客户端列表" aria-label="展开客户端列表">›</button>
|
||||||
@@ -59,11 +59,26 @@
|
|||||||
try { saved = localStorage.getItem(KEY) === "1"; } catch (e) {}
|
try { saved = localStorage.getItem(KEY) === "1"; } catch (e) {}
|
||||||
apply(saved);
|
apply(saved);
|
||||||
|
|
||||||
|
var MODE_KEY = "hub_desk_instance_modes";
|
||||||
var list = document.getElementById("desk-list");
|
var list = document.getElementById("desk-list");
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
var items = Array.prototype.slice.call(list.querySelectorAll("li.desk-list-item[data-id]"));
|
var items = Array.prototype.slice.call(list.querySelectorAll("li.desk-list-item[data-id]"));
|
||||||
if (!items.length) return;
|
if (!items.length) return;
|
||||||
|
|
||||||
|
function readModeCache() {
|
||||||
|
try {
|
||||||
|
var raw = sessionStorage.getItem(MODE_KEY);
|
||||||
|
var parsed = raw ? JSON.parse(raw) : {};
|
||||||
|
return parsed && typeof parsed === "object" ? parsed : {};
|
||||||
|
} catch (e) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeModeCache(map) {
|
||||||
|
try { sessionStorage.setItem(MODE_KEY, JSON.stringify(map || {})); } catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
function groupLabel(mode) {
|
function groupLabel(mode) {
|
||||||
var li = document.createElement("li");
|
var li = document.createElement("li");
|
||||||
li.className = "desk-group-label";
|
li.className = "desk-group-label";
|
||||||
@@ -97,6 +112,58 @@
|
|||||||
other.forEach(function (li) { list.appendChild(li); });
|
other.forEach(function (li) { list.appendChild(li); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cached = readModeCache();
|
||||||
|
if (Object.keys(cached).length) regroup(cached);
|
||||||
|
|
||||||
|
function setActive(iid) {
|
||||||
|
items.forEach(function (li) {
|
||||||
|
li.classList.toggle("active", String(li.getAttribute("data-id")) === String(iid));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchClient(li) {
|
||||||
|
var iid = li.getAttribute("data-id");
|
||||||
|
if (!iid) return;
|
||||||
|
var name = li.getAttribute("data-name") || "";
|
||||||
|
var baseUrl = li.getAttribute("data-base-url") || "";
|
||||||
|
var frame = document.getElementById("desk-frame");
|
||||||
|
if (!frame) {
|
||||||
|
window.location.href = "/desk?id=" + encodeURIComponent(iid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setActive(iid);
|
||||||
|
var nameEl = document.getElementById("desk-current-name");
|
||||||
|
var urlEl = document.getElementById("desk-current-url");
|
||||||
|
if (nameEl) nameEl.textContent = name;
|
||||||
|
if (urlEl) urlEl.textContent = baseUrl;
|
||||||
|
frame.setAttribute("title", name);
|
||||||
|
fetch("/api/instances/" + iid + "/open_url", {
|
||||||
|
credentials: "same-origin",
|
||||||
|
headers: { Accept: "application/json" },
|
||||||
|
})
|
||||||
|
.then(function (r) { return r.json(); })
|
||||||
|
.then(function (d) {
|
||||||
|
if (!d || !d.ok || !d.url) throw new Error((d && d.msg) || "无法打开");
|
||||||
|
frame.src = d.url;
|
||||||
|
var blank = document.getElementById("desk-open-blank");
|
||||||
|
if (blank) blank.href = d.url;
|
||||||
|
try { history.replaceState(null, "", "/desk?id=" + encodeURIComponent(iid)); } catch (e) {}
|
||||||
|
})
|
||||||
|
.catch(function () {
|
||||||
|
window.location.href = "/desk?id=" + encodeURIComponent(iid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
list.addEventListener("click", function (ev) {
|
||||||
|
var a = ev.target.closest("a");
|
||||||
|
if (!a) return;
|
||||||
|
var li = a.closest("li.desk-list-item[data-id]");
|
||||||
|
if (!li) return;
|
||||||
|
if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey || ev.button !== 0) return;
|
||||||
|
ev.preventDefault();
|
||||||
|
switchClient(li);
|
||||||
|
});
|
||||||
|
|
||||||
Promise.all(
|
Promise.all(
|
||||||
items.map(function (li) {
|
items.map(function (li) {
|
||||||
var iid = li.getAttribute("data-id");
|
var iid = li.getAttribute("data-id");
|
||||||
@@ -106,11 +173,12 @@
|
|||||||
})
|
})
|
||||||
.then(function (r) { return r.json().catch(function () { return {}; }); })
|
.then(function (r) { return r.json().catch(function () { return {}; }); })
|
||||||
.then(function (v) { return { id: iid, mode: (v && v.mode) || "" }; })
|
.then(function (v) { return { id: iid, mode: (v && v.mode) || "" }; })
|
||||||
.catch(function () { return { id: iid, mode: "" }; });
|
.catch(function () { return { id: iid, mode: cached[iid] || "" }; });
|
||||||
})
|
})
|
||||||
).then(function (rows) {
|
).then(function (rows) {
|
||||||
var map = {};
|
var map = {};
|
||||||
rows.forEach(function (row) { map[row.id] = row.mode; });
|
rows.forEach(function (row) { map[row.id] = row.mode; });
|
||||||
|
writeModeCache(map);
|
||||||
regroup(map);
|
regroup(map);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user