141 lines
3.9 KiB
JavaScript
141 lines
3.9 KiB
JavaScript
// 赛马竞猜事件监听模块,负责广播事件转发和页面恢复当前场次。
|
|
|
|
/**
|
|
* 读取赛马面板 Alpine 状态。
|
|
*
|
|
* @returns {Record<string, any>|null}
|
|
*/
|
|
function getHorseRacePanelState() {
|
|
const panel = document.getElementById("horse-race-panel");
|
|
|
|
if (!panel || typeof window.Alpine?.$data !== "function") {
|
|
return null;
|
|
}
|
|
|
|
return window.Alpine.$data(panel);
|
|
}
|
|
|
|
/**
|
|
* 读取赛马悬浮按钮 Alpine 状态。
|
|
*
|
|
* @returns {Record<string, any>|null}
|
|
*/
|
|
function getHorseRaceFabState() {
|
|
const fab = document.getElementById("horse-race-fab");
|
|
|
|
if (!fab || typeof window.Alpine?.$data !== "function") {
|
|
return null;
|
|
}
|
|
|
|
return window.Alpine.$data(fab);
|
|
}
|
|
|
|
/**
|
|
* 从当前进行中的场次恢复赛马面板状态。
|
|
*
|
|
* @param {Record<string, any>} panelState 赛马面板 Alpine 状态
|
|
* @param {Record<string, any>} race 当前场次
|
|
* @returns {void}
|
|
*/
|
|
function restoreCurrentHorseRace(panelState, race) {
|
|
const seconds = Number(race.seconds_left || 0);
|
|
|
|
panelState.raceId = race.id;
|
|
panelState.horses = race.horses || [];
|
|
panelState.totalPool = race.total_pool || 0;
|
|
|
|
if (race.my_bet) {
|
|
panelState.myBet = true;
|
|
panelState.myBetHorseId = race.my_bet.horse_id;
|
|
panelState.myBetAmount = race.my_bet.amount;
|
|
|
|
const selectedHorse = panelState.horses.find((horse) => horse.id === race.my_bet.horse_id);
|
|
panelState.myBetHorseName = selectedHorse ? `${selectedHorse.emoji}${selectedHorse.name}` : "";
|
|
}
|
|
|
|
if (race.status === "betting" && seconds > 0) {
|
|
panelState.phase = "betting";
|
|
panelState.countdown = seconds;
|
|
return;
|
|
}
|
|
|
|
panelState.phase = race.status === "running" ? "running" : "settled";
|
|
}
|
|
|
|
/**
|
|
* 没有当前场次时重置赛马面板状态。
|
|
*
|
|
* @param {Record<string, any>} panelState 赛马面板 Alpine 状态
|
|
* @returns {void}
|
|
*/
|
|
function resetHorseRacePanel(panelState) {
|
|
panelState.phase = "idle";
|
|
panelState.raceId = null;
|
|
panelState.horses = [];
|
|
panelState.totalPool = 0;
|
|
panelState.countdown = 0;
|
|
}
|
|
|
|
/**
|
|
* 页面加载后恢复历史记录、金币和当前场次。
|
|
*
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async function restoreHorseRaceOnReady() {
|
|
try {
|
|
const panelState = getHorseRacePanelState();
|
|
|
|
if (!panelState) {
|
|
return;
|
|
}
|
|
|
|
const historyData = await panelState.requestJson("/horse-race/history");
|
|
panelState.history = (historyData.history || []).reverse();
|
|
|
|
const currentData = await panelState.requestJson("/horse-race/current");
|
|
panelState.syncUserGold(currentData.jjb);
|
|
|
|
// 游戏可访问时常驻显示 FAB,方便用户随时打开赛马面板。
|
|
const fabState = getHorseRaceFabState();
|
|
if (fabState) {
|
|
fabState.visible = true;
|
|
}
|
|
|
|
if (currentData.race) {
|
|
restoreCurrentHorseRace(panelState, currentData.race);
|
|
return;
|
|
}
|
|
|
|
resetHorseRacePanel(panelState);
|
|
} catch (error) {
|
|
console.warn("[赛马] 初始化失败", error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 绑定赛马广播事件和页面恢复逻辑。
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
export function bindHorseRaceEvents() {
|
|
if (typeof window === "undefined" || typeof document === "undefined" || window.__horseRaceEventsBound) {
|
|
return;
|
|
}
|
|
|
|
window.__horseRaceEventsBound = true;
|
|
|
|
window.addEventListener("chat:horse.opened", (event) => {
|
|
getHorseRacePanelState()?.openRace(event.detail);
|
|
});
|
|
|
|
window.addEventListener("chat:horse.progress", (event) => {
|
|
getHorseRacePanelState()?.updateProgress(event.detail);
|
|
});
|
|
|
|
window.addEventListener("chat:horse.settled", (event) => {
|
|
getHorseRacePanelState()?.showResult(event.detail);
|
|
});
|
|
|
|
document.addEventListener("DOMContentLoaded", () => window.deferChatGameBootstrap?.(restoreHorseRaceOnReady));
|
|
}
|