迁移房间列表跳转事件

This commit is contained in:
2026-04-25 10:32:25 +08:00
parent 83fff919a5
commit 20317f4699
2 changed files with 50 additions and 9 deletions
+4
View File
@@ -62,6 +62,7 @@ export {
} from "./chat-room/preferences-status.js"; } from "./chat-room/preferences-status.js";
export { bindChatRightPanelControls } from "./chat-room/right-panel.js"; export { bindChatRightPanelControls } from "./chat-room/right-panel.js";
export { export {
bindRoomStatusControls,
normalizeRoomStatus, normalizeRoomStatus,
renderRoomStatusRow, renderRoomStatusRow,
renderRoomsOnlineStatus, renderRoomsOnlineStatus,
@@ -131,6 +132,7 @@ import {
} from "./chat-room/preferences-status.js"; } from "./chat-room/preferences-status.js";
import { bindChatRightPanelControls } from "./chat-room/right-panel.js"; import { bindChatRightPanelControls } from "./chat-room/right-panel.js";
import { import {
bindRoomStatusControls,
normalizeRoomStatus, normalizeRoomStatus,
renderRoomStatusRow, renderRoomStatusRow,
renderRoomsOnlineStatus, renderRoomsOnlineStatus,
@@ -207,6 +209,7 @@ if (typeof window !== "undefined") {
setSoundMuted, setSoundMuted,
shouldMigrateLocalChatPreferences, shouldMigrateLocalChatPreferences,
bindChatRightPanelControls, bindChatRightPanelControls,
bindRoomStatusControls,
normalizeRoomStatus, normalizeRoomStatus,
renderRoomStatusRow, renderRoomStatusRow,
renderRoomsOnlineStatus, renderRoomsOnlineStatus,
@@ -261,6 +264,7 @@ if (typeof window !== "undefined") {
bindShopControls(); bindShopControls();
bindVipControls(); bindVipControls();
bindChatRightPanelControls(); bindChatRightPanelControls();
bindRoomStatusControls();
bindMobileDrawerControls(); bindMobileDrawerControls();
bindWelcomeMenuControls(); bindWelcomeMenuControls();
bindBlockMenuControls(); bindBlockMenuControls();
+46 -9
View File
@@ -6,6 +6,9 @@ import { escapeHtml } from "./html.js";
const EMPTY_ROOMS_HTML = const EMPTY_ROOMS_HTML =
'<div style="text-align:center;color:#bbb;padding:16px 0;font-size:11px;">暂无房间</div>'; '<div style="text-align:center;color:#bbb;padding:16px 0;font-size:11px;">暂无房间</div>';
// 事件委托只需要注册一次,避免房间在线状态定时刷新后重复绑定。
let roomStatusControlsBound = false;
/** /**
* 转换接口房间数据,过滤异常房间编号。 * 转换接口房间数据,过滤异常房间编号。
* *
@@ -39,18 +42,52 @@ export function resolveRoomUrl(roomId, roomUrlResolver = undefined) {
} }
/** /**
* 生成可放入 onclick 属性的安全跳转语句 * 生成房间跳转数据属性,实际跳转由事件委托统一处理
* 这里暂时保留属性字符串,是为了兼容现有 HTML 字符串渲染入口 * 只输出 data 属性,避免在线房间列表继续混入内联 onclick
* URL 先 JSON 字符串化再转义,避免地址内容突破属性上下文。
* *
* @param {number} roomId * @param {number} roomId
* @param {(roomId:number) => string} [roomUrlResolver] * @param {(roomId:number) => string} [roomUrlResolver]
* @returns {string} * @returns {string}
*/ */
function buildRoomClickHandler(roomId, roomUrlResolver = undefined) { function buildRoomClickAttributes(roomId, roomUrlResolver = undefined) {
const safeUrlLiteral = escapeHtml(JSON.stringify(resolveRoomUrl(roomId, roomUrlResolver))); const safeUrl = escapeHtml(resolveRoomUrl(roomId, roomUrlResolver));
return `onclick="location.href=${safeUrlLiteral}"`; return `data-room-url="${safeUrl}"`;
}
/**
* 绑定房间列表跳转事件。
* 右侧面板和手机抽屉都复用 data-room-url,刷新 HTML 后无需重新绑定。
*
* @returns {void}
*/
export function bindRoomStatusControls() {
if (roomStatusControlsBound || typeof document === "undefined") {
return;
}
roomStatusControlsBound = true;
document.addEventListener("click", (event) => {
if (!(event.target instanceof Element)) {
return;
}
const roomLink = event.target.closest("[data-room-url]");
if (!roomLink) {
return;
}
const roomUrl = roomLink.getAttribute("data-room-url");
if (!roomUrl) {
return;
}
event.preventDefault();
window.location.href = roomUrl;
});
} }
/** /**
@@ -73,14 +110,14 @@ export function renderRoomStatusRow(room, options = {}) {
: '<span style="font-size:9px;color:#336699;opacity:.7;margin-left:3px;">当前</span>') : '<span style="font-size:9px;color:#336699;opacity:.7;margin-left:3px;">当前</span>')
: ""; : "";
// 当前房间不生成跳转事件,避免重复进入同一房间触发无意义刷新。 // 当前房间不生成跳转事件,避免重复进入同一房间触发无意义刷新。
const clickHandler = isCurrent ? "" : buildRoomClickHandler(room.id, options.roomUrlResolver); const clickAttributes = isCurrent ? "" : buildRoomClickAttributes(room.id, options.roomUrlResolver);
const badge = room.online > 0 const badge = room.online > 0
? `<span style="background:#e8f5e9;color:#2e7d32;border-radius:8px;padding:0 ${variant === "mobile" ? "6px" : "5px"};font-size:10px;font-weight:bold;white-space:nowrap;flex-shrink:0;">${room.online}${variant === "mobile" ? "" : " "}人</span>` ? `<span style="background:#e8f5e9;color:#2e7d32;border-radius:8px;padding:0 ${variant === "mobile" ? "6px" : "5px"};font-size:10px;font-weight:bold;white-space:nowrap;flex-shrink:0;">${room.online}${variant === "mobile" ? "" : " "}人</span>`
: `<span style="background:#f5f5f5;color:#bbb;border-radius:8px;padding:0 ${variant === "mobile" ? "6px" : "5px"};font-size:10px;white-space:nowrap;flex-shrink:0;">空</span>`; : `<span style="background:#f5f5f5;color:#bbb;border-radius:8px;padding:0 ${variant === "mobile" ? "6px" : "5px"};font-size:10px;white-space:nowrap;flex-shrink:0;">空</span>`;
// 手机和桌面只区分容器尺寸与视觉密度,房间数据口径保持同一套。 // 手机和桌面只区分容器尺寸与视觉密度,房间数据口径保持同一套。
if (variant === "mobile") { if (variant === "mobile") {
return `<div ${clickHandler} return `<div ${clickAttributes}
style="display:flex;align-items:center;justify-content:space-between; style="display:flex;align-items:center;justify-content:space-between;
padding:6px 10px;border-bottom:1px solid #eef2f8;background:${bg}; padding:6px 10px;border-bottom:1px solid #eef2f8;background:${bg};
cursor:${isCurrent ? "default" : "pointer"};"> cursor:${isCurrent ? "default" : "pointer"};">
@@ -92,7 +129,7 @@ export function renderRoomStatusRow(room, options = {}) {
const border = isCurrent ? "#aac5f0" : "#e0eaf5"; const border = isCurrent ? "#aac5f0" : "#e0eaf5";
return `<div ${clickHandler} return `<div ${clickAttributes}
style="display:flex;align-items:center;justify-content:space-between; style="display:flex;align-items:center;justify-content:space-between;
padding:5px 8px;margin:2px 3px;border-radius:5px; padding:5px 8px;margin:2px 3px;border-radius:5px;
border:1px solid ${border};background:${bg}; border:1px solid ${border};background:${bg};