async function backfillData() { const button = document.querySelector("#backfillButton"); button.disabled = true; setLoading(true, "正在回补历史交易日"); try { const payload = await apiRequest("/api/backfill", "POST", { start_date: document.querySelector("#backfillStart").value, end_date: document.querySelector("#backfillEnd").value, }); const failed = (payload.failed_count || 0); const skipped = (payload.skipped_non_trading_days || []).length; const suffix = failed ? `,失败 ${failed} 个` : skipped ? `,跳过 ${skipped} 个非交易日` : ""; showToast(`历史回补完成,共处理 ${payload.results.length} 个交易日${suffix}`); state.sentimentHistory = null; state.sentimentHistoryKey = ""; if (state.activeView === "sentimentCycleView") { await loadSentimentHistory(true); } await openAdminSettings(true); } catch (error) { showToast(error.message); } finally { setLoading(false); button.disabled = false; } } async function openAdminSettings(refreshOnly = false) { if (state.user?.role !== "admin") return; if (!refreshOnly) openModalDialog(elements.adminDialog); const status = document.querySelector("#adminConnectionStatus"); status.textContent = "正在读取系统状态"; try { const payload = await apiRequest("/api/admin/settings"); const data = payload.data || {}; const ifind = data.ifind || {}; status.textContent = `数据中枢 ${data.configured ? "已连接" : "未连接"} · iFinD ${ifind.configured ? "已配置" : "未配置"} · ${number(data.snapshot_dates)} 个交易日`; status.classList.toggle("connected", Boolean(data.configured)); setText("systemDataStatus", data.background_refresh_enabled ? "后台刷新已启用" : "后台刷新已暂停"); renderDatahubRouteStatus(data.datahub || {}); document.querySelector("#systemBackgroundRefresh").checked = Boolean(data.background_refresh_enabled); } catch (error) { status.textContent = error.message || "系统配置读取失败"; } } function dataHubConsoleUrl() { if (window.XIAOBAI_DATAHUB_URL) return String(window.XIAOBAI_DATAHUB_URL); // HEL-564: 固定内网地址。域名只反代 8765,按主机名推导会拼出打不开的 // <域名>:8766;数据中枢也不该被外网摸到。 return "http://192.168.200.11:8766/admin/"; } function openDataHubConsole() { if (state.user?.role !== "admin") return; window.open(dataHubConsoleUrl(), "_blank", "noopener"); } function renderDatahubRouteStatus(hub) { const box = document.querySelector("#datahubRouteStatus"); if (!box) return; const label = box.querySelector("span"); const enabled = number(hub.enabled_reads); const total = number(hub.total_reads) || enabled; const fallbacks = hub.fallback_labels || []; if (fallbacks.length) { box.dataset.tone = "warning"; if (label) label.textContent = `数据中枢主线路 ${enabled}/${total} · 备用 ${fallbacks.length} 类:${fallbacks.join("、")}`; return; } box.dataset.tone = hub.configured ? "success" : "idle"; if (label) { label.textContent = hub.configured ? `数据中枢主线路 ${enabled}/${total},当前无备用` : "数据中枢未配置,网站只保留已有真实快照"; } } async function saveMarketSettings(event) { event.preventDefault(); const button = event.currentTarget.querySelector("button[type='submit']"); button.disabled = true; try { await apiRequest("/api/admin/settings", "POST", { background_refresh_enabled: document.querySelector("#systemBackgroundRefresh").checked, }); showToast("行情刷新设置已保存"); await openAdminSettings(true); } catch (error) { showToast(error.message || "系统配置保存失败"); } finally { button.disabled = false; } } function bindAdminEvents() { document.querySelector("#settingsButton").addEventListener("click", openDataHubConsole); document.querySelector("#marketAdminButton").addEventListener("click", () => openAdminSettings()); document.querySelector("#closeAdminDialog").addEventListener("click", () => elements.adminDialog.close()); document.querySelector("#backfillButton").addEventListener("click", backfillData); document.querySelector("#systemMarketForm").addEventListener("submit", saveMarketSettings); document.querySelector("#adminRefreshButton").addEventListener("click", startAdminRefresh); }