diff --git a/resources/views/chat/partials/layout/input-bar.blade.php b/resources/views/chat/partials/layout/input-bar.blade.php
index eff8cf0..8a157ee 100644
--- a/resources/views/chat/partials/layout/input-bar.blade.php
+++ b/resources/views/chat/partials/layout/input-bar.blade.php
@@ -133,6 +133,18 @@ $welcomeMessages = [
onchange="toggleBlockedSystemSender('星海小博士', this.checked)">
星海小博士
+
+
diff --git a/resources/views/chat/partials/scripts.blade.php b/resources/views/chat/partials/scripts.blade.php
index 7e6ed23..3f6bebf 100644
--- a/resources/views/chat/partials/scripts.blade.php
+++ b/resources/views/chat/partials/scripts.blade.php
@@ -38,7 +38,7 @@
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 = ['钓鱼播报', '星海小博士'];
+ const BLOCKABLE_SYSTEM_SENDERS = ['钓鱼播报', '星海小博士', '百家乐', '跑马'];
// ── 消息区:手机端双触发打开用户名片(PC 端靠 ondblclick 内联属性)──
// span[data-u] 由 clickableUser() 生成,touchend 委托至容器避免每条消息单独绑定
@@ -107,6 +107,8 @@
function syncBlockedSystemSenderCheckboxes() {
const fishingCheckbox = document.getElementById('block-sender-fishing');
const doctorCheckbox = document.getElementById('block-sender-doctor');
+ const baccaratCheckbox = document.getElementById('block-sender-baccarat');
+ const horseRaceCheckbox = document.getElementById('block-sender-horse-race');
if (fishingCheckbox) {
fishingCheckbox.checked = blockedSystemSenders.has('钓鱼播报');
@@ -115,35 +117,74 @@
if (doctorCheckbox) {
doctorCheckbox.checked = blockedSystemSenders.has('星海小博士');
}
+
+ if (baccaratCheckbox) {
+ baccaratCheckbox.checked = blockedSystemSenders.has('百家乐');
+ }
+
+ if (horseRaceCheckbox) {
+ horseRaceCheckbox.checked = blockedSystemSenders.has('跑马');
+ }
}
/**
- * 判断当前消息发送者是否已被用户屏蔽。
+ * 根据消息内容识别其对应的屏蔽规则键。
*
- * @param {string} fromUser 发送者名称
- * @returns {boolean}
+ * @param {Record} msg 消息对象
+ * @returns {string|null}
*/
- function isBlockedSystemSender(fromUser) {
- return blockedSystemSenders.has(String(fromUser || ''));
+ function resolveBlockedSystemSenderKey(msg) {
+ const fromUser = String(msg?.from_user || '');
+ const content = String(msg?.content || '');
+
+ if (fromUser === '钓鱼播报') {
+ return '钓鱼播报';
+ }
+
+ if (fromUser === '星海小博士') {
+ return '星海小博士';
+ }
+
+ if ((fromUser === '系统传音' || fromUser === '系统') && content.includes('百家乐')) {
+ return '百家乐';
+ }
+
+ if ((fromUser === '系统传音' || fromUser === '系统') && (content.includes('赛马') || content.includes('跑马'))) {
+ return '跑马';
+ }
+
+ return null;
}
/**
- * 从当前已渲染的聊天窗口中移除指定发送者的所有消息。
+ * 批量切换当前已渲染消息的显示状态。
*
- * @param {string} sender 发送者名称
+ * @param {string} blockKey 屏蔽规则键
+ * @param {boolean} hidden true = 隐藏,false = 恢复显示
*/
- function removeRenderedMessagesBySender(sender) {
+ function setRenderedMessagesVisibilityBySender(blockKey, hidden) {
[container, container2].forEach(targetContainer => {
if (!targetContainer) {
return;
}
- targetContainer.querySelectorAll('[data-from-user]').forEach(node => {
- if (node.dataset.fromUser === sender) {
- node.remove();
+ targetContainer.querySelectorAll('[data-block-key]').forEach(node => {
+ if (node.dataset.blockKey === blockKey) {
+ if (hidden) {
+ node.dataset.blockHidden = '1';
+ node.style.display = 'none';
+ } else if (node.dataset.blockHidden === '1') {
+ node.removeAttribute('data-block-hidden');
+ node.style.display = '';
+ }
}
});
});
+
+ if (!hidden && autoScroll) {
+ container.scrollTop = container.scrollHeight;
+ container2.scrollTop = container2.scrollHeight;
+ }
}
/**
@@ -176,7 +217,7 @@
/**
* 更新指定系统播报项的屏蔽状态,并在勾选后立即清理当前窗口。
*
- * @param {string} sender 系统播报发送者
+ * @param {string} sender 系统播报发送者/规则键
* @param {boolean} blocked 是否屏蔽
*/
function toggleBlockedSystemSender(sender, blocked) {
@@ -186,10 +227,12 @@
if (blocked) {
blockedSystemSenders.add(sender);
- // 勾选后立刻移除聊天室窗口内已显示的对应播报内容。
- removeRenderedMessagesBySender(sender);
+ // 勾选后立刻隐藏聊天室窗口内已显示的对应播报内容。
+ setRenderedMessagesVisibilityBySender(sender, true);
} else {
blockedSystemSenders.delete(sender);
+ // 取消勾选后立即恢复先前被隐藏的对应播报内容。
+ setRenderedMessagesVisibilityBySender(sender, false);
}
persistBlockedSystemSenders();
@@ -799,19 +842,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 blockRuleKey = resolveBlockedSystemSenderKey(msg);
+ const shouldHideByBlock = blockRuleKey ? blockedSystemSenders.has(blockRuleKey) : false;
const div = document.createElement('div');
div.className = 'msg-line';
if (msg?.from_user) {
div.dataset.fromUser = msg.from_user;
}
+ if (blockRuleKey) {
+ div.dataset.blockKey = blockRuleKey;
+ }
const timeStr = msg.sent_at || '';
let timeStrOverride = false;
@@ -1061,6 +1104,12 @@
}
div.innerHTML = html;
+ // 命中屏蔽规则时,消息仍保留在 DOM 中,便于取消屏蔽后立即恢复显示。
+ if (shouldHideByBlock) {
+ div.dataset.blockHidden = '1';
+ div.style.display = 'none';
+ }
+
// 后端下发的带有 welcome_user 的也是系统欢迎/离开消息,加上属性标记
if (msg.welcome_user) {
div.setAttribute('data-system-user', msg.welcome_user);
diff --git a/tests/Feature/ChatControllerTest.php b/tests/Feature/ChatControllerTest.php
index d9d927f..f09c1a8 100644
--- a/tests/Feature/ChatControllerTest.php
+++ b/tests/Feature/ChatControllerTest.php
@@ -74,6 +74,8 @@ class ChatControllerTest extends TestCase
$response->assertSee('🔕 屏蔽', false);
$response->assertSee('钓鱼播报');
$response->assertSee('星海小博士');
+ $response->assertSee('百家乐');
+ $response->assertSee('跑马');
$response->assertSee('chat_blocked_system_senders');
$response->assertSee('toggleBlockedSystemSender');
}