/** * 菜单管理模块 - 管理 data/config.json 中的 menuItems */ // 菜单项列表 (从 config.json 读取) let configMenuItems = []; let currentConfig = {}; // 保存当前完整的配置 // 创建menuManager对象 const menuManager = { // 初始化菜单管理 init: async function() { console.log('初始化菜单管理 (config.json)...'); this.renderMenuTableHeader(); // 渲染表头 await this.loadMenuItems(); // 加载菜单项 return Promise.resolve(); }, // 渲染菜单表格头部 (根据 config.json 结构调整) renderMenuTableHeader: function() { const menuTable = document.getElementById('menuTable'); if (!menuTable) return; const thead = menuTable.querySelector('thead') || document.createElement('thead'); thead.innerHTML = ` # 文本 (Text) 链接 (Link) 新标签页 (New Tab) 操作 `; if (!menuTable.querySelector('thead')) { menuTable.appendChild(thead); } }, // 加载菜单项 (从 /api/config 获取) loadMenuItems: async function() { try { const menuTableBody = document.getElementById('menuTableBody'); if (menuTableBody) { menuTableBody.innerHTML = ' 正在加载菜单项...'; } const response = await fetch('/api/config'); // 请求配置接口 if (!response.ok) { throw new Error(`获取配置失败: ${response.statusText || response.status}`); } currentConfig = await response.json(); // 保存完整配置 configMenuItems = currentConfig.menuItems || []; // 提取菜单项,如果不存在则为空数组 this.renderMenuItems(); console.log('成功从 /api/config 加载菜单项', configMenuItems); } catch (error) { console.error('加载菜单项失败:', error); const menuTableBody = document.getElementById('menuTableBody'); if (menuTableBody) { menuTableBody.innerHTML = ` 加载菜单项失败: ${error.message} `; } } }, // 渲染菜单项 (根据 config.json 结构) renderMenuItems: function() { const menuTableBody = document.getElementById('menuTableBody'); if (!menuTableBody) return; menuTableBody.innerHTML = ''; // 清空现有内容 if (!Array.isArray(configMenuItems)) { console.error("configMenuItems 不是一个数组:", configMenuItems); menuTableBody.innerHTML = '菜单数据格式错误'; return; } configMenuItems.forEach((item, index) => { const row = document.createElement('tr'); // 使用 index 作为临时 ID 进行操作 row.innerHTML = ` ${index + 1} ${item.text || ''} ${item.link || ''} ${item.newTab ? '是' : '否'} `; menuTableBody.appendChild(row); }); }, // 显示新菜单项行 (调整字段) showNewMenuItemRow: function() { const menuTableBody = document.getElementById('menuTableBody'); if (!menuTableBody) return; const newRow = document.createElement('tr'); newRow.id = 'new-menu-item-row'; newRow.className = 'new-item-row'; newRow.innerHTML = ` # `; menuTableBody.appendChild(newRow); document.getElementById('new-text').focus(); }, // 保存新菜单项 (更新整个配置) saveNewMenuItem: async function() { try { const text = document.getElementById('new-text').value.trim(); const link = document.getElementById('new-link').value.trim(); const newTab = document.getElementById('new-newTab').value === 'true'; if (!text || !link) { throw new Error('文本和链接为必填项'); } const newMenuItem = { text, link, newTab }; // 创建更新后的配置对象 const updatedConfig = { ...currentConfig, menuItems: [...(currentConfig.menuItems || []), newMenuItem] // 添加新项 }; // 调用API保存整个配置 const response = await fetch('/api/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedConfig) // 发送更新后的完整配置 }); if (!response.ok) { const errorData = await response.json(); throw new Error(`保存配置失败: ${errorData.details || response.statusText}`); } // 重新加载菜单项以更新视图和 currentConfig await this.loadMenuItems(); this.cancelNewMenuItem(); // 移除编辑行 core.showAlert('菜单项已添加', 'success'); } catch (error) { console.error('添加菜单项失败:', error); core.showAlert('添加菜单项失败: ' + error.message, 'error'); } }, // 取消新菜单项 cancelNewMenuItem: function() { const newRow = document.getElementById('new-menu-item-row'); if (newRow) { newRow.remove(); } }, // 编辑菜单项 (使用 index 定位) editMenuItem: function(index) { const item = configMenuItems[index]; if (!item) { core.showAlert('找不到指定的菜单项', 'error'); return; } Swal.fire({ title: '
编辑菜单项
', html: `
菜单项显示的文本,保持简洁明了
完整URL路径(例如: https://example.com)或相对路径(例如: /docs)
${item.newTab ? '是' : '否'}
预览
`, showCancelButton: true, confirmButtonText: ' 保存', cancelButtonText: ' 取消', confirmButtonColor: '#3085d6', cancelButtonColor: '#6c757d', width: '550px', focusConfirm: false, customClass: { container: 'menu-edit-container', popup: 'menu-edit-popup', title: 'menu-edit-title', confirmButton: 'menu-edit-confirm', cancelButton: 'menu-edit-cancel' }, didOpen: () => { // 添加输入监听,更新预览 const textInput = document.getElementById('edit-text'); const linkInput = document.getElementById('edit-link'); const newTabToggle = document.getElementById('edit-newTab'); const toggleStatus = document.querySelector('.toggle-status'); const previewText = document.querySelector('.preview-text'); const previewLink = document.querySelector('.preview-link'); const previewIcon = document.querySelector('.preview-icon') || document.createElement('i'); if (!previewIcon.classList.contains('fas')) { previewIcon.className = 'fas fa-external-link-alt preview-icon'; } const updatePreview = () => { previewText.textContent = textInput.value || '菜单项'; previewLink.href = linkInput.value || '#'; previewLink.target = newTabToggle.checked ? '_blank' : '_self'; if (newTabToggle.checked) { if (!previewLink.contains(previewIcon)) { previewLink.appendChild(previewIcon); } } else { if (previewLink.contains(previewIcon)) { previewLink.removeChild(previewIcon); } } }; textInput.addEventListener('input', updatePreview); linkInput.addEventListener('input', updatePreview); newTabToggle.addEventListener('change', () => { toggleStatus.textContent = newTabToggle.checked ? '是' : '否'; updatePreview(); }); }, preConfirm: () => { const text = document.getElementById('edit-text').value.trim(); const link = document.getElementById('edit-link').value.trim(); const newTab = document.getElementById('edit-newTab').checked; if (!text) { Swal.showValidationMessage(' 菜单文本不能为空'); return false; } if (!link) { Swal.showValidationMessage(' 链接地址不能为空'); return false; } return { text, link, newTab }; } }).then(async (result) => { if (!result.isConfirmed) return; try { // 显示保存中状态 Swal.fire({ title: '保存中...', html: ' 正在保存菜单项', showConfirmButton: false, allowOutsideClick: false, willOpen: () => { Swal.showLoading(); } }); // 更新配置中的菜单项 configMenuItems[index] = result.value; // 创建更新后的配置对象 const updatedConfig = { ...currentConfig, menuItems: configMenuItems // 更新后的菜单项数组 }; // 调用API保存整个配置 const response = await fetch('/api/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedConfig) // 发送更新后的完整配置 }); if (!response.ok) { const errorData = await response.json(); throw new Error(`保存配置失败: ${errorData.details || response.statusText}`); } // 重新渲染菜单项 this.renderMenuItems(); // 显示成功消息 Swal.fire({ icon: 'success', title: '保存成功', html: ' 菜单项已更新', timer: 1500, showConfirmButton: false }); } catch (error) { console.error('更新菜单项失败:', error); Swal.fire({ icon: 'error', title: '保存失败', html: ` 更新菜单项失败: ${error.message}`, confirmButtonText: '确定' }); } }); }, // 删除菜单项 deleteMenuItem: function(index) { const item = configMenuItems[index]; if (!item) { core.showAlert('找不到指定的菜单项', 'error'); return; } Swal.fire({ title: '确认删除', text: `确定要删除菜单项 "${item.text}" 吗?`, icon: 'warning', showCancelButton: true, confirmButtonText: '删除', cancelButtonText: '取消', confirmButtonColor: '#d33' }).then(async (result) => { if (!result.isConfirmed) return; try { // 从菜单项数组中移除指定项 configMenuItems.splice(index, 1); // 创建更新后的配置对象 const updatedConfig = { ...currentConfig, menuItems: configMenuItems // 更新后的菜单项数组 }; // 调用API保存整个配置 const response = await fetch('/api/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedConfig) // 发送更新后的完整配置 }); if (!response.ok) { const errorData = await response.json(); throw new Error(`保存配置失败: ${errorData.details || response.statusText}`); } // 重新渲染菜单项 this.renderMenuItems(); core.showAlert('菜单项已删除', 'success'); } catch (error) { console.error('删除菜单项失败:', error); core.showAlert('删除菜单项失败: ' + error.message, 'error'); } }); } }; // 全局公开菜单管理模块 window.menuManager = menuManager;