diff --git a/scripts/patch_admin_timeline_ui.py b/scripts/patch_admin_timeline_ui.py
index bf28182..24e9882 100644
--- a/scripts/patch_admin_timeline_ui.py
+++ b/scripts/patch_admin_timeline_ui.py
@@ -58,20 +58,38 @@ def write_detail_collapse_script(theme_dir: Path) -> bool:
index = theme_dir / 'index.html'
if not assets.exists() or not index.exists():
return False
- js_path = assets / 'fcb-detail-collapse.js'
+ js_path = assets / 'fcb-lifecycle-collapse-v3.js'
js = r'''(() => {
const LIFE_RE = /(生命周期|Lifecycle)/i;
const STATE = new WeakMap();
- const getRows = section => [...section.querySelectorAll('div.grid')].filter(row => {
- if (row.classList.contains('fcbx-life-row-skip')) return false;
- const text = row.textContent || '';
- return !!row.querySelector('span.rounded-full') && !LIFE_RE.test(text);
- });
+ const getSection = section => {
+ const title = section.querySelector('h1,h2,h3,h4,h5');
+ if (!title || !LIFE_RE.test(title.textContent || '')) return null;
+ const box = title.nextElementSibling;
+ if (!box) return null;
+ return { title, box };
+ };
+ const getRows = section => {
+ const ctx = getSection(section);
+ if (!ctx) return [];
+ return [...ctx.box.children].filter(el => el instanceof HTMLElement);
+ };
const apply = section => {
- const rows = getRows(section);
+ const ctx = getSection(section);
+ if (!ctx) return;
+ const rows = [...ctx.box.children].filter(el => el instanceof HTMLElement);
if (rows.length <= 3) return;
const expanded = STATE.get(section) === true;
- rows.forEach((row, idx) => { row.hidden = !expanded && idx >= 3; });
+ section.classList.toggle('fcbx-life-expanded', expanded);
+ rows.forEach((row, idx) => {
+ const shouldHide = idx >= 3 && !expanded;
+ row.classList.toggle('fcbx-life-row-extra', idx >= 3);
+ if (shouldHide) {
+ if (row.style.display !== 'none') row.style.setProperty('display', 'none', 'important');
+ } else if (row.style.display) {
+ row.style.removeProperty('display');
+ }
+ });
const btn = section.querySelector(':scope > .fcbx-life-toggle') || section.querySelector('.fcbx-life-toggle');
if (btn) {
btn.textContent = expanded ? '收起生命周期记录' : `展开全部生命周期记录(共 ${rows.length} 条)`;
@@ -79,9 +97,9 @@ def write_detail_collapse_script(theme_dir: Path) -> bool:
}
};
const ensureSection = section => {
- const title = section.querySelector('h1,h2,h3,h4,h5');
- if (!title || !LIFE_RE.test(title.textContent || '')) return;
- const rows = getRows(section);
+ const ctx = getSection(section);
+ if (!ctx) return;
+ const rows = [...ctx.box.children].filter(el => el instanceof HTMLElement);
if (rows.length <= 3) return;
if (!STATE.has(section)) STATE.set(section, false);
let btn = section.querySelector(':scope > .fcbx-life-toggle');
@@ -100,18 +118,33 @@ def write_detail_collapse_script(theme_dir: Path) -> bool:
}
apply(section);
};
- const markRows = () => document.querySelectorAll('section').forEach(ensureSection);
+ const markRows = root => {
+ const scope = root?.querySelectorAll ? root : document;
+ scope.querySelectorAll('section').forEach(ensureSection);
+ };
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 });
- schedule();
+ const schedule = root => { cancelAnimationFrame(raf); raf = requestAnimationFrame(() => markRows(root)); };
+ window.addEventListener('hashchange', () => schedule(document));
+ document.addEventListener('DOMContentLoaded', () => schedule(document));
+ new MutationObserver(records => {
+ for (const rec of records) {
+ if ([...rec.addedNodes].some(n => n.nodeType === 1 && ((n.matches?.('section')) || n.querySelector?.('section')))) {
+ schedule(document);
+ break;
+ }
+ }
+ }).observe(document.body || document.documentElement, { childList: true, subtree: true });
+ schedule(document);
})();'''
rewrite(js_path, js)
html = index.read_text(encoding='utf-8')
- tag = ''
- if 'fcb-detail-collapse.js' not in html:
+ # Remove old detail-collapse injection so browsers cannot keep loading the stale “取件记录” script.
+ html = html.replace('\n', '')
+ html = html.replace('', '')
+ html = html.replace('\n', '')
+ html = html.replace('', '')
+ tag = ''
+ if 'fcb-lifecycle-collapse-v3.js' not in html:
html = html.replace('