refactor(frontend): replace toast system with zibll notyf

This commit is contained in:
kate522 committed 2026-08-18 02:38:43 +08:00
1 parent fb11a7ed0c
commit 86614c4905
33 files changed
+603 -802

No files matched your search

+8 -126
View File
@@ -3,7 +3,6 @@
*
* Unified core primitives for the entire frontend:
* aksrt.tbquire(deps, cb) — lazy script/CSS loader
* aksrt.notyf(msg, opts) — unified toast (same-ID update)
* aksrt.confirm(msg, opts) — i18n confirm dialog
* aksrt.scrollTopTo(target, off) — smart scroll with header offset
* aksrt.loading(el, show) — element-level loading overlay
@@ -93,123 +92,6 @@
return p;
};
// ══════════════════════════════════════════════════════════════
// §10.10 — notyf: unified toast with same-ID update
// ══════════════════════════════════════════════════════════════
var _notyfContainer = null;
var _notyfMap = {};
var NOTYF_DURATION = 5000;
function getNotyfContainer() {
if (_notyfContainer && _notyfContainer.parentNode) return _notyfContainer;
_notyfContainer = document.createElement('div');
_notyfContainer.className = 'aksrt-notyf';
_notyfContainer.setAttribute('role', 'alert');
_notyfContainer.setAttribute('aria-live', 'polite');
document.body.appendChild(_notyfContainer);
return _notyfContainer;
}
function createNotyfItem(msg, opts) {
var el = document.createElement('div');
el.className = 'aksrt-notyf__item aksrt-notyf--' + (opts.type || 'info');
if (opts.type === 'load') el.classList.add('aksrt-notyf--loading');
var iconMap = {
success: '<i class="fas fa-check-circle"></i>',
danger: '<i class="fas fa-exclamation-circle"></i>',
error: '<i class="fas fa-exclamation-circle"></i>',
warning: '<i class="fas fa-exclamation-triangle"></i>',
load: '<i class="fas fa-spinner fa-spin"></i>',
info: '<i class="fas fa-info-circle"></i>'
};
el.innerHTML =
'<span class="aksrt-notyf__icon">' + (iconMap[opts.type] || iconMap.info) + '</span>' +
'<span class="aksrt-notyf__text">' + escapeHtml(msg) + '</span>' +
'<button type="button" class="aksrt-notyf__close" aria-label="Close">&times;</button>';
el.querySelector('.aksrt-notyf__close').addEventListener('click', function () {
removeNotyf(el, opts.id);
});
return el;
}
function removeNotyf(el, id) {
el.classList.add('aksrt-notyf--out');
setTimeout(function () {
if (el.parentNode) el.parentNode.removeChild(el);
}, 300);
if (id && _notyfMap[id]) {
clearTimeout(_notyfMap[id].timer);
delete _notyfMap[id];
}
}
aksrt.notyf = function (msg, opts) {
if (typeof opts === 'string') opts = { type: opts };
opts = opts || {};
var type = opts.type || 'info';
var duration = type === 'load' ? 0 : (opts.duration || NOTYF_DURATION);
var id = opts.id || null;
var container = getNotyfContainer();
if (id && _notyfMap[id]) {
var existing = _notyfMap[id];
clearTimeout(existing.timer);
existing.el.className = 'aksrt-notyf__item aksrt-notyf--' + type;
existing.el.querySelector('.aksrt-notyf__text').textContent = msg;
var iconSpan = existing.el.querySelector('.aksrt-notyf__icon');
var iconMap2 = {
success: '<i class="fas fa-check-circle"></i>',
danger: '<i class="fas fa-exclamation-circle"></i>',
error: '<i class="fas fa-exclamation-circle"></i>',
warning: '<i class="fas fa-exclamation-triangle"></i>',
load: '<i class="fas fa-spinner fa-spin"></i>',
info: '<i class="fas fa-info-circle"></i>'
};
iconSpan.innerHTML = iconMap2[type] || iconMap2.info;
if (duration > 0) {
existing.timer = setTimeout(function () { removeNotyf(existing.el, id); }, duration);
}
return existing.el;
}
var el = createNotyfItem(msg, { type: type, id: id });
container.appendChild(el);
requestAnimationFrame(function () {
el.classList.add('aksrt-notyf--in');
});
var timer = null;
if (duration > 0) {
timer = setTimeout(function () { removeNotyf(el, id); }, duration);
}
if (id) {
_notyfMap[id] = { el: el, timer: timer };
}
return el;
};
aksrt.notyf.close = function (id) {
if (_notyfMap[id]) removeNotyf(_notyfMap[id].el, id);
};
// Backward compat: wire window.aksrtToast to notyf
window.aksrtToast = function (msg, type) {
aksrt.notyf(msg, { type: type || 'info', duration: 2200 });
};
// Alias used by several modules that call aksrt.toast(...)
aksrt.toast = function (msg, type) {
return aksrt.notyf(msg, typeof type === 'string' ? { type: type, duration: 2200 } : (type || { duration: 2200 }));
};
// ══════════════════════════════════════════════════════════════
// §10.10 — confirm: i18n confirm dialog + [data-confirm]
// ══════════════════════════════════════════════════════════════
@@ -551,7 +433,7 @@
if (action === 'like' || action === 'favorite') {
try {
if (localStorage.getItem(storageKey) && !btn.classList.contains('is-active')) {
aksrt.notyf(__('already_done', '已操作'), 'warning');
notyf(__('already_done', '已操作'), 'warning');
return;
}
} catch (ex) { /* storage unavailable */ }
@@ -562,7 +444,7 @@
var ajaxUrl = (window.aksrtData && aksrtData.ajaxUrl) || '/wp-admin/admin-ajax.php';
if (!(window.aksrtData && aksrtData.nonce)) {
btn.classList.remove('is-loading');
aksrt.notyf(__('action_failed', '操作失败'), 'danger');
notyf(__('action_failed', '操作失败'), 'danger');
return;
}
var params = new URLSearchParams();
@@ -602,19 +484,19 @@
} catch (ex) { /* */ }
if (json.data && json.data.message) {
aksrt.notyf(json.data.message, 'success');
notyf(json.data.message, 'success');
}
if (json.data && json.data.goto) {
window.location.href = json.data.goto;
}
} else {
aksrt.notyf((json.data && json.data.message) || __('action_failed', '操作失败'), 'danger');
notyf((json.data && json.data.message) || __('action_failed', '操作失败'), 'danger');
}
})
.catch(function (err) {
btn.classList.remove('is-loading');
aksrt.notyf(err.message || __('network_error', '网络错误'), 'danger');
notyf(err.message || __('network_error', '网络错误'), 'danger');
});
}
@@ -651,7 +533,7 @@
kind: 'generic',
});
} else if (json.data && json.data.message) {
aksrt.notyf(json.data.message, 'success');
notyf(json.data.message, 'success');
}
if (json.data && json.data.goto) {
window.location.href = json.data.goto;
@@ -660,12 +542,12 @@
window.location.reload();
}
} else {
aksrt.notyf((json.data && json.data.message) || __('action_failed', '操作失败'), 'danger');
notyf((json.data && json.data.message) || __('action_failed', '操作失败'), 'danger');
}
})
.catch(function (err) {
btn.classList.remove('is-loading');
aksrt.notyf(err.message || __('network_error', '网络错误'), 'danger');
notyf(err.message || __('network_error', '网络错误'), 'danger');
});
}