219 lines
7.3 KiB
HTML
219 lines
7.3 KiB
HTML
{{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}}
|