Files
x-panel/web/html/component/aSidebar.html
2026-05-03 11:34:48 +08:00

219 lines
7.3 KiB
HTML
Raw 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.
{{define "component/sidebar/content"}}
<template>
<div class="ant-sidebar">
<a-layout-sider :theme="themeSwitcher.currentTheme" collapsible :collapsed="collapsed"
@collapse="(isCollapsed, type) => collapseHandle(isCollapsed, type)" breakpoint="md" width="200">
<div class="sider-flex-wrapper">
<div class="sider-top">
<a-theme-switch></a-theme-switch>
</div>
<div class="sider-menu-container">
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="activeTab"
@click="({key}) => openLink(key)">
<a-menu-item v-for="tab in tabs" :key="tab.key">
<a-icon :type="tab.icon"></a-icon>
<span v-text="tab.title"></span>
</a-menu-item>
</a-menu>
</div>
<div class="sidebar-copyright-wrapper" v-show="!collapsed">
<div class="copyright-content">
<div class="brand-row">
<a-icon type="safety-certificate" theme="filled" class="brand-icon"></a-icon>
<span class="brand-name">X-Panel</span>
</div>
<div class="year-row">
<span>Copyright <a-icon type="copyright"></a-icon> 2022-2026</span>
</div>
</div>
</div>
</div>
</a-layout-sider>
<a-drawer placement="left" :closable="false" @close="closeDrawer" :visible="visible"
:wrap-class-name="themeSwitcher.currentTheme" :wrap-style="{ padding: 0 }" :style="{ height: '100%' }">
<div class="drawer-handle" @click="toggleDrawer" slot="handle">
<a-icon :type="visible ? 'close' : 'menu-fold'"></a-icon>
</div>
<a-theme-switch></a-theme-switch>
<a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="activeTab"
@click="({key}) => openLink(key)">
<a-menu-item v-for="tab in tabs" :key="tab.key">
<a-icon :type="tab.icon"></a-icon>
<span v-text="tab.title"></span>
</a-menu-item>
</a-menu>
</a-drawer>
</div>
</template>
{{end}}
{{define "component/aSidebar"}}
<style>
/* 1. 基础高度设置 */
.ant-sidebar, .ant-sidebar > .ant-layout-sider {
height: 100%;
}
/* [布局容器] */
.sider-flex-wrapper {
display: flex;
flex-direction: column; /* 从上到下排列 */
height: 100%;
overflow: hidden;
}
/* [菜单容器] */
.sider-menu-container {
/* [修改说明]:删除了 flex: 1。菜单高度现在由内容决定不会自动撑满 */
/* 添加 flex-shrink: 1 只是为了防止屏幕特别矮时菜单被切断,让它能出滚动条 */
flex-shrink: 1;
overflow-y: auto;
overflow-x: hidden;
}
.sider-menu-container .ant-menu {
border-right: none;
}
/* 2. 版权区域 */
.sidebar-copyright-wrapper {
/* [核心修改]margin-top: auto 是关键 */
/* 它的作用是:自动占据上方所有的空白空间,从而把自己推到容器的最底部 */
margin-top: auto;
flex-shrink: 0;
width: 100%;
padding: 15px 0 20px 0;
text-align: center;
background: inherit;
/* [已删除] border-top: ... (那条横线已经彻底删除了) */
}
/* 3. 品牌行样式 */
.brand-row {
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: 600;
margin-bottom: 4px;
opacity: 0.85;
letter-spacing: 0.5px;
}
.brand-icon {
margin-right: 6px;
font-size: 15px;
opacity: 0.8;
}
/* 4. 年份版权行样式 */
.year-row {
font-size: 11px;
opacity: 0.45;
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
display: flex;
justify-content: center;
align-items: center;
}
.year-row .anticon-copyright {
font-size: 10px;
margin: 0 3px;
position: relative;
}
/* 滚动条样式美化 */
.sider-menu-container::-webkit-scrollbar {
width: 4px;
}
.sider-menu-container::-webkit-scrollbar-thumb {
background: rgba(128, 128, 128, 0.2);
border-radius: 2px;
}
.sider-menu-container::-webkit-scrollbar-track {
background: transparent;
}
</style>
<script>
const SIDEBAR_COLLAPSED_KEY = "isSidebarCollapsed"
Vue.component('a-sidebar', {
data() {
return {
tabs: [
{
key: '{{ .base_path }}panel/',
icon: 'dashboard',
title: '{{ i18n "menu.dashboard"}}'
},
{
key: '{{ .base_path }}panel/inbounds',
icon: 'user',
title: '{{ i18n "menu.inbounds"}}'
},
{
key: '{{ .base_path }}panel/settings',
icon: 'setting',
title: '{{ i18n "menu.settings"}}'
},
{
key: '{{ .base_path }}panel/xray',
icon: 'tool',
title: '{{ i18n "menu.xray"}}'
},
{
key: '{{ .base_path }}panel/servers',
icon: 'cloud-server',
title: '{{ i18n "pages.controlledmanagement.title"}}'
},
{
key: '{{ .base_path }}panel/navigation',
icon: 'link',
title: '{{ i18n "menu.navigation"}}'
},
{
key: '{{ .base_path }}logout/',
icon: 'logout',
title: '{{ i18n "menu.logout"}}'
},
],
activeTab: [
'{{ .request_uri }}'
],
visible: false,
collapsed: JSON.parse(localStorage.getItem(SIDEBAR_COLLAPSED_KEY)),
}
},
methods: {
openLink(key) {
return key.startsWith('http') ?
window.open(key) :
location.href = key
},
closeDrawer() {
this.visible = false;
},
toggleDrawer() {
this.visible = !this.visible;
},
collapseHandle(collapsed, type) {
if (type === "clickTrigger") {
localStorage.setItem(SIDEBAR_COLLAPSED_KEY, collapsed);
this.collapsed = JSON.parse(localStorage.getItem(SIDEBAR_COLLAPSED_KEY));
}
}
},
template: `{{template "component/sidebar/content"}}`,
});
</script>
{{end}}