XNSim/XNSimHtml/components/sub-toolbar.js

324 lines
13 KiB
JavaScript
Raw Normal View History

2025-04-28 12:25:20 +08:00
class SubToolbar extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this._currentTool = 'home';
}
static get observedAttributes() {
return ['current-tool'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'current-tool' && oldValue !== newValue) {
this._currentTool = newValue;
this.updateSubMenu();
this.updateToolHeader();
}
}
connectedCallback() {
this.render();
this.addEventListeners();
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
width: 200px;
background: linear-gradient(180deg, #7986E7 0%, #8B6DB3 100%);
position: relative;
transition: width 0.3s ease;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
}
:host(.collapsed) {
width: 0;
}
.sub-toolbar-wrapper {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
:host(.collapsed) .sub-toolbar-content {
transform: translateX(-200px);
}
.sub-toolbar-content {
width: 200px;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
transition: transform 0.3s ease;
}
.sub-toolbar-header {
padding: 28px 20px;
height: 92px;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.1);
color: white;
font-size: 16px;
font-weight: bold;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
}
.sub-toolbar-header .icon {
width: 24px;
height: 24px;
margin-right: 10px;
}
.sub-menu {
display: none;
padding-top: 10px;
}
.sub-menu.active {
display: block;
}
.sub-item {
display: flex;
align-items: center;
padding: 10px 20px;
color: white;
cursor: pointer;
transition: all 0.3s;
}
.sub-item:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.sub-item.active {
background-color: rgba(255, 255, 255, 0.2);
}
.icon {
width: 24px;
height: 24px;
margin-right: 10px;
}
.toolbar-toggle {
position: absolute;
right: 0;
top: 50%;
transform: translate(50%, -50%);
width: 32px;
height: 32px;
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 1000;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
:host(.collapsed) .toolbar-toggle {
right: 0;
}
.toolbar-toggle:hover {
transform: translate(50%, -50%) scale(1.1);
}
.toggle-icon {
width: 20px;
height: 20px;
}
</style>
<div class="sub-toolbar-wrapper">
<div class="sub-toolbar-content">
<div class="sub-toolbar-header">
<img src="assets/icons/png/home.png" alt="主页" class="icon" id="currentToolIcon">
<span id="currentToolName">主页</span>
</div>
<!-- 主页子菜单 -->
<div class="sub-menu active" data-parent="home">
<div class="sub-item" data-icon="dashboard">
<img src="assets/icons/png/dashboard.png" alt="概览" class="icon">
概览
</div>
<div class="sub-item" data-icon="clock">
<img src="assets/icons/png/clock.png" alt="更新记录" class="icon">
更新记录
</div>
<div class="sub-item" data-icon="server">
<img src="assets/icons/png/server.png" alt="系统信息" class="icon">
系统信息
</div>
<div class="sub-item" data-icon="help">
<img src="assets/icons/png/help.png" alt="帮助" class="icon">
帮助
</div>
2025-05-07 16:02:39 +08:00
<div class="sub-item" data-icon="question">
<img src="assets/icons/png/question.png" alt="Q&A" class="icon">
Q&A
</div>
2025-04-28 12:25:20 +08:00
</div>
<!-- 配置子菜单 -->
<div class="sub-menu" data-parent="config">
<div class="sub-item" data-icon="chip">
<img src="assets/icons/png/chip.png" alt="运行环境配置" class="icon">
运行环境配置
</div>
<div class="sub-item" data-icon="cube">
<img src="assets/icons/png/cube.png" alt="模型配置" class="icon">
模型配置
</div>
<div class="sub-item" data-icon="settings">
<img src="assets/icons/png/settings.png" alt="服务配置" class="icon">
服务配置
</div>
</div>
<!-- 开发子菜单 -->
<div class="sub-menu" data-parent="develop">
<div class="sub-item" data-icon="plug">
<img src="assets/icons/png/plug.png" alt="接口配置" class="icon">
接口配置
</div>
<div class="sub-item" data-icon="cube">
<img src="assets/icons/png/cube.png" alt="模型开发" class="icon">
模型开发
</div>
<div class="sub-item" data-icon="settings">
<img src="assets/icons/png/settings.png" alt="服务开发" class="icon">
服务开发
</div>
</div>
<!-- 运行子菜单 -->
<div class="sub-menu" data-parent="run">
<div class="sub-item" data-icon="flask">
<img src="assets/icons/png/flask.png" alt="运行测试" class="icon">
运行测试
</div>
<div class="sub-item" data-icon="rocket">
<img src="assets/icons/png/rocket.png" alt="运行仿真" class="icon">
运行仿真
</div>
<div class="sub-item" data-icon="file">
<img src="assets/icons/png/file.png" alt="运行日志" class="icon">
运行日志
</div>
2025-04-28 12:25:20 +08:00
</div>
<!-- 监控子菜单 -->
<div class="sub-menu" data-parent="monitor">
<div class="sub-item" data-icon="desktop">
<img src="assets/icons/png/desktop.png" alt="仿真监控" class="icon">
仿真监控
</div>
<div class="sub-item" data-icon="cubes">
<img src="assets/icons/png/cubes.png" alt="模型监控" class="icon">
模型监控
</div>
<div class="sub-item" data-icon="chart-bar">
<img src="assets/icons/png/chart-bar.png" alt="数据监控" class="icon">
数据监控
</div>
<div class="sub-item" data-icon="database">
<img src="assets/icons/png/database.png" alt="数据采集" class="icon">
数据采集
</div>
</div>
<!-- 系统管理子菜单 -->
<div class="sub-menu" data-parent="system">
<div class="sub-item" data-icon="user">
<img src="assets/icons/png/user.png" alt="个人中心" class="icon">
个人中心
</div>
<div class="sub-item admin-only" data-icon="users">
<img src="assets/icons/png/users.png" alt="用户管理" class="icon">
用户管理
</div>
</div>
</div>
</div>
<div class="toolbar-toggle" title="收起">
<img src="assets/icons/png/chevron-dleft.png" alt="收起" class="toggle-icon">
</div>
`;
}
updateSubMenu() {
const subMenus = this.shadowRoot.querySelectorAll('.sub-menu');
subMenus.forEach(menu => {
menu.classList.toggle('active', menu.getAttribute('data-parent') === this._currentTool);
});
}
addEventListeners() {
// 切换按钮事件
const toggleButton = this.shadowRoot.querySelector('.toolbar-toggle');
toggleButton.addEventListener('click', () => {
this.classList.toggle('collapsed');
const isCollapsed = this.classList.contains('collapsed');
toggleButton.querySelector('img').src = `assets/icons/png/chevron-d${isCollapsed ? 'right' : 'left'}.png`;
toggleButton.querySelector('img').alt = isCollapsed ? '展开' : '收起';
toggleButton.title = isCollapsed ? '展开' : '收起';
});
// 子菜单项点击事件
const subItems = this.shadowRoot.querySelectorAll('.sub-item');
subItems.forEach(item => {
item.addEventListener('click', () => {
// 移除同级菜单项的激活状态
const siblings = item.parentElement.querySelectorAll('.sub-item');
siblings.forEach(si => si.classList.remove('active'));
// 激活当前菜单项
item.classList.add('active');
// 触发自定义事件
const event = new CustomEvent('sub-item-selected', {
detail: {
parent: item.closest('.sub-menu').getAttribute('data-parent'),
text: item.textContent.trim(),
icon: item.getAttribute('data-icon')
},
bubbles: true,
composed: true
});
this.dispatchEvent(event);
});
});
}
// 更新管理员选项的显示状态
updateAdminItems(accessLevel) {
const adminItems = this.shadowRoot.querySelectorAll('.admin-only');
adminItems.forEach(item => {
item.style.display = accessLevel >= 3 ? 'flex' : 'none';
});
}
updateToolHeader() {
const toolIcons = {
'home': { icon: 'home', text: '主页' },
'develop': { icon: 'develop', text: '开发' },
'config': { icon: 'sliders', text: '配置' },
'run': { icon: 'play', text: '运行' },
'monitor': { icon: 'chart', text: '监控' },
'system': { icon: 'cogs', text: '系统管理' }
};
const currentTool = toolIcons[this._currentTool] || toolIcons['home'];
const iconElement = this.shadowRoot.getElementById('currentToolIcon');
const nameElement = this.shadowRoot.getElementById('currentToolName');
iconElement.src = `assets/icons/png/${currentTool.icon}.png`;
iconElement.alt = currentTool.text;
nameElement.textContent = currentTool.text;
}
}
customElements.define('sub-toolbar', SubToolbar);