Files
Fuxsto-V4/Dashboard/msg.js
2025-10-18 10:19:37 +08:00

236 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 终极消息系统 (保留所有优秀特性)
(() => {
// 完美图标系统
const icons = {
success: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="msg-svg"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15l-4-4 1.41-1.41L11 14.17l6.59-6.59L19 9l-8 8z"/></svg>',
error: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="msg-svg"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/></svg>',
warning: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="msg-svg"><path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>',
info: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="msg-svg"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>'
};
// 专业配置系统
const config = {
duration: 3000,
spacing: 10,
maxMessages: 10,
closable: false,
enterAnimation: 'msg-slideIn',
exitAnimation: 'msg-fadeOutUp'
};
// 完美样式系统
const style = document.createElement('style');
style.textContent = `
@keyframes msg-slideIn {
0% { opacity: 0; transform: translate(-50%, -20px);
filter: blur(5px); }
100% { opacity: 1; transform: translate(-50%, 0);
filter: blur(0px); }
}
@keyframes msg-fadeOutUp {
0% { opacity: 1; transform: translate(-50%, 0);
filter: blur(0px); }
100% { opacity: 0; transform: translate(-50%, -100px);
filter: blur(5px); }
}
.msg {
position: fixed;
left: 50%;
transform: translateX(-50%);
min-width: 300px;
max-width: 90vw;
padding: 14px 20px;
border-radius: 15px;
background: #fff;
display: flex;
align-items: center;
z-index: 9999;
opacity: 0;
transition: top 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
font-family: system-ui, sans-serif;
}
.msg-enter {
animation: ${config.enterAnimation} 0.5s forwards;
}
.msg-exit {
animation: ${config.exitAnimation} 0.5s forwards;
}
.msg-icon {
width: 24px;
height: 24px;
margin-right: 12px;
flex-shrink: 0;
animation: msg-content-in 0.4s ease-in-out 0.5s forwards;
}
.msg-content {
flex: 1;
font-size: 14px;
line-height: 1.5;
padding-right: 8px;
transition: all 0.5s;
animation: msg-content-in 0.4s ease-in-out 0.55s forwards;
}
@keyframes msg-content-in {
0% { opacity: 1;
filter: blur(0px); }
50% { opacity: 1;
filter: blur(2px); }
} 100% { opacity: 1;
filter: blur(0px); }
}
.msg-close {
cursor: pointer;
width: 24px;
height: 24px;
margin-left: 8px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
transition: all 0.5s;
color: rgba(0,0,0,0.5);
flex-shrink: 0;
animation: msg-content-in 0.4s ease-in-out 0.6s forwards;
}
.msg-close:hover {
background: rgba(0,0,0,0.08);
color: rgba(0,0,0,0.8);
}
/* 专业配色方案 */
.msg-success { color: #10B981; box-shadow: 0px 0px 4px rgba(16, 185, 129, 0.2);}
.msg-error { color: #EF4444; box-shadow: 0px 0px 4px rgba(239, 68, 68, 0.2);}
.msg-warning { color: #F59E0B; box-shadow: 0px 0px 4px rgba(245, 158, 11, 0.2);}
.msg-info { color: #3B82F6; box-shadow: 0px 0px 4px rgba(59, 130, 246, 0.2);}
`;
document.head.appendChild(style);
// 终极消息管理器
class MsgManager {
static instances = [];
static add(msg) {
if (this.instances.length >= config.maxMessages) {
this.instances[0].close();
}
this.instances.push(msg);
this.updateLayout();
}
static remove(msg) {
const index = this.instances.indexOf(msg);
if (index > -1) {
this.instances.splice(index, 1);
this.updateLayout(true);
}
}
static updateLayout(animate = false) {
let top = 20;
this.instances.forEach(instance => {
instance.element.style.transition = animate ? 'top 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)' : 'none';
instance.element.style.top = `${top}px`;
top += instance.element.offsetHeight + config.spacing;
});
}
}
// 完美消息实例
class Msg {
constructor(type, content, options) {
this.type = type;
this.content = content;
this.options = { ...config, ...options };
this.element = this.createElement();
this.setupEvents();
this.show();
}
createElement() {
const el = document.createElement('div');
el.className = `msg msg-${this.type}`;
const closeBtn = this.options.closable
? '<div class="msg-close" role="button">×</div>'
: '';
el.innerHTML = `
<div class="msg-icon">${icons[this.type]}</div>
<div class="msg-content">${this.content}</div>
${closeBtn}
`;
return el;
}
setupEvents() {
if (this.options.closable) {
this.element.querySelector('.msg-close').addEventListener('click', () => this.close());
}
}
show() {
document.body.appendChild(this.element);
requestAnimationFrame(() => {
this.element.classList.add('msg-enter');
MsgManager.add(this);
});
this.autoCloseTimer = setTimeout(() => this.close(), this.options.duration);
}
close() {
clearTimeout(this.autoCloseTimer);
this.element.classList.remove('msg-enter');
this.element.classList.add('msg-exit');
setTimeout(() => {
this.element.remove();
MsgManager.remove(this);
}, 500);
}
}
// 终极API暴露
const Message = {
config(newConfig) {
Object.assign(config, newConfig);
},
success(content, options) {
return new Msg('success', content, options);
},
error(content, options) {
return new Msg('error', content, options);
},
warning(content, options) {
return new Msg('warning', content, options);
},
info(content, options) {
return new Msg('info', content, options);
},
closeAll() {
MsgManager.instances.slice().forEach(msg => msg.close());
}
};
window.Message = Message;
})();
// 完美调用示例
//Message.success('');
//Message.error('验证失败', { closable: true, duration: 5000 });