<!-- @format --> <template> <div class="nav-side" :key="'navSide_' + $route.name"> <div class="nav-sub" v-show="isShow && (showLayout || backTo)"> <ul style="margin: 0"> <li v-show="!backTo" ><span class="nav-sub-head ng-scope" translate="COMPANY">{{ title }}</span></li > <li v-show="backTo"> <span class="nav-sub-head h5 ng-scope nav-sub-head-back" style="box-sizing: border-box; cursor: pointer" @click="navigation(backTo)"> <i class="iconfont"></i> <span>返回</span> </span> </li> </ul> <!-- {{ menus }} --> <a-menu mode="inline" class="nav-menu" :open-keys="openKeys" v-model:selectedKeys="selectedKeys"> <template v-for="menu in menus"> <a-sub-menu v-if="menu.submenus" :key="menu.name"> <template #title>{{ menu.label }}</template> <a-menu-item v-for="subMenu in menu.submenus" :key="subMenu.name" :class="{ 'nav-current': fullPath.indexOf(subMenu.url) != -1 }"> <router-link class="nav-sub-item" active-class="nav-sub-current" :class="{ 'nav-sub-current': fullPath.indexOf(subMenu.url) != -1 }" :to="{ name: subMenu.name }" @click="navChange(subMenu)"> <span>{{ subMenu.label }}</span> </router-link> </a-menu-item> </a-sub-menu> <a-menu-item v-else :key="menu.name" :class="{ 'nav-current': fullPath.indexOf(`${menu.url}`) != -1 }"> <router-link class="nav-sub-item" active-class="nav-sub-current" :class="{ 'nav-sub-current': dealRouter(`${menu.url}`) }" @click="navChange(menu)" :to="{ name: menu.name }"> <span>{{ menu.label }}</span> </router-link> </a-menu-item> </template> </a-menu> </div> <div class="content-main"> <router-view /> </div> </div> </template> <script lang="ts"> import { SideMenu, configRegist } from '/nerv-lib/paas/store/modules/config-service'; import { computed, defineComponent, inject, reactive, ref, toRefs } from 'vue'; // import { storeToRefs, mapWritableState } from 'pinia'; import { useRoute, useRouter } from 'vue-router'; import { authorizationService } from '/nerv-lib/paas/store/modules/authorization-service'; import { cloneDeep } from 'lodash-es'; export default defineComponent({ name: 'SideNav', components: {}, setup() { const configReg = configRegist(); const router = useRouter(); const route = useRoute(); const menus = ref<Array<any>>([]); const backTo = ref<String>(''); let backToHandle = ref<Function>; const isThreeSider = ref(false); const state = reactive({ selectedKeys: [], }); const showLayout = inject('showLayout', true); const dealRouter = (val: any) => { return router.currentRoute.value.fullPath.indexOf(val) !== -1; }; const menuNameList = computed(() => { const { sideMenus } = route?.meta || {}; return sideMenus.menus.map((item) => item.name); }); function navChange(url: string) { Object.keys(sessionStorage).forEach((key) => { const tableSession = JSON.parse(sessionStorage[key] || '{}'); if (tableSession && tableSession.name && menuNameList.value.includes(tableSession.name)) { delete sessionStorage[key]; } }); } return { dealRouter, menus, backTo, router, isThreeSider, configReg, ...toRefs(state), navChange, showLayout, backToHandle, }; }, data(): { title: string; // menus: Array<any>; isShow: boolean; //backTo: string; currName: string; fullPath: string; openKeys: string[]; } { return { title: '', // menus: [], isShow: true, //backTo: '', //是否需要返回按钮 currName: '', //标记自己当前的路由配置取值key fullPath: '', //当前激活路由的url openKeys: [], }; }, watch: { router: { handler() { this.initSider(); }, deep: true, }, }, mounted() { this.initSider(); }, unmounted() { this.configReg.removeUrl(this.currName); }, methods: { initSider() { if (this.$route.meta.sideMenus) { const authService = authorizationService(); const modulesRes = authService.ModulesRes; const appInfo = cloneDeep(modulesRes.find((item) => item.app === authService.getApp())); const moduleName = this.$route.matched[0].name as string; const sideMenus = cloneDeep(this.$route.meta.sideMenus as SideMenu); const name = this.$route.name; this.fullPath = this.$route.fullPath; this.title = sideMenus.title as string; this.backTo = sideMenus.backTo || ''; this.backToHandle = sideMenus?.backToHandle; this.menus = []; this.openKeys = []; const { projectName } = this.$route.params; function getMenuItem(name: string) { console.log('---', name); const menu = sideMenus.menus.find((item) => item.name === name); if ( menu && authService.checkPermission( moduleName, menu.name as string, undefined, projectName as string, ) ) { return menu; } } function getMenuItemcustom(record: object, name: string) { const menu = sideMenus.menus.find((item) => item.name === name); if ( menu && authService.checkPermission( record.useOtherAuthority.app, (record.useOtherAuthority.bindView ? record.useOtherAuthority.bindView : menu.name) as string, undefined, projectName as string, ) ) { return menu; } } if (sideMenus.root) { this.selectedKeys = []; appInfo?.menus?.forEach((item: Recordable) => { if (item.isDir) { const _item = { name: item.name, label: item.label, submenus: [], }; let open = false; //处理 模块受其他项目权限控制的情况 if (item.useOtherAuthority) { item.submenus.forEach((subItem) => { const _subItem = getMenuItemcustom(item, subItem.name); !!_subItem && _item.submenus.push(_subItem); if (this.fullPath.includes(subItem.url ? subItem.url : subItem.path)) { this.selectedKeys = [subItem.name]; // 通过输入路由匹配到文件夹下的菜单,一开始须手动加入 open = true; } }); } else { item.submenus.forEach((subItem) => { const _subItem = getMenuItem(subItem.name); !!_subItem && _item.submenus.push(_subItem); if (this.fullPath.includes(subItem.url ? subItem.url : subItem.path)) { this.selectedKeys = [subItem.name]; // 通过输入路由匹配到文件夹下的菜单,一开始须手动加入 open = true; } }); } // if(item.submenus.length===0){ // } if (open) this.openKeys.push(item.name); console.log('_item1', _item); if (_item.submenus && _item.submenus.length !== 0) { this.menus.push(_item); } } else { //如果存在isGlobal if (item.isGlobal) { let globalList = []; sideMenus.menus.forEach((subItem) => { if (subItem.app === item.name) { globalList.push(subItem); } }); globalList.forEach((global) => { const _item = authService.checkPermission( item.name, global.name, undefined, projectName as string, ); !!_item && this.menus.push(global); }); } else { if (item.useOtherAuthority) { const _item = getMenuItemcustom(item, item.name); !!_item && this.menus.push(_item); } else { const _item = getMenuItem(item.name); !!_item && this.menus.push(_item); } } } }); } else { this.menus = sideMenus.menus.filter((menu) => { return ( authService.checkPermission( menu.app ? menu.app : moduleName, menu.bindView ? menu.bindView : (menu.name as string), undefined, projectName as string, ) || menu.openPermission ); }); } console.log('--------', this.menus); this.isShow = true; if (name === sideMenus.name && this.menus.length > 0) { this.$router.push({ name: this.menus[0].name }); } } }, navigation(url: string) { if (this.backToHandle && Function(this.backToHandle)) { this.backToHandle(); return; } //this.navChange(url); this.$router.push({ name: url }); }, }, }); </script> <style lang="less" scoped> .nav-side { display: flex; height: 100%; .nav-sub { float: left; // height: 100%; overflow: auto; width: 149px; min-width: 149px; background: @layout-sider-background !important; background-size: cover; .nav-sub-head { padding-left: 16px; padding-right: 16px; display: inline-block; box-sizing: border-box; width: 100%; font-weight: 700; height: 56px; line-height: 56px; } .nav-sub-head-back { .iconfont { color: #00acff !important; display: inline-block; transform: scale(0.7); font-size: 12px; } span { color: #00acff !important; } } .nav-sub-item { color: #212529; display: inline-block; box-sizing: border-box; width: 100%; height: 48px; line-height: 48px; &:hover { background-color: #fff; } } .nav-sub-current { background-color: #fff !important; color: @link-color !important; } } :deep(.ant-menu) { background-color: unset; .ant-menu-item { background-color: unset; margin-top: 0; &.nav-current { background-color: #fff; color: #00acff; } &:hover { background-color: #fff; color: #00acff; } &::after { border-right: none; } &.ant-menu-item-selected::after { border-right: none; } } } } .content-main { // width: calc(100% - 149px); width: 100%; min-width: 650px; background-color: #ffffff; overflow: auto; } ul, li { list-style: none; padding: 0; } </style>