parent.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <template>
  2. <div class="layout-parent">
  3. <Vertical v-if="isShowLeftMenu" :menuList="menuLeftList" />
  4. <router-view v-slot="{ Component }">
  5. <transition :name="setTransitionName" mode="out-in">
  6. <keep-alive>
  7. <component :is="Component" :key="state.refreshRouterViewKey" :class="isShowLeftMenu ? 'w100vh-210' : 'w100'" v-show="!isIframePage" v-if="route.meta.isKeepAlive" />
  8. </keep-alive>
  9. </transition>
  10. <transition :name="setTransitionName" mode="out-in">
  11. <component :is="Component" :key="state.refreshRouterViewKey" :class="isShowLeftMenu ? 'w100vh-210' : 'w100'" v-show="!isIframePage" v-if="!route.meta.isKeepAlive" />
  12. </transition>
  13. </router-view>
  14. <transition :name="setTransitionName" mode="out-in">
  15. <Iframes :class="isShowLeftMenu ? 'w100vh-210' : 'w100'" v-show="isIframePage" :refreshKey="state.iframeRefreshKey" :name="setTransitionName" :list="state.iframeList" />
  16. </transition>
  17. </div>
  18. </template>
  19. <script setup lang="ts" name="layoutParentView">
  20. import { useKeepALiveNames } from '/@/stores/keepAliveNames';
  21. import { useThemeConfig } from '/@/stores/themeConfig';
  22. import { Session } from '/@/utils/storage';
  23. import mittBus from '/@/utils/mitt';
  24. import { useRoutesList } from '/@/stores/routesList';
  25. import other from '/@/utils/other';
  26. const routeStores = useRoutesList();
  27. console.log(routeStores.routesList, 'routeStores.routesList');
  28. // 引入组件
  29. const Iframes = defineAsyncComponent(() => import('/@/layout/routerView/iframes.vue'));
  30. const Vertical = defineAsyncComponent(() => import('/@/layout/navMenu/vertical.vue'));
  31. // 定义变量内容
  32. const route = useRoute();
  33. const router = useRouter();
  34. const storesKeepAliveNames = useKeepALiveNames();
  35. const storesThemeConfig = useThemeConfig();
  36. const { keepAliveNames, cachedViews } = storeToRefs(storesKeepAliveNames);
  37. const { themeConfig } = storeToRefs(storesThemeConfig);
  38. const state = reactive<ParentViewState>({
  39. refreshRouterViewKey: '', // 非 iframe tagsview 右键菜单刷新时
  40. iframeRefreshKey: '', // iframe tagsview 右键菜单刷新时
  41. keepAliveNameList: [],
  42. iframeList: [],
  43. });
  44. const menuLeftList = computed(() => {
  45. const parentName = route.path.split('/')[1];
  46. const parentRoute = routeStores.routesList.filter((item: RouteItem) => {
  47. if(route.path.includes("/admin/log")) {
  48. return item.path.includes("/system")
  49. }
  50. return item.path.includes(parentName)
  51. });
  52. return parentRoute[0].children || [];
  53. });
  54. console.log(menuLeftList.value, '移动');
  55. const isShowLeftMenu = computed(() => {
  56. return !other.isMobile() && menuLeftList.value.length > 0;
  57. });
  58. // 设置主界面切换动画
  59. const setTransitionName = computed(() => {
  60. return themeConfig.value.animation;
  61. });
  62. // 设置 iframe 显示/隐藏
  63. const isIframePage = computed(() => {
  64. return route.meta.isIframe;
  65. });
  66. // 获取 iframe 组件列表(未进行渲染)
  67. const getIframeListRoutes = async () => {
  68. router.getRoutes().forEach((v) => {
  69. if (v.meta.isIframe) {
  70. v.meta.isIframeOpen = false;
  71. v.meta.loading = true;
  72. state.iframeList.push({ ...v });
  73. }
  74. });
  75. };
  76. // 页面加载前,处理缓存,页面刷新时路由缓存处理
  77. onBeforeMount(() => {
  78. state.keepAliveNameList = keepAliveNames.value;
  79. mittBus.on('onTagsViewRefreshRouterView', (fullPath: string) => {
  80. state.keepAliveNameList = keepAliveNames.value.filter((name: string) => route.name !== name);
  81. state.refreshRouterViewKey = '';
  82. state.iframeRefreshKey = '';
  83. nextTick(() => {
  84. state.refreshRouterViewKey = fullPath;
  85. state.iframeRefreshKey = fullPath;
  86. state.keepAliveNameList = keepAliveNames.value;
  87. });
  88. });
  89. });
  90. // 页面加载时
  91. onMounted(() => {
  92. getIframeListRoutes();
  93. nextTick(() => {
  94. setTimeout(() => {
  95. if (themeConfig.value.isCacheTagsView) {
  96. let tagsViewArr: RouteItem[] = Session.get('tagsViewList') || [];
  97. cachedViews.value = tagsViewArr.filter((item) => item.meta?.isKeepAlive).map((item) => item.name as string);
  98. }
  99. }, 0);
  100. });
  101. });
  102. // 页面卸载时
  103. onUnmounted(() => {
  104. mittBus.off('onTagsViewRefreshRouterView', () => {});
  105. });
  106. // 监听路由变化,防止 tagsView 多标签时,切换动画消失
  107. // https://toscode.gitee.com/lyt-top/vue-next-admin/pulls/38/files
  108. watch(
  109. () => route.fullPath,
  110. () => {
  111. state.refreshRouterViewKey = decodeURI(route.fullPath);
  112. },
  113. {
  114. immediate: true,
  115. }
  116. );
  117. </script>
  118. <style lang="scss" scoped>
  119. .w100vh-210 {
  120. width: calc(100vw - 210px);
  121. left: 210px !important;
  122. overflow-y: scroll;
  123. }
  124. .el-menu--vertical {
  125. width: 210px !important;
  126. height: calc(100vh - 95px) !important;
  127. border: 1px solid #DDE4ED !important;
  128. // margin-top: -30px;
  129. margin: 5px 0;
  130. position: fixed;
  131. background-color: #fff;
  132. :deep(.el-menu-item), :deep(.el-sub-menu__title) {
  133. color: #646464 !important;
  134. }
  135. }
  136. </style>