// 乐彩百家乐悬浮按钮组件,负责拖动位置持久化和打开游戏面板。 const BACCARAT_FAB_STORAGE_KEY = "baccarat_fab_pos"; /** * 安全读取悬浮按钮上次保存的位置。 * * @returns {{x?: number, y?: number}|null} */ function readSavedBaccaratFabPosition() { try { return JSON.parse(localStorage.getItem(BACCARAT_FAB_STORAGE_KEY) || "null"); } catch (error) { return null; } } /** * 创建百家乐悬浮按钮 Alpine 组件。 * * @returns {Record} */ export function baccaratFab() { const saved = readSavedBaccaratFabPosition(); return { visible: false, posX: saved?.x ?? 18, posY: saved?.y ?? 90, dragging: false, _startX: 0, _startY: 0, _origX: 0, _origY: 0, _moved: false, /** * 开始拖动悬浮按钮。 * * @param {PointerEvent} event 指针事件 * @returns {void} */ startDrag(event) { this.dragging = true; this._moved = false; this._startX = event.clientX; this._startY = event.clientY; this._origX = this.posX; this._origY = this.posY; event.currentTarget.setPointerCapture?.(event.pointerId); }, /** * 拖动过程中约束按钮不超出视口。 * * @param {PointerEvent} event 指针事件 * @returns {void} */ onDrag(event) { if (!this.dragging) { return; } const dx = event.clientX - this._startX; const dy = event.clientY - this._startY; if (Math.abs(dx) > 3 || Math.abs(dy) > 3) { this._moved = true; } this.posX = Math.max(4, Math.min(window.innerWidth - 60, this._origX - dx)); this.posY = Math.max(4, Math.min(window.innerHeight - 60, this._origY + dy)); }, /** * 结束拖动;没有移动时按点击处理并打开面板。 * * @returns {void} */ endDrag() { if (!this.dragging) { return; } this.dragging = false; localStorage.setItem(BACCARAT_FAB_STORAGE_KEY, JSON.stringify({ x: this.posX, y: this.posY, })); if (!this._moved) { this.openPanel(); } }, /** * 打开百家乐面板,并恢复当前局倒计时。 * * @returns {void} */ openPanel() { const panel = document.getElementById("baccarat-panel"); if (!panel || typeof window.Alpine?.$data !== "function") { return; } const panelState = window.Alpine.$data(panel); panelState.show = true; panelState.loadCurrentRound(); // 重新打开面板时,如果仍在下注阶段,需要恢复本地倒计时。 if (panelState.phase === "betting" && panelState.countdown > 0 && !panelState.countdownTimer) { panelState.startCountdown(); } }, }; } /** * 挂载百家乐悬浮按钮全局组件名,兼容 Blade 的 x-data。 * * @returns {void} */ export function bindBaccaratFabControls() { if (typeof window === "undefined") { return; } window.baccaratFab = baccaratFab; }