From d4a6a799fe890b64a39afc4b7c3a025b1c402653 Mon Sep 17 00:00:00 2001 From: lkddi Date: Sat, 25 Apr 2026 13:51:50 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E8=81=8A=E5=A4=A9=E5=AE=A4To?= =?UTF-8?q?ast=E9=80=9A=E7=9F=A5=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/js/chat-room.js | 4 + resources/js/chat-room/toast.js | 116 ++++++++++++++++++ .../partials/toast-notification.blade.php | 101 --------------- 3 files changed, 120 insertions(+), 101 deletions(-) create mode 100644 resources/js/chat-room/toast.js diff --git a/resources/js/chat-room.js b/resources/js/chat-room.js index 0d7ffff..cb075ad 100644 --- a/resources/js/chat-room.js +++ b/resources/js/chat-room.js @@ -7,6 +7,7 @@ export { bindDailySignInControls } from "./chat-room/daily-sign-in.js"; export { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js"; export { bindChatImageUploadControl } from "./chat-room/image-upload.js"; export { bindChatComposerControls } from "./chat-room/composer.js"; +export { bindChatToast } from "./chat-room/toast.js"; export { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js"; export { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js"; export { @@ -82,6 +83,7 @@ import { bindDailySignInControls } from "./chat-room/daily-sign-in.js"; import { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js"; import { bindChatImageUploadControl } from "./chat-room/image-upload.js"; import { bindChatComposerControls } from "./chat-room/composer.js"; +import { bindChatToast } from "./chat-room/toast.js"; import { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js"; import { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js"; import { @@ -162,6 +164,7 @@ if (typeof window !== "undefined") { bindChatFontSizeControl, bindChatImageUploadControl, bindChatComposerControls, + bindChatToast, bindFriendPanelControls, closeFriendPanel, friendSearch, @@ -271,6 +274,7 @@ if (typeof window !== "undefined") { bindChatFontSizeControl(); bindChatImageUploadControl(); bindChatComposerControls(); + bindChatToast(); bindFriendPanelControls(); bindToolbarControls(); bindAdminMenuControls(); diff --git a/resources/js/chat-room/toast.js b/resources/js/chat-room/toast.js new file mode 100644 index 0000000..0cb5728 --- /dev/null +++ b/resources/js/chat-room/toast.js @@ -0,0 +1,116 @@ +// 聊天室右下角 Toast 通知组件,提供 window.chatToast.show 兼容入口。 + +/** + * 淡出并移除 Toast 卡片。 + * + * @param {HTMLElement} card + * @returns {void} + */ +function dismissToast(card) { + card.style.opacity = "0"; + window.setTimeout(() => card.remove(), 400); +} + +/** + * 创建右下角 Toast 通知 API。 + * + * @param {HTMLElement} container + * @returns {{show: Function}} + */ +function createChatToast(container) { + return { + /** + * 显示一条 Toast 通知卡片。 + * + * @param {object} options + * @param {string} options.title 标题文字 + * @param {string} options.message 内容 HTML + * @param {string} [options.icon] 左侧 Emoji + * @param {string} [options.color] 强调色 + * @param {number} [options.duration] 自动消失毫秒,0 表示不自动消失 + * @param {object|null} [options.action] 操作按钮 { label, onClick } + * @returns {void} + */ + show({ + title, + message, + icon = "💬", + color = "#336699", + duration = 6000, + action = null, + }) { + const card = document.createElement("div"); + card.style.cssText = ` + background:#fff; border-radius:10px; overflow:hidden; + box-shadow:0 8px 32px rgba(0,0,0,.18); + min-width:260px; max-width:320px; + font-size:13px; color:#374151; line-height:1.6; + pointer-events:all; + animation:toastSlideIn .3s ease; + opacity:1; transition:opacity .4s; + `; + + const actionHtml = action ? ` +
+ +
` : ""; + + card.innerHTML = ` +
+ + ${icon} ${title} + + +
+
+
${message}
+ ${actionHtml} +
+ `; + + card.querySelector(".chat-toast-close")?.addEventListener("click", () => dismissToast(card)); + + if (action) { + card.querySelector(".chat-toast-action-btn")?.addEventListener("click", () => { + action.onClick?.(); + dismissToast(card); + }); + } + + container.appendChild(card); + + // Toast 出现时沿用旧体验播放提示音。 + window.chatSound?.ding?.(); + + if (duration > 0) { + window.setTimeout(() => dismissToast(card), duration); + } + }, + }; +} + +/** + * 绑定全局 Toast API。 + * + * @returns {void} + */ +export function bindChatToast() { + if (typeof document === "undefined" || window.chatToast) { + return; + } + + const container = document.getElementById("chat-toast-container"); + if (!container) { + return; + } + + window.chatToast = createChatToast(container); +} diff --git a/resources/views/chat/partials/toast-notification.blade.php b/resources/views/chat/partials/toast-notification.blade.php index 89b4e45..0dea54f 100644 --- a/resources/views/chat/partials/toast-notification.blade.php +++ b/resources/views/chat/partials/toast-notification.blade.php @@ -25,107 +25,6 @@ display:flex; flex-direction:column-reverse; gap:10px; pointer-events:none;"> - -