From 414dc52a3b40d5e090743ba2fc505ff45543fe92 Mon Sep 17 00:00:00 2001 From: lkddi Date: Sat, 25 Apr 2026 15:03:33 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E7=99=BE=E5=AE=B6=E4=B9=90?= =?UTF-8?q?=E6=82=AC=E6=B5=AE=E6=8C=89=E9=92=AE=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/js/chat-room.js | 7 + resources/js/chat-room/baccarat-fab.js | 131 ++++++++++++++++++ .../partials/games/baccarat-panel.blade.php | 63 +-------- 3 files changed, 139 insertions(+), 62 deletions(-) create mode 100644 resources/js/chat-room/baccarat-fab.js diff --git a/resources/js/chat-room.js b/resources/js/chat-room.js index ca939d8..5c03798 100644 --- a/resources/js/chat-room.js +++ b/resources/js/chat-room.js @@ -23,6 +23,7 @@ * - user-target-actions.js:处理点击用户名切换私聊目标和打开名片。 * - welcome-menu.js:处理欢迎菜单交互。 * - admin-menu.js:处理聊天室管理菜单交互。 + * - baccarat-fab.js:处理百家乐悬浮按钮拖动与打开面板。 * - baccarat-loss-cover-admin.js:处理百家乐买单活动管理弹层。 * - baccarat-loss-cover.js:处理百家乐买单活动前台弹窗。 * - game-hall.js:处理娱乐大厅弹窗和游戏入口卡片。 @@ -86,6 +87,7 @@ export { bindToolbarControls, runFeatureShortcut, runToolbarAction } from "./cha export { bindUserTargetActions, openUserCard, switchTarget } from "./chat-room/user-target-actions.js"; export { bindWelcomeMenuControls } from "./chat-room/welcome-menu.js"; export { bindAdminMenuControls } from "./chat-room/admin-menu.js"; +export { baccaratFab, bindBaccaratFabControls } from "./chat-room/baccarat-fab.js"; export { bindBaccaratLossCoverAdminControls, closeAdminBaccaratLossCoverModal, @@ -229,6 +231,7 @@ import { bindToolbarControls, runFeatureShortcut, runToolbarAction } from "./cha import { bindUserTargetActions, openUserCard, switchTarget } from "./chat-room/user-target-actions.js"; import { bindWelcomeMenuControls } from "./chat-room/welcome-menu.js"; import { bindAdminMenuControls } from "./chat-room/admin-menu.js"; +import { baccaratFab, bindBaccaratFabControls } from "./chat-room/baccarat-fab.js"; import { bindBaccaratLossCoverAdminControls, closeAdminBaccaratLossCoverModal, @@ -382,6 +385,8 @@ if (typeof window !== "undefined") { switchTarget, bindWelcomeMenuControls, bindAdminMenuControls, + baccaratFab, + bindBaccaratFabControls, bindBaccaratLossCoverAdminControls, closeAdminBaccaratLossCoverModal, closeCurrentBaccaratLossCoverEvent, @@ -523,6 +528,7 @@ if (typeof window !== "undefined") { window.scheduleRenderMobileUserList = scheduleRenderMobileUserList; window.switchMobileTab = switchMobileTab; window.switchTarget = switchTarget; + window.baccaratFab = baccaratFab; window.clearChatBotContext = clearChatBotContext; window.sendToChatBot = sendToChatBot; window.slotFab = slotFab; @@ -626,6 +632,7 @@ if (typeof window !== "undefined") { bindToolbarControls(); bindUserTargetActions(); bindAdminMenuControls(); + bindBaccaratFabControls(); bindBaccaratLossCoverAdminControls(); bindBaccaratLossCoverControls(); bindGameHallControls(); diff --git a/resources/js/chat-room/baccarat-fab.js b/resources/js/chat-room/baccarat-fab.js new file mode 100644 index 0000000..99d3c61 --- /dev/null +++ b/resources/js/chat-room/baccarat-fab.js @@ -0,0 +1,131 @@ +// 乐彩百家乐悬浮按钮组件,负责拖动位置持久化和打开游戏面板。 + +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; +} diff --git a/resources/views/chat/partials/games/baccarat-panel.blade.php b/resources/views/chat/partials/games/baccarat-panel.blade.php index b663a95..2891a4d 100644 --- a/resources/views/chat/partials/games/baccarat-panel.blade.php +++ b/resources/views/chat/partials/games/baccarat-panel.blade.php @@ -333,68 +333,7 @@ - +{{-- 乐彩百家乐悬浮按钮脚本已迁移到 resources/js/chat-room/baccarat-fab.js --}}