// 聊天室神秘占卜游戏面板,提供 fortunePanel Alpine 组件和空闲初始化。 /** * 读取 CSRF Token。 * * @returns {string} */ function csrf() { return document.querySelector("meta[name=csrf-token]")?.content || ""; } /** * 创建神秘占卜面板 Alpine 组件。 * * @returns {object} */ export function fortunePanel() { return { show: false, activeTab: "tell", loading: false, shaking: false, freeCount: 1, freeUsed: 0, hasFreeLeft: true, extraCost: 500, todayLatest: null, resultGrade: "", resultLabel: "", resultColor: "#a855f7", resultText: "", resultBuff: null, historyLogs: [], /** * 加载今日占卜状态。 * * @returns {Promise} */ async loadTodayStatus() { try { const response = await fetch("/fortune/today"); const data = await response.json(); if (!data.enabled) { return; } this.freeCount = data.free_count || 1; this.freeUsed = data.free_used || 0; this.hasFreeLeft = data.has_free_left ?? true; this.extraCost = data.extra_cost || 500; this.todayLatest = data.latest || null; } catch (error) { // 占卜状态失败不影响聊天室主流程。 } }, /** * 执行一次占卜。 * * @returns {Promise} */ async doFortune() { if (this.loading) { return; } this.loading = true; this.shaking = true; // 摇卦动画先播放,再请求服务端结果,保持旧版节奏。 await new Promise((resolve) => window.setTimeout(resolve, 600)); this.shaking = false; try { const response = await fetch("/fortune/tell", { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json", "X-CSRF-TOKEN": csrf(), }, }); const data = await response.json(); if (data.ok) { this.resultGrade = data.grade; this.resultLabel = data.grade_label; this.resultColor = data.grade_color; this.resultText = data.text; this.resultBuff = data.buff_desc; // 免费次数只在服务端确认免费占卜成功后本地递增。 if (data.is_free) { this.freeUsed += 1; this.hasFreeLeft = this.freeUsed < this.freeCount; } return; } window.chatDialog?.alert?.(data.message || "占卜失败", "提示", "#ef4444"); } catch (error) { window.chatDialog?.alert?.("网络异常,请稍后重试。", "错误", "#ef4444"); } finally { this.loading = false; } }, /** * 加载占卜历史记录。 * * @returns {Promise} */ async loadHistory() { if (this.historyLogs.length > 0) { return; } try { const response = await fetch("/fortune/history"); const data = await response.json(); this.historyLogs = data.history || []; } catch (error) { this.historyLogs = []; } }, }; } /** * 空闲时预加载今日占卜状态。 * * @returns {void} */ function scheduleFortuneBootstrap() { document.addEventListener("DOMContentLoaded", () => window.deferChatGameBootstrap?.(async () => { try { const response = await fetch("/fortune/today"); const data = await response.json(); if (!data.enabled) { return; } const panel = document.getElementById("fortune-panel"); if (!panel || !window.Alpine) { return; } const panelData = window.Alpine.$data(panel); panelData.freeCount = data.free_count || 1; panelData.freeUsed = data.free_used || 0; panelData.hasFreeLeft = data.has_free_left ?? true; panelData.extraCost = data.extra_cost || 500; panelData.todayLatest = data.latest || null; } catch (error) { console.warn("[神秘占卜] 初始化失败", error); } })); } /** * 绑定神秘占卜全局 Alpine 工厂函数。 * * @returns {void} */ export function bindFortunePanelControls() { if (typeof window === "undefined") { return; } window.fortunePanel = fortunePanel; scheduleFortuneBootstrap(); }