This commit is contained in:
vipg
2025-11-12 16:50:19 +08:00
parent e5e82b8a8c
commit f5277b087b
10 changed files with 964 additions and 158 deletions

View File

@@ -1,19 +1,177 @@
/* 侧边栏组件 */
import { menuConfig } from '../config/menu.js';
import { Router } from '../core/router.js';
/**
* 侧边栏菜单组件
*/
window.Sidebar = {
/**
* 初始化侧边栏
* @param {jQuery} container - 容器元素
*/
init(container) {
this.container = container;
this.collapse = localStorage.getItem(SystemConfig.menuCollapseKey) === 'true';
this.renderMenu();
this.bindEvents();
this.updateCollapseState();
},
export function renderSidebar() {
const sidebar = document.createElement('div');
sidebar.className = 'sidebar';
// 渲染菜单
const menuHtml = menuConfig.map(item => `
<div class="menu-item" onclick="Router.push('${item.path}')">
<i class="icon-${item.icon}"></i>
<span>${item.name}</span>
</div>
`).join('');
sidebar.innerHTML = menuHtml;
return sidebar;
}
/**
* 渲染菜单
*/
renderMenu() {
const menuHtml = this.generateMenuHtml(MenuConfig);
this.container.html(menuHtml);
},
/**
* 生成菜单HTML递归处理多级菜单
* @param {array} menuList - 菜单列表
* @returns {string} - 菜单HTML
*/
generateMenuHtml(menuList) {
let html = '<ul class="sidebar-menu">';
menuList.forEach(menu => {
const hasChildren = menu.children && menu.children.length > 0;
const isActive = window.location.pathname.includes(menu.url);
html += `<li class="menu-item ${hasChildren ? 'has-children' : ''} ${isActive ? 'active' : ''}" data-id="${menu.id}">`;
// 菜单标题
html += `<div class="menu-title">`;
html += `<span class="menu-icon">${menu.icon}</span>`;
html += `<span class="menu-text">${menu.title}</span>`;
if (hasChildren) {
html += `<span class="menu-toggle ${this.collapse ? 'collapsed' : ''}">${this.collapse ? '+' : '-'}</span>`;
}
html += `</div>`;
// 子菜单
if (hasChildren) {
html += `<ul class="sub-menu ${this.collapse ? 'hidden' : ''}">`;
html += this.generateMenuHtml(menu.children);
html += `</ul>`;
} else if (menu.url) {
// 菜单项链接
html += `<a href="${menu.url}" class="menu-link"></a>`;
}
html += `</li>`;
});
html += '</ul>';
return html;
},
/**
* 绑定事件
*/
bindEvents() {
// 菜单折叠/展开
this.container.on('click', '.menu-toggle', (e) => {
const $toggle = $(e.currentTarget);
const $subMenu = $toggle.closest('.menu-item').find('.sub-menu');
this.collapse = !this.collapse;
localStorage.setItem(SystemConfig.menuCollapseKey, this.collapse);
$toggle.text(this.collapse ? '+' : '-');
$subMenu.toggleClass('hidden', this.collapse);
this.updateCollapseState();
});
// 菜单项点击(无链接时展开子菜单)
this.container.on('click', '.menu-title:not(.has-children)', (e) => {
const $title = $(e.currentTarget);
const $link = $title.siblings('.menu-link');
if ($link.length) {
$link[0].click();
}
});
},
/**
* 更新折叠状态样式
*/
updateCollapseState() {
$('.sidebar').toggleClass('collapsed', this.collapse);
$('.main-content').toggleClass('sidebar-collapsed', this.collapse);
}
};
// 添加侧边栏样式
$('head').append(`
<style>
.sidebar {
width: 240px;
height: 100%;
background-color: var(--bg-light-color);
border-right: 1px solid var(--border-color);
transition: width 0.3s ease;
overflow: hidden;
}
.sidebar.collapsed {
width: 60px;
}
.sidebar-menu {
list-style: none;
}
.menu-item {
margin-bottom: 2px;
}
.menu-title {
display: flex;
align-items: center;
padding: 12px 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.menu-title:hover {
background-color: var(--hover-color);
}
.menu-item.active .menu-title {
background-color: var(--active-color);
}
.menu-icon {
margin-right: 12px;
font-size: 18px;
}
.menu-text {
flex: 1;
transition: opacity 0.3s ease;
}
.sidebar.collapsed .menu-text {
opacity: 0;
width: 0;
margin: 0;
}
.menu-toggle {
font-size: 14px;
cursor: pointer;
transition: transform 0.3s ease;
}
.sub-menu {
list-style: none;
background-color: var(--bg-color);
transition: all 0.3s ease;
}
.sub-menu.hidden {
display: none;
}
.menu-link {
display: block;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
}
.main-content {
flex: 1;
padding: 20px;
transition: margin-left 0.3s ease;
}
.main-content.sidebar-collapsed {
margin-left: -180px;
}
</style>
`);