class InterfaceToolbar extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.showAdvancedSearch = false; } static get idlImportGuide() { return ` 1. 支持从IDL文件(.idl)导入接口数据 2. IDL文件格式规范: module XNSim { // 机型名称 module C909 { // ATA章节名称 module ATAxx { // 输入结构体名称 struct InputStrName { @optional 变量类型 变量名称; ... } // 输出结构体名称 struct OutputStrName { @optional 变量类型 变量名称; ... } ... } } } 3. 导入过程中请勿关闭页面`; } static get icdImportGuide() { return ` 1. 支持从Excel文件(.xlsx/.xls)导入接口数据 2. 请确保Excel文件具有Inputs和Outputs两个工作表 3. Inputs工作表必须包含以下几列: Input Variable Name Variable Type Description Variable Dimensions 4. Outputs工作表必须包含以下几列: Output Variable Name Variable Type Description Variable Dimensions 5. 导入过程中请勿关闭页面`; } connectedCallback() { this.render(); this.addEventListeners(); } addEventListeners() { const addBtn = this.shadowRoot.querySelector('.add-btn'); const deleteBtn = this.shadowRoot.querySelector('.delete-btn'); const importBtn = this.shadowRoot.querySelector('.import-btn'); const codegenBtn = this.shadowRoot.querySelector('.codegen-btn'); const searchInput = this.shadowRoot.querySelector('.search-input'); const searchBtn = this.shadowRoot.querySelector('.search-btn'); const resetBtn = this.shadowRoot.querySelector('.reset-btn'); const advancedSearchBtn = this.shadowRoot.querySelector('.advanced-search-btn'); const advancedSearchPanel = this.shadowRoot.querySelector('.advanced-search-panel'); const ataSelect = this.shadowRoot.querySelector('#filterAta'); const structSelect = this.shadowRoot.querySelector('#filterStruct'); const importModal = this.shadowRoot.querySelector('#importModal'); const importExcelBtn = this.shadowRoot.querySelector('#importExcelBtn'); const importIdlBtn = this.shadowRoot.querySelector('#importIdlBtn'); const cancelImportBtn = this.shadowRoot.querySelector('#cancelImportBtn'); addBtn.addEventListener('click', () => { this.dispatchEvent(new CustomEvent('add-variable')); }); deleteBtn.addEventListener('click', () => { this.dispatchEvent(new CustomEvent('delete-variable')); }); importBtn.addEventListener('click', () => { importModal.style.display = 'block'; }); codegenBtn.addEventListener('click', async () => { // 获取当前构型ID和构型名称 const savedSelection = localStorage.getItem('xnsim-selection'); if (!savedSelection) { alert('请先选择构型'); return; } let selection; try { selection = JSON.parse(savedSelection); } catch (e) { alert('构型信息解析失败'); return; } const configurationId = selection.configurationId; if (!configurationId) { alert('请先选择构型'); return; } this.showCodegenMask('准备生成代码...', 0); // 步骤配置 const steps = [ { url: '/api/interface-gen/step1', msg: '初始化接口生成参数...', body: { configID: configurationId } }, { url: '/api/interface-gen/step2', msg: '获取接口数据...' }, { url: '/api/interface-gen/step3', msg: '创建构型接口目录...' }, { url: '/api/interface-gen/step4', msg: '生成IDL文件...' }, { url: '/api/interface-gen/step5', msg: '生成FastDDS接口代码...' }, { url: '/api/interface-gen/step6', msg: '生成DDS接口代码...' }, { url: '/api/interface-gen/step7', msg: '生成CMakeLists文件...' }, { url: '/api/interface-gen/step8', msg: 'CMake构建并安装...' }, { url: '/api/interface-gen/step9', msg: '执行sudo ldconfig...' } ]; let success = true; for (let i = 0; i < steps.length; i++) { const step = steps[i]; const percent = Math.round((i / steps.length) * 100); this.updateCodegenProgress(step.msg, percent); try { let response; if (step.body) { response = await fetch(step.url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(step.body) }); } else { response = await fetch(step.url, { method: 'POST' }); } const result = await response.json(); if (!result.success) { this.updateCodegenProgress(`❌ ${step.msg} 失败:${result.message}`, percent); success = false; break; } else { this.updateCodegenProgress(`✅ ${step.msg} 完成`, percent + 1); } } catch (err) { this.updateCodegenProgress(`❌ ${step.msg} 异常:${err.message}`, percent); success = false; break; } await new Promise(r => setTimeout(r, 400)); } if (success) { this.updateCodegenProgress('🎉 代码生成全部完成!', 100); await new Promise(r => setTimeout(r, 400)); } setTimeout(() => { this.hideCodegenMask(); if (success) { alert('代码生成全部完成!'); } else { alert('代码生成失败,请检查进度提示!'); } }, 800); }); importExcelBtn.addEventListener('click', () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.xlsx,.xls'; input.onchange = (e) => { const file = e.target.files[0]; if (file) { this.dispatchEvent(new CustomEvent('import-data', { detail: { file, type: 'excel' } })); importModal.style.display = 'none'; } }; input.click(); }); importIdlBtn.addEventListener('click', () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.idl'; input.onchange = (e) => { const file = e.target.files[0]; if (file) { this.dispatchEvent(new CustomEvent('import-data', { detail: { file, type: 'idl' } })); importModal.style.display = 'none'; } }; input.click(); }); cancelImportBtn.addEventListener('click', () => { importModal.style.display = 'none'; }); // 点击模态框外部关闭 importModal.addEventListener('click', (e) => { if (e.target === importModal) { importModal.style.display = 'none'; } }); searchBtn.addEventListener('click', () => { const keyword = searchInput.value.trim(); this.dispatchEvent(new CustomEvent('search', { detail: { keyword } })); }); resetBtn.addEventListener('click', () => { // 重置搜索框 searchInput.value = ''; // 重置高级搜索下拉框 ataSelect.value = ''; structSelect.value = ''; // 触发重置事件 this.dispatchEvent(new CustomEvent('reset-search')); }); advancedSearchBtn.addEventListener('click', () => { this.showAdvancedSearch = !this.showAdvancedSearch; advancedSearchPanel.style.display = this.showAdvancedSearch ? 'flex' : 'none'; advancedSearchBtn.classList.toggle('active'); }); // 监听高级搜索的筛选条件变化 [ataSelect, structSelect].forEach(select => { select.addEventListener('change', () => { this.dispatchEvent(new CustomEvent('advanced-search', { detail: { ataName: ataSelect.value, structName: structSelect.value } })); }); }); } render() { this.shadowRoot.innerHTML = `