diff --git a/resources/js/chat-room.js b/resources/js/chat-room.js index 55c9a83..9c9ae61 100644 --- a/resources/js/chat-room.js +++ b/resources/js/chat-room.js @@ -7,7 +7,16 @@ export { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, res export { bindChatImageUploadControl } from "./chat-room/image-upload.js"; export { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel } from "./chat-room/friend-panel.js"; export { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js"; -export { bindMobileDrawerControls } from "./chat-room/mobile-drawer.js"; +export { + bindMobileDrawerControls, + closeMobileDrawer, + loadMobileRoomList, + openMobileDrawer, + renderMobileRoomList, + renderMobileUserList, + scheduleRenderMobileUserList, + switchMobileTab, +} from "./chat-room/mobile-drawer.js"; export { bindMarriageStatusControls } from "./chat-room/marriage-status.js"; export { bindToolbarControls } from "./chat-room/toolbar.js"; export { bindWelcomeMenuControls } from "./chat-room/welcome-menu.js"; @@ -66,7 +75,16 @@ import { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, res import { bindChatImageUploadControl } from "./chat-room/image-upload.js"; import { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel } from "./chat-room/friend-panel.js"; import { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js"; -import { bindMobileDrawerControls } from "./chat-room/mobile-drawer.js"; +import { + bindMobileDrawerControls, + closeMobileDrawer, + loadMobileRoomList, + openMobileDrawer, + renderMobileRoomList, + renderMobileUserList, + scheduleRenderMobileUserList, + switchMobileTab, +} from "./chat-room/mobile-drawer.js"; import { bindMarriageStatusControls } from "./chat-room/marriage-status.js"; import { bindToolbarControls } from "./chat-room/toolbar.js"; import { bindWelcomeMenuControls } from "./chat-room/welcome-menu.js"; @@ -134,6 +152,13 @@ if (typeof window !== "undefined") { loadFriends, openFriendPanel, bindMobileDrawerControls, + closeMobileDrawer, + loadMobileRoomList, + openMobileDrawer, + renderMobileRoomList, + renderMobileUserList, + scheduleRenderMobileUserList, + switchMobileTab, bindToolbarControls, bindWelcomeMenuControls, bindAdminMenuControls, @@ -190,6 +215,13 @@ if (typeof window !== "undefined") { window.closeFriendPanel = closeFriendPanel; window.friendSearch = friendSearch; window.openFriendPanel = openFriendPanel; + window.closeMobileDrawer = closeMobileDrawer; + window.loadMobileRoomList = loadMobileRoomList; + window.openMobileDrawer = openMobileDrawer; + window.renderMobileRoomList = renderMobileRoomList; + window.renderMobileUserList = renderMobileUserList; + window.scheduleRenderMobileUserList = scheduleRenderMobileUserList; + window.switchMobileTab = switchMobileTab; window.closeAdminBaccaratLossCoverModal = closeAdminBaccaratLossCoverModal; window.closeCurrentBaccaratLossCoverEvent = closeCurrentBaccaratLossCoverEvent; window.openAdminBaccaratLossCoverModal = openAdminBaccaratLossCoverModal; diff --git a/resources/js/chat-room/mobile-drawer.js b/resources/js/chat-room/mobile-drawer.js index 4f3f187..797f928 100644 --- a/resources/js/chat-room/mobile-drawer.js +++ b/resources/js/chat-room/mobile-drawer.js @@ -1,6 +1,15 @@ -// 手机端抽屉基础控件事件绑定,替代浮动按钮、关闭按钮与名单 tab 的内联事件。 +// 手机端抽屉业务模块,承接工具菜单、在线名单和房间列表的 Blade 内联脚本。 + +import { escapeHtml } from "./html.js"; +import { renderRoomsOnlineStatusToContainer } from "./rooms.js"; let mobileDrawerEventsBound = false; +let mobileDrawerOpen = null; +let mobileUserListRenderTimer = null; +let mobileRoomsOnlineStatusCache = null; +let mobileRoomsOnlineStatusCacheAt = 0; + +const MOBILE_ROOMS_ONLINE_STATUS_CACHE_TTL = 10000; /** * 执行手机抽屉工具入口动作。 @@ -26,6 +35,7 @@ function runMobileToolAction(action) { return; } + // 兼容设置弹窗尚未迁移为全局函数的页面。 const settingsModal = document.getElementById("settings-modal"); if (settingsModal) { settingsModal.style.display = "flex"; @@ -52,6 +62,208 @@ function confirmMobileLeaveRoom() { }); } +/** + * 打开指定手机端抽屉。 + * + * @param {"toolbar"|"users"|string} which 抽屉名称 + * @returns {void} + */ +export function openMobileDrawer(which) { + if (!["toolbar", "users"].includes(which)) { + return; + } + + // 切换抽屉时只关闭旧面板,不恢复 body overflow,避免中间态闪烁。 + if (mobileDrawerOpen && mobileDrawerOpen !== which) { + document.getElementById(`mobile-drawer-${mobileDrawerOpen}`)?.classList.remove("open"); + } + + const drawer = document.getElementById(`mobile-drawer-${which}`); + const mask = document.getElementById("mobile-drawer-mask"); + if (!drawer || !mask) { + return; + } + + drawer.classList.add("open"); + mask.classList.add("open"); + mobileDrawerOpen = which; + document.body.style.overflow = "hidden"; + + if (which === "users") { + renderMobileUserList(); + } +} + +/** + * 关闭当前打开的手机端抽屉。 + * + * @param {boolean} resetOverflow 是否恢复 body overflow + * @returns {void} + */ +export function closeMobileDrawer(resetOverflow = true) { + if (mobileDrawerOpen) { + document.getElementById(`mobile-drawer-${mobileDrawerOpen}`)?.classList.remove("open"); + mobileDrawerOpen = null; + } + + document.getElementById("mobile-drawer-mask")?.classList.remove("open"); + if (resetOverflow) { + document.body.style.overflow = ""; + } +} + +/** + * 切换名单抽屉内的用户/房间 Tab。 + * + * @param {"users"|"rooms"|string} tab Tab 名称 + * @returns {void} + */ +export function switchMobileTab(tab) { + if (!["users", "rooms"].includes(tab)) { + return; + } + + const panelUsers = document.getElementById("mob-panel-users"); + const panelRooms = document.getElementById("mob-panel-rooms"); + const tabUsers = document.getElementById("mob-tab-users"); + const tabRooms = document.getElementById("mob-tab-rooms"); + + if (panelUsers) { + panelUsers.style.display = tab === "users" ? "flex" : "none"; + } + if (panelRooms) { + panelRooms.style.display = tab === "rooms" ? "block" : "none"; + } + + syncMobileTabButton(tabUsers, tab === "users"); + syncMobileTabButton(tabRooms, tab === "rooms"); + + if (tab === "rooms") { + void loadMobileRoomList(); + } +} + +/** + * 同步手机抽屉 Tab 按钮选中样式。 + * + * @param {HTMLElement|null} button 按钮元素 + * @param {boolean} active 是否选中 + * @returns {void} + */ +function syncMobileTabButton(button, active) { + if (!button) { + return; + } + + button.style.background = active ? "#336699" : "transparent"; + button.style.color = active ? "#fff" : "#336699"; + button.style.fontWeight = active ? "bold" : "normal"; +} + +/** + * 将在线用户渲染到手机端名单容器。 + * + * @returns {void} + */ +export function renderMobileUserList() { + const onlineUsers = window.onlineUsers; + if (!onlineUsers || typeof onlineUsers !== "object") { + return; + } + + const sortValue = document.getElementById("mob-user-sort-select")?.value || "default"; + const keyword = (document.getElementById("mob-user-search-input")?.value || "").trim().toLowerCase(); + const container = document.getElementById("mob-online-users-list"); + if (!container) { + return; + } + + if (typeof window._renderUserListToContainer === "function") { + window._renderUserListToContainer(container, sortValue, keyword); + } else { + // 降级渲染只展示用户名,保障主渲染函数异常缺失时手机名单仍可用。 + const users = Object.keys(onlineUsers); + container.innerHTML = users.length + ? users + .filter((username) => !keyword || username.toLowerCase().includes(keyword)) + .map((username) => `