nav-menu.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /**
  2. * 导航菜单加载模块
  3. * 负责从config加载并渲染前端导航菜单
  4. */
  5. // 用于跟踪菜单是否已加载
  6. let menuLoaded = false;
  7. // 立即执行初始化函数
  8. (function() {
  9. // console.log('[菜单模块] 初始化开始');
  10. try {
  11. // 页面加载完成后执行,但不在这里调用加载函数
  12. document.addEventListener('DOMContentLoaded', function() {
  13. // console.log('[菜单模块] DOM内容加载完成,等待loadMenu或loadNavMenu调用');
  14. // 不在这里调用,避免重复加载
  15. });
  16. // console.log('[菜单模块] 初始化完成,等待调用');
  17. } catch (error) {
  18. console.error('[菜单模块] 初始化失败:', error);
  19. }
  20. })();
  21. // 加载导航菜单
  22. async function loadNavMenu() {
  23. if (menuLoaded) {
  24. // console.log('[菜单模块] 菜单已加载,跳过');
  25. return;
  26. }
  27. // console.log('[菜单模块] loadNavMenu() 函数被调用');
  28. const navMenu = document.getElementById('navMenu');
  29. if (!navMenu) {
  30. console.error('[菜单模块] 无法找到id为navMenu的元素,菜单加载失败');
  31. return;
  32. }
  33. try {
  34. // console.log('[菜单模块] 正在从/api/config获取菜单配置...');
  35. // 从API获取配置
  36. const response = await fetch('/api/config');
  37. // console.log('[菜单模块] API响应状态:', response.status, response.statusText);
  38. if (!response.ok) {
  39. throw new Error(`获取配置失败: ${response.status} ${response.statusText}`);
  40. }
  41. const config = await response.json();
  42. // console.log('[菜单模块] 成功获取配置:', config);
  43. // 确保menuItems存在且是数组
  44. if (!config.menuItems || !Array.isArray(config.menuItems) || config.menuItems.length === 0) {
  45. console.warn('[菜单模块] 配置中没有菜单项或格式不正确', config);
  46. navMenu.innerHTML = '<span class="no-menu" style="color: #ff6b6b; font-size: 14px;">未设置菜单</span>';
  47. menuLoaded = true;
  48. return;
  49. }
  50. // 渲染菜单
  51. renderNavMenu(navMenu, config.menuItems);
  52. menuLoaded = true;
  53. } catch (error) {
  54. console.error('[菜单模块] 加载导航菜单失败:', error);
  55. navMenu.innerHTML = `<span class="menu-error" style="color: #ff6b6b; font-size: 14px;">菜单加载失败: ${error.message}</span>`;
  56. }
  57. }
  58. // 渲染导航菜单
  59. function renderNavMenu(navMenuElement, menuItems) {
  60. try {
  61. // console.log('[菜单模块] 开始渲染导航菜单,菜单项数量:', menuItems.length);
  62. // 清空现有内容
  63. navMenuElement.innerHTML = '';
  64. // 移动设备菜单切换按钮
  65. const menuToggle = document.createElement('div');
  66. menuToggle.id = 'menuToggle';
  67. menuToggle.className = 'menu-toggle';
  68. menuToggle.innerHTML = '<i class="fas fa-bars"></i>';
  69. menuToggle.style.color = '#333'; // 设置为深色
  70. menuToggle.style.fontSize = '28px'; // 增大菜单图标
  71. navMenuElement.appendChild(menuToggle);
  72. // 菜单项容器
  73. const menuList = document.createElement('ul');
  74. menuList.className = 'nav-list';
  75. menuList.style.display = 'flex';
  76. menuList.style.listStyle = 'none';
  77. menuList.style.margin = '0';
  78. menuList.style.padding = '0';
  79. // 添加菜单项
  80. menuItems.forEach((item, index) => {
  81. // console.log(`[菜单模块] 渲染菜单项 #${index+1}:`, item);
  82. const menuItem = document.createElement('li');
  83. menuItem.style.marginLeft = '25px'; // 增加间距
  84. const link = document.createElement('a');
  85. link.href = item.link || '#';
  86. link.textContent = item.text || '未命名菜单';
  87. // 使用内联样式确保文字颜色可见,并增大字体
  88. link.style.color = '#333'; // 黑色文字
  89. link.style.textDecoration = 'none';
  90. link.style.fontSize = '16px'; // 从14px增大到16px
  91. link.style.fontWeight = 'bold';
  92. link.style.padding = '8px 15px'; // 增大内边距
  93. link.style.borderRadius = '4px';
  94. link.style.transition = 'background-color 0.3s, color 0.3s';
  95. // 添加鼠标悬停效果
  96. link.addEventListener('mouseover', function() {
  97. this.style.backgroundColor = '#3d7cf4'; // 蓝色背景
  98. this.style.color = '#fff'; // 白色文字
  99. });
  100. // 鼠标移出时恢复原样
  101. link.addEventListener('mouseout', function() {
  102. this.style.backgroundColor = 'transparent';
  103. this.style.color = '#333';
  104. });
  105. if (item.newTab) {
  106. link.target = '_blank';
  107. link.rel = 'noopener noreferrer';
  108. }
  109. menuItem.appendChild(link);
  110. menuList.appendChild(menuItem);
  111. });
  112. navMenuElement.appendChild(menuList);
  113. // 绑定移动端菜单切换事件
  114. menuToggle.addEventListener('click', () => {
  115. // console.log('[菜单模块] 菜单切换按钮被点击');
  116. navMenuElement.classList.toggle('active');
  117. });
  118. // console.log(`[菜单模块] 成功渲染了 ${menuItems.length} 个导航菜单项`);
  119. } catch (error) {
  120. console.error('[菜单模块] 渲染导航菜单失败:', error);
  121. navMenuElement.innerHTML = `<span class="menu-error" style="color: #ff6b6b; font-size: 14px;">菜单渲染失败: ${error.message}</span>`;
  122. }
  123. }
  124. // 添加loadMenu函数,作为loadNavMenu的别名,确保与index.html中的调用匹配
  125. function loadMenu() {
  126. // console.log('[菜单模块] 调用loadMenu() - 转发到loadNavMenu()');
  127. loadNavMenu();
  128. }