Files
qnc-webview-v3/src/views/Report.vue
2026-02-02 15:02:01 +08:00

201 lines
6.1 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>
<BaseReport v-if="queryState === 'success'" :order-id="orderId" :order-no="orderNo" :feature="feature"
:reportData="reportData" :reportParams="reportParams" :reportName="reportName" :reportDateTime="reportDateTime"
:isEmpty="isEmpty" :isDone="isDone" :isExample="false" />
<div v-else-if="queryState === 'pending'" class="loading-container">
<div class="loading-spinner"></div>
<p>报告生成中请稍候...</p>
</div>
<div class="p-4" v-else-if="queryState === 'failed'">
<LEmpty />
</div>
</template>
<script setup>
import LEmpty from "@/components/LEmpty.vue";
import { aesDecrypt } from "@/utils/crypto";
const AES_KEY = import.meta.env.VITE_INQUIRE_AES_KEY;
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 orderId = ref(null);
const orderNo = ref("");
const queryState = ref("");
const pollingInterval = ref(null);
onBeforeMount(() => {
const query = new URLSearchParams(window.location.search);
orderNo.value = query.get("out_trade_no");
orderId.value = query.get("order_id");
if (!orderNo.value && !orderId.value) {
orderId.value = route.query.orderId;
orderNo.value = route.query.orderNo;
}
if (!orderId.value && !orderNo.value) return;
getReport();
});
onBeforeUnmount(() => {
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
}
});
const getReport = async () => {
let queryUrl = "";
if (orderNo.value) {
queryUrl = `/query/orderNo/${orderNo.value}`;
} else if (orderId.value) {
queryUrl = `/query/orderId/${orderId.value}`;
} else {
return;
}
const { data, error } = await useApiFetch(queryUrl).get().json();
if (!AES_KEY) {
console.error("缺少解密密钥");
isEmpty.value = true;
isDone.value = true;
return;
}
if (data.value && !error.value) {
if (data.value.code === 200) {
let decryptedData = data.value.data;
if (typeof decryptedData === "string") {
try {
const decryptedStr = aesDecrypt(decryptedData, AES_KEY);
decryptedData = JSON.parse(decryptedStr);
} catch (err) {
console.error("报告数据解密失败", err);
isEmpty.value = true;
isDone.value = true;
return;
}
}
if (!decryptedData) {
isEmpty.value = true;
isDone.value = true;
return;
}
queryState.value = decryptedData.query_state;
if (queryState.value === "success") {
feature.value = decryptedData.product || "";
const sortedQueryData = Array.isArray(decryptedData.query_data)
? [...decryptedData.query_data].sort((a, b) => {
return a.feature.sort - b.feature.sort;
})
: [];
reportData.value = sortedQueryData;
reportParams.value = decryptedData.query_params || {};
reportName.value = decryptedData.product_name || "";
reportDateTime.value = decryptedData.create_time || null;
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();
}, 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 || data.value.code === 100005) {
// 200002报告生成中100005兼容旧后端“报告未就绪”时的 DB_ERROR按生成中轮询
queryState.value = "pending";
if (!pollingInterval.value) {
pollingInterval.value = setInterval(() => {
getReport();
}, 2000);
}
}
} else if (data.value?.code === 200002) {
// 接口返回 200002 时可能走不到上面分支,单独处理
queryState.value = "pending";
if (!pollingInterval.value) {
pollingInterval.value = setInterval(() => {
getReport();
}, 2000);
}
} else if (data.value?.code === 100005) {
// 兼容:报告未就绪时后端返回 100005按“生成中”轮询
queryState.value = "pending";
if (!pollingInterval.value) {
pollingInterval.value = setInterval(() => {
getReport();
}, 2000);
}
}
};
</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;
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>