mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-11 07:55:59 +08:00
211 lines
6.5 KiB
Vue
211 lines
6.5 KiB
Vue
<template>
|
|
<div
|
|
class="sidebar-container"
|
|
element-loading-text="Loading..."
|
|
:element-loading-spinner="loadingSvg"
|
|
element-loading-svg-view-box="-10, -10, 50, 50"
|
|
element-loading-background="rgba(122, 122, 122, 0.01)"
|
|
>
|
|
<div class="fixed">
|
|
<PrimaryMenu />
|
|
</div>
|
|
<Logo :isCollapse="isCollapse" />
|
|
<el-scrollbar>
|
|
<el-menu
|
|
:default-active="activeMenu"
|
|
:router="menuRouter"
|
|
:collapse="isCollapse"
|
|
:collapse-transition="false"
|
|
:unique-opened="true"
|
|
@select="handleMenuClick"
|
|
>
|
|
<SubItem :menuList="routerMenus" />
|
|
<el-menu-item :index="''">
|
|
<el-icon @click="logout">
|
|
<SvgIcon :iconName="'p-logout'" />
|
|
</el-icon>
|
|
<template #title>
|
|
<span @click="logout">{{ $t('commons.login.logout') }}</span>
|
|
</template>
|
|
</el-menu-item>
|
|
</el-menu>
|
|
</el-scrollbar>
|
|
<Collapse />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, onMounted, defineEmits } from 'vue';
|
|
import { RouteRecordRaw, useRoute } from 'vue-router';
|
|
import { loadingSvg } from '@/utils/svg';
|
|
import Logo from './components/Logo.vue';
|
|
import Collapse from './components/Collapse.vue';
|
|
import SubItem from './components/SubItem.vue';
|
|
import router, { menuList } from '@/routers/router';
|
|
import { checkIsIntl, logOutApi } from '@/api/modules/auth';
|
|
import i18n from '@/lang';
|
|
import { ElMessageBox } from 'element-plus';
|
|
import { GlobalStore, MenuStore } from '@/store';
|
|
import { MsgSuccess } from '@/utils/message';
|
|
import { isString } from '@vueuse/core';
|
|
import { getSettingInfo } from '@/api/modules/setting';
|
|
import PrimaryMenu from '@/assets/images/menu-bg.svg?component';
|
|
|
|
const route = useRoute();
|
|
const menuStore = MenuStore();
|
|
const globalStore = GlobalStore();
|
|
defineProps({
|
|
menuRouter: {
|
|
type: Boolean,
|
|
default: true,
|
|
required: false,
|
|
},
|
|
});
|
|
const activeMenu = computed(() => {
|
|
const { meta, path } = route;
|
|
return isString(meta.activeMenu) ? meta.activeMenu : path;
|
|
});
|
|
const isCollapse = computed((): boolean => menuStore.isCollapse);
|
|
|
|
let routerMenus = computed((): RouteRecordRaw[] => {
|
|
return menuStore.menuList.filter((route) => route.meta && !route.meta.hideInSidebar) as RouteRecordRaw[];
|
|
});
|
|
|
|
const screenWidth = ref(0);
|
|
|
|
interface Node {
|
|
id: string;
|
|
title: string;
|
|
path?: string;
|
|
label: string;
|
|
isCheck: boolean;
|
|
children?: Node[];
|
|
}
|
|
const listeningWindow = () => {
|
|
window.onresize = () => {
|
|
return (() => {
|
|
screenWidth.value = document.body.clientWidth;
|
|
if (!isCollapse.value && screenWidth.value < 1200) menuStore.setCollapse();
|
|
if (isCollapse.value && screenWidth.value > 1200) menuStore.setCollapse();
|
|
})();
|
|
};
|
|
};
|
|
listeningWindow();
|
|
const emit = defineEmits(['menuClick']);
|
|
const handleMenuClick = (path) => {
|
|
emit('menuClick', path);
|
|
};
|
|
const logout = () => {
|
|
ElMessageBox.confirm(i18n.global.t('commons.msg.sureLogOut'), i18n.global.t('commons.msg.infoTitle'), {
|
|
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
|
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
|
type: 'warning',
|
|
})
|
|
.then(() => {
|
|
systemLogOut();
|
|
router.push({ name: 'entrance', params: { code: globalStore.entrance } });
|
|
globalStore.setLogStatus(false);
|
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
|
})
|
|
.catch(() => {});
|
|
};
|
|
|
|
const systemLogOut = async () => {
|
|
await logOutApi();
|
|
};
|
|
|
|
function extractLabels(node: Node, result: string[]): void {
|
|
if (node.isCheck) {
|
|
result.push(node.label);
|
|
}
|
|
if (node.children) {
|
|
for (const childNode of node.children) {
|
|
extractLabels(childNode, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getCheckedLabels(json: Node): string[] {
|
|
let result: string[] = [];
|
|
extractLabels(json, result);
|
|
return result;
|
|
}
|
|
|
|
const search = async () => {
|
|
await checkIsSystemIntl();
|
|
let checkedLabels: string | any[];
|
|
if (!globalStore.isIntl) {
|
|
const res = await getSettingInfo();
|
|
const json: Node = JSON.parse(res.data.xpackHideMenu);
|
|
checkedLabels = getCheckedLabels(json);
|
|
}
|
|
|
|
let rstMenuList: RouteRecordRaw[] = [];
|
|
menuStore.menuList.forEach((item) => {
|
|
let menuItem = JSON.parse(JSON.stringify(item));
|
|
let menuChildren: RouteRecordRaw[] = [];
|
|
if (menuItem.path === '/xpack') {
|
|
if (checkedLabels.length) {
|
|
menuItem.children.forEach((child: any) => {
|
|
for (const str of checkedLabels) {
|
|
if (child.name === str) {
|
|
child.hidden = false;
|
|
}
|
|
}
|
|
if (child.hidden === false) {
|
|
menuChildren.push(child);
|
|
if (checkedLabels.length === 2) {
|
|
menuItem.meta.title = child.meta.title;
|
|
} else {
|
|
menuItem.meta.title = 'xpack.menu';
|
|
}
|
|
}
|
|
});
|
|
menuItem.meta.hideInSidebar = false;
|
|
}
|
|
menuItem.children = menuChildren as RouteRecordRaw[];
|
|
rstMenuList.push(menuItem);
|
|
} else {
|
|
menuItem.children.forEach((child: any) => {
|
|
if (child.hidden == undefined || child.hidden == false) {
|
|
menuChildren.push(child);
|
|
}
|
|
});
|
|
menuItem.children = menuChildren as RouteRecordRaw[];
|
|
rstMenuList.push(menuItem);
|
|
}
|
|
});
|
|
menuStore.menuList = rstMenuList;
|
|
};
|
|
|
|
const checkIsSystemIntl = async () => {
|
|
const res = await checkIsIntl();
|
|
globalStore.isIntl = res.data;
|
|
};
|
|
|
|
onMounted(() => {
|
|
menuStore.setMenuList(menuList);
|
|
search();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import './index.scss';
|
|
|
|
.sidebar-container {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
background: var(--panel-menu-bg-color) no-repeat top;
|
|
|
|
.el-scrollbar {
|
|
flex: 1;
|
|
.el-menu {
|
|
overflow: auto;
|
|
overflow-x: hidden;
|
|
border-right: none;
|
|
}
|
|
}
|
|
}
|
|
</style>
|