This commit is contained in:
dekun
2026-05-30 11:52:21 +08:00
parent fd5e333daf
commit 4cd5a48dc1
9 changed files with 298 additions and 16 deletions
+10
View File
@@ -70,6 +70,16 @@
<div class="errors">{{ form.sort_order.errors[0] }}</div>
{% endif %}
</div>
<div class="form-row">
{{ form.embed_kind.label }}
{{ form.embed_kind() }}
<p class="hint" style="margin:0.35rem 0 0">
选「复盘中控」时:路径填 <code>/monitor</code>;本地 iframe 打开会先走中控登录页或代登录。
</p>
{% if form.embed_kind.errors %}
<div class="errors">{{ form.embed_kind.errors[0] }}</div>
{% endif %}
</div>
<div class="toolbar" style="margin-top: 1.25rem">
{{ form.submit(class="btn btn-primary", style="width: auto") }}
<a class="btn btn-secondary" href="{{ url_for('admin_services') }}">取消</a>
+1 -1
View File
@@ -49,7 +49,7 @@
<tbody>
{% for s in services %}
<tr>
<td>{{ s.name }}</td>
<td>{{ s.name }}{% if s.embed_kind == 'hub' %} <span class="hint">(中控)</span>{% endif %}</td>
<td><code style="font-size: 0.82rem">{{ s.build_url() }}</code></td>
<td>{{ s.group.name if s.group else '—' }}</td>
<td>{{ s.sort_order }}</td>
+126 -9
View File
@@ -41,7 +41,12 @@
href="#"
class="nav-link"
role="button"
data-url="{{ svc.build_url()|e }}"
data-url="{{ svc.build_open_url()|e }}"
data-base-url="{{ svc.build_url()|e }}"
data-origin="{{ svc.build_origin()|e }}"
data-next-path="{{ (svc.path or '/monitor')|e }}"
data-embed-kind="{{ (svc.embed_kind or '')|e }}"
data-service-id="{{ svc.id }}"
data-name="{{ svc.name | e }}"
>{{ svc.name }}</a
>
@@ -75,7 +80,12 @@
<button
type="button"
class="service-card"
data-url="{{ svc.build_url()|e }}"
data-url="{{ svc.build_open_url()|e }}"
data-base-url="{{ svc.build_url()|e }}"
data-origin="{{ svc.build_origin()|e }}"
data-next-path="{{ (svc.path or '/monitor')|e }}"
data-embed-kind="{{ (svc.embed_kind or '')|e }}"
data-service-id="{{ svc.id }}"
data-name="{{ svc.name | e }}"
>
<span class="service-card-title">{{ svc.name }}</span>
@@ -99,6 +109,15 @@
<span class="frame-title" id="current-service-name"></span>
</div>
<div class="frame-toolbar-actions">
<button
type="button"
class="btn btn-secondary btn-toolbar-refresh"
id="frame-hub-login"
title="通过本地导航代登录云端中控(需配置 NAV_HUB_USERNAME / NAV_HUB_PASSWORD"
hidden
>
中控登录
</button>
<button type="button" class="btn btn-secondary btn-toolbar-refresh" id="frame-refresh">
刷新
</button>
@@ -121,6 +140,7 @@
</div>
<script>
(function () {
var hubAutoLogin = {{ 'true' if hub_auto_login else 'false' }};
var layoutMain = document.getElementById("layout-main");
var btnSidebarCollapse = document.getElementById("sidebar-collapse");
var btnSidebarExpand = document.getElementById("sidebar-expand");
@@ -161,7 +181,64 @@
var btnRefresh = document.getElementById("frame-refresh");
var btnForceRefresh = document.getElementById("frame-force-refresh");
var btnBack = document.getElementById("frame-back-overview");
var btnHubLogin = document.getElementById("frame-hub-login");
var currentBaseUrl = "";
var currentOpenUrl = "";
var currentEmbedKind = "";
var currentServiceId = "";
var currentOrigin = "";
var currentNextPath = "/monitor";
function isHubEmbed(kind) {
return (kind || "").toLowerCase() === "hub";
}
function toggleHubLoginBtn(show) {
if (btnHubLogin) btnHubLogin.hidden = !show;
}
function applyIframeUrl(url) {
if (!url) return;
frame.src = url;
}
function hubLoginViaProxy(done) {
if (!currentServiceId && !currentOrigin) {
if (done) done(false, "未选择中控服务");
return;
}
var body = { service_id: parseInt(currentServiceId, 10) || undefined, next: currentNextPath };
fetch("/api/embed/hub-login", {
method: "POST",
headers: { "Content-Type": "application/json", "Accept": "application/json" },
body: JSON.stringify(body),
})
.then(function (r) {
return r.json().then(function (j) {
return { ok: r.ok, j: j };
});
})
.then(function (res) {
if (res.ok && res.j.ok && res.j.embed_auth_url) {
currentBaseUrl = res.j.embed_auth_url.split("?")[0].replace(/\/embed-auth$/, "") + (currentNextPath || "/monitor");
applyIframeUrl(res.j.embed_auth_url);
if (done) done(true);
return;
}
if (done) done(false, (res.j && res.j.detail) || "中控登录失败");
})
.catch(function (e) {
if (done) done(false, String(e));
});
}
window.addEventListener("message", function (ev) {
var data = ev.data;
if (!data || data.type !== "hub:login-ok") return;
if (data.embed_auth_url) {
applyIframeUrl(data.embed_auth_url);
}
});
function setActive(el) {
links.forEach(function (a) {
@@ -178,14 +255,29 @@
return found;
}
function openService(url, name, preferredNav) {
function openService(url, name, preferredNav, meta) {
if (!url) return;
currentBaseUrl = url;
meta = meta || {};
currentOpenUrl = url;
currentBaseUrl = meta.baseUrl || url;
currentEmbedKind = meta.embedKind || "";
currentServiceId = meta.serviceId || "";
currentOrigin = meta.origin || "";
currentNextPath = meta.nextPath || "/monitor";
nameEl.textContent = name || "";
dashboard.hidden = true;
frameStack.hidden = false;
frame.hidden = false;
frame.src = url;
toggleHubLoginBtn(isHubEmbed(currentEmbedKind));
if (isHubEmbed(currentEmbedKind) && hubAutoLogin) {
hubLoginViaProxy(function (ok, err) {
if (!ok) applyIframeUrl(url);
});
var nav = preferredNav || findNavLink(url);
setActive(nav);
return;
}
applyIframeUrl(url);
var nav = preferredNav || findNavLink(url);
setActive(nav);
}
@@ -215,13 +307,13 @@
}
function reloadUrl() {
var u = currentBaseUrl;
var u = currentOpenUrl || currentBaseUrl;
if (!u) return;
frame.src = buildCacheBustUrl(u, false);
}
function forceReloadUrl() {
var u = currentBaseUrl;
var u = currentOpenUrl || currentBaseUrl;
if (!u) return;
frame.src = "about:blank";
frame.onload = function () {
@@ -232,19 +324,34 @@
function showDashboard() {
currentBaseUrl = "";
currentOpenUrl = "";
currentEmbedKind = "";
currentServiceId = "";
currentOrigin = "";
frame.src = "about:blank";
frame.hidden = true;
frameStack.hidden = true;
dashboard.hidden = false;
toggleHubLoginBtn(false);
setActive(null);
}
function readServiceMeta(el) {
return {
baseUrl: el.getAttribute("data-base-url") || el.getAttribute("data-url") || "",
embedKind: el.getAttribute("data-embed-kind") || "",
serviceId: el.getAttribute("data-service-id") || "",
origin: el.getAttribute("data-origin") || "",
nextPath: el.getAttribute("data-next-path") || "/monitor",
};
}
links.forEach(function (a) {
a.addEventListener("click", function (e) {
e.preventDefault();
var url = a.getAttribute("data-url");
var name = a.getAttribute("data-name") || "";
openService(url, name, a);
openService(url, name, a, readServiceMeta(a));
});
});
@@ -252,10 +359,20 @@
btn.addEventListener("click", function () {
var url = btn.getAttribute("data-url");
var name = btn.getAttribute("data-name") || "";
openService(url, name, null);
openService(url, name, null, readServiceMeta(btn));
});
});
if (btnHubLogin) {
btnHubLogin.addEventListener("click", function () {
btnHubLogin.disabled = true;
hubLoginViaProxy(function (ok, err) {
btnHubLogin.disabled = false;
if (!ok && err) window.alert(err);
});
});
}
btnRefresh.addEventListener("click", function () {
reloadUrl();
});