264 lines
8.7 KiB
JavaScript
264 lines
8.7 KiB
JavaScript
|
|
// 聊天室管理员命令模块:设置公告、公屏讲话、清屏、刷新全员、特效触发。
|
||
|
|
// 从 Blade 内联脚本迁移至 Vite 管理。
|
||
|
|
|
||
|
|
function csrf() {
|
||
|
|
return document.querySelector('meta[name="csrf-token"]')?.content ?? "";
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 设置房间公告。
|
||
|
|
*/
|
||
|
|
function promptAnnouncement() {
|
||
|
|
const fullText = document.getElementById("announcement-text")?.textContent?.trim() || "";
|
||
|
|
const pureText = fullText.replace(/ ——\S+ \d{2}-\d{2} \d{2}:\d{2}$/, "").trim();
|
||
|
|
window.chatDialog
|
||
|
|
.prompt("请输入新的房间公告/祝福语:", pureText, "设置公告", "#336699")
|
||
|
|
.then((newText) => {
|
||
|
|
if (newText === null || newText.trim() === "") return;
|
||
|
|
|
||
|
|
fetch(`/room/${window.chatContext.roomId}/announcement`, {
|
||
|
|
method: "POST",
|
||
|
|
headers: {
|
||
|
|
"X-CSRF-TOKEN": csrf(),
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
"Accept": "application/json",
|
||
|
|
},
|
||
|
|
body: JSON.stringify({ announcement: newText.trim() }),
|
||
|
|
})
|
||
|
|
.then((res) => res.json())
|
||
|
|
.then((data) => {
|
||
|
|
if (data.status === "success") {
|
||
|
|
const marquee = document.getElementById("announcement-text");
|
||
|
|
if (marquee) marquee.textContent = data.announcement;
|
||
|
|
window.chatDialog.alert("公告已更新!", "提示", "#16a34a");
|
||
|
|
} else {
|
||
|
|
window.chatDialog.alert(data.message || "更新失败", "操作失败", "#cc4444");
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.catch((e) => {
|
||
|
|
window.chatDialog.alert("设置公告失败:" + e.message, "操作失败", "#cc4444");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 站长公屏讲话。
|
||
|
|
*/
|
||
|
|
function promptAnnounceMessage() {
|
||
|
|
window.chatDialog
|
||
|
|
.prompt("请输入公屏讲话内容:", "", "📢 公屏讲话", "#7c3aed")
|
||
|
|
.then((content) => {
|
||
|
|
if (!content || !content.trim()) return;
|
||
|
|
|
||
|
|
fetch("/command/announce", {
|
||
|
|
method: "POST",
|
||
|
|
headers: {
|
||
|
|
"X-CSRF-TOKEN": csrf(),
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
"Accept": "application/json",
|
||
|
|
},
|
||
|
|
body: JSON.stringify({
|
||
|
|
content: content.trim(),
|
||
|
|
room_id: window.chatContext.roomId,
|
||
|
|
}),
|
||
|
|
})
|
||
|
|
.then((res) => res.json())
|
||
|
|
.then((data) => {
|
||
|
|
if (data.status !== "success") {
|
||
|
|
window.chatDialog.alert(data.message || "发送失败", "操作失败", "#cc4444");
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.catch((e) => {
|
||
|
|
window.chatDialog.alert("发送失败:" + e.message, "操作失败", "#cc4444");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 管理员全员清屏。
|
||
|
|
*/
|
||
|
|
function adminClearScreen() {
|
||
|
|
window.chatDialog
|
||
|
|
.confirm("确定要清除所有人的聊天记录吗?(悄悄话将保留)", "全员清屏", "#dc2626")
|
||
|
|
.then((ok) => {
|
||
|
|
if (!ok) return;
|
||
|
|
|
||
|
|
fetch("/command/clear-screen", {
|
||
|
|
method: "POST",
|
||
|
|
headers: {
|
||
|
|
"X-CSRF-TOKEN": csrf(),
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
"Accept": "application/json",
|
||
|
|
},
|
||
|
|
body: JSON.stringify({ room_id: window.chatContext.roomId }),
|
||
|
|
})
|
||
|
|
.then((res) => res.json())
|
||
|
|
.then((data) => {
|
||
|
|
if (data.status !== "success") {
|
||
|
|
window.chatDialog.alert(data.message || "清屏失败", "操作失败", "#cc4444");
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.catch((e) => {
|
||
|
|
window.chatDialog.alert("清屏失败:" + e.message, "操作失败", "#cc4444");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 管理员触发全屏特效。
|
||
|
|
*
|
||
|
|
* @param {string} type 特效类型:fireworks / rain / lightning / snow / sakura / meteors / gold-rain / hearts / confetti / fireflies
|
||
|
|
*/
|
||
|
|
function triggerEffect(type) {
|
||
|
|
const roomId = window.chatContext?.roomId;
|
||
|
|
if (!roomId) return;
|
||
|
|
fetch("/command/effect", {
|
||
|
|
method: "POST",
|
||
|
|
headers: {
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
"X-CSRF-TOKEN": csrf(),
|
||
|
|
},
|
||
|
|
body: JSON.stringify({ room_id: roomId, type }),
|
||
|
|
})
|
||
|
|
.then((r) => r.json())
|
||
|
|
.then((data) => {
|
||
|
|
if (data.status !== "success")
|
||
|
|
window.chatDialog.alert(data.message, "操作失败", "#cc4444");
|
||
|
|
})
|
||
|
|
.catch((err) => console.error("特效触发失败:", err));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 选择特效后关闭菜单并触发。
|
||
|
|
*
|
||
|
|
* @param {string} type 特效类型
|
||
|
|
*/
|
||
|
|
function selectEffect(type) {
|
||
|
|
const menu = document.getElementById("admin-menu");
|
||
|
|
if (menu) menu.style.display = "none";
|
||
|
|
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": csrf(),
|
||
|
|
"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");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 执行管理菜单中的快捷操作,并在执行前关闭菜单。
|
||
|
|
*
|
||
|
|
* @param {string} action 管理动作类型
|
||
|
|
*/
|
||
|
|
function runAdminAction(action) {
|
||
|
|
const menu = document.getElementById("admin-menu");
|
||
|
|
if (menu) menu.style.display = "none";
|
||
|
|
|
||
|
|
switch (action) {
|
||
|
|
case "announcement":
|
||
|
|
promptAnnouncement();
|
||
|
|
break;
|
||
|
|
case "announce-message":
|
||
|
|
promptAnnounceMessage();
|
||
|
|
break;
|
||
|
|
case "admin-clear":
|
||
|
|
adminClearScreen();
|
||
|
|
break;
|
||
|
|
case "red-packet":
|
||
|
|
window.sendRedPacket?.();
|
||
|
|
break;
|
||
|
|
case "loss-cover":
|
||
|
|
window.openAdminBaccaratLossCoverModal?.();
|
||
|
|
break;
|
||
|
|
case "refresh-all":
|
||
|
|
refreshAllBrowsers();
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 切换管理菜单显示/隐藏。
|
||
|
|
*/
|
||
|
|
function toggleAdminMenu(event) {
|
||
|
|
event.stopPropagation();
|
||
|
|
const menu = document.getElementById("admin-menu");
|
||
|
|
const welcomeMenu = document.getElementById("welcome-menu");
|
||
|
|
const blockMenu = document.getElementById("block-menu");
|
||
|
|
const featureMenu = document.getElementById("feature-menu");
|
||
|
|
const dailyStatusEditor = document.getElementById("daily-status-editor-overlay");
|
||
|
|
|
||
|
|
if (!menu) return;
|
||
|
|
|
||
|
|
[welcomeMenu, blockMenu, featureMenu, dailyStatusEditor].forEach((el) => {
|
||
|
|
if (el) el.style.display = "none";
|
||
|
|
});
|
||
|
|
|
||
|
|
menu.style.display = menu.style.display === "none" ? "block" : "none";
|
||
|
|
}
|
||
|
|
|
||
|
|
// 挂载到 window 供 Blade 脚本及其他模块使用。
|
||
|
|
window.promptAnnouncement = promptAnnouncement;
|
||
|
|
window.promptAnnounceMessage = promptAnnounceMessage;
|
||
|
|
window.adminClearScreen = adminClearScreen;
|
||
|
|
window.triggerEffect = triggerEffect;
|
||
|
|
window.selectEffect = selectEffect;
|
||
|
|
window.refreshAllBrowsers = refreshAllBrowsers;
|
||
|
|
window.runAdminAction = runAdminAction;
|
||
|
|
window.toggleAdminMenu = toggleAdminMenu;
|
||
|
|
|
||
|
|
export {
|
||
|
|
promptAnnouncement,
|
||
|
|
promptAnnounceMessage,
|
||
|
|
adminClearScreen,
|
||
|
|
triggerEffect,
|
||
|
|
selectEffect,
|
||
|
|
refreshAllBrowsers,
|
||
|
|
runAdminAction,
|
||
|
|
toggleAdminMenu,
|
||
|
|
};
|