迁移任命公告事件脚本
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
// 统一转发各子模块导出,方便测试或后续模块继续复用同一组工具。
|
// 统一转发各子模块导出,方便测试或后续模块继续复用同一组工具。
|
||||||
export { escapeHtml, escapeHtmlWithLineBreaks } from "./chat-room/html.js";
|
export { escapeHtml, escapeHtmlWithLineBreaks } from "./chat-room/html.js";
|
||||||
|
export { bindAppointmentAnnouncementControls, showAppointmentBanner } from "./chat-room/appointment-announcement.js";
|
||||||
export { bindChatBanner } from "./chat-room/banner.js";
|
export { bindChatBanner } from "./chat-room/banner.js";
|
||||||
export { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
export { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
||||||
export { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
export { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
||||||
@@ -79,6 +80,7 @@ export {
|
|||||||
export { createMessageQueue } from "./chat-room/message-queue.js";
|
export { createMessageQueue } from "./chat-room/message-queue.js";
|
||||||
|
|
||||||
import { escapeHtml, escapeHtmlWithLineBreaks } from "./chat-room/html.js";
|
import { escapeHtml, escapeHtmlWithLineBreaks } from "./chat-room/html.js";
|
||||||
|
import { bindAppointmentAnnouncementControls, showAppointmentBanner } from "./chat-room/appointment-announcement.js";
|
||||||
import { bindChatBanner } from "./chat-room/banner.js";
|
import { bindChatBanner } from "./chat-room/banner.js";
|
||||||
import { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
import { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
||||||
import { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
import { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
||||||
@@ -160,6 +162,8 @@ if (typeof window !== "undefined") {
|
|||||||
window.ChatRoomTools = {
|
window.ChatRoomTools = {
|
||||||
escapeHtml,
|
escapeHtml,
|
||||||
escapeHtmlWithLineBreaks,
|
escapeHtmlWithLineBreaks,
|
||||||
|
bindAppointmentAnnouncementControls,
|
||||||
|
showAppointmentBanner,
|
||||||
bindChatBanner,
|
bindChatBanner,
|
||||||
bindGlobalDialogControls,
|
bindGlobalDialogControls,
|
||||||
bindDailySignInControls,
|
bindDailySignInControls,
|
||||||
@@ -273,6 +277,7 @@ if (typeof window !== "undefined") {
|
|||||||
|
|
||||||
// 页面加载后立即注册事件委托,具体业务逻辑仍由各子模块负责。
|
// 页面加载后立即注册事件委托,具体业务逻辑仍由各子模块负责。
|
||||||
bindChatBanner();
|
bindChatBanner();
|
||||||
|
bindAppointmentAnnouncementControls();
|
||||||
bindGlobalDialogControls();
|
bindGlobalDialogControls();
|
||||||
bindDailySignInControls();
|
bindDailySignInControls();
|
||||||
bindChatFontSizeControl();
|
bindChatFontSizeControl();
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
// 聊天室任命/撤销公告监听,负责渲染大卡片和频道内系统提示。
|
||||||
|
|
||||||
|
import { escapeHtml } from "./html.js";
|
||||||
|
|
||||||
|
const APPOINTMENT_PHRASES = [
|
||||||
|
"望再接再厉,大展宏图,为大家服务!",
|
||||||
|
"期待在任期间带领大家更上一层楼!",
|
||||||
|
"众望所归,任重道远,加油!",
|
||||||
|
"新官上任,一展风采,前程似锦!",
|
||||||
|
"相信你能胜任,期待你的精彩表现!",
|
||||||
|
];
|
||||||
|
|
||||||
|
const REVOKE_PHRASES = [
|
||||||
|
"感谢在任期间的辛勤付出,辛苦了!",
|
||||||
|
"江湖路长,愿前程似锦,未来可期!",
|
||||||
|
"感谢您为大家的奉献,一路顺风!",
|
||||||
|
"在任一场,情谊长存,感谢付出!",
|
||||||
|
"相信以后还有更多精彩,继续加油!",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前聊天消息时间。
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function getChatTimeString() {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
return [
|
||||||
|
now.getHours().toString().padStart(2, "0"),
|
||||||
|
now.getMinutes().toString().padStart(2, "0"),
|
||||||
|
now.getSeconds().toString().padStart(2, "0"),
|
||||||
|
].join(":");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从候选文案中随机挑选一条公告补充语。
|
||||||
|
*
|
||||||
|
* @param {string[]} phrases
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function pickAnnouncementPhrase(phrases) {
|
||||||
|
return phrases[Math.floor(Math.random() * phrases.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示任命或撤销的大卡片公告。
|
||||||
|
*
|
||||||
|
* @param {object} data
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function showAppointmentBanner(data) {
|
||||||
|
if (!window.chatBanner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const department = data.department_name ? `${escapeHtml(data.department_name)} · ` : "";
|
||||||
|
const isRevoke = data.type === "revoke";
|
||||||
|
|
||||||
|
if (isRevoke) {
|
||||||
|
window.chatBanner.show({
|
||||||
|
id: "appointment-banner",
|
||||||
|
icon: "📋",
|
||||||
|
title: "职务撤销",
|
||||||
|
name: `${escapeHtml(data.position_icon)} ${escapeHtml(data.target_username)}`,
|
||||||
|
body: `${department}${escapeHtml(data.position_name)} 职务已被撤销`,
|
||||||
|
sub: `由 ${escapeHtml(data.operator_name)} 执行`,
|
||||||
|
gradient: ["#374151", "#4b5563", "#6b7280"],
|
||||||
|
titleColor: "#d1d5db",
|
||||||
|
autoClose: 4500,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.chatBanner.show({
|
||||||
|
id: "appointment-banner",
|
||||||
|
icon: "🎊🎖️🎊",
|
||||||
|
title: "任命公告",
|
||||||
|
name: `${escapeHtml(data.position_icon)} ${escapeHtml(data.target_username)}`,
|
||||||
|
body: `荣任 ${department}${escapeHtml(data.position_name)}`,
|
||||||
|
sub: `由 ${escapeHtml(data.operator_name)} 任命`,
|
||||||
|
gradient: ["#4f46e5", "#7c3aed", "#db2777"],
|
||||||
|
titleColor: "#fde68a",
|
||||||
|
autoClose: 4500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建任命/撤销频道内系统消息节点。
|
||||||
|
*
|
||||||
|
* @param {object} data
|
||||||
|
* @param {boolean} isRevoke
|
||||||
|
* @param {string} department
|
||||||
|
* @param {string} phrase
|
||||||
|
* @param {string} timeString
|
||||||
|
* @returns {HTMLDivElement}
|
||||||
|
*/
|
||||||
|
function createAppointmentMessage(data, isRevoke, department, phrase, timeString) {
|
||||||
|
const message = document.createElement("div");
|
||||||
|
message.className = "msg-line";
|
||||||
|
|
||||||
|
if (isRevoke) {
|
||||||
|
message.style.cssText = "background:#f3f4f6; border-left:3px solid #9ca3af; border-radius:4px; padding:4px 10px; margin:2px 0;";
|
||||||
|
message.innerHTML = `
|
||||||
|
<span style="color:#6b7280;">📋 </span>
|
||||||
|
<span style="color:#374151;"><b>${escapeHtml(data.target_username)}</b> 的 ${escapeHtml(data.position_icon)} ${department}${escapeHtml(data.position_name)} 职务已被 <b>${escapeHtml(data.operator_name)}</b> 撤销。${phrase}</span>
|
||||||
|
<span class="msg-time">(${timeString})</span>
|
||||||
|
`;
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.style.cssText = "background:#f5f3ff; border-left:3px solid #7c3aed; border-radius:4px; padding:4px 10px; margin:2px 0;";
|
||||||
|
message.innerHTML = `
|
||||||
|
<span style="color:#7c3aed;">🎖️ </span>
|
||||||
|
<span style="color:#3730a3;">恭喜 <b>${escapeHtml(data.target_username)}</b> 荣任 ${escapeHtml(data.position_icon)} ${department}<b>${escapeHtml(data.position_name)}</b>,由 <b>${escapeHtml(data.operator_name)}</b> 任命。${phrase}</span>
|
||||||
|
<span class="msg-time">(${timeString})</span>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将系统消息追加到指定聊天窗格并滚动到底部。
|
||||||
|
*
|
||||||
|
* @param {HTMLElement|null} container
|
||||||
|
* @param {HTMLDivElement} message
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function appendAppointmentMessage(container, message) {
|
||||||
|
if (!container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.appendChild(message);
|
||||||
|
container.scrollTop = container.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理任命/撤销公告事件。
|
||||||
|
*
|
||||||
|
* @param {CustomEvent} event
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function handleAppointmentAnnouncement(event) {
|
||||||
|
const data = event.detail || {};
|
||||||
|
const isRevoke = data.type === "revoke";
|
||||||
|
const department = data.department_name ? `${escapeHtml(data.department_name)} · ` : "";
|
||||||
|
|
||||||
|
// 任命公告才播放礼花,撤销只显示灰色公告卡片。
|
||||||
|
if (!isRevoke) {
|
||||||
|
window.EffectManager?.play?.("fireworks");
|
||||||
|
}
|
||||||
|
|
||||||
|
showAppointmentBanner(data);
|
||||||
|
|
||||||
|
const phrase = pickAnnouncementPhrase(isRevoke ? REVOKE_PHRASES : APPOINTMENT_PHRASES);
|
||||||
|
const myName = window.chatContext?.username ?? "";
|
||||||
|
const isInvolved = myName === data.operator_name || myName === data.target_username;
|
||||||
|
const targetContainer = isInvolved
|
||||||
|
? document.getElementById("chat-messages-container2")
|
||||||
|
: document.getElementById("chat-messages-container");
|
||||||
|
|
||||||
|
// 操作者和被操作者写入私聊面板,其余用户写入公屏。
|
||||||
|
appendAppointmentMessage(
|
||||||
|
targetContainer,
|
||||||
|
createAppointmentMessage(data, isRevoke, department, phrase, getChatTimeString()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定任命/撤销公告浏览器事件。
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function bindAppointmentAnnouncementControls() {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("chat:appointment-announced", handleAppointmentAnnouncement);
|
||||||
|
}
|
||||||
@@ -1,128 +1,6 @@
|
|||||||
<script>
|
{{--
|
||||||
// ══════════════════════════════════════════
|
文件功能:聊天室系统事件脚本占位
|
||||||
// 任命公告:复用现有礼花特效 + 隆重弹窗
|
|
||||||
// ══════════════════════════════════════════
|
|
||||||
|
|
||||||
/**
|
任命/撤销公告监听已迁移到 resources/js/chat-room/appointment-announcement.js,
|
||||||
* 显示任命公告弹窗(居中,5 秒后淡出)
|
由 resources/js/chat-room.js 统一通过 Vite 加载并绑定 chat:appointment-announced 事件。
|
||||||
*/
|
--}}
|
||||||
/**
|
|
||||||
* 显示任命公告弹窗(改用 chatBanner 公共组件)。
|
|
||||||
*
|
|
||||||
* @param {Object} data 任命数据:type, target_username, position_icon, position_name, department_name, operator_name
|
|
||||||
*/
|
|
||||||
function showAppointmentBanner(data) {
|
|
||||||
const dept = data.department_name ? escapeHtml(data.department_name) + ' · ' : '';
|
|
||||||
const isRevoke = data.type === 'revoke';
|
|
||||||
|
|
||||||
if (isRevoke) {
|
|
||||||
window.chatBanner.show({
|
|
||||||
id: 'appointment-banner',
|
|
||||||
icon: '📋',
|
|
||||||
title: '职务撤销',
|
|
||||||
name: `${escapeHtml(data.position_icon)} ${escapeHtml(data.target_username)}`,
|
|
||||||
body: `${dept}${escapeHtml(data.position_name)} 职务已被撤销`,
|
|
||||||
sub: `由 ${escapeHtml(data.operator_name)} 执行`,
|
|
||||||
gradient: ['#374151', '#4b5563', '#6b7280'],
|
|
||||||
titleColor: '#d1d5db',
|
|
||||||
autoClose: 4500,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
window.chatBanner.show({
|
|
||||||
id: 'appointment-banner',
|
|
||||||
icon: '🎊🎖️🎊',
|
|
||||||
title: '任命公告',
|
|
||||||
name: `${escapeHtml(data.position_icon)} ${escapeHtml(data.target_username)}`,
|
|
||||||
body: `荣任 ${dept}${escapeHtml(data.position_name)}`,
|
|
||||||
sub: `由 ${escapeHtml(data.operator_name)} 任命`,
|
|
||||||
gradient: ['#4f46e5', '#7c3aed', '#db2777'],
|
|
||||||
titleColor: '#fde68a',
|
|
||||||
autoClose: 4500,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 监听任命公告事件:根据 type 区分任命(礼花+紫色弹窗)和撤销(灰色弹窗)
|
|
||||||
*/
|
|
||||||
window.addEventListener('chat:appointment-announced', (e) => {
|
|
||||||
const data = e.detail;
|
|
||||||
const isRevoke = data.type === 'revoke';
|
|
||||||
const dept = data.department_name ? escapeHtml(data.department_name) + ' · ' : '';
|
|
||||||
|
|
||||||
// ── 任命才有礼花 ──
|
|
||||||
if (!isRevoke && typeof EffectManager !== 'undefined') {
|
|
||||||
EffectManager.play('fireworks');
|
|
||||||
}
|
|
||||||
|
|
||||||
showAppointmentBanner(data);
|
|
||||||
|
|
||||||
// ── 聊天区系统消息:操作者/被操作者 → 私聊面板;其余人 → 公屏 ──
|
|
||||||
const now = new Date();
|
|
||||||
const timeStr = now.getHours().toString().padStart(2, '0') + ':' +
|
|
||||||
now.getMinutes().toString().padStart(2, '0') + ':' +
|
|
||||||
now.getSeconds().toString().padStart(2, '0');
|
|
||||||
|
|
||||||
const myName = window.chatContext?.username ?? '';
|
|
||||||
const isInvolved = myName === data.operator_name || myName === data.target_username;
|
|
||||||
|
|
||||||
// 随机鼓励语库
|
|
||||||
const appointPhrases = [
|
|
||||||
'望再接再厉,大展宏图,为大家服务!',
|
|
||||||
'期待在任期间带领大家更上一层楼!',
|
|
||||||
'众望所归,任重道远,加油!',
|
|
||||||
'新官上任,一展风采,前程似锦!',
|
|
||||||
'相信你能胜任,期待你的精彩表现!',
|
|
||||||
];
|
|
||||||
const revokePhrases = [
|
|
||||||
'感谢在任期间的辛勤付出,辛苦了!',
|
|
||||||
'江湖路长,愿前程似锦,未来可期!',
|
|
||||||
'感谢您为大家的奉献,一路顺风!',
|
|
||||||
'在任一场,情谊长存,感谢付出!',
|
|
||||||
'相信以后还有更多精彩,继续加油!',
|
|
||||||
];
|
|
||||||
const randomPhrase = isRevoke ?
|
|
||||||
revokePhrases[Math.floor(Math.random() * revokePhrases.length)] :
|
|
||||||
appointPhrases[Math.floor(Math.random() * appointPhrases.length)];
|
|
||||||
|
|
||||||
// 构建消息 DOM(内容相同,分配到不同面板)
|
|
||||||
function buildSysMsg() {
|
|
||||||
const sysDiv = document.createElement('div');
|
|
||||||
sysDiv.className = 'msg-line';
|
|
||||||
if (isRevoke) {
|
|
||||||
sysDiv.style.cssText =
|
|
||||||
'background:#f3f4f6; border-left:3px solid #9ca3af; border-radius:4px; padding:4px 10px; margin:2px 0;';
|
|
||||||
sysDiv.innerHTML =
|
|
||||||
`<span style="color:#6b7280;">📋 </span>` +
|
|
||||||
`<span style="color:#374151;"><b>${escapeHtml(data.target_username)}</b> 的 ${escapeHtml(data.position_icon)} ${dept}${escapeHtml(data.position_name)} 职务已被 <b>${escapeHtml(data.operator_name)}</b> 撤销。${randomPhrase}</span>` +
|
|
||||||
`<span class="msg-time">(${timeStr})</span>`;
|
|
||||||
} else {
|
|
||||||
sysDiv.style.cssText =
|
|
||||||
'background:#f5f3ff; border-left:3px solid #7c3aed; border-radius:4px; padding:4px 10px; margin:2px 0;';
|
|
||||||
sysDiv.innerHTML =
|
|
||||||
`<span style="color:#7c3aed;">🎖️ </span>` +
|
|
||||||
`<span style="color:#3730a3;">恭喜 <b>${escapeHtml(data.target_username)}</b> 荣任 ${escapeHtml(data.position_icon)} ${dept}<b>${escapeHtml(data.position_name)}</b>,由 <b>${escapeHtml(data.operator_name)}</b> 任命。${randomPhrase}</span>` +
|
|
||||||
`<span class="msg-time">(${timeStr})</span>`;
|
|
||||||
}
|
|
||||||
return sysDiv;
|
|
||||||
}
|
|
||||||
|
|
||||||
const say1 = document.getElementById('chat-messages-container');
|
|
||||||
const say2 = document.getElementById('chat-messages-container2');
|
|
||||||
|
|
||||||
if (isInvolved) {
|
|
||||||
// 操作者 / 被操作者:消息进私聊面板(包厢窗口)
|
|
||||||
if (say2) {
|
|
||||||
say2.appendChild(buildSysMsg());
|
|
||||||
say2.scrollTop = say2.scrollHeight;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 其他人:消息进公屏
|
|
||||||
if (say1) {
|
|
||||||
say1.appendChild(buildSysMsg());
|
|
||||||
say1.scrollTop = say1.scrollHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user