Files
Situation-Awareness-Platfor…/src/components/v2/NavSidebar/index.vue
2025-03-12 18:41:20 +08:00

287 lines
7.9 KiB
Vue
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.
<template>
<div class="navtabs-avatardiv pb-24 pr-24 pl-[10px]" v-if="showAvatar">
<GAvatar :src="avatarParam?.avatar" :style="isOrg?'border:.5px solid #d3d3d3;border-radius: var(--border-radius);':''" :name="avatarParam?.name" :width="48" :height="48" :is_round="isRound"></GAvatar>
<div class="navtabs-text ml-[16px]">
<div class="info-span text-base text-G900 navtabs-omit">{{ avatarParam?.name }}</div>
<div class="info-subtext text-sm text-CG600 navtabs-omit">{{ avatarParam?.infoSubText }}</div>
</div>
</div>
<div class="g-nav-sidebar w-[200px] pb-[48px]">
<slot name="sidebarInfo"></slot>
<!-- ui增加分类名和分割线 -->
<template v-if="menuShow">
<div v-for="(typeItem, index) in setMenuTypes(menulist)" :key="`${typeItem.label}_${index}`">
<div class="mt-[16px] mb-[8px] text-[#9C9DB4] pl-[16px]" v-if="typeItem.label">{{ typeItem.label }}</div>
<d-menu mode="vertical" :default-select-keys="[id]" :open-keys="openKeys" @select="handleNav">
<template v-for="item in typeItem.children" :key="item.id">
<d-menu-item v-if="!item.children" :key="item.id">
<template #icon v-if="item?.icon">
<Icon :name="item?.icon" class="common-icon"></Icon>
<Icon :name="item?.activeIcon" class="active-icon"></Icon>
</template>
{{ item.label }}</d-menu-item>
<d-sub-menu v-if="item.children" :title="item.label" :key="item.id">
<template #icon v-if="item?.icon">
<!-- <Icon :name="item?.icon"></Icon> -->
<div class="icon-div">
<Icon :name="item?.icon"></Icon>
<Icon v-if="item.isNew" class="icon-new" :name="'gt-new'" size="28px"></Icon>
</div>
</template>
<d-menu-item v-for="item1 in item.children" :key="item1.id">
<template #icon v-if="item1?.icon">
<Icon :name="item1?.icon"></Icon>
</template>
{{ item1.label }}</d-menu-item>
</d-sub-menu>
</template>
</d-menu>
<div class="row-line" v-if="setMenuTypes(menulist)?.length - 1 > index"></div>
</div>
</template>
</div>
</template>
<script setup lang="ts">
import { ref, watch, nextTick, computed } from 'vue';
import { onBeforeRouteUpdate, useRouter, useRoute } from 'vue-router';
import { type listType } from './types';
import menu from '@/constant/menu';
import { orgInfoStore, type OrgInfo } from '@/stores/Org/index';
import { useAccountStore } from '@/stores/user';
const { accountInfo } = useAccountStore();
interface IProps {
// 声明props内容
showAvatar?: boolean,
isRound?: boolean,
avatarParam?: {
avatar?: string,
name?: string,
infoSubText?: string, // 预留,暂时没有传值
[x: string]: any
}
}
const props = withDefaults(defineProps<IProps>(), {
showAvatar: true,
isRound: false,
avatarParam: () => {
return {
visibility: ''
};
}
});
const orgStore = orgInfoStore();
const route = useRoute();
const menulist = ref<listType[]>(menu[route.meta.sidebarType]);
const router = useRouter();
const nsId = computed(() => orgStore.communityInfo?.ns_id);
const isOrg = computed(() => /^\/org\//.test(route.path));
const devHost = '';
// const devHost = (import.meta as any).env.MODE === 'development' ? 'https://loc-devpress.csdn.net:444' : '';
const id = ref();
const openKeys = ref([]);
const setCurSelected = () => {
// 白名单处理Webhook创建、详情页要选中导航
id.value = router.currentRoute.value.name?.includes('repoWebhook') ? 'repoWebhook' : router.currentRoute.value.name;
menulist.value?.forEach(item => {
if (item?.children?.some(e => e.id === id.value)) {
openKeys.value.push(item.id);
}
});
};
// 判断社区是否显示
const menuShow = ref(true);
const onShowCom = () => {
menuShow.value = false;
menulist.value = menu[route.meta.sidebarType].filter((item: any) => {
if (item.label === '社区管理') {
return orgStore.orgInfo.visibility === 'public';
}
return true;
});
nextTick(() => {
menuShow.value = true;
});
};
const onShowPipeLine = async () => {
menuShow.value = false;
menulist.value = menu[route.meta.sidebarType].filter((item: any) => {
if (item.label === '流水线') {
return accountInfo.atomgit_username;
}
return true;
});
nextTick(() => {
menuShow.value = true;
});
};
watch(() => orgStore.orgInfo, () => {
onShowCom();
}, { deep: true });
watch(() => accountInfo.atomgit_username, () => {
onShowPipeLine();
}, { deep: true });
onBeforeRouteUpdate((to) => {
id.value = to.name; // 页面加载激活对应tab
menulist.value = menu[to.meta.sidebarType]; // 根据meta中的type确定导航内容
if (route.meta.sidebarType === 'userSetting') {
onShowPipeLine();
}
});
watch(() => router.currentRoute.value.path, (newValue, oldValue) => {
menulist.value = menu[route?.meta?.sidebarType];
if (route.meta.sidebarType === 'orgSetting') {
onShowCom();
}
if (route.meta.sidebarType === 'userSetting') {
onShowPipeLine();
}
setCurSelected();
}, { immediate: true });
// 点击tab跳转路由
const handleNav = (val) => {
if (/^\/organization/.test(val.key)) {
window.open(`${devHost}${val.key}/${nsId.value}`, '_self');
} else router.push({ name: val.key });
};
// 分类处理函数-增加分类名称显示
const setMenuTypes = (menu:any) => {
const res = []; const typeMap = new Map();
for (let i = 0; i < menu.length; ++i) {
const { menuType } = menu[i];
if (menuType) {
let type = typeMap.get(menuType);
if (!type) {
type = { label: menuType, children: [] };
res.push(type);
typeMap.set(menuType, type);
}
type.children.push(menu[i]);
} else {
if (res.length && res[res.length - 1].label === '') res[res.length - 1].children.push(menu[i]);
else res.push({ label: '', children: [menu[i]] });
}
}
return res;
};
</script>
<style lang="scss" scoped>
.g-nav-sidebar {
:deep(.devui-menu-vertical) {
border-right: 0;
background: none !important;
.devui-menu-item {
color: var(--devui-text);
.devui-menu-icon + span {
margin-left: 8px;
}
.active-icon {
display: none;
}
&:hover {
background: var(--tab-active-bg) !important;
border-radius: var(--devui-border-radius);
.active-icon {
display: inline-block;
}
.common-icon {
display: none;
}
}
}
.devui-menu-item-select {
background: var(--tab-active-bg) !important;
border-radius: var(--devui-border-radius);
.active-icon {
display: inline-block;
}
.common-icon {
display: none;
}
}
.layer_1 {
.devui-menu-item,
.devui-submenu-title {
padding: 0 16px !important;
}
}
.layer_2 {
.devui-menu-item {
padding: 0 50px !important;
}
.devui-submenu-title {
padding: 0 10px !important;
}
}
.layer_2>div.devui-submenu-title,
ul.devui-submenu .devui-menu-item {
background: none;
}
.icon-chevron-up {
color: var(--color-CG600);
}
}
.row-line {
width: calc(100% - 32px);
margin-left: 16px;
height: 1px;
background: var(--devui-dividing-line);
margin-top: 16px;
}
}
.navtabs-avatardiv {
width: 100%;
display: flex;
.navtabs-text {
flex: 1;
width: 0;
display: flex;
flex-direction: column;
justify-content: center;
}
.info-span {
font-weight: 500;
line-height: 24px;
}
.info-subtext {
// font-size: var(--text-sm);
font-weight: 400;
// color: var(--color-CG600);
line-height: 20px;
}
}
.navtabs-omit {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.icon-div {
position: relative;
.icon-new {
position: absolute;
top: -18px;
left: 8px;
}
}</style>