Files
wb-java-nc-shop/target/classes/static/js/sidebar-replacer.js
2026-01-11 18:14:42 +08:00

301 lines
11 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 侧边栏自动替换脚本
* 自动检测并替换旧的导航栏为侧边栏
*/
(function() {
'use strict';
// 侧边栏CSS
const sidebarCSS = `
.sidebar {
position: fixed;
top: 0;
left: 0;
width: 260px;
height: 100vh;
background: linear-gradient(180deg, #2c3e50 0%, #34495e 100%);
color: #fff;
z-index: 1000;
display: flex;
flex-direction: column;
transition: transform 0.3s ease;
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
}
.sidebar-header {
padding: 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.sidebar-brand {
font-size: 1.25rem;
font-weight: 600;
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
padding: 1rem 0;
}
.sidebar-nav .nav-link {
color: rgba(255, 255, 255, 0.8);
padding: 0.75rem 1.5rem;
transition: all 0.3s;
border-left: 3px solid transparent;
display: flex;
align-items: center;
text-decoration: none;
}
.sidebar-nav .nav-link:hover {
background-color: rgba(255, 255, 255, 0.1);
color: #fff;
border-left-color: #0d6efd;
}
.sidebar-nav .nav-link.active {
background-color: rgba(13, 110, 253, 0.2);
color: #fff;
border-left-color: #0d6efd;
font-weight: 600;
}
.sidebar-nav .nav-link i {
width: 24px;
font-size: 1.1rem;
margin-right: 0.75rem;
}
.sidebar-nav .nav-text {
flex: 1;
}
.sidebar-footer {
padding: 1rem;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
@media (max-width: 767.98px) {
.sidebar {
transform: translateX(-100%);
}
.sidebar.show {
transform: translateX(0);
}
.sidebar-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1049;
display: none;
transition: opacity 0.3s;
}
.sidebar-overlay.show {
display: block;
}
.top-navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 56px;
background: linear-gradient(180deg, #2c3e50 0%, #34495e 100%);
z-index: 1048;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
body {
padding-top: 56px;
}
}
@media (min-width: 768px) {
.main-content {
margin-left: 260px;
min-height: 100vh;
position: relative;
z-index: 1;
width: calc(100% - 260px);
}
}
.sidebar-nav::-webkit-scrollbar {
width: 6px;
}
.sidebar-nav::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
}
.sidebar-nav::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
}
.sidebar-nav::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.3);
}
`;
// 菜单配置
const menuConfig = [
{ href: '/merchant/dashboard.html', icon: 'bi-speedometer2', text: '首页', page: 'dashboard' },
{ href: '/merchant/products.html', icon: 'bi-box-seam', text: '商品管理', page: 'products' },
{ href: '/merchant/orders.html', icon: 'bi-receipt-cutoff', text: '订单管理', page: 'orders' },
{ href: '/merchant/inventory.html', icon: 'bi-archive', text: '库存管理', page: 'inventory' },
{ href: '/merchant/statistics.html', icon: 'bi-bar-chart-line', text: '数据统计', page: 'statistics' },
{ href: '/merchant/announcements.html', icon: 'bi-megaphone', text: '公告管理', page: 'announcements' },
{ href: '/merchant/messages.html', icon: 'bi-chat-dots', text: '留言管理', page: 'messages' },
{ href: '/merchant/reviews.html', icon: 'bi-star', text: '评价管理', page: 'reviews' },
{ href: '/merchant/users.html', icon: 'bi-people', text: '用户管理', page: 'users' }
];
// 检测当前页面
function detectCurrentPage() {
const path = window.location.pathname;
for (const item of menuConfig) {
if (path.includes(item.page)) {
return item.page;
}
}
return 'dashboard';
}
// 生成侧边栏HTML
function generateSidebar(activePage) {
const menuHTML = menuConfig.map(item => {
const activeClass = item.page === activePage ? 'active' : '';
return `
<li class="nav-item">
<a class="nav-link ${activeClass}" href="${item.href}" data-page="${item.page}">
<i class="bi ${item.icon}"></i>
<span class="nav-text">${item.text}</span>
</a>
</li>
`;
}).join('');
return `
<div class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="d-flex align-items-center">
<i class="bi bi-shop fs-4 me-2"></i>
<span class="sidebar-brand">商家后台</span>
</div>
<button class="btn btn-link text-white p-0 d-md-none" id="sidebarCloseBtn">
<i class="bi bi-x-lg"></i>
</button>
</div>
<nav class="sidebar-nav">
<ul class="nav flex-column">
${menuHTML}
</ul>
</nav>
<div class="sidebar-footer">
<a href="/merchant/logout" class="btn btn-outline-light w-100">
<i class="bi bi-box-arrow-right"></i>
<span class="ms-2">退出登录</span>
</a>
</div>
</div>
<div class="sidebar-overlay" id="sidebarOverlay"></div>
<nav class="top-navbar d-md-none">
<div class="container-fluid d-flex align-items-center">
<button class="btn btn-link text-white p-0" id="sidebarToggleBtn">
<i class="bi bi-list fs-4"></i>
</button>
<span class="ms-3 text-white fw-bold">商家后台</span>
</div>
</nav>
`;
}
// 初始化侧边栏
function initSidebar() {
// 添加CSS
if (!document.getElementById('merchant-sidebar-styles')) {
const style = document.createElement('style');
style.id = 'merchant-sidebar-styles';
style.textContent = sidebarCSS;
document.head.appendChild(style);
}
// 替换导航栏
const oldNav = document.querySelector('nav.navbar');
if (oldNav && !document.getElementById('sidebar')) {
const activePage = detectCurrentPage();
oldNav.outerHTML = generateSidebar(activePage);
// 包装主内容 - 确保不重复包装
let mainContent = document.querySelector('.main-content');
if (!mainContent) {
// 查找body的直接子元素中的container
const bodyChildren = Array.from(document.body.children);
let container = null;
// 优先查找container-fluid然后是container
for (const child of bodyChildren) {
if (child.classList.contains('container-fluid') || child.classList.contains('container')) {
if (!child.closest('.main-content') && !child.closest('.sidebar') && !child.closest('.sidebar-overlay') && !child.closest('.top-navbar')) {
container = child;
break;
}
}
}
if (container) {
mainContent = document.createElement('div');
mainContent.className = 'main-content';
container.parentNode.insertBefore(mainContent, container);
mainContent.appendChild(container);
}
}
// 初始化交互
setupSidebarInteractions();
}
}
// 设置侧边栏交互
function setupSidebarInteractions() {
const sidebar = document.getElementById('sidebar');
const sidebarOverlay = document.getElementById('sidebarOverlay');
const sidebarToggleBtn = document.getElementById('sidebarToggleBtn');
const sidebarCloseBtn = document.getElementById('sidebarCloseBtn');
if (!sidebar) return;
function openSidebar() {
sidebar.classList.add('show');
if (sidebarOverlay) sidebarOverlay.classList.add('show');
document.body.style.overflow = 'hidden';
}
function closeSidebar() {
sidebar.classList.remove('show');
if (sidebarOverlay) sidebarOverlay.classList.remove('show');
document.body.style.overflow = '';
}
if (sidebarToggleBtn) {
sidebarToggleBtn.addEventListener('click', openSidebar);
}
if (sidebarCloseBtn) {
sidebarCloseBtn.addEventListener('click', closeSidebar);
}
if (sidebarOverlay) {
sidebarOverlay.addEventListener('click', closeSidebar);
}
// 点击导航项时,移动端自动关闭
const navLinks = document.querySelectorAll('.sidebar-nav .nav-link');
navLinks.forEach(link => {
link.addEventListener('click', function() {
if (window.innerWidth < 768) {
closeSidebar();
}
});
});
}
// 页面加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initSidebar);
} else {
initSidebar();
}
})();