mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-06-16 11:00:20 +02:00
93 lines
3.0 KiB
JavaScript
93 lines
3.0 KiB
JavaScript
/**
|
|
* 统一弹窗:先显示遮罩、下一帧再填大段内容,避免与 backdrop 绘制抢主线程。
|
|
*/
|
|
(function () {
|
|
const BODY_LOCK = 'app-modal-open';
|
|
const LEGACY_BODY_LOCK = 'projects-modal-open';
|
|
const OVERLAY_SELECTOR =
|
|
'.projects-modal-overlay, .c2-modal-overlay, .modal, .info-collect-cell-modal, #login-overlay';
|
|
|
|
const FLEX_MODAL_IDS = new Set([
|
|
'role-modal',
|
|
'skill-modal',
|
|
'agent-md-modal',
|
|
'batch-manage-modal',
|
|
'create-group-modal',
|
|
'login-overlay',
|
|
]);
|
|
|
|
function resolveEl(idOrEl) {
|
|
if (!idOrEl) return null;
|
|
return typeof idOrEl === 'string' ? document.getElementById(idOrEl) : idOrEl;
|
|
}
|
|
|
|
function isElVisible(el) {
|
|
if (!el) return false;
|
|
const s = window.getComputedStyle(el);
|
|
return s.display !== 'none' && s.visibility !== 'hidden';
|
|
}
|
|
|
|
function defaultDisplay(el) {
|
|
if (el.classList.contains('projects-modal-overlay') || el.classList.contains('c2-modal-overlay')) {
|
|
return 'flex';
|
|
}
|
|
if (el.classList.contains('info-collect-cell-modal')) {
|
|
return 'flex';
|
|
}
|
|
if (FLEX_MODAL_IDS.has(el.id)) {
|
|
return 'flex';
|
|
}
|
|
return 'block';
|
|
}
|
|
|
|
function syncBodyLock() {
|
|
const anyOpen = Array.from(document.querySelectorAll(OVERLAY_SELECTOR)).some(isElVisible);
|
|
document.body.classList.toggle(BODY_LOCK, anyOpen);
|
|
const projectsOpen = Array.from(document.querySelectorAll('.projects-modal-overlay')).some(isElVisible);
|
|
document.body.classList.toggle(LEGACY_BODY_LOCK, projectsOpen);
|
|
}
|
|
|
|
function openAppModal(idOrEl, opts) {
|
|
opts = opts || {};
|
|
const el = resolveEl(idOrEl);
|
|
if (!el) return null;
|
|
el.style.display = opts.display || defaultDisplay(el);
|
|
syncBodyLock();
|
|
if (opts.focus === false) return el;
|
|
const sel =
|
|
opts.focusSelector ||
|
|
'input.form-input, textarea.form-input, select.form-input, input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled])';
|
|
const focusTarget = opts.focusEl || el.querySelector(sel);
|
|
if (focusTarget) {
|
|
requestAnimationFrame(function () {
|
|
focusTarget.focus();
|
|
});
|
|
}
|
|
return el;
|
|
}
|
|
|
|
function closeAppModal(idOrEl) {
|
|
const el = resolveEl(idOrEl);
|
|
if (el) el.style.display = 'none';
|
|
syncBodyLock();
|
|
return el;
|
|
}
|
|
|
|
function isAppModalOpen(idOrEl) {
|
|
return isElVisible(resolveEl(idOrEl));
|
|
}
|
|
|
|
/** 双 rAF:等遮罩绘制完成后再写入大段 DOM / 表单 */
|
|
function deferModalContent(fn) {
|
|
requestAnimationFrame(function () {
|
|
requestAnimationFrame(fn);
|
|
});
|
|
}
|
|
|
|
window.openAppModal = openAppModal;
|
|
window.closeAppModal = closeAppModal;
|
|
window.isAppModalOpen = isAppModalOpen;
|
|
window.deferModalContent = deferModalContent;
|
|
window.syncAppModalBodyLock = syncBodyLock;
|
|
})();
|