新增聊天室刷新同步与全员刷新功能
This commit is contained in:
@@ -74,7 +74,8 @@
|
||||
chatBotEnabled: {{ $chatbotEnabledState ? 'true' : 'false' }},
|
||||
botUser: @json($botUserData),
|
||||
hasPosition: {{ Auth::user()->activePosition || Auth::user()->user_level >= $superLevel ? 'true' : 'false' }},
|
||||
hasRoomManagementPermission: {{ ! empty($hasRoomManagementPermission) ? 'true' : 'false' }},
|
||||
hasRoomManagementPermission: {{ (! empty($hasRoomManagementPermission) || Auth::id() === 1) ? 'true' : 'false' }},
|
||||
isSiteOwner: {{ Auth::id() === 1 ? 'true' : 'false' }},
|
||||
positionPermissions: @json($positionPermissions),
|
||||
positionPermissionMap: @json($roomPermissionMap ?? []),
|
||||
@php
|
||||
@@ -98,6 +99,7 @@
|
||||
revokeUrl: "{{ route('chat.appoint.revoke') }}",
|
||||
rewardUrl: "{{ route('command.reward') }}",
|
||||
rewardQuotaUrl: "{{ route('command.reward_quota') }}",
|
||||
refreshAllUrl: "{{ route('command.refresh_all') }}",
|
||||
chatPreferencesUrl: "{{ route('user.update_chat_preferences') }}",
|
||||
userJjb: {{ (int) $user->jjb }}, // 当前用户金币(求婚前金额预检查用)
|
||||
myGold: {{ (int) $user->jjb }}, // 赠金币面板显示余额用(赠送成功后前端更新)
|
||||
|
||||
@@ -181,7 +181,7 @@ $welcomeMessages = [
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($canPublicBroadcast || $canClearScreen || $canSendRedPacket || $canManageLossCover)
|
||||
@if ($canPublicBroadcast || $canClearScreen || $canSendRedPacket || $canManageLossCover || Auth::id() === 1)
|
||||
<div style="font-size:10px;color:#9a3412;padding:10px 2px 6px;">聊天室管理</div>
|
||||
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;">
|
||||
@if ($canPublicBroadcast)
|
||||
@@ -200,6 +200,10 @@ $welcomeMessages = [
|
||||
<button type="button" onclick="runAdminAction('loss-cover')"
|
||||
style="font-size:11px;padding:6px 8px;background:#fff;color:#15803d;border:1px solid #86efac;border-radius:6px;cursor:pointer;">🎁 买单活动</button>
|
||||
@endif
|
||||
@if (Auth::id() === 1)
|
||||
<button type="button" onclick="runAdminAction('refresh-all')"
|
||||
style="font-size:11px;padding:6px 8px;background:#fff;color:#0f766e;border:1px solid #99f6e4;border-radius:6px;cursor:pointer;">♻️ 刷新全员</button>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@@ -672,6 +672,9 @@
|
||||
case 'loss-cover':
|
||||
openAdminBaccaratLossCoverModal();
|
||||
break;
|
||||
case 'refresh-all':
|
||||
refreshAllBrowsers();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -691,6 +694,57 @@
|
||||
triggerEffect(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 站长通知当前房间所有在线用户刷新页面。
|
||||
*/
|
||||
async function refreshAllBrowsers() {
|
||||
if (!window.chatContext?.isSiteOwner || !window.chatContext?.refreshAllUrl) {
|
||||
window.chatDialog?.alert('仅站长可执行全员刷新。', '无权限', '#cc4444');
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmed = await window.chatDialog?.confirm(
|
||||
'确定通知当前房间所有在线用户刷新页面吗?\n适用于功能更新后强制同步最新按钮与权限状态。',
|
||||
'♻️ 刷新全员',
|
||||
'#0f766e'
|
||||
);
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(window.chatContext.refreshAllUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '',
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
room_id: window.chatContext.roomId,
|
||||
reason: '功能更新,站长要求刷新页面',
|
||||
}),
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (data.status === 'success') {
|
||||
window.chatToast?.show({
|
||||
title: '已发送刷新通知',
|
||||
message: data.message,
|
||||
icon: '♻️',
|
||||
color: '#0f766e',
|
||||
duration: 3500,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
window.chatDialog?.alert(data.message || '发送刷新通知失败', '操作失败', '#cc4444');
|
||||
} catch (error) {
|
||||
window.chatDialog?.alert('网络异常,请稍后再试', '错误', '#cc4444');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将选中的欢迎语模板填入输入框,{name} 替换为当前选中的聊天对象,
|
||||
* 并在前面加上「部门 职务 姓名:」前缀,然后自动发送
|
||||
@@ -1436,6 +1490,48 @@
|
||||
document.getElementById('room-title-display').innerText = e.detail.title;
|
||||
});
|
||||
|
||||
/**
|
||||
* 收到站长的全员刷新通知后,先弹出提示,再延迟刷新页面。
|
||||
*/
|
||||
window.addEventListener('chat:browser-refresh-requested', (e) => {
|
||||
const detail = e.detail || {};
|
||||
const operatorName = escapeHtml(String(detail.operator || '站长'));
|
||||
const reasonText = escapeHtml(String(detail.reason || '页面功能已更新,请重新载入。'));
|
||||
|
||||
window.chatToast?.show({
|
||||
title: '页面即将刷新',
|
||||
message: `<b>${operatorName}</b> 通知全员刷新页面。<br><span style="color:#475569;">${reasonText}</span>`,
|
||||
icon: '♻️',
|
||||
color: '#0f766e',
|
||||
duration: 2200,
|
||||
});
|
||||
|
||||
window.setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 900);
|
||||
});
|
||||
|
||||
/**
|
||||
* 任命/撤职后,目标用户收到定向刷新通知,自动同步页面上的权限按钮。
|
||||
*/
|
||||
window.addEventListener('chat:user-browser-refresh-requested', (e) => {
|
||||
const detail = e.detail || {};
|
||||
const operatorName = escapeHtml(String(detail.operator || '管理员'));
|
||||
const reasonText = escapeHtml(String(detail.reason || '你的权限状态已发生变化,页面即将刷新。'));
|
||||
|
||||
window.chatToast?.show({
|
||||
title: '权限同步中',
|
||||
message: `<b>${operatorName}</b> 已更新你的职务状态。<br><span style="color:#475569;">${reasonText}</span>`,
|
||||
icon: '🔄',
|
||||
color: '#7c3aed',
|
||||
duration: 2600,
|
||||
});
|
||||
|
||||
window.setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// ── 管理员全员清屏事件(等待 Echo 就绪后监听) ───────
|
||||
function setupScreenClearedListener() {
|
||||
if (!window.Echo || !window.chatContext) {
|
||||
@@ -1484,6 +1580,32 @@
|
||||
// DOMContentLoaded 后启动,确保 Vite 编译的 JS 已加载
|
||||
document.addEventListener('DOMContentLoaded', setupScreenClearedListener);
|
||||
|
||||
/**
|
||||
* 注册房间级“刷新全员”监听。
|
||||
*
|
||||
* 放在 Blade 脚本内,避免前端资源未重新构建时收不到刷新广播。
|
||||
*/
|
||||
function setupRoomBrowserRefreshListener() {
|
||||
if (!window.Echo || !window.chatContext) {
|
||||
setTimeout(setupRoomBrowserRefreshListener, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
window.Echo.join(`room.${window.chatContext.roomId}`)
|
||||
.listen('BrowserRefreshRequested', (e) => {
|
||||
console.log('收到全员刷新事件:', e);
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('chat:browser-refresh-requested', {
|
||||
detail: e
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
console.log('BrowserRefreshRequested 监听器已注册');
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', setupRoomBrowserRefreshListener);
|
||||
|
||||
// ── 开发日志发布通知(仅 Room 1 大厅可见)────────────
|
||||
/**
|
||||
* 监听 ChangelogPublished 事件,在大厅聊天区展示系统通知
|
||||
@@ -1642,11 +1764,12 @@
|
||||
window.addEventListener('chat:effect', (e) => {
|
||||
const type = e.detail?.type;
|
||||
const target = e.detail?.target_username; // null = 全员,otherwise 指定昵称
|
||||
const operator = e.detail?.operator; // 定向赠送时,购买者自己也应能看到特效
|
||||
const myName = window.chatContext?.username;
|
||||
|
||||
// null 表示全员,或者 target 匹配自己才播放
|
||||
// null 表示全员;若有指定接收者,则购买者本人和指定用户都播放
|
||||
if (type && typeof EffectManager !== 'undefined') {
|
||||
if (!target || target === myName) {
|
||||
if (!target || target === myName || operator === myName) {
|
||||
EffectManager.play(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,13 +349,10 @@
|
||||
});
|
||||
const data = await res.json();
|
||||
const revOk = data.status === 'success';
|
||||
this.$alert(
|
||||
data.message,
|
||||
revOk ? '撤销成功' : '操作失败',
|
||||
revOk ? '#6b7280' : '#cc4444'
|
||||
);
|
||||
if (revOk) {
|
||||
this.showUserModal = false;
|
||||
} else {
|
||||
this.$alert(data.message, '操作失败', '#cc4444');
|
||||
}
|
||||
} catch (e) {
|
||||
this.$alert('网络异常', '错误', '#cc4444');
|
||||
|
||||
Reference in New Issue
Block a user