// --- static/tree-ui.js ---
// ==========================================
// 🌟 效能終極優化:全域快取與延遲渲染 (Lazy Rendering)
// ==========================================
export const folderDataCache = {};
export const filterFolderCache = {};
// 🧹 [修復 Leak] 徹底清空樹狀圖快取,釋放記憶體
export function clearTreeCache() {
for (let key in folderDataCache) delete folderDataCache[key];
for (let key in filterFolderCache) delete filterFolderCache[key];
}
// 魔法函數:當資料夾被點擊展開時,才將 HTML 渲染進去
window.lazyLoadFolder = function(elementId, isFilter = false) {
const detailsEl = document.getElementById(`details-${elementId}`);
// 如果已經載入過,就不重複渲染
if (!detailsEl || detailsEl.dataset.loaded === 'true') return;
// 從 dataset 讀取當初存下來的屬性
const currentPath = detailsEl.dataset.path;
const isCommandGroup = detailsEl.dataset.isGroup === 'true';
const mode = detailsEl.dataset.mode;
const contentDiv = document.getElementById(isFilter ? `filter-content-${elementId}` : `content-${elementId}`);
const cache = isFilter ? filterFolderCache[elementId] : folderDataCache[elementId];
if (contentDiv && cache) {
if (isFilter) {
contentDiv.innerHTML = buildRealFilterTree(cache.data, currentPath, cache.hiddenKeys, isCommandGroup, mode);
} else {
contentDiv.innerHTML = buildTree(cache, currentPath, isCommandGroup, mode);
}
detailsEl.dataset.loaded = 'true'; // 標記為已載入
}
};
// ==========================================
// 🌟 輔助函數:全部展開與全部收合 (支援延遲渲染)
// ==========================================
export function expandAll(elementId) {
const details = document.getElementById(`details-${elementId}`);
if (details) {
// 如果還沒載入,先強制載入它
if (!details.dataset.loaded) {
const isFilter = details.id.includes('filter-');
window.lazyLoadFolder(elementId, isFilter);
}
details.open = true;
// 找出剛剛渲染出來的第一層子資料夾,遞迴展開
const contentDiv = details.querySelector(':scope > div');
if (contentDiv) {
const childDetails = contentDiv.querySelectorAll(':scope > details');
childDetails.forEach(d => {
const subId = d.id.replace('details-', '');
expandAll(subId); // 遞迴展開
});
}
}
}
export function collapseAll(elementId) {
const details = document.getElementById(`details-${elementId}`);
if (details) {
const subDetails = details.querySelectorAll('details');
subDetails.forEach(d => d.open = false);
details.open = false;
}
}
// ==========================================
// 🌟 核心函數:生成完整設備配置樹狀圖 (Lazy 版)
// ==========================================
export function buildTree(node, path = '', isParentCommandGroup = false, mode = 'running') {
const htmlParts = [];
if (!node || typeof node !== 'object') return htmlParts.join('');
for (const [key, value] of Object.entries(node)) {
const currentPath = path ? `${path}::${key}` : key;
let cliCommand = currentPath.replace(/::/g, ' ').replace(/\s*\[\d+\]/g, '');
if (typeof value === 'object' && value !== null) {
const hasNestedObject = Object.values(value).some(v => typeof v === 'object' && v !== null);
const isCommandGroup = isParentCommandGroup || !hasNestedObject;
const elementId = `${mode}-folder-${currentPath.replace(/[^a-zA-Z0-9]/g, '-')}`;
const folderSuffix = isCommandGroup ? '(指令群組)' : '';
// 🌟 將資料存入快取,供延遲渲染使用
folderDataCache[elementId] = value;
const svgFolderClosed = ``;
const svgFolderOpen = ``;
const svgGroupClosed = ``;
const svgGroupOpen = ``;
const iconClosed = isCommandGroup ? svgGroupClosed : svgFolderClosed;
const iconOpen = isCommandGroup ? svgGroupOpen : svgFolderOpen;
const expandAllIcon = ``;
const collapseAllIcon = ``;
const expandCollapseBtns = `
${expandAllIcon}
${collapseAllIcon}
`;
htmlParts.push(`
${iconClosed}
${key}${folderSuffix}
${expandCollapseBtns}