init
This commit is contained in:
commit
b10790c212
40 changed files with 4149 additions and 0 deletions
57
frontend/js/notifications.js
Normal file
57
frontend/js/notifications.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// js/notifications.js - 提供Toast和Dialog两种通知
|
||||
|
||||
// 这个模块在初始化时需要知道容器的DOM元素
|
||||
let toastContainer;
|
||||
let dialogContainer;
|
||||
|
||||
function hideToast(toastElement) {
|
||||
if (!toastElement) return;
|
||||
toastElement.classList.remove('show');
|
||||
toastElement.addEventListener('transitionend', () => toastElement.remove(), { once: true });
|
||||
}
|
||||
|
||||
export const notification = {
|
||||
init: (toastEl, dialogEl) => {
|
||||
toastContainer = toastEl;
|
||||
dialogContainer = dialogEl;
|
||||
},
|
||||
toast: (message, type = 'info', duration = 3000) => {
|
||||
const icons = { success: 'fa-check-circle', error: 'fa-times-circle', info: 'fa-info-circle', warning: 'fa-exclamation-triangle' };
|
||||
const iconClass = icons[type] || 'fa-info-circle';
|
||||
const toastElement = document.createElement('div');
|
||||
toastElement.className = `toast ${type}`;
|
||||
toastElement.innerHTML = `<i class="toast-icon fa-solid ${iconClass}"></i><p class="toast-message">${message}</p><button class="toast-close" data-toast-close>×</button>`;
|
||||
toastContainer.appendChild(toastElement);
|
||||
requestAnimationFrame(() => toastElement.classList.add('show'));
|
||||
const timeoutId = setTimeout(() => hideToast(toastElement), duration);
|
||||
toastElement.querySelector('[data-toast-close]').addEventListener('click', () => {
|
||||
clearTimeout(timeoutId);
|
||||
hideToast(toastElement);
|
||||
});
|
||||
},
|
||||
confirm: (message) => {
|
||||
return new Promise(resolve => {
|
||||
const dialogHTML = `
|
||||
<div class="dialog-box">
|
||||
<p class="dialog-message">${message}</p>
|
||||
<div class="dialog-actions">
|
||||
<button class="btn btn-secondary" data-action="cancel">取消</button>
|
||||
<button class="btn btn-primary" data-action="confirm">确定</button>
|
||||
</div>
|
||||
</div>`;
|
||||
dialogContainer.innerHTML = dialogHTML;
|
||||
dialogContainer.classList.add('active');
|
||||
const eventHandler = (e) => {
|
||||
const actionButton = e.target.closest('[data-action]');
|
||||
if (!actionButton) return;
|
||||
closeDialog(actionButton.dataset.action === 'confirm');
|
||||
};
|
||||
const closeDialog = (result) => {
|
||||
dialogContainer.removeEventListener('click', eventHandler);
|
||||
dialogContainer.classList.remove('active');
|
||||
setTimeout(() => { dialogContainer.innerHTML = ''; resolve(result); }, 200);
|
||||
};
|
||||
dialogContainer.addEventListener('click', eventHandler);
|
||||
});
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue