237 lines
7.4 KiB
JavaScript
237 lines
7.4 KiB
JavaScript
|
|
/**
|
|||
|
|
* 共享侧边栏加载器
|
|||
|
|
* 动态加载侧边栏组件,支持高亮当前页面
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
(function() {
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
// 侧边栏容器占位样式(防止加载时闪烁)
|
|||
|
|
const containerStyles = `
|
|||
|
|
#sidebar-container {
|
|||
|
|
width: 16rem;
|
|||
|
|
min-width: 16rem;
|
|||
|
|
height: 100vh;
|
|||
|
|
background-color: #001529;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
@media (max-width: 768px) {
|
|||
|
|
#sidebar-container {
|
|||
|
|
display: none;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
`;
|
|||
|
|
|
|||
|
|
// 侧边栏样式
|
|||
|
|
const sidebarStyles = `
|
|||
|
|
.sidebar-section-title {
|
|||
|
|
padding: 0.5rem 1rem;
|
|||
|
|
font-size: 0.75rem;
|
|||
|
|
color: rgba(191, 203, 217, 0.7);
|
|||
|
|
font-weight: 500;
|
|||
|
|
text-transform: uppercase;
|
|||
|
|
letter-spacing: 0.05em;
|
|||
|
|
}
|
|||
|
|
.nav-link:hover {
|
|||
|
|
background-color: rgba(0, 21, 41, 0.2);
|
|||
|
|
}
|
|||
|
|
.sidebar-item-active {
|
|||
|
|
background-color: rgba(24, 144, 255, 0.1) !important;
|
|||
|
|
color: #1890ff !important;
|
|||
|
|
border-left: 4px solid #1890ff;
|
|||
|
|
}
|
|||
|
|
.sidebar-slider {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 0;
|
|||
|
|
width: 4px;
|
|||
|
|
height: 0;
|
|||
|
|
background-color: #1890ff;
|
|||
|
|
border-radius: 0 2px 2px 0;
|
|||
|
|
transition: top 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|||
|
|
height 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|||
|
|
opacity 0.3s ease;
|
|||
|
|
pointer-events: none;
|
|||
|
|
z-index: 10;
|
|||
|
|
opacity: 0;
|
|||
|
|
}
|
|||
|
|
.nav-item-wrapper {
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
.nav-link {
|
|||
|
|
position: relative;
|
|||
|
|
z-index: 1;
|
|||
|
|
}
|
|||
|
|
`;
|
|||
|
|
|
|||
|
|
// 立即注入容器样式(防止闪烁)
|
|||
|
|
(function injectContainerStyles() {
|
|||
|
|
const styleEl = document.createElement('style');
|
|||
|
|
styleEl.id = 'sidebar-container-styles';
|
|||
|
|
styleEl.textContent = containerStyles;
|
|||
|
|
document.head.appendChild(styleEl);
|
|||
|
|
})();
|
|||
|
|
|
|||
|
|
// 根据当前页面路径确定活动页面
|
|||
|
|
function getCurrentPage() {
|
|||
|
|
const path = window.location.pathname;
|
|||
|
|
const search = window.location.search;
|
|||
|
|
const fileName = path.split('/').pop().replace('.html', '');
|
|||
|
|
|
|||
|
|
// 检查 URL 参数
|
|||
|
|
const urlParams = new URLSearchParams(search);
|
|||
|
|
const pageParam = urlParams.get('page');
|
|||
|
|
if (pageParam) {
|
|||
|
|
return pageParam;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 根据文件名映射
|
|||
|
|
const pageMap = {
|
|||
|
|
'main': 'fine-tune',
|
|||
|
|
'hardware': 'hardware',
|
|||
|
|
'logs': 'logs',
|
|||
|
|
'tools': 'tools',
|
|||
|
|
'fine-tune-create': 'fine-tune',
|
|||
|
|
'training-log': 'fine-tune',
|
|||
|
|
'dataset-create': 'dataset-manage',
|
|||
|
|
'dataset-preview': 'dataset-manage',
|
|||
|
|
'model-manage': 'model-manage',
|
|||
|
|
'model-manage-create': 'model-manage',
|
|||
|
|
'model-eval': 'model-eval',
|
|||
|
|
'model-eval-create': 'model-eval',
|
|||
|
|
'model-compare-create': 'model-compare',
|
|||
|
|
'model-compare-chat': 'model-compare',
|
|||
|
|
'model-compare-result': 'model-compare',
|
|||
|
|
'model-dimension-create': 'model-eval',
|
|||
|
|
'model-inference': 'model-manage',
|
|||
|
|
'custom-tool-create': 'tools'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return pageMap[fileName] || 'fine-tune';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 加载侧边栏
|
|||
|
|
async function loadSidebar() {
|
|||
|
|
const container = document.getElementById('sidebar-container');
|
|||
|
|
if (!container) {
|
|||
|
|
console.warn('未找到 sidebar-container 元素');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 计算组件路径
|
|||
|
|
const currentPath = window.location.pathname;
|
|||
|
|
let basePath = '';
|
|||
|
|
if (currentPath.includes('/pages/')) {
|
|||
|
|
basePath = 'components/';
|
|||
|
|
} else {
|
|||
|
|
basePath = 'pages/components/';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const response = await fetch(basePath + 'sidebar.html');
|
|||
|
|
if (!response.ok) {
|
|||
|
|
throw new Error('加载侧边栏失败: ' + response.status);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const html = await response.text();
|
|||
|
|
container.innerHTML = html;
|
|||
|
|
|
|||
|
|
// 注入样式
|
|||
|
|
if (!document.getElementById('sidebar-styles')) {
|
|||
|
|
const styleEl = document.createElement('style');
|
|||
|
|
styleEl.id = 'sidebar-styles';
|
|||
|
|
styleEl.textContent = sidebarStyles;
|
|||
|
|
document.head.appendChild(styleEl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修正 logo 路径
|
|||
|
|
const logo = container.querySelector('#sidebar-logo');
|
|||
|
|
if (logo) {
|
|||
|
|
const depth = currentPath.split('/pages/').length > 1 ? '../' : '';
|
|||
|
|
logo.src = depth + 'assets/logo/logo.png';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 高亮当前页面
|
|||
|
|
const currentPage = window.sidebarCurrentPage || getCurrentPage();
|
|||
|
|
highlightCurrentPage(currentPage);
|
|||
|
|
|
|||
|
|
// 初始化滑块
|
|||
|
|
initSlider();
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('加载侧边栏出错:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 高亮当前页面
|
|||
|
|
function highlightCurrentPage(currentPage) {
|
|||
|
|
document.querySelectorAll('.nav-link').forEach(link => {
|
|||
|
|
const page = link.dataset.page;
|
|||
|
|
if (page === currentPage) {
|
|||
|
|
link.classList.add('sidebar-item-active');
|
|||
|
|
link.classList.remove('hover:bg-[#001529]/20', 'transition-colors');
|
|||
|
|
} else {
|
|||
|
|
link.classList.remove('sidebar-item-active');
|
|||
|
|
link.classList.add('hover:bg-[#001529]/20', 'transition-colors');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 初始化滑块
|
|||
|
|
function initSlider() {
|
|||
|
|
const slider = document.getElementById('sidebar-slider');
|
|||
|
|
if (!slider) return;
|
|||
|
|
|
|||
|
|
// 找到当前活动项
|
|||
|
|
const activeLink = document.querySelector('.nav-link.sidebar-item-active');
|
|||
|
|
if (activeLink) {
|
|||
|
|
const wrapper = activeLink.closest('.nav-item-wrapper');
|
|||
|
|
if (wrapper) {
|
|||
|
|
updateSliderPosition(wrapper);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 绑定导航点击事件
|
|||
|
|
document.querySelectorAll('.nav-link').forEach(link => {
|
|||
|
|
link.addEventListener('click', function(e) {
|
|||
|
|
const wrapper = this.closest('.nav-item-wrapper');
|
|||
|
|
if (wrapper) {
|
|||
|
|
updateSliderPosition(wrapper);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新滑块位置
|
|||
|
|
function updateSliderPosition(targetWrapper) {
|
|||
|
|
const slider = document.getElementById('sidebar-slider');
|
|||
|
|
if (!slider || !targetWrapper) return;
|
|||
|
|
|
|||
|
|
const nav = document.querySelector('nav');
|
|||
|
|
if (!nav) return;
|
|||
|
|
|
|||
|
|
const navRect = nav.getBoundingClientRect();
|
|||
|
|
const wrapperRect = targetWrapper.getBoundingClientRect();
|
|||
|
|
|
|||
|
|
const top = wrapperRect.top - navRect.top + nav.scrollTop;
|
|||
|
|
const height = wrapperRect.height;
|
|||
|
|
|
|||
|
|
slider.style.top = top + 'px';
|
|||
|
|
slider.style.height = height + 'px';
|
|||
|
|
slider.style.opacity = '1';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 导出到全局
|
|||
|
|
window.SidebarLoader = {
|
|||
|
|
load: loadSidebar,
|
|||
|
|
highlight: highlightCurrentPage,
|
|||
|
|
getCurrentPage: getCurrentPage
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// DOM 加载完成后自动加载侧边栏
|
|||
|
|
if (document.readyState === 'loading') {
|
|||
|
|
document.addEventListener('DOMContentLoaded', loadSidebar);
|
|||
|
|
} else {
|
|||
|
|
loadSidebar();
|
|||
|
|
}
|
|||
|
|
})();
|