工作台左侧客户端列表按 sim / live 分组,没有对应模式则不显示该组标题。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -782,6 +782,13 @@ button, .btn {
|
|||||||
}
|
}
|
||||||
.desk-list { list-style: none; padding: 0; margin: 0; }
|
.desk-list { list-style: none; padding: 0; margin: 0; }
|
||||||
.desk-list li { margin: 6px 0; }
|
.desk-list li { margin: 6px 0; }
|
||||||
|
.desk-list .desk-group-label {
|
||||||
|
margin: 10px 0 4px;
|
||||||
|
padding: 0 2px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.desk-list .desk-group-label:first-child { margin-top: 0; }
|
||||||
|
.desk.is-side-collapsed .desk-group-label { display: none; }
|
||||||
.desk-list li a {
|
.desk-list li a {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 7px 9px;
|
padding: 7px 9px;
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{% block title %}期权中控{% endblock %}</title>
|
<title>{% block title %}期权中控{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='hub.css') }}?v=16">
|
<link rel="stylesheet" href="{{ url_for('static', filename='hub.css') }}?v=17">
|
||||||
</head>
|
</head>
|
||||||
<body class="{% if request.path.startswith('/login') %}page-login{% elif request.path.startswith('/desk') %}page-desk{% elif request.path.startswith('/stats') %}page-stats{% elif request.path.startswith('/instances') %}page-instances{% elif request.path == '/' %}page-dashboard{% endif %}">
|
<body class="{% if request.path.startswith('/login') %}page-login{% elif request.path.startswith('/desk') %}page-desk{% elif request.path.startswith('/stats') %}page-stats{% elif request.path.startswith('/instances') %}page-instances{% elif request.path == '/' %}page-dashboard{% endif %}">
|
||||||
{% if session.get('logged_in') %}
|
{% if session.get('logged_in') %}
|
||||||
|
|||||||
+118
-63
@@ -1,63 +1,118 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}工作台 · 期权中控{% endblock %}
|
{% block title %}工作台 · 期权中控{% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<section class="desk" id="desk-root">
|
<section class="desk" id="desk-root">
|
||||||
<aside class="desk-side" id="desk-side">
|
<aside class="desk-side" id="desk-side">
|
||||||
<div class="desk-side-head">
|
<div class="desk-side-head">
|
||||||
<h2 class="desk-side-title">客户端</h2>
|
<h2 class="desk-side-title">客户端</h2>
|
||||||
<button type="button" class="desk-side-toggle" id="desk-side-toggle" title="折叠/展开" aria-label="折叠客户端列表">‹</button>
|
<button type="button" class="desk-side-toggle" id="desk-side-toggle" title="折叠/展开" aria-label="折叠客户端列表">‹</button>
|
||||||
</div>
|
</div>
|
||||||
<ul class="desk-list">
|
<ul class="desk-list" id="desk-list">
|
||||||
{% for inst in instances %}
|
{% for inst in instances %}
|
||||||
<li class="{% if current and current.id == inst.id %}active{% endif %}" title="{{ inst.name }}">
|
<li class="desk-list-item{% if current and current.id == inst.id %} active{% endif %}" data-id="{{ inst.id }}" 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>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="muted desk-list-empty">无启用实例</li>
|
<li class="muted desk-list-empty">无启用实例</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</aside>
|
</aside>
|
||||||
<div class="desk-main">
|
<div class="desk-main">
|
||||||
{% 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>{{ current.name }}</strong>
|
||||||
<span class="muted">{{ current.base_url }}</span>
|
<span class="muted">{{ current.base_url }}</span>
|
||||||
<a class="btn" href="{{ open_url }}" target="_blank" rel="noopener">新标签打开</a>
|
<a class="btn" 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" 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>
|
||||||
</div>
|
</div>
|
||||||
<div class="empty">请从左侧选择客户端,或到「实例」添加公网 crypto_okx.</div>
|
<div class="empty">请从左侧选择客户端,或到「实例」添加公网 crypto_okx.</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
var KEY = "hub_desk_side_collapsed";
|
var KEY = "hub_desk_side_collapsed";
|
||||||
var root = document.getElementById("desk-root");
|
var root = document.getElementById("desk-root");
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
function apply(collapsed) {
|
function apply(collapsed) {
|
||||||
root.classList.toggle("is-side-collapsed", !!collapsed);
|
root.classList.toggle("is-side-collapsed", !!collapsed);
|
||||||
try { localStorage.setItem(KEY, collapsed ? "1" : "0"); } catch (e) {}
|
try { localStorage.setItem(KEY, collapsed ? "1" : "0"); } catch (e) {}
|
||||||
}
|
}
|
||||||
function toggle() {
|
function toggle() {
|
||||||
apply(!root.classList.contains("is-side-collapsed"));
|
apply(!root.classList.contains("is-side-collapsed"));
|
||||||
}
|
}
|
||||||
var btn = document.getElementById("desk-side-toggle");
|
var btn = document.getElementById("desk-side-toggle");
|
||||||
var bar = document.getElementById("desk-side-toggle-bar");
|
var bar = document.getElementById("desk-side-toggle-bar");
|
||||||
if (btn) btn.addEventListener("click", toggle);
|
if (btn) btn.addEventListener("click", toggle);
|
||||||
if (bar) bar.addEventListener("click", toggle);
|
if (bar) bar.addEventListener("click", toggle);
|
||||||
var saved = false;
|
var saved = false;
|
||||||
try { saved = localStorage.getItem(KEY) === "1"; } catch (e) {}
|
try { saved = localStorage.getItem(KEY) === "1"; } catch (e) {}
|
||||||
apply(saved);
|
apply(saved);
|
||||||
})();
|
|
||||||
</script>
|
var list = document.getElementById("desk-list");
|
||||||
{% endblock %}
|
if (!list) return;
|
||||||
|
var items = Array.prototype.slice.call(list.querySelectorAll("li.desk-list-item[data-id]"));
|
||||||
|
if (!items.length) return;
|
||||||
|
|
||||||
|
function groupLabel(mode) {
|
||||||
|
var li = document.createElement("li");
|
||||||
|
li.className = "desk-group-label";
|
||||||
|
li.setAttribute("aria-hidden", "true");
|
||||||
|
var span = document.createElement("span");
|
||||||
|
span.className = "overview-mode-tag overview-mode-tag--" + mode;
|
||||||
|
span.textContent = mode;
|
||||||
|
li.appendChild(span);
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
|
||||||
|
function regroup(modeById) {
|
||||||
|
var sim = [];
|
||||||
|
var live = [];
|
||||||
|
var other = [];
|
||||||
|
items.forEach(function (li) {
|
||||||
|
var m = String(modeById[li.getAttribute("data-id")] || "").toLowerCase();
|
||||||
|
if (m === "sim") sim.push(li);
|
||||||
|
else if (m === "live") live.push(li);
|
||||||
|
else other.push(li);
|
||||||
|
});
|
||||||
|
list.innerHTML = "";
|
||||||
|
if (sim.length) {
|
||||||
|
list.appendChild(groupLabel("sim"));
|
||||||
|
sim.forEach(function (li) { list.appendChild(li); });
|
||||||
|
}
|
||||||
|
if (live.length) {
|
||||||
|
list.appendChild(groupLabel("live"));
|
||||||
|
live.forEach(function (li) { list.appendChild(li); });
|
||||||
|
}
|
||||||
|
other.forEach(function (li) { list.appendChild(li); });
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all(
|
||||||
|
items.map(function (li) {
|
||||||
|
var iid = li.getAttribute("data-id");
|
||||||
|
return fetch("/api/instances/" + iid + "/version", {
|
||||||
|
credentials: "same-origin",
|
||||||
|
headers: { Accept: "application/json" },
|
||||||
|
})
|
||||||
|
.then(function (r) { return r.json().catch(function () { return {}; }); })
|
||||||
|
.then(function (v) { return { id: iid, mode: (v && v.mode) || "" }; })
|
||||||
|
.catch(function () { return { id: iid, mode: "" }; });
|
||||||
|
})
|
||||||
|
).then(function (rows) {
|
||||||
|
var map = {};
|
||||||
|
rows.forEach(function (row) { map[row.id] = row.mode; });
|
||||||
|
regroup(map);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user