iframe-router-view.vue 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. <script lang="ts" setup>
  2. import type { RouteLocationNormalized } from 'vue-router';
  3. import { computed, ref } from 'vue';
  4. import { useRoute } from 'vue-router';
  5. import { preferences } from '@vben/preferences';
  6. import { useTabbarStore } from '@vben/stores';
  7. import { VbenSpinner } from '@vben-core/shadcn-ui';
  8. defineOptions({ name: 'IFrameRouterView' });
  9. const spinningList = ref<boolean[]>([]);
  10. const tabbarStore = useTabbarStore();
  11. const route = useRoute();
  12. const enableTabbar = computed(() => preferences.tabbar.enable);
  13. const iframeRoutes = computed(() => {
  14. if (!enableTabbar.value) {
  15. return route.meta.iframeSrc ? [route] : [];
  16. }
  17. return tabbarStore.getTabs.filter((tab) => !!tab.meta?.iframeSrc);
  18. });
  19. const tabNames = computed(
  20. () => new Set(iframeRoutes.value.map((item) => item.name as string)),
  21. );
  22. const showIframe = computed(() => iframeRoutes.value.length > 0);
  23. function routeShow(tabItem: RouteLocationNormalized) {
  24. return tabItem.name === route.name;
  25. }
  26. function canRender(tabItem: RouteLocationNormalized) {
  27. const { meta, name } = tabItem;
  28. if (!name || !tabbarStore.renderRouteView) {
  29. return false;
  30. }
  31. if (!enableTabbar.value) {
  32. return routeShow(tabItem);
  33. }
  34. // 跟随 keepAlive 状态,与其他tab页保持一致
  35. if (
  36. !meta?.keepAlive &&
  37. tabNames.value.has(name as string) &&
  38. name !== route.name
  39. ) {
  40. return false;
  41. }
  42. return tabbarStore.getTabs.some((tab) => tab.name === name);
  43. }
  44. function hideLoading(index: number) {
  45. spinningList.value[index] = false;
  46. }
  47. function showSpinning(index: number) {
  48. const curSpinning = spinningList.value[index];
  49. // 首次加载时显示loading
  50. return curSpinning === undefined ? true : curSpinning;
  51. }
  52. </script>
  53. <template>
  54. <template v-if="showIframe">
  55. <template v-for="(item, index) in iframeRoutes" :key="item.fullPath">
  56. <div
  57. v-if="canRender(item)"
  58. v-show="routeShow(item)"
  59. class="relative size-full"
  60. >
  61. <VbenSpinner :spinning="showSpinning(index)" />
  62. <iframe
  63. :src="item.meta.iframeSrc as string"
  64. class="size-full"
  65. @load="hideLoading(index)"
  66. ></iframe>
  67. </div>
  68. </template>
  69. </template>
  70. </template>