auto-save 2026-05-09 18:03 (~6)

This commit is contained in:
2026-05-09 18:03:31 +08:00
parent ef06c99d56
commit fb92072f49
6 changed files with 214 additions and 15 deletions

View File

@@ -343,6 +343,7 @@ function switchTab(name) {
if (name === "cron") refreshCron();
if (name === "memory") refreshMemory();
if (name === "tools") refreshTools();
if (name === "settings") refreshFeishuApps();
if (name === "runs") setTimeout(() => document.getElementById("runPrompt")?.focus(), 50);
if (name === "dashboard" && _dashboardDirty) {
// 推迟到下一帧,避免阻塞切换动画
@@ -353,6 +354,55 @@ function switchTab(name) {
}
}
// ---------- 飞书集成 ----------
let _feishuAppsLoading = false;
async function refreshFeishuApps() {
const box = document.getElementById("feishuApps");
if (!box || _feishuAppsLoading) return;
_feishuAppsLoading = true;
box.innerHTML = '<div class="settings-help">正在读取飞书桥接服务...</div>';
try {
const res = await fetch("/feishu/apps", { cache: "no-store" });
if (!res.ok) throw new Error("HTTP " + res.status);
const data = await res.json();
const apps = Array.isArray(data.apps) ? data.apps : [];
if (!apps.length) {
box.innerHTML = '<div class="settings-help">还没有读取到飞书机器人配置。</div>';
return;
}
box.innerHTML = apps.map(app => {
const appId = escapeHTML(app.app_id || "");
const callbackUrl = escapeHTML(app.callback_url || "");
const isDefault = app.app_id === data.default_app_id;
const tokenCount = Number(app.verification_tokens_count || 0);
return `
<div class="feishu-app-card">
<div class="feishu-app-top">
<div>
<div class="feishu-app-title">${appId}</div>
<div class="feishu-app-meta">${isDefault ? "默认应用" : "独立应用"} · ${tokenCount} 个校验 Token</div>
</div>
<span class="feishu-status">已接入</span>
</div>
<div class="feishu-callback">
<span>${callbackUrl}</span>
<button class="icon-btn-mini" onclick="copyText('${callbackUrl}')" title="复制回调地址">
<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
</button>
</div>
<div class="feishu-app-foot">
<span>事件: im.message.receive_v1</span>
<span>通知目标: ${app.has_default_receive_id ? escapeHTML(app.default_receive_id_type || "chat_id") : "按请求传入"}</span>
</div>
</div>`;
}).join("");
} catch (e) {
box.innerHTML = `<div class="settings-help">飞书桥接服务读取失败: ${escapeHTML(e.message || e)}</div>`;
} finally {
_feishuAppsLoading = false;
}
}
// ---------- 带认证续期的 fetch ----------
// nginx 的 hermes_auth cookie 默认 24h 过期;过期后 /api/v1/* 全部 401。
// 这里在 401 时尝试一次静默续期(浏览器若缓存了 Basic Auth 会自动带上),
@@ -3283,6 +3333,9 @@ function startResearch() {
function openLog() {
toast("日志查看暂未实现,可 SSH 到 Mac mini 查看 ~/.hermes/logs/");
}
function copyText(text) {
navigator.clipboard?.writeText(text).then(() => toast("已复制"));
}
function toast(text) {
const el = document.createElement("div");
el.textContent = text;