// AI 厂商后台事件代理,集中管理全局开关、厂商状态、默认厂商和连通性测试。 let adminAiProvidersControlsBound = false; /** * 读取 CSRF 令牌,供后台 AJAX 请求使用。 * * @returns {string} */ function getCsrfToken() { return document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") ?? ""; } /** * 使用后台接口切换状态类请求。 * * @param {string} url * @returns {Promise} */ async function postJson(url) { const response = await fetch(url, { method: "POST", headers: { "X-CSRF-TOKEN": getCsrfToken(), Accept: "application/json", }, }); return response.json(); } /** * 同步聊天机器人总开关按钮与状态文案。 * * @param {HTMLButtonElement} button * @param {boolean} enabled * @returns {void} */ function renderChatBotState(button, enabled) { const knob = button.firstElementChild; const statusText = document.getElementById("chatbot-status-text"); button.classList.toggle("bg-emerald-500", enabled); button.classList.toggle("bg-gray-300", !enabled); knob?.classList.toggle("translate-x-6", enabled); knob?.classList.toggle("translate-x-1", !enabled); if (statusText) { statusText.textContent = enabled ? "已开启" : "已关闭"; statusText.classList.toggle("text-emerald-600", enabled); statusText.classList.toggle("text-gray-400", !enabled); } } /** * 切换全局聊天机器人开关。 * * @param {HTMLButtonElement} button * @returns {Promise} */ async function toggleChatBot(button) { try { const toggleUrl = button.getAttribute("data-ai-chatbot-toggle-url"); if (!toggleUrl) { return; } const data = await postJson(toggleUrl); if (data.status === "success") { renderChatBotState(button, Boolean(data.enabled)); window.alert(data.message); } } catch (error) { window.alert(`操作失败:${error.message}`); } } /** * 切换厂商启用状态,成功后刷新列表。 * * @param {HTMLButtonElement} button * @returns {Promise} */ async function toggleProvider(button) { try { const toggleUrl = button.getAttribute("data-ai-provider-toggle-url"); if (!toggleUrl) { return; } const data = await postJson(toggleUrl); if (data.status === "success") { window.location.reload(); } } catch (error) { window.alert(`操作失败:${error.message}`); } } /** * 将当前厂商设为默认,成功后刷新列表。 * * @param {HTMLButtonElement} button * @returns {Promise} */ async function setDefaultProvider(button) { try { const defaultUrl = button.getAttribute("data-ai-provider-default-url"); if (!defaultUrl) { return; } const data = await postJson(defaultUrl); if (data.status === "success") { window.location.reload(); } } catch (error) { window.alert(`操作失败:${error.message}`); } } /** * 测试 AI 厂商接口连通性,并恢复按钮状态。 * * @param {HTMLButtonElement} button * @returns {Promise} */ async function testProviderConnection(button) { const testUrl = button.getAttribute("data-ai-provider-test-url"); const providerName = button.getAttribute("data-ai-provider-name") ?? "AI 厂商"; if (!testUrl) { return; } const originalText = button.textContent; button.textContent = "测试中…"; button.disabled = true; try { const data = await postJson(testUrl); if (data.ok) { window.alert(`✅ 「${providerName}」 连通成功!\n⤵ 响应耗时:${data.ms}ms(包含冷启动)\n🤖 模型回复:${data.message}`); } else { window.alert(`❌ 「${providerName}」 连通失败!\n耗时:${data.ms}ms\n错误:${data.message}`); } } catch (error) { window.alert(`请求异常:${error.message}`); } finally { button.textContent = originalText; button.disabled = false; } } /** * 绑定 AI 厂商后台页操作。 * * @returns {void} */ export function bindAdminAiProvidersControls() { if (adminAiProvidersControlsBound || typeof document === "undefined") { return; } adminAiProvidersControlsBound = true; document.addEventListener("click", (event) => { if (!(event.target instanceof Element)) { return; } const chatBotToggle = event.target.closest("[data-ai-chatbot-toggle-url]"); if (chatBotToggle instanceof HTMLButtonElement) { event.preventDefault(); void toggleChatBot(chatBotToggle); return; } const providerToggle = event.target.closest("[data-ai-provider-toggle-url]"); if (providerToggle instanceof HTMLButtonElement) { event.preventDefault(); void toggleProvider(providerToggle); return; } const defaultButton = event.target.closest("[data-ai-provider-default-url]"); if (defaultButton instanceof HTMLButtonElement) { event.preventDefault(); void setDefaultProvider(defaultButton); return; } const testButton = event.target.closest("[data-ai-provider-test-url]"); if (testButton instanceof HTMLButtonElement) { event.preventDefault(); void testProviderConnection(testButton); } }); }