Files
chatroom/resources/js/admin/ai-providers.js
T
2026-04-25 13:35:20 +08:00

199 lines
5.5 KiB
JavaScript

// AI 厂商后台事件代理,集中管理全局开关、厂商状态、默认厂商和连通性测试。
let adminAiProvidersControlsBound = false;
/**
* 读取 CSRF 令牌,供后台 AJAX 请求使用。
*
* @returns {string}
*/
function getCsrfToken() {
return document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") ?? "";
}
/**
* 使用后台接口切换状态类请求。
*
* @param {string} url
* @returns {Promise<object>}
*/
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<void>}
*/
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<void>}
*/
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<void>}
*/
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<void>}
*/
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);
}
});
}