Files
tyass-webview/src/views/ReportShare.vue
2026-02-27 12:24:34 +08:00

219 lines
6.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="min-h-screen bg-gray-50">
<van-nav-bar title="天远助手" left-arrow @click-left="goHome" fixed placeholder safe-area-inset-topxc z>
<template #right>
<van-button type="primary" size="small" class="!bg-blue-500 !border-blue-500" @click="goHome">
首页
</van-button>
</template>
</van-nav-bar>
<BaseReport v-if="queryState === 'success' && !isExpired" :isShare="true" :feature="feature"
:reportData="reportData" :reportParams="reportParams" :reportName="reportName"
:reportDateTime="reportDateTime" :isEmpty="isEmpty" :isDone="isDone" />
<div v-else-if="queryState === 'pending'" class="loading-container">
<div class="loading-spinner"></div>
<p>报告生成中请稍候...</p>
</div>
<div v-else-if="isExpired" class="expired-container">
<div class="expired-content">
<van-icon name="clock-o" size="48" color="#999" />
<h2 class="text-xl font-bold text-gray-700 mt-4">
分享链接已过期
</h2>
<p class="text-gray-500 mt-2">
该分享链接已超过7天有效期请重新获取分享链接
</p>
</div>
</div>
<div class="p-4" v-else-if="queryState === 'failed'">
<LEmpty />
</div>
</div>
</template>
<script setup>
import LEmpty from "@/components/LEmpty.vue";
import { useRouter } from "vue-router";
const router = useRouter();
const route = useRoute();
const feature = ref("");
const reportData = ref([]);
const reportParams = ref({});
const reportName = ref("");
const reportDateTime = ref(null);
const isEmpty = ref(false);
const isDone = ref(false);
const isExpired = ref(false);
const queryState = ref("");
const pollingInterval = ref(null);
onBeforeMount(() => {
// 从动态路由参数中获取 linkIdentifier
const linkIdentifier = route.params.linkIdentifier;
if (!linkIdentifier) {
isEmpty.value = true;
isDone.value = true;
return;
}
// 解码 linkIdentifier
try {
const decodedLink = decodeURIComponent(linkIdentifier);
getReport(decodedLink);
} catch (err) {
console.error("分享链接无效");
isEmpty.value = true;
isDone.value = true;
}
});
onBeforeUnmount(() => {
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
}
});
const getReport = async (linkId) => {
if (!linkId) return;
const { data, error } = await useApiFetch(`/query/share/${linkId}`)
.get()
.json();
if (data.value && !error.value) {
if (data.value.code === 200) {
// 检查分享链接状态
if (data.value.data.status === "expired") {
isExpired.value = true;
isDone.value = true;
// 如果过期,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
return;
}
queryState.value = data.value.data.query_state;
if (queryState.value === "success") {
reportData.value = data.value.data.query_data.sort((a, b) => {
return a.feature.sort - b.feature.sort;
});
feature.value = data.value.data.product;
reportParams.value = data.value.data.query_params;
reportName.value = data.value.data.product_name;
reportDateTime.value = data.value.data.create_time;
isDone.value = true;
// 如果成功,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
} else if (queryState.value === "pending") {
// 如果是pending状态且没有轮询启动轮询
if (!pollingInterval.value) {
pollingInterval.value = setInterval(() => {
getReport(linkId);
}, 2000); // 每2秒轮询一次
}
} else if (queryState.value === "failed") {
isEmpty.value = true;
isDone.value = true;
// 如果失败,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
}
} else if (data.value.code === 200003) {
isEmpty.value = true;
isDone.value = true;
} else if (data.value.code === 200002) {
isPending.value = true;
isDone.value = true;
}
}
};
const goHome = () => {
router.push("/");
};
</script>
<style lang="scss" scoped>
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
.loading-spinner {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
p {
color: #666;
font-size: 16px;
}
}
.expired-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background-color: #f8f9fa;
padding: 20px;
.expired-content {
text-align: center;
padding: 40px;
background: white;
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
max-width: 400px;
width: 100%;
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.van-nav-bar) {
.van-nav-bar__title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.van-nav-bar__left {
.van-icon {
color: #333;
}
}
}
:deep(.van-button) {
height: 32px;
padding: 0 16px;
font-size: 14px;
}
</style>