push
This commit is contained in:
278
lib/saas/view/system/layout/customSider.vue
Normal file
278
lib/saas/view/system/layout/customSider.vue
Normal file
@@ -0,0 +1,278 @@
|
||||
<!-- @format -->
|
||||
|
||||
<template>
|
||||
<div class="ns-left-menu-space" :class="{ 'ns-left-menu-space-collapsed': collapsed }">
|
||||
<a-layout-sider
|
||||
class="ns-left-menu"
|
||||
:width="208"
|
||||
:style="`background-image:url(${sideBgImg})`"
|
||||
:collapsedWidth="48"
|
||||
:collapsed="collapsed"
|
||||
breakpoint="lg"
|
||||
:trigger="null">
|
||||
<a-menu
|
||||
mode="inline"
|
||||
:inlineIndent="16"
|
||||
:openKeys="collapsed ? [] : initSiderOpenKey"
|
||||
:selectedKeys="initSiderKey"
|
||||
v-for="(item, index) in menuList"
|
||||
:key="index">
|
||||
<a-sub-menu
|
||||
v-if="item.type === 'menus' && item.menus && item.menus.length"
|
||||
:key="item.code">
|
||||
<template #title>
|
||||
<span role="img" class="anticon">
|
||||
<i
|
||||
style="margin-right: 5px; transform: translateY(2px); font-size: 14px"
|
||||
v-if="item.icon?.includes('icon-')"
|
||||
:class="`iconfont ${item.icon}`"></i>
|
||||
<ns-icon v-else :name="item.icon ? item.icon : ''" size="16" />
|
||||
</span>
|
||||
<span>{{ item.label }}</span>
|
||||
</template>
|
||||
<!-- 跳转外部链接 -->
|
||||
<!-- <div v-if="item.meta?.isNewOpen">
|
||||
<div
|
||||
v-for="newOpen in item.meta?.itemList ? item.meta?.itemList : []"
|
||||
:key="newOpen.code">
|
||||
<a-menu-item v-if="checkOpAuth(newOpen.code)" :key="newOpen.code">
|
||||
<a
|
||||
:href="newOpen.url ? newOpen.url : newOpen.getUrl ? newOpen.getUrl() : ''"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
{{ newOpen.name }}
|
||||
</a></a-menu-item
|
||||
>
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- <div v-else> -->
|
||||
<div v-for="sitem in item.menus" :key="sitem.code">
|
||||
<a-menu-item
|
||||
v-if="
|
||||
sitem.type === 'noChildrenMenu' ||
|
||||
(sitem.type === 'menus' && (!sitem.menus || !sitem.menus?.length))
|
||||
"
|
||||
:key="sitem.code">
|
||||
<a @click="goTargetRouter(sitem)">
|
||||
<span style="margin-left: 8px">
|
||||
{{ sitem.label }}
|
||||
</span>
|
||||
</a>
|
||||
</a-menu-item>
|
||||
<a-sub-menu
|
||||
v-if="sitem.type === 'menus' && sitem.menus && sitem.menus.length"
|
||||
:key="sitem.code">
|
||||
<template #title>
|
||||
<span role="img" style="margin-left: 8px" class="anticon" v-show="sitem.icon">
|
||||
<i
|
||||
style="margin-right: 5px; transform: translateY(2px); font-size: 14px"
|
||||
v-if="sitem.icon?.includes('icon-')"
|
||||
:class="`iconfont ${sitem.icon}`"></i>
|
||||
<ns-icon v-else :name="sitem.icon" size="16" />
|
||||
</span>
|
||||
<span>{{ sitem.label }}</span>
|
||||
</template>
|
||||
<a-menu-item v-for="ditem in sitem.menus" :key="ditem.code">
|
||||
<a @click="goTargetRouter(ditem)">
|
||||
<span style="margin-left: 8px">{{ ditem.label }}</span>
|
||||
</a>
|
||||
</a-menu-item>
|
||||
</a-sub-menu>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</a-sub-menu>
|
||||
<a-menu-item
|
||||
v-if="
|
||||
item.type === 'noChildrenMenu' ||
|
||||
(item.type === 'menus' && (!item.menus || !item.menus?.length))
|
||||
"
|
||||
:class="initSiderKey.includes(item.code) ? 'firstMenuItem-selected' : ''"
|
||||
:key="item.code">
|
||||
<a @click="goTargetRouter(item)">
|
||||
<span role="img" class="anticon" v-show="item.icon">
|
||||
<i
|
||||
style="margin-right: 5px; transform: translateY(2px); font-size: 14px"
|
||||
v-if="item.icon?.includes('icon-')"
|
||||
:class="`iconfont ${item.icon}`"></i>
|
||||
<ns-icon v-else :name="item.icon ? item.icon : ''" size="16" />
|
||||
</span>
|
||||
<span>{{ item.label }}</span>
|
||||
</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<div class="ns-left-menu-trigger" @click="leftMenuTrigger">
|
||||
<menu-unfold-outlined v-if="collapsed" class="trigger" />
|
||||
<menu-fold-outlined v-else class="trigger" />
|
||||
</div>
|
||||
</a-layout-sider>
|
||||
<div class="ns-left-menu-trigger" @click="leftMenuTrigger">
|
||||
<ns-icon name="trigger" class="trigger" size="22" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, inject, ref, watchEffect, computed } from 'vue';
|
||||
import { Emitter } from 'mitt';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { appConfigStore } from '/nerv-lib/saas/store/modules/app-config';
|
||||
import { emitEvents } from '/nerv-base/view/system/application.d';
|
||||
import { storeToRefs } from 'pinia';
|
||||
export default defineComponent({
|
||||
name: 'CustomSider',
|
||||
components: {
|
||||
MenuUnfoldOutlined,
|
||||
MenuFoldOutlined,
|
||||
},
|
||||
props: {
|
||||
menuList: { type: Array },
|
||||
initSiderKey: { type: Array },
|
||||
initSiderOpenKey: { type: Array },
|
||||
},
|
||||
setup: (props) => {
|
||||
const mittEmit = inject('mittEmit') as Emitter<emitEvents>;
|
||||
const configStore = appConfigStore();
|
||||
const { getThemeConfig: themeConfig } = storeToRefs(configStore);
|
||||
const router = useRouter();
|
||||
const dealRouter = (menuList, routerInfo) => {
|
||||
menuList?.forEach((item) => {
|
||||
if (item.name === routerInfo.name) {
|
||||
const redirectItem = item.children?.filter((x) => !x.isHide)[0];
|
||||
if (redirectItem) {
|
||||
router.push({ name: redirectItem.name });
|
||||
}
|
||||
} else {
|
||||
if (item.children?.length) {
|
||||
dealRouter(item.children, routerInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const sideBgImg = computed(() => {
|
||||
if (themeConfig.sideUrl) {
|
||||
return themeConfig.sideUrl;
|
||||
} else {
|
||||
return `${import.meta.env.VITE_PUBLIC_PATH}asset/image/side.png`;
|
||||
}
|
||||
});
|
||||
const goTargetRouter = (menu: object) => {
|
||||
let code = menu.code;
|
||||
if (configStore.resourceName) {
|
||||
code = code.toString().replace(configStore.resourceName, '');
|
||||
}
|
||||
let toName = code;
|
||||
if (menu.type === 'noChildrenMenu' && menu.menus && menu.menus.length) {
|
||||
toName = `${code}Index`;
|
||||
}
|
||||
router.push({
|
||||
name: toName,
|
||||
});
|
||||
};
|
||||
watchEffect(() => {
|
||||
if (!router.currentRoute.value.redirectedFrom) {
|
||||
dealRouter(props.menuList, router.currentRoute.value);
|
||||
}
|
||||
});
|
||||
const collapsed = ref<boolean>(false);
|
||||
const leftMenuTrigger = () => {
|
||||
collapsed.value = !collapsed.value;
|
||||
mittEmit.emit('leftMenuTrigger', collapsed.value);
|
||||
};
|
||||
return {
|
||||
sideBgImg,
|
||||
themeConfig,
|
||||
goTargetRouter,
|
||||
leftMenuTrigger,
|
||||
collapsed,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ns-left-menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
background-color: @white;
|
||||
padding-top: 48px;
|
||||
:deep(::-webkit-scrollbar) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#iframeApplication .ns-left-menu {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.ant-menu-submenu-title .anticon + span {
|
||||
margin-left: 8px !important;
|
||||
}
|
||||
.ns-left-menu-space {
|
||||
width: 208px;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s;
|
||||
flex: 0 0 208px;
|
||||
&.ns-left-menu-space-collapsed {
|
||||
width: 48px;
|
||||
flex: 0 0 48px;
|
||||
}
|
||||
}
|
||||
.ns-left-menu-space-collapsed {
|
||||
.ns-left-menu-trigger {
|
||||
width: 48px !important;
|
||||
justify-content: center;
|
||||
padding-left: 0px;
|
||||
}
|
||||
.trigger {
|
||||
padding: 0;
|
||||
transform: rotate(180deg);
|
||||
// transform: rotateX('90deg');
|
||||
}
|
||||
}
|
||||
|
||||
.ns-left-menu-trigger {
|
||||
width: 208px;
|
||||
height: 40px;
|
||||
transition: all 0.2s;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
cursor: pointer;
|
||||
background: #163361;
|
||||
bottom: 0px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: left;
|
||||
padding-left: 24px;
|
||||
|
||||
// justify-content: center;
|
||||
&:hover {
|
||||
.trigger {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.trigger {
|
||||
font-size: 18px;
|
||||
line-height: 64px;
|
||||
transform: rotate(0deg);
|
||||
transition: color 0.3s;
|
||||
}
|
||||
.ant-menu-submenu-selected > .ant-menu-submenu-title > .ant-menu-submenu-expand-icon,
|
||||
.ant-menu-submenu-selected > .ant-menu-submenu-title > .ant-menu-submenu-arrow {
|
||||
color: red !important;
|
||||
}
|
||||
.ant-menu-submenu-selected .secendIcon {
|
||||
color: @primary-color !important;
|
||||
}
|
||||
.ant-menu-inline,
|
||||
.ant-menu-vertical,
|
||||
.ant-menu-vertical-left {
|
||||
border: unset;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user