迁移手机抽屉脚本到Vite模块

This commit is contained in:
2026-04-25 08:21:30 +08:00
parent 2f09d5e2ed
commit 308e5690fe
4 changed files with 266 additions and 238 deletions
+34 -2
View File
@@ -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;
+227 -8
View File
@@ -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) => `<div class="user-item" style="padding:5px 8px;font-size:12px;border-bottom:1px solid #eee;">${escapeHtml(username)}</div>`)
.join("")
: '<div style="text-align:center;color:#aaa;padding:20px;font-size:12px;">暂无用户</div>';
}
const footerElement = document.getElementById("mob-online-count-footer");
if (footerElement) {
footerElement.textContent = Object.keys(onlineUsers).length;
}
}
/**
* 调度手机端在线名单渲染,避免搜索输入时同步重建整份名单。
*
* @returns {void}
*/
export function scheduleRenderMobileUserList() {
if (mobileUserListRenderTimer !== null) {
return;
}
const scheduleRender = window.requestAnimationFrame || ((callback) => window.setTimeout(callback, 16));
mobileUserListRenderTimer = scheduleRender(() => {
mobileUserListRenderTimer = null;
renderMobileUserList();
});
}
/**
* 拉取房间列表并渲染到手机端房间容器。
*
* @returns {Promise<void>}
*/
export async function loadMobileRoomList() {
const container = document.getElementById("mob-rooms-online-list");
if (!container) {
return;
}
if (mobileRoomsOnlineStatusCache && Date.now() - mobileRoomsOnlineStatusCacheAt < MOBILE_ROOMS_ONLINE_STATUS_CACHE_TTL) {
renderMobileRoomList(mobileRoomsOnlineStatusCache, container);
return;
}
const statusUrl = container.getAttribute("data-mobile-rooms-status-url") || "";
if (!statusUrl) {
container.innerHTML = '<div style="text-align:center;color:#f00;padding:10px;font-size:11px;">缺少房间接口</div>';
return;
}
container.innerHTML = '<div style="text-align:center;color:#aaa;padding:16px;font-size:11px;">加载中...</div>';
try {
const response = await fetch(statusUrl);
const data = await response.json();
mobileRoomsOnlineStatusCache = data;
mobileRoomsOnlineStatusCacheAt = Date.now();
renderMobileRoomList(data, container);
} catch (error) {
container.innerHTML = '<div style="text-align:center;color:#f00;padding:10px;font-size:11px;">加载失败</div>';
}
}
/**
* 渲染手机端房间列表。
*
* @param {Record<string, unknown>} data 接口返回数据
* @param {HTMLElement} container 目标容器
* @returns {void}
*/
export function renderMobileRoomList(data, container) {
renderRoomsOnlineStatusToContainer(data, container, {
currentRoomId: window.chatContext?.roomId,
variant: "mobile",
emptyHtml: '<div style="text-align:center;color:#bbb;padding:16px;font-size:11px;">暂无房间</div>',
});
}
/**
* 绑定手机端抽屉基础控件事件。
*
@@ -68,23 +280,24 @@ export function bindMobileDrawerControls() {
return;
}
// 手机抽屉内多数节点由 Blade 与后续 AJAX 动态生成,统一使用 document 事件代理。
const drawerTrigger = event.target.closest("[data-mobile-drawer-open]");
if (drawerTrigger) {
event.preventDefault();
window.openMobileDrawer?.(drawerTrigger.dataset.mobileDrawerOpen);
openMobileDrawer(drawerTrigger.dataset.mobileDrawerOpen || "");
return;
}
if (event.target.closest("[data-mobile-drawer-close]")) {
event.preventDefault();
window.closeMobileDrawer?.();
closeMobileDrawer();
return;
}
const toolAction = event.target.closest("[data-mobile-tool-action]");
if (toolAction) {
event.preventDefault();
window.closeMobileDrawer?.();
closeMobileDrawer();
const action = toolAction.getAttribute("data-mobile-tool-action") || "";
if (action === "leave") {
@@ -99,7 +312,7 @@ export function bindMobileDrawerControls() {
const toolUrl = event.target.closest("[data-mobile-tool-url]");
if (toolUrl) {
event.preventDefault();
window.closeMobileDrawer?.();
closeMobileDrawer();
const url = toolUrl.getAttribute("data-mobile-tool-url");
if (url) {
@@ -112,7 +325,7 @@ export function bindMobileDrawerControls() {
const tabTrigger = event.target.closest("[data-mobile-drawer-tab]");
if (tabTrigger) {
event.preventDefault();
window.switchMobileTab?.(tabTrigger.dataset.mobileDrawerTab);
switchMobileTab(tabTrigger.dataset.mobileDrawerTab || "");
}
});
@@ -121,7 +334,7 @@ export function bindMobileDrawerControls() {
return;
}
window.renderMobileUserList?.();
renderMobileUserList();
});
document.addEventListener("input", (event) => {
@@ -129,6 +342,12 @@ export function bindMobileDrawerControls() {
return;
}
window.scheduleRenderMobileUserList?.();
scheduleRenderMobileUserList();
});
window.addEventListener("chatroom:users-updated", () => {
if (mobileDrawerOpen === "users") {
renderMobileUserList();
}
});
}