diff --git a/platform/frontend/navigation-component.js b/platform/frontend/navigation-component.js index 200da48..20f679a 100644 --- a/platform/frontend/navigation-component.js +++ b/platform/frontend/navigation-component.js @@ -1,143 +1,116 @@ -// 最简导航组件 - 原生DOM操作(无h函数) +// 纯DOM导航 - 通过 installNavigation 直接插入 (function() { console.log('[Nav] 脚本加载'); function injectStyles() { if (document.getElementById('navigation-styles')) return; const styles = ` - .navigation-wrapper { position: relative; } - .navigation-wrapper .sidebar { - position: fixed; top: 60px; left: 0; bottom: 0; width: 180px; - background: #ffffff; padding: 12px; box-shadow: 2px 0 8px rgba(0,0,0,0.1); - overflow-y: auto; z-index: 99999; border-right: 1px solid #ebeef5; - } + .navigation-wrapper .sidebar { position: fixed; top: 60px; left: 0; bottom: 0; width: 180px; background: #fff; padding: 12px; box-shadow: 2px 0 8px rgba(0,0,0,0.1); overflow-y: auto; z-index: 99999; border-right: 1px solid #ebeef5; } .navigation-wrapper .sidebar-header { padding: 12px 8px 16px; border-bottom: 1px solid #ebeef5; margin-bottom: 12px; } .navigation-wrapper .sidebar-header h3 { margin: 0; font-size: 16px; font-weight: 600; color: #303133; } - .navigation-wrapper .sidebar-btn { - width: 100%; text-align: left; padding: 10px 12px; border: none; background: transparent; border-radius: 8px; - margin-bottom: 6px; cursor: pointer; transition: all 0.3s; color: #606266; font-size: 14px; display: flex; align-items: center; gap: 6px; - } + .navigation-wrapper .sidebar-btn { width: 100%; text-align: left; padding: 10px 12px; border: none; background: transparent; border-radius: 8px; margin-bottom: 6px; cursor: pointer; transition: all 0.3s; color: #606266; font-size: 14px; display: flex; align-items: center; gap: 6px; } .navigation-wrapper .sidebar-btn:hover { background: #f5f7fa; color: #409eff; } .navigation-wrapper .sidebar-btn.active { background: #ecf5ff; color: #409eff; font-weight: 600 !important; } - .navigation-wrapper .mobile-nav { - display: none; position: fixed; bottom: 0; left: 0; right: 0; background: #1890ff; - box-shadow: 0 -2px 8px rgba(0,0,0,0.2); padding: 8px 0; z-index: 99999; justify-content: space-around; - } - .navigation-wrapper .mobile-nav-btn { - flex: 1; border: none; background: transparent; padding: 10px 4px; text-align: center; - font-size: 12px; color: white !important; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 2px; - transition: background 0.2s; - } - .navigation-wrapper .mobile-nav-btn:hover { background: rgba(255,255,255,0.2); color: white !important; } + .navigation-wrapper .mobile-nav { display: none; position: fixed; bottom: 0; left: 0; right: 0; background: #1890ff; box-shadow: 0 -2px 8px rgba(0,0,0,0.2); padding: 8px 0; z-index: 99999; justify-content: space-around; } + .navigation-wrapper .mobile-nav-btn { flex: 1; border: none; background: transparent; padding: 10px 4px; text-align: center; font-size: 12px; color: white !important; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 2px; } + .navigation-wrapper .mobile-nav-btn:hover { background: rgba(255,255,255,0.2); } .navigation-wrapper .mobile-nav-btn.active { background: rgba(255,255,255,0.3); font-weight: 600 !important; } - @media (max-width: 768px) { - .navigation-wrapper .sidebar { display: none !important; } - .navigation-wrapper .mobile-nav { display: flex !important; } - } - @media (min-width: 769px) { .navigation-wrapper .mobile-nav { display: none !important; } } + @media (max-width: 768px) { .navigation-wrapper .sidebar { display: none !important; } .navigation-wrapper .mobile-nav { display: flex !important; } } body > #app > .main-content { margin-left: 180px !important; padding-top: 60px !important; } @media (max-width: 768px) { body > #app > .main-content { margin-left: 0 !important; padding-bottom: 60px !important; } } `; - const styleEl = document.createElement('style'); - styleEl.id = 'navigation-styles'; - styleEl.textContent = styles; - document.head.appendChild(styleEl); + document.head.appendChild(Object.assign(document.createElement('style'), { id: 'navigation-styles', textContent: styles })); console.log('[Nav] 样式已注入'); } - const installNavigation = (app) => { - console.log('[Nav] installNavigation called'); + function createNavigation(currentPage, isAdmin, onNavigate) { + const wrapper = document.createElement('div'); + wrapper.className = 'navigation-wrapper'; + + // 侧边栏 + const sidebar = document.createElement('aside'); + sidebar.className = 'sidebar'; + sidebar.innerHTML = ` + + + `; + + // 移动端底部导航 + const mobileNav = document.createElement('nav'); + mobileNav.className = 'mobile-nav'; + mobileNav.innerHTML = ` + + + + ${isAdmin ? `` : ''} + ${isAdmin ? `` : ''} + `; + + wrapper.appendChild(sidebar); + wrapper.appendChild(mobileNav); + + // 绑定点击事件 + wrapper.querySelectorAll('button').forEach(btn => { + btn.addEventListener('click', () => { + const page = btn.getAttribute('data-page'); + console.log('[Nav] 导航到:', page); + if (onNavigate) onNavigate(page); + }); + }); + + return wrapper; + } + + // 新的 installNavigation 接口:接收 app 对象(为了兼容),但实际不注册组件 + window.installNavigation = function(app, options = {}) { + console.log('[Nav] installNavigation called (DOM mode)'); injectStyles(); - - // 定义组件选项 - const component = { - name: 'NavigationComponent', - props: { currentPage: { type: String, required: true }, isAdmin: { type: Boolean, default: false } }, - mounted() { - console.log('[NavigationComponent] 已挂载', this.currentPage, this.isAdmin); - - // 在组件挂载后立即渲染导航栏到DOM - setTimeout(() => { - const container = this.$el; // 组件根元素 - container.innerHTML = ''; - - // 渲染侧边栏 - const sidebar = document.createElement('aside'); - sidebar.className = 'sidebar'; - - const header = document.createElement('div'); - header.className = 'sidebar-header'; - const headerTitle = document.createElement('h3'); - headerTitle.textContent = '宇之然平台'; - header.appendChild(headerTitle); - - const nav = document.createElement('nav'); - nav.className = 'sidebar-nav'; - - const items = [ - { icon: '📊', label: '系统概览', page: '/' }, - { icon: '📋', label: '选题管理', page: 'topics.html' }, - { icon: '📄', label: '系统日志', page: 'logs.html' }, - ...(this.isAdmin ? [{ icon: '👥', label: '用户管理', page: 'users.html' }, { icon: '⚙️', label: '系统管理', page: 'admin.html' }] : []) - ]; - - items.forEach(item => { - const btn = document.createElement('button'); - btn.className = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html','')) - ? 'sidebar-btn active' : 'sidebar-btn'; - btn.textContent = item.icon + ' ' + item.label; - - btn.addEventListener('click', () => { - console.log('[NavigationComponent] 点击导航到:', item.page); - this.$emit('navigate', item.page); - }); - - nav.appendChild(btn); - }); - - sidebar.appendChild(header); - sidebar.appendChild(nav); - container.appendChild(sidebar); - - // 渲染移动端底部导航 - if (window.innerWidth <= 768) { - const mobileNav = document.createElement('nav'); - mobileNav.className = 'mobile-nav'; - - const mobileItems = [ - { icon: '📊', label: '', page: '/' }, - { icon: '📋', label: '选题', page: 'topics.html' }, - { icon: '📄', label: '日志', page: 'logs.html' }, - ...(this.isAdmin ? [{ icon: '👥', label: '用户', page: 'users.html' }, { icon: '⚙️', label: '系统', page: 'admin.html' }] : []) - ]; - - mobileItems.forEach(item => { - const btn = document.createElement('button'); - btn.className = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html','')) - ? 'mobile-nav-btn active' : 'mobile-nav-btn'; - - const content = item.label ? (item.icon + ' ' + item.label) : item.icon; - btn.textContent = content; - - btn.addEventListener('click', () => { - console.log('[NavigationComponent] 点击导航到:', item.page); - this.$emit('navigate', item.page); - }); - - mobileNav.appendChild(btn); - }); - - container.appendChild(mobileNav); - } - }, 0); + + // 延迟执行,确保DOM就绪 + const init = () => { + const container = document.getElementById('app'); + if (!container) { + console.warn('[Nav] #app 未找到,等待'); + setTimeout(init, 100); + return; } + + // 尝试从 Vue 实例获取 isAdmin 和 currentPage + let isAdmin = false; + let currentPage = 'dashboard'; + let redirectToPage = null; + + // 尝试从 Vue 实例提取数据 + if (app && app._instance && app._instance.proxy) { + const proxy = app._instance.proxy; + if (proxy.isAdmin !== undefined) isAdmin = proxy.isAdmin; + if (proxy.currentPage !== undefined) currentPage = proxy.currentPage; + if (proxy.redirectToPage) redirectToPage = proxy.redirectToPage; + } else if (window.Vue && Vue.app && Vue.app._instance && Vue.app._instance.proxy) { + const proxy = Vue.app._instance.proxy; + if (proxy.isAdmin !== undefined) isAdmin = proxy.isAdmin; + if (proxy.currentPage !== undefined) currentPage = proxy.currentPage; + if (proxy.redirectToPage) redirectToPage = proxy.redirectToPage; + } + + // 移除旧的导航容器(如果有) + const oldNav = container.querySelector('.navigation-wrapper'); + if (oldNav) oldNav.remove(); + + const nav = createNavigation(currentPage, isAdmin, redirectToPage || ((page) => { window.location.href = page; })); + container.insertBefore(nav, container.firstChild); + console.log('[Nav] 导航已插入'); }; - - app.component('navigation-component', component); - console.log('[Nav] 组件已注册'); + + init(); return app; }; - - window.installNavigation = installNavigation; - console.log('[Nav] 脚本已加载'); + + console.log('[Nav] 脚本已加载(纯DOM版)'); })();