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 @@
+
+
-
+
+
+
-
+