新增 屏蔽消息功能
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
6. 钓鱼小游戏(startFishing / reelFish / autoFish)
|
||||
7. 发送消息(sendMessage,IME 防重触发)
|
||||
8. 特效控制(triggerEffect / applyFontSize / toggleSoundMute)
|
||||
9. 系统播报屏蔽(toggleBlockMenu / toggleBlockedSystemSender)
|
||||
|
||||
已拆分至独立文件:
|
||||
- window.chatBanner → chat-banner.blade.php
|
||||
@@ -36,6 +37,8 @@
|
||||
const toUserSelect = document.getElementById('to_user');
|
||||
const onlineCount = document.getElementById('online-count');
|
||||
const onlineCountBottom = document.getElementById('online-count-bottom');
|
||||
const BLOCKED_SYSTEM_SENDERS_STORAGE_KEY = 'chat_blocked_system_senders';
|
||||
const BLOCKABLE_SYSTEM_SENDERS = ['钓鱼播报', '星海小博士'];
|
||||
|
||||
// ── 消息区:手机端双触发打开用户名片(PC 端靠 ondblclick 内联属性)──
|
||||
// span[data-u] 由 clickableUser() 生成,touchend 委托至容器避免每条消息单独绑定
|
||||
@@ -67,6 +70,133 @@
|
||||
let onlineUsers = {};
|
||||
let autoScroll = true;
|
||||
let _maxMsgId = 0; // 记录当前收到的最大消息 ID
|
||||
let blockedSystemSenders = new Set(loadBlockedSystemSenders());
|
||||
|
||||
/**
|
||||
* 从 localStorage 读取已屏蔽的系统播报发送者列表。
|
||||
*
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function loadBlockedSystemSenders() {
|
||||
try {
|
||||
const saved = JSON.parse(localStorage.getItem(BLOCKED_SYSTEM_SENDERS_STORAGE_KEY) || '[]');
|
||||
if (!Array.isArray(saved)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 仅允许白名单内的系统播报项进入配置,避免脏数据污染。
|
||||
return saved.filter(sender => BLOCKABLE_SYSTEM_SENDERS.includes(sender));
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前屏蔽配置持久化到 localStorage。
|
||||
*/
|
||||
function persistBlockedSystemSenders() {
|
||||
localStorage.setItem(
|
||||
BLOCKED_SYSTEM_SENDERS_STORAGE_KEY,
|
||||
JSON.stringify(Array.from(blockedSystemSenders))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步屏蔽菜单中的复选框状态。
|
||||
*/
|
||||
function syncBlockedSystemSenderCheckboxes() {
|
||||
const fishingCheckbox = document.getElementById('block-sender-fishing');
|
||||
const doctorCheckbox = document.getElementById('block-sender-doctor');
|
||||
|
||||
if (fishingCheckbox) {
|
||||
fishingCheckbox.checked = blockedSystemSenders.has('钓鱼播报');
|
||||
}
|
||||
|
||||
if (doctorCheckbox) {
|
||||
doctorCheckbox.checked = blockedSystemSenders.has('星海小博士');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前消息发送者是否已被用户屏蔽。
|
||||
*
|
||||
* @param {string} fromUser 发送者名称
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isBlockedSystemSender(fromUser) {
|
||||
return blockedSystemSenders.has(String(fromUser || ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从当前已渲染的聊天窗口中移除指定发送者的所有消息。
|
||||
*
|
||||
* @param {string} sender 发送者名称
|
||||
*/
|
||||
function removeRenderedMessagesBySender(sender) {
|
||||
[container, container2].forEach(targetContainer => {
|
||||
if (!targetContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
targetContainer.querySelectorAll('[data-from-user]').forEach(node => {
|
||||
if (node.dataset.fromUser === sender) {
|
||||
node.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换系统播报屏蔽菜单的显示状态。
|
||||
*
|
||||
* @param {Event} event 点击事件
|
||||
*/
|
||||
function toggleBlockMenu(event) {
|
||||
event.stopPropagation();
|
||||
const menu = document.getElementById('block-menu');
|
||||
const welcomeMenu = document.getElementById('welcome-menu');
|
||||
const adminMenu = document.getElementById('admin-menu');
|
||||
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (welcomeMenu) {
|
||||
welcomeMenu.style.display = 'none';
|
||||
}
|
||||
|
||||
if (adminMenu) {
|
||||
adminMenu.style.display = 'none';
|
||||
}
|
||||
|
||||
syncBlockedSystemSenderCheckboxes();
|
||||
menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新指定系统播报项的屏蔽状态,并在勾选后立即清理当前窗口。
|
||||
*
|
||||
* @param {string} sender 系统播报发送者
|
||||
* @param {boolean} blocked 是否屏蔽
|
||||
*/
|
||||
function toggleBlockedSystemSender(sender, blocked) {
|
||||
if (!BLOCKABLE_SYSTEM_SENDERS.includes(sender)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (blocked) {
|
||||
blockedSystemSenders.add(sender);
|
||||
// 勾选后立刻移除聊天室窗口内已显示的对应播报内容。
|
||||
removeRenderedMessagesBySender(sender);
|
||||
} else {
|
||||
blockedSystemSenders.delete(sender);
|
||||
}
|
||||
|
||||
persistBlockedSystemSenders();
|
||||
syncBlockedSystemSenderCheckboxes();
|
||||
}
|
||||
|
||||
syncBlockedSystemSenderCheckboxes();
|
||||
|
||||
/**
|
||||
* 转义会员横幅文本,避免横幅层被注入 HTML。
|
||||
@@ -319,12 +449,16 @@
|
||||
event.stopPropagation();
|
||||
const menu = document.getElementById('welcome-menu');
|
||||
const adminMenu = document.getElementById('admin-menu');
|
||||
const blockMenu = document.getElementById('block-menu');
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
if (adminMenu) {
|
||||
adminMenu.style.display = 'none';
|
||||
}
|
||||
if (blockMenu) {
|
||||
blockMenu.style.display = 'none';
|
||||
}
|
||||
menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
@@ -335,12 +469,16 @@
|
||||
event.stopPropagation();
|
||||
const menu = document.getElementById('admin-menu');
|
||||
const welcomeMenu = document.getElementById('welcome-menu');
|
||||
const blockMenu = document.getElementById('block-menu');
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
if (welcomeMenu) {
|
||||
welcomeMenu.style.display = 'none';
|
||||
}
|
||||
if (blockMenu) {
|
||||
blockMenu.style.display = 'none';
|
||||
}
|
||||
menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
@@ -441,6 +579,11 @@
|
||||
if (adminMenu) {
|
||||
adminMenu.style.display = 'none';
|
||||
}
|
||||
|
||||
const blockMenu = document.getElementById('block-menu');
|
||||
if (blockMenu) {
|
||||
blockMenu.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// ── 动作选择 ──────────────────────────────────────
|
||||
@@ -656,11 +799,19 @@
|
||||
_maxMsgId = msg.id;
|
||||
}
|
||||
|
||||
// 用户勾选屏蔽后,历史消息和实时消息统一在这里拦截,不再进入渲染流程。
|
||||
if (isBlockedSystemSender(msg?.from_user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isMe = msg.from_user === window.chatContext.username;
|
||||
const fontColor = msg.font_color || '#000000';
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.className = 'msg-line';
|
||||
if (msg?.from_user) {
|
||||
div.dataset.fromUser = msg.from_user;
|
||||
}
|
||||
|
||||
const timeStr = msg.sent_at || '';
|
||||
let timeStrOverride = false;
|
||||
@@ -1351,9 +1502,11 @@
|
||||
}).catch(err => console.error('特效触发失败:', err));
|
||||
}
|
||||
window.toggleAdminMenu = toggleAdminMenu;
|
||||
window.toggleBlockMenu = toggleBlockMenu;
|
||||
window.runAdminAction = runAdminAction;
|
||||
window.selectEffect = selectEffect;
|
||||
window.triggerEffect = triggerEffect;
|
||||
window.toggleBlockedSystemSender = toggleBlockedSystemSender;
|
||||
|
||||
// ── 字号设置(持久化到 localStorage)─────────────────
|
||||
/**
|
||||
@@ -1391,6 +1544,7 @@
|
||||
const muted = localStorage.getItem('chat_sound_muted') === '1';
|
||||
const muteChk = document.getElementById('sound_muted');
|
||||
if (muteChk) muteChk.checked = muted;
|
||||
syncBlockedSystemSenderCheckboxes();
|
||||
});
|
||||
|
||||
// ── 特效禁音开关 ─────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user