// 聊天室共享运行时状态,桥接 Blade 闭包作用域与 Vite 模块。 // 所有需要跨模块共享的可变状态集中在此管理,通过 window.chatState 访问。 export const BLOCKABLE_SYSTEM_SENDERS = ["钓鱼播报", "星海小博士", "百家乐", "跑马", "神秘箱子"]; export const BLOCKED_SYSTEM_SENDERS_STORAGE_KEY = "chat_blocked_system_senders"; export const CHAT_SOUND_MUTED_STORAGE_KEY = "chat_sound_muted"; export const PUBLIC_MESSAGE_NODE_LIMIT = 600; export const PRIVATE_MESSAGE_NODE_LIMIT = 300; export const CHAT_MESSAGE_FLUSH_BATCH_SIZE = 8; export const ROOMS_ONLINE_STATUS_CACHE_TTL = 10000; export const HEARTBEAT_INTERVAL = 60 * 1000; export const SYSTEM_USERS = ["钓鱼播报", "星海小博士", "系统传音", "系统公告", "送花播报", "系统", "欢迎", "系统播报", "神秘箱子"]; // 消息动作文字映射表:情绪型(着/地,放"对"之前)和动作型(了,替换"对X说") export const ACTION_TEXT_MAP = { "微笑": { type: "emotion", word: "微笑着" }, "大笑": { type: "emotion", word: "大笑着" }, "愤怒": { type: "emotion", word: "愤怒地" }, "哭泣": { type: "emotion", word: "哭泣着" }, "害羞": { type: "emotion", word: "害羞地" }, "鄙视": { type: "emotion", word: "鄙视地" }, "得意": { type: "emotion", word: "得意地" }, "疑惑": { type: "emotion", word: "疑惑地" }, "同情": { type: "emotion", word: "同情地" }, "无奈": { type: "emotion", word: "无奈地" }, "拳打": { type: "verb", word: "拳打了" }, "飞吻": { type: "verb", word: "飞吻了" }, "偷看": { type: "verb", word: "偷看了" }, }; // ── DOM 引用(惰性获取,避免模块加载时 DOM 未就绪)── function getContainer() { return document.getElementById("chat-messages-container"); } function getContainer2() { return document.getElementById("chat-messages-container2"); } function getUserList() { return document.getElementById("online-users-list"); } function getToUserSelect() { return document.getElementById("to_user"); } function getOnlineCount() { return document.getElementById("online-count"); } function getOnlineCountBottom() { return document.getElementById("online-count-bottom"); } // ── 可变状态 ── let onlineUsers = {}; let autoScroll = true; let maxMsgId = 0; let pendingChatMessages = []; let chatMessageFlushTimer = null; let userListRenderTimer = null; let userFilterRenderTimer = null; let userBadgeRotationTick = 0; let lastAutosaveNode = null; let roomsRefreshTimer = null; let roomsOnlineStatusCache = null; let roomsOnlineStatusCacheAt = 0; let isMutedUntil = 0; let imeComposing = false; let isSending = false; let sendStartedAt = 0; let leaveRequestInFlight = false; let heartbeatFailCount = 0; const MAX_HEARTBEAT_FAILS = 3; // 偏好状态 let blockedSystemSenders = new Set(); let initialChatPreferences = null; // ── 访问器 ── function getOnlineUsers() { return onlineUsers; } function setOnlineUsers(v) { onlineUsers = v; window.onlineUsers = onlineUsers; } function getAutoScroll() { return autoScroll; } function setAutoScroll(v) { autoScroll = Boolean(v); } function getMaxMsgId() { return maxMsgId; } function setMaxMsgId(v) { if (v > maxMsgId) maxMsgId = v; } function getBlockedSystemSenders() { return blockedSystemSenders; } function setBlockedSystemSenders(v) { blockedSystemSenders = v; } function getIsMutedUntil() { return isMutedUntil; } function setIsMutedUntil(v) { isMutedUntil = v; } // ── 构建聊天状态对象 ── const chatState = { // 常量 BLOCKABLE_SYSTEM_SENDERS, BLOCKED_SYSTEM_SENDERS_STORAGE_KEY, CHAT_SOUND_MUTED_STORAGE_KEY, PUBLIC_MESSAGE_NODE_LIMIT, PRIVATE_MESSAGE_NODE_LIMIT, CHAT_MESSAGE_FLUSH_BATCH_SIZE, ROOMS_ONLINE_STATUS_CACHE_TTL, HEARTBEAT_INTERVAL, SYSTEM_USERS, ACTION_TEXT_MAP, MAX_HEARTBEAT_FAILS, // DOM 引用 get container() { return getContainer(); }, get container2() { return getContainer2(); }, get userList() { return getUserList(); }, get toUserSelect() { return getToUserSelect(); }, get onlineCount() { return getOnlineCount(); }, get onlineCountBottom() { return getOnlineCountBottom(); }, // 在线用户 get onlineUsers() { return onlineUsers; }, set onlineUsers(v) { onlineUsers = v; window.onlineUsers = onlineUsers; }, // 自动滚屏 get autoScroll() { return autoScroll; }, set autoScroll(v) { autoScroll = Boolean(v); }, // 最大消息 ID get maxMsgId() { return maxMsgId; }, set maxMsgId(v) { maxMsgId = v; }, trackMaxMsgId(v) { if (v > maxMsgId) maxMsgId = v; }, // 消息队列 get pendingChatMessages() { return pendingChatMessages; }, set pendingChatMessages(v) { pendingChatMessages = v; }, get chatMessageFlushTimer() { return chatMessageFlushTimer; }, set chatMessageFlushTimer(v) { chatMessageFlushTimer = v; }, // 用户列表渲染 get userListRenderTimer() { return userListRenderTimer; }, set userListRenderTimer(v) { userListRenderTimer = v; }, get userFilterRenderTimer() { return userFilterRenderTimer; }, set userFilterRenderTimer(v) { userFilterRenderTimer = v; }, get userBadgeRotationTick() { return userBadgeRotationTick; }, set userBadgeRotationTick(v) { userBadgeRotationTick = v; }, // 存点节点 get lastAutosaveNode() { return lastAutosaveNode; }, set lastAutosaveNode(v) { lastAutosaveNode = v; }, // 房间在线状态缓存 get roomsRefreshTimer() { return roomsRefreshTimer; }, set roomsRefreshTimer(v) { roomsRefreshTimer = v; }, get roomsOnlineStatusCache() { return roomsOnlineStatusCache; }, set roomsOnlineStatusCache(v) { roomsOnlineStatusCache = v; }, get roomsOnlineStatusCacheAt() { return roomsOnlineStatusCacheAt; }, set roomsOnlineStatusCacheAt(v) { roomsOnlineStatusCacheAt = v; }, // 禁言 get isMutedUntil() { return isMutedUntil; }, set isMutedUntil(v) { isMutedUntil = v; }, // 发送锁 get imeComposing() { return imeComposing; }, set imeComposing(v) { imeComposing = v; }, get isSending() { return isSending; }, set isSending(v) { isSending = v; }, get sendStartedAt() { return sendStartedAt; }, set sendStartedAt(v) { sendStartedAt = v; }, // 退出房间 get leaveRequestInFlight() { return leaveRequestInFlight; }, set leaveRequestInFlight(v) { leaveRequestInFlight = v; }, // 心跳计数 get heartbeatFailCount() { return heartbeatFailCount; }, set heartbeatFailCount(v) { heartbeatFailCount = v; }, // 偏好 get blockedSystemSenders() { return blockedSystemSenders; }, set blockedSystemSenders(v) { blockedSystemSenders = v; }, get initialChatPreferences() { return initialChatPreferences; }, set initialChatPreferences(v) { initialChatPreferences = v; }, // 重置所有状态(用于测试或强制同步) reset() { onlineUsers = {}; window.onlineUsers = onlineUsers; autoScroll = true; maxMsgId = 0; pendingChatMessages = []; chatMessageFlushTimer = null; userListRenderTimer = null; userFilterRenderTimer = null; userBadgeRotationTick = 0; lastAutosaveNode = null; roomsRefreshTimer = null; roomsOnlineStatusCache = null; roomsOnlineStatusCacheAt = 0; isMutedUntil = 0; imeComposing = false; isSending = false; sendStartedAt = 0; leaveRequestInFlight = false; heartbeatFailCount = 0; blockedSystemSenders = new Set(); }, }; // 挂载到 window 供 Blade 脚本及其他模块使用 window.chatState = chatState; // 向后兼容 Blade 中已暴露的 window 接口 export function hydrateOnlineUserPayload(username, payload) { const nextPayload = { ...(onlineUsers[username] || {}) }; // 清除旧状态字段 delete nextPayload.daily_status_key; delete nextPayload.daily_status_label; delete nextPayload.daily_status_icon; delete nextPayload.daily_status_group; delete nextPayload.daily_status_expires_at; onlineUsers[username] = { ...nextPayload, ...payload }; window.onlineUsers = onlineUsers; } window.hydrateOnlineUserPayload = hydrateOnlineUserPayload; export function renderUserList() { // 占位:实际渲染逻辑由 user-list.js 挂载到 window.chatState.renderUserList if (typeof window.renderUserList === "function") { window.renderUserList(); } } export { onlineUsers, autoScroll, maxMsgId };