hyapp-h5/common/loading.js
2026-07-09 13:25:54 +08:00

105 lines
3.6 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.

(function () {
// 通用全屏 loading拉鲁猫吉祥物 + 转圈)。
// 样式复用 common/theme.css 的 .hy-loading 系列类:新页面按仓库约定必须引入 theme.css
// 组件自身只负责 DOM 注入和显隐状态,不重复维护一份样式副本避免两处漂移。
// 吉祥物图取 theme.css 默认值lalu 紫猫动画 webp其他 app 主题可在
// [data-hy-app-code='...'] 下覆盖 .hy-loading__mascot 的 background 换皮。
var LOADING_ID = 'hy-global-loading';
// show/hide 采用引用计数:并发请求各自 show/hide 时,最后一个 hide 才真正关闭遮罩,
// 避免先完成的请求把还在加载的请求的遮罩提前关掉。
var visibleCount = 0;
function ensureNode() {
var node = document.getElementById(LOADING_ID);
if (node) return node;
node = document.createElement('div');
node.id = LOADING_ID;
node.className = 'hy-loading';
node.setAttribute('role', 'status');
node.setAttribute('aria-live', 'polite');
node.setAttribute('aria-hidden', 'true');
var mascot = document.createElement('div');
mascot.className = 'hy-loading__mascot';
mascot.setAttribute('aria-hidden', 'true');
var spinner = document.createElement('div');
spinner.className = 'hy-loading__spinner';
spinner.setAttribute('aria-hidden', 'true');
var text = document.createElement('div');
text.className = 'hy-loading__text';
text.hidden = true;
node.appendChild(mascot);
node.appendChild(spinner);
node.appendChild(text);
document.body.appendChild(node);
return node;
}
function render() {
var node = ensureNode();
var active = visibleCount > 0;
node.classList.toggle('is-active', active);
node.setAttribute('aria-hidden', active ? 'false' : 'true');
}
function setText(node, message) {
var text = node.querySelector('.hy-loading__text');
if (!text) return;
var value = String(message || '').trim();
// 文案由调用方传入已本地化的字符串组件不内置多语言字典common/i18n.js 归页面消费)。
text.textContent = value;
text.hidden = !value;
}
function show(options) {
if (!document.body) {
// 页面脚本可能在 body 就绪前调用;挂到 DOMContentLoaded 重放,保持调用方无需关心时序。
document.addEventListener(
'DOMContentLoaded',
function () {
show(options);
},
{ once: true }
);
return;
}
visibleCount += 1;
var node = ensureNode();
setText(node, options && options.text);
render();
}
function hide(force) {
if (force) {
visibleCount = 0;
} else if (visibleCount > 0) {
visibleCount -= 1;
}
if (!document.getElementById(LOADING_ID)) return;
render();
}
function isVisible() {
return visibleCount > 0;
}
window.HyAppLoading = {
show: show,
hide: hide,
isVisible: isVisible,
};
// 与 HyAppToast 的 hyapp:toast 对齐的事件桥:原生壳或其他脚本可通过事件控制遮罩。
window.addEventListener('hyapp:loading', function (event) {
var detail = event.detail || {};
if (detail.visible === false) {
hide(detail.force === true);
return;
}
show(detail);
});
})();