parent.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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) => item.path.includes(parentName));
  47. return parentRoute[0].children || [];
  48. });
  49. console.log(menuLeftList.value, '移动');
  50. const isShowLeftMenu = computed(() => {
  51. return !other.isMobile() && menuLeftList.value.length > 0;
  52. });
  53. // 设置主界面切换动画
  54. const setTransitionName = computed(() => {
  55. return themeConfig.value.animation;
  56. });
  57. // 设置 iframe 显示/隐藏
  58. const isIframePage = computed(() => {
  59. return route.meta.isIframe;
  60. });
  61. // 获取 iframe 组件列表(未进行渲染)
  62. const getIframeListRoutes = async () => {
  63. router.getRoutes().forEach((v) => {
  64. if (v.meta.isIframe) {
  65. v.meta.isIframeOpen = false;
  66. v.meta.loading = true;
  67. state.iframeList.push({ ...v });
  68. }
  69. });
  70. };
  71. // 页面加载前,处理缓存,页面刷新时路由缓存处理
  72. onBeforeMount(() => {
  73. state.keepAliveNameList = keepAliveNames.value;
  74. mittBus.on('onTagsViewRefreshRouterView', (fullPath: string) => {
  75. state.keepAliveNameList = keepAliveNames.value.filter((name: string) => route.name !== name);
  76. state.refreshRouterViewKey = '';
  77. state.iframeRefreshKey = '';
  78. nextTick(() => {
  79. state.refreshRouterViewKey = fullPath;
  80. state.iframeRefreshKey = fullPath;
  81. state.keepAliveNameList = keepAliveNames.value;
  82. });
  83. });
  84. });
  85. // 页面加载时
  86. onMounted(() => {
  87. getIframeListRoutes();
  88. nextTick(() => {
  89. setTimeout(() => {
  90. if (themeConfig.value.isCacheTagsView) {
  91. let tagsViewArr: RouteItem[] = Session.get('tagsViewList') || [];
  92. cachedViews.value = tagsViewArr.filter((item) => item.meta?.isKeepAlive).map((item) => item.name as string);
  93. }
  94. }, 0);
  95. });
  96. });
  97. // 页面卸载时
  98. onUnmounted(() => {
  99. mittBus.off('onTagsViewRefreshRouterView', () => {});
  100. });
  101. // 监听路由变化,防止 tagsView 多标签时,切换动画消失
  102. // https://toscode.gitee.com/lyt-top/vue-next-admin/pulls/38/files
  103. watch(
  104. () => route.fullPath,
  105. () => {
  106. state.refreshRouterViewKey = decodeURI(route.fullPath);
  107. },
  108. {
  109. immediate: true,
  110. }
  111. );
  112. </script>
  113. <style lang="scss" scoped>
  114. .w100vh-210 {
  115. width: calc(100vw - 210px);
  116. left: 210px !important;
  117. overflow-y: scroll;
  118. }
  119. .el-menu--vertical {
  120. width: 210px !important;
  121. height: calc(100vh - 95px) !important;
  122. border: 1px solid #DDE4ED !important;
  123. // margin-top: -30px;
  124. margin: 5px 0;
  125. position: fixed;
  126. background-color: #fff;
  127. :deep(.el-menu-item), :deep(.el-sub-menu__title) {
  128. color: #646464 !important;
  129. }
  130. }
  131. </style>