| | |
| | | </div> |
| | | </div> |
| | | |
| | | <RouterView v-if="isRefresh" v-slot="{ Component, route }" :style="contentStyle"> |
| | | <div v-if="routeRenderError" class="art-page-view art-route-state"> |
| | | <div class="art-route-state__panel"> |
| | | <div class="art-route-state__title">页面加载失败</div> |
| | | <div class="art-route-state__desc">{{ routeRenderError }}</div> |
| | | <ElButton type="primary" @click="reloadCurrentRoute">重新加载</ElButton> |
| | | </div> |
| | | </div> |
| | | |
| | | <RouterView v-else-if="isRefresh" v-slot="{ Component, route }" :style="contentStyle"> |
| | | <!-- 缓存路由动画 --> |
| | | <Transition :name="showTransitionMask ? '' : actualTransition" mode="out-in" appear> |
| | | <KeepAlive :max="10" :exclude="keepAliveExclude"> |
| | |
| | | const isOpenRouteInfo = import.meta.env.VITE_OPEN_ROUTE_INFO |
| | | const showTransitionMask = ref(false) |
| | | const isFirstLoad = ref(true) |
| | | const routeRenderError = ref('') |
| | | const isFullPage = computed(() => route.matched.some((r) => r.meta?.isFullPage)) |
| | | const prevIsFullPage = ref(isFullPage.value) |
| | | const actualTransition = computed(() => { |
| | |
| | | isRefresh.value = true |
| | | }) |
| | | } |
| | | const reloadCurrentRoute = () => { |
| | | routeRenderError.value = '' |
| | | reload() |
| | | } |
| | | watch(refresh, reload, { flush: 'post' }) |
| | | watch( |
| | | () => route.fullPath, |
| | | () => { |
| | | routeRenderError.value = '' |
| | | } |
| | | ) |
| | | onErrorCaptured((error) => { |
| | | routeRenderError.value = error instanceof Error ? error.message : String(error || '页面渲染异常') |
| | | return false |
| | | }) |
| | | onMounted(() => { |
| | | nextTick(() => { |
| | | isFirstLoad.value = false |
| | | }) |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .art-route-state { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-height: 320px; |
| | | } |
| | | |
| | | .art-route-state__panel { |
| | | width: min(560px, 100%); |
| | | padding: 28px 32px; |
| | | background: var(--default-box-color); |
| | | border: 1px solid var(--art-card-border); |
| | | border-radius: calc(var(--custom-radius) + 6px); |
| | | box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04); |
| | | } |
| | | |
| | | .art-route-state__title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: var(--art-text-primary); |
| | | } |
| | | |
| | | .art-route-state__desc { |
| | | margin-top: 8px; |
| | | margin-bottom: 16px; |
| | | color: var(--art-text-secondary); |
| | | line-height: 1.7; |
| | | word-break: break-word; |
| | | } |
| | | |
| | | </style> |