From 9147d5e679c57d0599a95885b1b8cfd77ce985a1 Mon Sep 17 00:00:00 2001 From: lt Date: Fri, 8 May 2026 13:22:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=E6=8A=BD=E7=A6=BB=E9=A1=B5?= =?UTF-8?q?=E7=9C=89=E4=B8=BA=E5=85=AC=E5=85=B1=E7=BB=84=E4=BB=B6=EF=BC=9B?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=BC=E8=88=AA=E7=82=B9=E5=87=BB=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 navbar-component.js:固定页眉,统一标题、用户信息、退出按钮 - 重构所有页面(index/topics/logs/admin/users)使用 navbar-component - 清理原有 navbar 相关样式,避免冲突 - 导航组件增加 main-content padding-top 自动调整 - 修复导航按钮点击事件(确保 触发) - 导航组件样式强应用,解决遮挡和布局问题 --- platform/frontend/admin.html | 19 +++--- platform/frontend/index.html | 23 +++---- platform/frontend/logs.html | 19 +++--- platform/frontend/navbar-component.js | 83 +++++++++++++++++++++++ platform/frontend/navigation-component.js | 62 ++++++++++------- platform/frontend/topics.html | 19 +++--- platform/frontend/users.html | 19 +++--- 7 files changed, 169 insertions(+), 75 deletions(-) create mode 100644 platform/frontend/navbar-component.js diff --git a/platform/frontend/admin.html b/platform/frontend/admin.html index 035de62..079f2c2 100644 --- a/platform/frontend/admin.html +++ b/platform/frontend/admin.html @@ -68,18 +68,17 @@ + +
- + + +
- + + +
- + { + console.log('[Navbar] installNavbar called'); + injectStyles(); + const h = getHFromApp(app) || (window.Vue && Vue.h) || function(tag, data, children) { + const el = document.createElement(tag); + if (data && data.class) el.className = data.class; + if (children) { + if (Array.isArray(children)) children.forEach(c => { if (typeof c === 'string') el.appendChild(document.createTextNode(c)); else if (c && c.nodeType) el.appendChild(c); }); + else if (typeof children === 'string') el.textContent = children; + } + if (data && data.on) Object.keys(data.on).forEach(ev => el.addEventListener(ev, data.on[ev])); + }; + + const NavbarComponent = { + name: 'NavbarComponent', + props: { + title: { type: String, default: '宇之然内容创作平台' }, + username: { type: String, default: '' }, + isAdmin: { type: Boolean, default: false }, + onLogout: { type: Function, default: null } + }, + render(){ + const createElement = arguments[0] || h; + return createElement('nav', { class: 'navbar-component' }, [ + createElement('div', { class: 'navbar-content', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' } }, [ + createElement('h1', { class: 'navbar-title' }, this.title), + createElement('div', { class: 'navbar-user' }, [ + createElement('div', { class: 'user-info' }, [ + createElement('div', { class: 'avatar' }, this.username ? this.username.charAt(0).toUpperCase() : '?'), + this.username ? createElement('span', this.username) : null + ]), + this.isAdmin ? createElement('span', { style: { marginLeft: '8px', fontSize: '12px', background: 'rgba(255,255,255,0.3)', padding: '2px 8px', borderRadius: '10px' } }, '管理员') : null, + createElement('button', { + class: 'logout-btn', + style: { background: 'rgba(255,255,255,0.2)', border: 'none', color: 'white', padding: '6px 12px', borderRadius: '6px', cursor: 'pointer', marginLeft: '12px' }, + on: { click: () => { if (this.onLogout) this.onLogout(); else window.location.href = '/login.html'; } } + }, '退出') + ]) + ]) + ]); + } + }; + + app.component('navbar-component', NavbarComponent); + console.log('[Navbar] 组件已注册'); + return app; + }; + + window.installNavbar = installNavbar; + console.log('[Navbar] 脚本已加载'); +})(); diff --git a/platform/frontend/navigation-component.js b/platform/frontend/navigation-component.js index 14abdd6..fb87d55 100644 --- a/platform/frontend/navigation-component.js +++ b/platform/frontend/navigation-component.js @@ -1,11 +1,10 @@ -// Vue 3 导航组件 - 修复布局和事件 +// Vue 3 导航组件 - 最终版(确保事件传递) (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; @@ -35,20 +34,8 @@ .navigation-wrapper .mobile-nav { display: flex !important; } } @media (min-width: 769px) { .navigation-wrapper .mobile-nav { display: none !important; } } - /* 主内容区域避开固定侧边栏 */ - body > #app > .navigation-wrapper + .main-content, - body > #app > .main-content { - margin-left: 180px !important; - } - @media (max-width: 768px) { - body > #app > .navigation-wrapper + .main-content, - body > #app > .main-content { - margin-left: 0 !important; - padding-bottom: 60px !important; - } - } - /* 侧边栏固定定位时不调整主内容,让 main-content 自然位于文档流中,仅需确保 padding-top 避开 navbar */ - body > #app > .main-content { padding-top: 0; } + 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'; @@ -76,6 +63,7 @@ else if (typeof children === 'string') el.textContent = children; } if (data && data.on) Object.keys(data.on).forEach(ev => el.addEventListener(ev, data.on[ev])); + return el; }; console.log('[Nav] 使用 h 函数:', typeof h); @@ -83,11 +71,23 @@ name: 'NavigationComponent', props: { currentPage: { type: String, required: true }, isAdmin: { type: Boolean, default: false } }, mounted() { console.log('[NavigationComponent] 已挂载'); }, - render() { + render(){ + const createElement = arguments[0] || h; + // 获取 emit 方法:通过 this.$emit 或从闭包中捕获 + const emit = this.$emit || function() {}; + const navigate = (page) => { - console.log('[NavigationComponent] 导航到:', page); - this.$emit('navigate', page); + console.log('[NavigationComponent] 点击导航到:', page); + // 直接调用 emit 函数 + if (typeof emit === 'function') { + emit('navigate', page); + } else if (this.$emit) { + this.$emit('navigate', page); + } else { + console.warn('[NavigationComponent] 无法发送事件,emit unavailable'); + } }; + const sidebarItems = [ { icon: '📊', label: '系统概览', page: '/' }, { icon: '📋', label: '选题管理', page: 'topics.html' }, @@ -100,22 +100,32 @@ { icon: '📄', label: '日志', page: 'logs.html' }, ...(this.isAdmin ? [{ icon: '👥', label: '用户', page: 'users.html' }, { icon: '⚙️', label: '系统', page: 'admin.html' }] : []) ]; - return h('div', { class: 'navigation-wrapper' }, [ - h('aside', { class: 'sidebar' }, [ - h('div', { class: 'sidebar-header' }, [h('h3', '宇之然平台')]), - h('nav', { class: 'sidebar-nav' }, sidebarItems.map(item => { + + return createElement('div', { class: 'navigation-wrapper' }, [ + createElement('aside', { class: 'sidebar' }, [ + createElement('div', { class: 'sidebar-header' }, [createElement('h3', '宇之然平台')]), + createElement('nav', { class: 'sidebar-nav' }, sidebarItems.map(item => { const isActive = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html','')); - return h('button', { key: item.page, class: isActive ? 'sidebar-btn active' : 'sidebar-btn', on: { click: () => navigate(item.page) } }, item.icon + ' ' + item.label); + return createElement('button', { + key: item.page, + class: isActive ? 'sidebar-btn active' : 'sidebar-btn', + on: { click: (e) => { e.preventDefault(); navigate(item.page); } } + }, item.icon + ' ' + item.label); })) ]), - h('nav', { class: 'mobile-nav' }, mobileItems.map(item => { + createElement('nav', { class: 'mobile-nav' }, mobileItems.map(item => { const isActive = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html','')); const content = item.label ? (item.icon + ' ' + item.label) : item.icon; - return h('button', { key: item.page, class: isActive ? 'mobile-nav-btn active' : 'mobile-nav-btn', on: { click: () => navigate(item.page) } }, content); + return createElement('button', { + key: item.page, + class: isActive ? 'mobile-nav-btn active' : 'mobile-nav-btn', + on: { click: (e) => { e.preventDefault(); navigate(item.page); } } + }, content); })) ]); } }; + app.component('navigation-component', component); console.log('[Nav] 组件已注册'); return app; diff --git a/platform/frontend/topics.html b/platform/frontend/topics.html index 154be74..b32ab51 100644 --- a/platform/frontend/topics.html +++ b/platform/frontend/topics.html @@ -117,18 +117,17 @@ + +
- + + +
- +