Files
chatroom/resources/js/chat-room/appointment-announcement.js
T
2026-04-25 13:55:47 +08:00

182 lines
5.8 KiB
JavaScript

// 聊天室任命/撤销公告监听,负责渲染大卡片和频道内系统提示。
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);
}