From c3b3ed36811f7fddd1b775e2ef7dfb26e1dcfa6a Mon Sep 17 00:00:00 2001 From: MichaelWin Date: Mon, 3 Nov 2025 10:39:46 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E5=B0=81?= =?UTF-8?q?=E8=A3=85=E6=8F=90=E7=A4=BA=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/static/assets/js/message.js | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/main/resources/static/assets/js/message.js diff --git a/src/main/resources/static/assets/js/message.js b/src/main/resources/static/assets/js/message.js new file mode 100644 index 0000000..d06b825 --- /dev/null +++ b/src/main/resources/static/assets/js/message.js @@ -0,0 +1,145 @@ +if (!window.Vue) { + const vueScript = document.createElement('script'); + vueScript.src = 'https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js'; + document.head.appendChild(vueScript); +} + +if (!document.querySelector('link[href*="bootstrap-icons"]')) { + const iconLink = document.createElement('link'); + iconLink.rel = 'stylesheet'; + iconLink.href = 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css'; + document.head.appendChild(iconLink); +} + +const style = document.createElement('style'); +style.textContent = ` + .h5-message-container { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 9999; + pointer-events: none; + } + + .h5-message { + display: flex; + align-items: center; + padding: 14px 24px; + border-radius: 8px; + color: #fff; + font-size: 16px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); + animation: h5MsgShow 0.4s ease-out forwards; + } + .h5-message.success { background-color: rgba(40, 167, 69, 0.95); } + .h5-message.error { background-color: rgba(220, 53, 69, 0.95); } + .h5-message.warning { background-color: rgba(255, 193, 7, 0.95); color: #333; } + .h5-message.info { background-color: rgba(13, 110, 253, 0.95); } + .h5-message-icon { + margin-right: 10px; + font-size: 20px; + } + @keyframes h5MsgShow { + from { opacity: 0; transform: translate(-50%, -50%) scale(0.9); } + to { opacity: 1; transform: translate(-50%, -50%) scale(1); } + } + .h5-message.hide { animation: h5MsgHide 0.4s ease-in forwards; } + @keyframes h5MsgHide { + from { opacity: 1; transform: translate(-50%, -50%) scale(1); } + to { opacity: 0; transform: translate(-50%, -50%) scale(0.9); } + } +`; +document.head.appendChild(style); + +const messageTemplate = ` +
+ + {{ message }} +
+`; +const messageInstances = []; +function showMessage(options) { + if (typeof options === 'string') { + options = { message: options }; + } + + const config = { + message: '', + type: 'info', + duration: 3000, + ...options, + duration: Math.max(1000, options.duration || 3000) + }; + + const checkVueLoaded = setInterval(() => { + if (window.Vue) { + clearInterval(checkVueLoaded); + + const container = document.createElement('div'); + container.className = 'h5-message-container'; + document.body.appendChild(container); + const app = Vue.createApp({ + template: messageTemplate, + data() { + return { + message: config.message, + type: config.type, + visible: true + }; + }, + computed: { + iconClass() { + const icons = { + success: 'bi bi-check-circle', + error: 'bi bi-exclamation-circle', + warning: 'bi bi-exclamation-triangle', + info: 'bi bi-info-circle' + }; + return icons[this.type] || icons.info; + } + }, + mounted() { + const showTimer = setTimeout(() => { + this.visible = false; + const hideTimer = setTimeout(() => { + + const index = messageInstances.indexOf(app); + if (index > -1) { + messageInstances.splice(index, 1); + } + app.unmount(container); + document.body.removeChild(container); + clearTimeout(hideTimer); + }, 400); + + clearTimeout(showTimer); + }, config.duration); + } + }); + const instance = app.mount(container); + messageInstances.push(instance); + } + }, 50); + + setTimeout(() => { + clearInterval(checkVueLoaded); + if (!window.Vue) { + alert(config.message); + } + }, 1000); +} + + +window.$message = showMessage; + +['success', 'error', 'warning', 'info'].forEach(type => { + window.$message[type] = (message, duration) => { + window.$message({ + message, + type, + // 确保时长有效(用户未传则用默认3秒) + duration: duration ? Math.max(1000, duration) : 500 + }); + }; +}); \ No newline at end of file