import { escapeHtml, inferEnhancementClass, inferEnhancementLabel } from '../common.js'; // 侧栏数据源树。数据源当作"盘符",可展开显示一层根目录快捷入口。 // 事件通过回调向编排器上报:onOpenSource / onOpenPath / onContextMenu。 export function createSidebar(rootElement, { onOpenSource, onContextMenu }) { let sources = []; let activeSourceId = null; function statusDotClass(source) { // 复用增强状态的语义色:ready/busy/error/idle switch (inferEnhancementClass(source)) { case 'status-ready': return 'ready'; case 'status-busy': return 'busy'; case 'status-error': return 'error'; default: return 'idle'; } } function render() { if (sources.length === 0) { rootElement.innerHTML = '
暂无数据源,请从「上传任务库」添加。
'; return; } rootElement.innerHTML = sources .map((source) => { const active = source.id === activeSourceId; const label = source.displayName || source.originalFilename || source.id; const dot = statusDotClass(source); const title = `${label} · ${inferEnhancementLabel(source)}`; return `
${escapeHtml(label)}
`; }) .join(''); } function findSource(sourceId) { return sources.find((source) => source.id === sourceId) ?? null; } rootElement.addEventListener('click', (event) => { const item = event.target.closest('.explorer-tree-item'); if (!(item instanceof HTMLElement)) { return; } onOpenSource?.(item.dataset.sourceId); }); rootElement.addEventListener('keydown', (event) => { if (event.key !== 'Enter' && event.key !== ' ') { return; } const item = event.target.closest('.explorer-tree-item'); if (!(item instanceof HTMLElement)) { return; } event.preventDefault(); onOpenSource?.(item.dataset.sourceId); }); rootElement.addEventListener('contextmenu', (event) => { const item = event.target.closest('.explorer-tree-item'); if (!(item instanceof HTMLElement)) { return; } event.preventDefault(); onContextMenu?.(item.dataset.sourceId, { x: event.clientX, y: event.clientY }); }); return { setSources(nextSources) { sources = Array.isArray(nextSources) ? nextSources : []; render(); }, setActive(sourceId) { activeSourceId = sourceId; render(); }, getSource: findSource, getSources() { return sources; } }; }