env 配置为中控 Bridge Token 增加一键复制。

便于从客户端直接复制到中控登记实例。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-01 11:18:44 +08:00
parent a4a9634ba8
commit ed9fd05a84
3 changed files with 89 additions and 1 deletions
@@ -297,7 +297,21 @@
}
input.dataset.envKey = field.key;
input.className = "env-field-input";
if (field.key === "HUB_BRIDGE_TOKEN" && !field.sensitive && field.type !== "bool" && field.type !== "select") {
const wrap = document.createElement("div");
wrap.className = "env-field-input-wrap env-field-input-wrap--copy";
wrap.appendChild(input);
const copyBtn = document.createElement("button");
copyBtn.type = "button";
copyBtn.className = "btn-secondary btn-sm env-copy-btn";
copyBtn.dataset.envCopy = "HUB_BRIDGE_TOKEN";
copyBtn.title = "复制 Token";
copyBtn.textContent = "复制";
wrap.appendChild(copyBtn);
row.appendChild(wrap);
} else {
row.appendChild(input);
}
if (field.hidden) {
row.hidden = true;
row.style.display = "none";
@@ -637,12 +651,58 @@
}
}
async function copyTextToClipboard(text) {
const value = String(text || "");
if (!value) throw new Error("内容为空");
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(value);
return;
}
const ta = document.createElement("textarea");
ta.value = value;
ta.setAttribute("readonly", "");
ta.style.position = "fixed";
ta.style.left = "-9999px";
document.body.appendChild(ta);
ta.select();
const ok = document.execCommand("copy");
document.body.removeChild(ta);
if (!ok) throw new Error("复制失败");
}
async function copyEnvFieldValue(key, btn) {
const status = document.getElementById("env-config-status");
const input = document.querySelector('.env-field-input[data-env-key="' + key + '"]');
const value = input ? String(input.value || "").trim() : "";
try {
await copyTextToClipboard(value);
if (btn) {
const old = btn.textContent;
btn.textContent = "已复制";
btn.disabled = true;
setTimeout(() => {
btn.textContent = old || "复制";
btn.disabled = false;
}, 1200);
}
setStatus(status, "已复制到剪贴板");
} catch (e) {
setStatus(status, (e && e.message) || "复制失败", true);
}
}
function installDelegatedHandlers() {
if (document.documentElement.dataset.prefsDelegateBound === "1") return;
document.documentElement.dataset.prefsDelegateBound = "1";
document.addEventListener("click", (ev) => {
const target = ev.target;
if (!(target instanceof Element)) return;
const copyBtn = target.closest("[data-env-copy]");
if (copyBtn) {
ev.preventDefault();
void copyEnvFieldValue(copyBtn.getAttribute("data-env-copy") || "", copyBtn);
return;
}
if (target.closest("#display-prefs-save")) {
ev.preventDefault();
void saveDisplayPrefs();
+18
View File
@@ -2684,6 +2684,24 @@ html[data-theme="light"] .journal-detail-img-thumb {
box-sizing: border-box;
}
.env-field-input-wrap {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.env-field-input-wrap .env-field-input {
flex: 1 1 auto;
min-width: 0;
}
.env-field-input-wrap--copy .env-copy-btn {
flex: 0 0 auto;
margin-top: 0;
white-space: nowrap;
}
.env-config-loading-wrap {
padding: 24px;
text-align: center;
@@ -73,6 +73,7 @@
onfocus="this.removeAttribute('readonly')"
>
{% else %}
<div class="env-field-input-wrap{% if field.key == 'HUB_BRIDGE_TOKEN' %} env-field-input-wrap--copy{% endif %}">
<input
class="env-field-input"
id="env-f-{{ field.key }}"
@@ -88,6 +89,15 @@
data-bwignore="true"
data-form-type="other"
>
{% if field.key == 'HUB_BRIDGE_TOKEN' %}
<button
type="button"
class="btn-secondary btn-sm env-copy-btn"
data-env-copy="HUB_BRIDGE_TOKEN"
title="复制 Token"
>复制</button>
{% endif %}
</div>
{% endif %}
</div>
{% endfor %}