fix: iframe spinner

This commit is contained in:
vben
2024-06-08 22:46:22 +08:00
parent dcc1fcd528
commit fcf4b9ae5b
5 changed files with 47 additions and 22 deletions

View File

@@ -19,6 +19,7 @@ export * from './pin-input';
export * from './popover';
export * from './segmented';
export * from './sheet';
export * from './spinner';
export * from './tooltip';
export * from './ui/alert-dialog';
export * from './ui/avatar';

View File

@@ -1,6 +1,4 @@
<script lang="ts" setup>
import type { TimeoutHandle } from '@vben/types';
import { ref, watch } from 'vue';
interface Props {
@@ -20,11 +18,12 @@ defineOptions({
});
const props = withDefaults(defineProps<Props>(), {
minLoadingTime: 200,
minLoadingTime: 50,
});
const startTime = ref(0);
const showSpinner = ref(false);
const timer = ref<TimeoutHandle>();
const renderSpinner = ref(true);
const timer = ref<ReturnType<typeof setTimeout>>();
watch(
() => props.spinning,
@@ -39,18 +38,29 @@ watch(
const loadingTime = performance.now() - startTime.value;
showSpinner.value = loadingTime > props.minLoadingTime;
if (showSpinner.value) {
renderSpinner.value = true;
}
}, props.minLoadingTime);
},
{
immediate: true,
},
);
function onTransitionEnd() {
renderSpinner.value = false;
}
</script>
<template>
<div
v-if="showSpinner"
class="flex-center bg-overlay absolute left-0 top-0 size-full backdrop-blur-sm"
v-if="renderSpinner"
:class="{
'invisible opacity-0': !showSpinner,
}"
class="flex-center bg-overlay absolute left-0 top-0 size-full backdrop-blur-sm transition-all duration-500"
@transitionend="onTransitionEnd"
>
<div
class="loader before:bg-primary/50 after:bg-primary relative h-12 w-12 before:absolute before:left-0 before:top-[60px] before:h-[5px] before:w-12 before:animate-[loader-shadow-ani_0.5s_linear_infinite] before:rounded-[50%] before:content-[''] after:absolute after:left-0 after:top-0 after:h-full after:w-full after:animate-[loader-jump-ani_0.5s_linear_infinite] after:rounded after:content-['']"

View File

@@ -1,14 +1,16 @@
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { type RouteLocationNormalized, useRoute } from 'vue-router';
import type { RouteLocationNormalized } from 'vue-router';
import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { Spinner } from '@vben/common-ui';
import { preferences } from '@vben-core/preferences';
import { Spinner } from '@vben-core/shadcn-ui';
import { useTabsStore } from '@vben-core/stores';
defineOptions({ name: 'IFrameRouterView' });
const spinning = ref(true);
const spinningList = ref<boolean[]>([]);
const tabsStore = useTabsStore();
const route = useRoute();
@@ -53,23 +55,30 @@ function canRender(tabItem: RouteLocationNormalized) {
return tabsStore.getTabs.some((tab) => tab.name === name);
}
function hideLoading() {
spinning.value = false;
function hideLoading(index: number) {
spinningList.value[index] = false;
}
function showSpinning(index: number) {
const curSpinning = spinningList.value[index];
// 首次加载时显示loading
return curSpinning === undefined ? true : curSpinning;
}
</script>
<template>
<template v-if="showIframe">
<template v-for="item in iframeRoutes" :key="item.fullPath">
{{ iframeRoutes.length }}
<template v-for="(item, index) in iframeRoutes" :key="item.fullPath">
<div
v-show="routeShow(item)"
v-if="canRender(item)"
class="relative size-full"
>
<Spinner :spinning="spinning" />
<Spinner :spinning="showSpinning(index)" />
<iframe
:src="item.meta.iframeSrc as string"
class="size-full"
@load="hideLoading"
@load="hideLoading(index)"
></iframe>
</div>
</template>