🐛 提升生命周期展开收起响应 #5

Merged
orion merged 1 commits from test/custom-admin-ui into master 2026-07-09 17:33:11 +08:00
+40 -24
View File
@@ -62,39 +62,55 @@ def write_detail_collapse_script(theme_dir: Path) -> bool:
js = r'''(() => {
const EVENT_RE = /(第\s*\d+\s*次取件|取件\s*[#]\s*\d+|Retrieval\s*#\s*\d+)/i;
const LIFE_RE = /(生命周期|Lifecycle)/i;
const markRows = () => {
document.querySelectorAll('section').forEach(section => {
const STATE = new WeakMap();
const getRows = section => [...section.querySelectorAll('div.grid')].filter(row => EVENT_RE.test(row.textContent || ''));
const apply = section => {
const rows = getRows(section);
if (rows.length <= 3) return;
const expanded = STATE.get(section) === true;
rows.forEach((row, idx) => { row.hidden = !expanded && idx >= 3; });
const btn = section.querySelector(':scope > .fcbx-life-toggle') || section.querySelector('.fcbx-life-toggle');
if (btn) {
btn.textContent = expanded ? '收起取件记录' : `展开全部取件记录(共 ${rows.length} 次)`;
btn.setAttribute('aria-expanded', expanded ? 'true' : 'false');
}
};
const ensureSection = section => {
const title = section.querySelector('h1,h2,h3,h4,h5');
if (!title || !LIFE_RE.test(title.textContent || '')) return;
const rows = [...section.querySelectorAll('div.grid')].filter(row => EVENT_RE.test(row.textContent || ''));
const rows = getRows(section);
if (rows.length <= 3) return;
if (section.dataset.fcbxLifecycleReady !== '1') {
section.dataset.fcbxLifecycleReady = '1';
section.dataset.fcbxLifecycleCollapsed = '1';
const btn = document.createElement('button');
if (!STATE.has(section)) STATE.set(section, false);
let btn = section.querySelector(':scope > .fcbx-life-toggle');
if (!btn) {
btn = document.createElement('button');
btn.type = 'button';
btn.className = 'fcbx-life-toggle mt-3 rounded-lg border px-3 py-2 text-sm font-medium transition';
btn.style.cssText = 'border-color:rgba(148,163,184,.55);display:inline-flex;align-items:center;gap:.35rem;';
btn.addEventListener('click', event => {
event.preventDefault();
event.stopPropagation();
section.dataset.fcbxLifecycleCollapsed = section.dataset.fcbxLifecycleCollapsed === '1' ? '0' : '1';
apply(section);
});
(section.lastElementChild || section).appendChild(btn);
btn.style.cssText = 'border-color:rgba(148,163,184,.55);display:inline-flex;align-items:center;gap:.35rem;touch-action:manipulation;user-select:none;';
section.appendChild(btn);
}
apply(section);
});
};
const apply = section => {
const rows = [...section.querySelectorAll('div.grid')].filter(row => EVENT_RE.test(row.textContent || ''));
const collapsed = section.dataset.fcbxLifecycleCollapsed !== '0';
rows.forEach((row, idx) => { row.style.display = collapsed && idx >= 3 ? 'none' : ''; });
const btn = section.querySelector('.fcbx-life-toggle');
if (btn) btn.textContent = collapsed ? `展开全部取件记录(共 ${rows.length} 次)` : '收起取件记录';
const markRows = () => document.querySelectorAll('section').forEach(ensureSection);
const toggle = target => {
const btn = target.closest?.('.fcbx-life-toggle');
if (!btn) return false;
const section = btn.closest('section');
if (!section) return false;
STATE.set(section, STATE.get(section) !== true);
apply(section);
return true;
};
let timer = 0;
const schedule = () => { clearTimeout(timer); timer = setTimeout(markRows, 80); };
const onToggle = event => {
if (!toggle(event.target)) return;
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation?.();
};
document.addEventListener('pointerdown', onToggle, true);
document.addEventListener('click', onToggle, true);
let raf = 0;
const schedule = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(markRows); };
window.addEventListener('hashchange', schedule);
document.addEventListener('DOMContentLoaded', schedule);
new MutationObserver(schedule).observe(document.documentElement, { childList: true, subtree: true });