Compare commits
3 Commits
e021548adf
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 69a81a927a | |||
| 4bbdde51f6 | |||
| 97fd7d3a04 |
@@ -278,3 +278,66 @@ export function getInviteLink(params) {
|
||||
const queryString = buildQueryString(params || {});
|
||||
return useApiFetch(`/agent/invite_link${queryString}`).get().json();
|
||||
}
|
||||
|
||||
// ==================== 白名单相关接口 ====================
|
||||
|
||||
/**
|
||||
* 获取可屏蔽的 feature 列表(带价格)
|
||||
*/
|
||||
export function getWhitelistFeatures() {
|
||||
return useApiFetch("/agent/whitelist/features").get().json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建白名单订单
|
||||
* @param {object} params - 创建参数
|
||||
* @param {string} params.id_card - 身份证号
|
||||
* @param {string[]} params.feature_ids - 要屏蔽的 feature ID 列表
|
||||
*/
|
||||
export function createWhitelistOrder(params) {
|
||||
return useApiFetch("/agent/whitelist/order/create").post(params).json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询白名单列表
|
||||
* @param {object} params - 查询参数
|
||||
* @param {number} params.page - 页码
|
||||
* @param {number} params.page_size - 每页数量
|
||||
* @param {string} params.id_card - 身份证号(可选)
|
||||
*/
|
||||
export function getWhitelistList(params) {
|
||||
const queryString = buildQueryString(params || {});
|
||||
return useApiFetch(`/agent/whitelist/list${queryString}`).get().json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查模块是否已下架
|
||||
* @param {object} params - 查询参数
|
||||
* @param {string} params.id_card - 身份证号
|
||||
* @param {string} params.feature_api_id - Feature 的 API 标识
|
||||
* @param {string} params.query_id - 查询记录 ID(可选)
|
||||
*/
|
||||
export function checkFeatureWhitelistStatus(params) {
|
||||
const queryString = buildQueryString(params || {});
|
||||
return useApiFetch(`/agent/whitelist/check${queryString}`).get().json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下架单个模块(免费或需支付)
|
||||
* @param {object} params - 下架参数
|
||||
* @param {string} params.feature_api_id - Feature 的 API 标识
|
||||
* @param {string} params.query_id - 查询记录 ID(必填)
|
||||
*/
|
||||
export function offlineFeature(params) {
|
||||
return useApiFetch("/agent/whitelist/offline").post(params).json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查订单是否属于当前代理推广
|
||||
* @param {object} params - 查询参数
|
||||
* @param {string} params.order_id - 订单 ID
|
||||
*/
|
||||
export function checkOrderAgent(params) {
|
||||
const queryString = buildQueryString(params || {});
|
||||
return useApiFetch(`/agent/order/agent${queryString}`).get().json();
|
||||
}
|
||||
|
||||
@@ -3,12 +3,17 @@ import ShareReportButton from "./ShareReportButton.vue";
|
||||
import TitleBanner from "./TitleBanner.vue";
|
||||
import VerificationCard from "./VerificationCard.vue";
|
||||
import StyledTabs from "./StyledTabs.vue";
|
||||
import Payment from "./Payment.vue";
|
||||
import { splitDWBG8B4DForTabs } from '@/ui/CDWBG8B4D/utils/simpleSplitter.js';
|
||||
import { splitDWBG6A2CForTabs } from '@/ui/DWBG6A2C/utils/simpleSplitter.js';
|
||||
import { splitJRZQ7F1AForTabs } from '@/ui/JRZQ7F1A/utils/simpleSplitter.js';
|
||||
import { splitCJRZQ5E9FForTabs } from '@/ui/CJRZQ5E9F/utils/simpleSplitter.js';
|
||||
import { splitCQYGL3F8EForTabs } from '@/ui/CQYGL3F8E/utils/simpleSplitter.js';
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import { useAgentStore } from "@/stores/agentStore";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { showFailToast } from "vant";
|
||||
import { checkFeatureWhitelistStatus, offlineFeature, checkOrderAgent } from "@/api/agent";
|
||||
|
||||
// 动态导入产品背景图片的函数
|
||||
const loadProductBackground = async (productType) => {
|
||||
@@ -53,6 +58,11 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
queryId: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
feature: {
|
||||
type: String,
|
||||
required: true,
|
||||
@@ -98,8 +108,20 @@ const {
|
||||
isEmpty,
|
||||
isDone,
|
||||
isExample,
|
||||
orderId,
|
||||
orderNo,
|
||||
queryId,
|
||||
} = toRefs(props);
|
||||
|
||||
const agentStore = useAgentStore();
|
||||
const { isDiamond } = storeToRefs(agentStore);
|
||||
|
||||
// 订单是否属于当前代理推广
|
||||
const isAgentOrder = ref(false);
|
||||
|
||||
// 获取身份证号(从 reportParams 中)
|
||||
const idCard = computed(() => reportParams.value?.id_card || "");
|
||||
|
||||
const active = ref(null);
|
||||
const backgroundContainerRef = ref(null); // 背景容器的引用
|
||||
|
||||
@@ -153,6 +175,21 @@ onMounted(async () => {
|
||||
|
||||
// 监听窗口大小变化,重新计算高度
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// 检查订单是否属于当前代理推广
|
||||
if (!isExample.value && orderId.value) {
|
||||
try {
|
||||
const { data, error } = await checkOrderAgent({ order_id: orderId.value });
|
||||
if (data.value && !error.value && data.value.code === 200) {
|
||||
isAgentOrder.value = data.value.data.is_agent_order;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("检查订单代理状态失败:", err);
|
||||
}
|
||||
}
|
||||
if (isAgentOrder.value && idCard.value && !isExample.value) {
|
||||
checkAllFeaturesStatus();
|
||||
}
|
||||
});
|
||||
|
||||
// 处理窗口大小变化(带防抖)
|
||||
@@ -242,6 +279,200 @@ const trapezoidBgStyle = computed(() => {
|
||||
return {};
|
||||
});
|
||||
|
||||
// 模块下架状态映射:主模块ID -> { isOfflined, whitelistPrice, isSubmitting }
|
||||
const featureOfflineStatus = ref(new Map());
|
||||
|
||||
const getMainApiId = (apiId) => {
|
||||
if (!apiId) return "";
|
||||
const index = apiId.indexOf("_");
|
||||
return index > 0 ? apiId.substring(0, index) : apiId;
|
||||
};
|
||||
|
||||
const checkFeatureStatus = async (featureApiId, forceRefresh = false) => {
|
||||
if (!idCard.value || !featureApiId) return;
|
||||
const mainApiId = getMainApiId(featureApiId);
|
||||
if (!mainApiId) return;
|
||||
if (!forceRefresh && featureOfflineStatus.value.has(mainApiId)) return;
|
||||
try {
|
||||
const { data, error } = await checkFeatureWhitelistStatus({
|
||||
id_card: idCard.value,
|
||||
feature_api_id: mainApiId,
|
||||
query_id: queryId.value || "",
|
||||
});
|
||||
if (data.value && !error.value && data.value.code === 200) {
|
||||
const isWhitelisted = data.value.data.is_whitelisted || false;
|
||||
const dataDeleted = data.value.data.data_deleted !== undefined ? data.value.data.data_deleted : true;
|
||||
featureOfflineStatus.value.set(mainApiId, {
|
||||
isOfflined: isWhitelisted && dataDeleted,
|
||||
whitelistPrice: data.value.data.whitelist_price || 0,
|
||||
isSubmitting: false,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("检查模块状态失败:", err);
|
||||
}
|
||||
};
|
||||
|
||||
const checkAllFeaturesStatus = async () => {
|
||||
if (!idCard.value || !isAgentOrder.value || isExample.value) return;
|
||||
const featureApiIds = processedReportData.value.map((item) => item.data.apiID);
|
||||
const mainApiIds = [...new Set(featureApiIds.map((id) => getMainApiId(id)))];
|
||||
for (const mainApiId of mainApiIds) {
|
||||
if (mainApiId) await checkFeatureStatus(mainApiId);
|
||||
}
|
||||
};
|
||||
|
||||
const getFeatureStatus = (featureApiId) => {
|
||||
const mainApiId = getMainApiId(featureApiId);
|
||||
return featureOfflineStatus.value.get(mainApiId) || {
|
||||
isOfflined: false,
|
||||
whitelistPrice: 0,
|
||||
isSubmitting: false,
|
||||
};
|
||||
};
|
||||
|
||||
const currentOfflineFeature = ref(null);
|
||||
const showOfflineConfirmDialog = ref(false);
|
||||
|
||||
const handleOfflineClick = async (featureApiId, featureName) => {
|
||||
const mainApiId = getMainApiId(featureApiId);
|
||||
const status = getFeatureStatus(mainApiId);
|
||||
if (status.isOfflined) {
|
||||
showFailToast("该模块已下架");
|
||||
return;
|
||||
}
|
||||
if (status.whitelistPrice <= 0) {
|
||||
await confirmOfflineDirectly(mainApiId, featureName);
|
||||
return;
|
||||
}
|
||||
currentOfflineFeature.value = {
|
||||
featureApiId: mainApiId,
|
||||
featureName,
|
||||
whitelistPrice: status.whitelistPrice,
|
||||
};
|
||||
showOfflineConfirmDialog.value = true;
|
||||
};
|
||||
|
||||
const showWhitelistPayment = ref(false);
|
||||
const whitelistPaymentData = ref({ product_name: "", sell_price: 0 });
|
||||
const whitelistPaymentId = ref("");
|
||||
const whitelistPaymentType = ref("whitelist");
|
||||
|
||||
const getCurrentReportUrl = () => {
|
||||
if (orderNo.value) return `/report?orderNo=${orderNo.value}`;
|
||||
if (orderId.value) return `/report?orderId=${orderId.value}`;
|
||||
return "";
|
||||
};
|
||||
|
||||
const confirmOfflineDirectly = async (mainApiId, featureName) => {
|
||||
if (!idCard.value || !mainApiId) return;
|
||||
const status = getFeatureStatus(mainApiId);
|
||||
status.isSubmitting = true;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...status });
|
||||
try {
|
||||
if (!queryId.value) {
|
||||
showFailToast("缺少查询记录ID,无法下架");
|
||||
const cur = getFeatureStatus(mainApiId);
|
||||
cur.isSubmitting = false;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...cur });
|
||||
return;
|
||||
}
|
||||
const { data, error } = await offlineFeature({
|
||||
query_id: queryId.value,
|
||||
feature_api_id: mainApiId,
|
||||
});
|
||||
if (!data.value || error.value || data.value.code !== 200) {
|
||||
showFailToast(data.value?.msg || "下架失败");
|
||||
const cur = getFeatureStatus(mainApiId);
|
||||
cur.isSubmitting = false;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...cur });
|
||||
return;
|
||||
}
|
||||
const resp = data.value.data || {};
|
||||
if (resp.need_pay) {
|
||||
const cur = getFeatureStatus(mainApiId);
|
||||
cur.isSubmitting = false;
|
||||
cur.whitelistPrice = resp.amount || 0;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...cur });
|
||||
whitelistPaymentData.value = {
|
||||
product_name: `${featureName || "模块"} 下架`,
|
||||
sell_price: resp.amount || 0,
|
||||
};
|
||||
whitelistPaymentId.value = `${idCard.value}|${mainApiId}`;
|
||||
whitelistPaymentType.value = "whitelist";
|
||||
showWhitelistPayment.value = true;
|
||||
return;
|
||||
}
|
||||
showFailToast("下架成功");
|
||||
const updated = getFeatureStatus(mainApiId);
|
||||
updated.isSubmitting = false;
|
||||
updated.isOfflined = true;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...updated });
|
||||
if (queryId.value || orderId.value) window.location.reload();
|
||||
} catch (err) {
|
||||
console.error("下架模块失败:", err);
|
||||
showFailToast("下架模块失败");
|
||||
const cur = getFeatureStatus(mainApiId);
|
||||
cur.isSubmitting = false;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...cur });
|
||||
}
|
||||
};
|
||||
|
||||
const confirmOffline = async () => {
|
||||
if (!currentOfflineFeature.value) return;
|
||||
const { featureApiId } = currentOfflineFeature.value;
|
||||
const mainApiId = featureApiId;
|
||||
if (!queryId.value) {
|
||||
showFailToast("缺少查询记录ID,无法下架");
|
||||
return;
|
||||
}
|
||||
const status = getFeatureStatus(mainApiId);
|
||||
status.isSubmitting = true;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...status });
|
||||
try {
|
||||
const { data, error } = await offlineFeature({
|
||||
query_id: queryId.value,
|
||||
feature_api_id: mainApiId,
|
||||
});
|
||||
if (!data.value || error.value || data.value.code !== 200) {
|
||||
showFailToast(data.value?.msg || "下架失败");
|
||||
const cur = getFeatureStatus(mainApiId);
|
||||
cur.isSubmitting = false;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...cur });
|
||||
return;
|
||||
}
|
||||
const resp = data.value.data || {};
|
||||
if (resp.need_pay) {
|
||||
showOfflineConfirmDialog.value = false;
|
||||
whitelistPaymentData.value = {
|
||||
product_name: `${currentOfflineFeature.value?.featureName || "模块"} 下架`,
|
||||
sell_price: resp.amount || 0,
|
||||
};
|
||||
whitelistPaymentId.value = `${idCard.value}|${mainApiId}`;
|
||||
whitelistPaymentType.value = "whitelist";
|
||||
showWhitelistPayment.value = true;
|
||||
const cur = getFeatureStatus(mainApiId);
|
||||
cur.isSubmitting = false;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...cur });
|
||||
return;
|
||||
}
|
||||
showFailToast("下架成功");
|
||||
showOfflineConfirmDialog.value = false;
|
||||
currentOfflineFeature.value = null;
|
||||
const updated = getFeatureStatus(mainApiId);
|
||||
updated.isSubmitting = false;
|
||||
updated.isOfflined = true;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...updated });
|
||||
if (queryId.value || orderId.value) window.location.reload();
|
||||
} catch (err) {
|
||||
console.error("下架模块失败:", err);
|
||||
showFailToast("下架模块失败");
|
||||
const cur = getFeatureStatus(mainApiId);
|
||||
cur.isSubmitting = false;
|
||||
featureOfflineStatus.value.set(mainApiId, { ...cur });
|
||||
}
|
||||
};
|
||||
|
||||
const featureMap = {
|
||||
IVYZ5733: {
|
||||
name: "婚姻状态",
|
||||
@@ -353,6 +584,11 @@ const featureMap = {
|
||||
component: defineAsyncComponent(() => import("@/ui/IVYZ3P9M.vue")),
|
||||
remark: '学历信息展示学生姓名、身份证号、学校、专业、入学与毕业时间、学历层次以及学习形式等字段,可结合字典编码了解具体含义。',
|
||||
},
|
||||
IVYZ0S0D: {
|
||||
name: "劳动仲裁信息",
|
||||
component: defineAsyncComponent(() => import("@/ui/IVYZ0S0D.vue")),
|
||||
remark: '劳动仲裁信息展示被查询人在失信限高、劳动争议、社会保险、福利待遇、人事争议、仲裁流程及通知函触达等方面的风险信息。',
|
||||
},
|
||||
IVYZ8I9J: {
|
||||
name: "网络社交异常",
|
||||
component: defineAsyncComponent(() => import("@/ui/IVYZ8I9J.vue")),
|
||||
@@ -383,9 +619,9 @@ const featureMap = {
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/OverdueRiskSection.vue")),
|
||||
},
|
||||
DWBG8B4D_CourtInfo: {
|
||||
name: "法院曝光台信息",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/MultCourtInfoSection.vue")),
|
||||
},
|
||||
name: "法院曝光台信息",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/MultCourtInfoSection.vue")),
|
||||
},
|
||||
DWBG8B4D_LoanEvaluation: {
|
||||
name: "借贷评估",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/LoanEvaluationSection.vue")),
|
||||
@@ -680,13 +916,14 @@ const featureRiskLevels = {
|
||||
'JRZQ09J8': 10, // 收入评估
|
||||
'JRZQ3C9R': 10, // 支付行为指数
|
||||
// 'IVYZ0S0D': 10, // 个人仲裁信息
|
||||
|
||||
|
||||
|
||||
// 🔵 低风险类 - 权重 3-5
|
||||
'IVYZ5733': 4, // 婚姻状态
|
||||
'IVYZ9A2B': 4, // 学历信息
|
||||
'IVYZ3P9M': 4, // 学历信息查询(实时版)
|
||||
|
||||
'IVYZ0S0D': 10, // 劳动仲裁信息
|
||||
|
||||
|
||||
// 📊 复合报告类 - 按子模块动态计算
|
||||
'DWBG8B4D': 0, // 谛听多维报告(由子模块计算)
|
||||
@@ -702,7 +939,7 @@ const featureRiskLevels = {
|
||||
'DWBG8B4D_LeasingRisk': 18,
|
||||
'DWBG8B4D_RiskSupervision': 25,
|
||||
'DWBG8B4D_RiskWarningTab': 30,
|
||||
'DWBG8B4D_CourtInfo':31,
|
||||
'DWBG8B4D_CourtInfo': 31,
|
||||
|
||||
// 司南报告子模块
|
||||
'DWBG6A2C_StandLiveInfo': 10,
|
||||
@@ -717,7 +954,7 @@ const featureRiskLevels = {
|
||||
'DWBG6A2C_CreditDetail': 15,
|
||||
'DWBG6A2C_RentalBehavior': 15,
|
||||
'DWBG6A2C_RiskSupervision': 25,
|
||||
'DWBG6A2C_CourtRiskInfo':29,
|
||||
'DWBG6A2C_CourtRiskInfo': 29,
|
||||
|
||||
// 贷款风险评估子模块
|
||||
'CJRZQ5E9F_RiskOverview': 25,
|
||||
@@ -888,9 +1125,16 @@ const showPublicSecurityRecord = import.meta.env.VITE_SHOW_PUBLIC_SECURITY_RECOR
|
||||
</van-tab>
|
||||
<van-tab v-for="(item, index) in processedReportData" :key="`${item.data.apiID}_${index}`"
|
||||
:title="featureMap[item.data.apiID]?.name">
|
||||
<TitleBanner :id="item.data.apiID" class="mb-4">
|
||||
{{ featureMap[item.data.apiID]?.name }}
|
||||
</TitleBanner>
|
||||
<div class="flex items-center justify-between gap-2 mb-4">
|
||||
<TitleBanner :id="item.data.apiID" class="mb-0 flex-1">
|
||||
{{ featureMap[item.data.apiID]?.name }}
|
||||
</TitleBanner>
|
||||
<van-button v-if="!isShare && !isExample && isAgentOrder && !getFeatureStatus(item.data.apiID).isOfflined"
|
||||
size="small" type="default" :loading="getFeatureStatus(item.data.apiID).isSubmitting"
|
||||
@click="handleOfflineClick(item.data.apiID, featureMap[item.data.apiID]?.name)">
|
||||
下架
|
||||
</van-button>
|
||||
</div>
|
||||
<component :is="featureMap[item.data.apiID]?.component" :ref="el => {
|
||||
if (el) {
|
||||
const refKey = `${item.data.apiID}_${index}`;
|
||||
@@ -943,6 +1187,18 @@ const showPublicSecurityRecord = import.meta.env.VITE_SHOW_PUBLIC_SECURITY_RECOR
|
||||
<div>{{ companyName }}版权所有</div>
|
||||
</div>
|
||||
|
||||
<!-- 下架确认弹窗(付费场景) -->
|
||||
<van-dialog v-model:show="showOfflineConfirmDialog" title="确认下架"
|
||||
show-cancel-button @confirm="confirmOffline">
|
||||
<div class="p-4 text-gray-600">
|
||||
确定要下架「{{ currentOfflineFeature?.featureName || '该模块' }}」吗?需支付 ¥{{ currentOfflineFeature?.whitelistPrice?.toFixed(2) || '0.00' }}。
|
||||
</div>
|
||||
</van-dialog>
|
||||
|
||||
<!-- 白名单下架支付弹窗 -->
|
||||
<Payment v-model="showWhitelistPayment" :data="whitelistPaymentData"
|
||||
:id="whitelistPaymentId" :type="whitelistPaymentType" :return-url="getCurrentReportUrl()" />
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -85,6 +85,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
returnUrl: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
const show = defineModel();
|
||||
|
||||
@@ -132,10 +136,9 @@ async function getPayment() {
|
||||
// 测试支付模式:直接跳转到结果页面
|
||||
if (selectedPaymentMethod.value === "test" || selectedPaymentMethod.value === "test_empty") {
|
||||
orderNo.value = data.value.data.order_no;
|
||||
router.push({
|
||||
path: "/payment/result",
|
||||
query: { orderNo: data.value.data.order_no },
|
||||
});
|
||||
const query = { orderNo: data.value.data.order_no };
|
||||
if (props.returnUrl) query.returnUrl = props.returnUrl;
|
||||
router.push({ path: "/payment/result", query });
|
||||
} else if (selectedPaymentMethod.value === "alipay") {
|
||||
orderNo.value = data.value.data.order_no;
|
||||
// 存储订单ID以便支付宝返回时获取
|
||||
@@ -156,10 +159,9 @@ async function getPayment() {
|
||||
// 支付成功:短延迟再跳转,给后端回调与异步任务留出时间,避免结果页查报告报错
|
||||
showToast({ message: "支付成功,正在跳转...", type: "success" });
|
||||
setTimeout(() => {
|
||||
router.push({
|
||||
path: "/payment/result",
|
||||
query: { orderNo: data.value.data.order_no },
|
||||
});
|
||||
const query = { orderNo: data.value.data.order_no };
|
||||
if (props.returnUrl) query.returnUrl = props.returnUrl;
|
||||
router.push({ path: "/payment/result", query });
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
524
src/ui/IVYZ0S0D.vue
Normal file
524
src/ui/IVYZ0S0D.vue
Normal file
@@ -0,0 +1,524 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useRiskNotifier } from '@/composables/useRiskNotifier';
|
||||
|
||||
const props = defineProps({
|
||||
data: { type: Object, default: () => ({}) },
|
||||
params: { type: Object, default: () => ({}) },
|
||||
apiId: { type: String, default: '' },
|
||||
index: { type: Number, default: 0 },
|
||||
notifyRiskStatus: { type: Function, default: () => { } },
|
||||
});
|
||||
|
||||
const periodTab = ref('threeYears'); // 近三年 | 近五年
|
||||
|
||||
// 支持 data 或 data.result(接口返回的 result 对象)
|
||||
const result = computed(() => props.data?.result ?? props.data ?? {});
|
||||
|
||||
const getStatusText = (value) => {
|
||||
if (value === 1) return '未命中';
|
||||
if (value === 2) return '命中';
|
||||
return '—';
|
||||
};
|
||||
|
||||
// 获取通知函期间描述文本(支持数字或字符串如 "2")
|
||||
const getNoticeLetterPeriodText = (period) => {
|
||||
const p = Number(period);
|
||||
const periodMap = { 0: '没有被发送通知函', 1: '近2年内', 2: '2-4年', 3: '5年以上' };
|
||||
return periodMap[p] ?? '—';
|
||||
};
|
||||
|
||||
// 检查是否至少有一个数据类别有内容
|
||||
const hasAnyData = computed(() => {
|
||||
const r = result.value;
|
||||
return Object.keys(r).length > 0;
|
||||
});
|
||||
|
||||
// 汇总数据 - 按分类分组 { key, title, rows }
|
||||
const summaryGroups = computed(() => {
|
||||
const groups = [];
|
||||
const basic = result.value.basic_info;
|
||||
if (basic?.risk_flag !== undefined) {
|
||||
groups.push({ key: 'basic', title: '基础风险', rows: [{ label: '该人员是否有风险', value: basic.risk_flag }] });
|
||||
}
|
||||
const dishonesty = result.value.dishonesty?.dishonesty;
|
||||
const highConsumption = result.value.high_consumption?.high_consumption;
|
||||
if (dishonesty !== undefined || highConsumption !== undefined) {
|
||||
const rows = [];
|
||||
if (dishonesty !== undefined) rows.push({ label: '失信人员风险', value: dishonesty });
|
||||
if (highConsumption !== undefined) rows.push({ label: '限制高消费人员风险', value: highConsumption });
|
||||
groups.push({ key: 'credit', title: '失信限高', rows });
|
||||
}
|
||||
const labor = result.value.labor_disputes;
|
||||
if (labor) {
|
||||
const items = [['劳动争议', labor.labor_disputes], ['劳动合同纠纷', labor.labor_contract], ['劳动关系纠纷', labor.labor_relation], ['追索劳动报酬纠纷', labor.wage_claim], ['经济补偿金纠纷', labor.compensation], ['集体合同纠纷', labor.collective_contract], ['劳务派遣合同纠纷', labor.dispatch_contract], ['非全日制用工纠纷', labor.part_time], ['竞业限制纠纷', labor.non_compete]];
|
||||
const rows = items.filter((item) => item[1] !== undefined).map((item) => ({ label: item[0], value: item[1] }));
|
||||
if (rows.length) groups.push({ key: 'labor', title: '劳动争议', rows });
|
||||
}
|
||||
const social = result.value.social_insurance;
|
||||
if (social) {
|
||||
const items = [['社会保险纠纷', social.social_insurance], ['养老保险待遇纠纷', social.pension], ['工伤保险待遇纠纷', social.injury_insurance], ['医疗保险待遇纠纷', social.medical_insurance], ['生育保险待遇纠纷', social.maternity_insurance], ['商业保险待遇纠纷', social.commercial_insurance]];
|
||||
const rows = items.filter((item) => item[1] !== undefined).map((item) => ({ label: item[0], value: item[1] }));
|
||||
if (rows.length) groups.push({ key: 'social', title: '社会保险', rows });
|
||||
}
|
||||
if (result.value.welfare_disputes?.welfare !== undefined) {
|
||||
groups.push({ key: 'welfare', title: '福利待遇', rows: [{ label: '福利待遇纠纷', value: result.value.welfare_disputes.welfare }] });
|
||||
}
|
||||
const personnel = result.value.personnel_disputes;
|
||||
if (personnel) {
|
||||
const items = [['人事争议类纠纷', personnel.personnel_dispute], ['辞职争议纠纷', personnel.resignation_dispute], ['辞退争议纠纷', personnel.dismissal_dispute], ['聘用合同争议纠纷', personnel.employment_contract]];
|
||||
const rows = items.filter((item) => item[1] !== undefined).map((item) => ({ label: item[0], value: item[1] }));
|
||||
if (rows.length) groups.push({ key: 'personnel', title: '人事争议', rows });
|
||||
}
|
||||
const arb = result.value.arbitration;
|
||||
if (arb && (arb.arbitration_confirmation !== undefined || arb.arbitration_revocation !== undefined)) {
|
||||
const rows = [];
|
||||
if (arb.arbitration_confirmation !== undefined) rows.push({ label: '申请仲裁确认', value: arb.arbitration_confirmation });
|
||||
if (arb.arbitration_revocation !== undefined) rows.push({ label: '撤销仲裁裁决', value: arb.arbitration_revocation });
|
||||
groups.push({ key: 'arbitration', title: '仲裁流程', rows });
|
||||
}
|
||||
const notice = result.value.notice_letter;
|
||||
if (notice?.notice_letter !== undefined) {
|
||||
const rows = [{ label: '通知函触达', value: notice.notice_letter }];
|
||||
if (notice.notice_letter_period !== undefined && notice.notice_letter === 2) rows.push({ label: '通知函发送时间', value: null, period: notice.notice_letter_period });
|
||||
groups.push({ key: 'notice', title: '通知函触达', rows });
|
||||
}
|
||||
return groups;
|
||||
});
|
||||
|
||||
const summaryRows = computed(() => summaryGroups.value.flatMap((g) => g.rows));
|
||||
|
||||
// 真正的风险项(文档:失信限高、劳动争议、社会保险、福利待遇、人事争议、仲裁流程、通知函触达)
|
||||
// 排除 basic_info.risk_flag(汇总结论)和 notice_letter_period(非风险项)
|
||||
const riskItemRows = computed(() =>
|
||||
summaryGroups.value
|
||||
.filter((g) => g.key !== 'basic')
|
||||
.flatMap((g) => g.rows)
|
||||
.filter((r) => r.value === 1 || r.value === 2)
|
||||
);
|
||||
|
||||
// 近三年/近五年 - 按分类分组
|
||||
const periodGroups = computed(() => {
|
||||
const suffix = periodTab.value === 'threeYears' ? '_3y' : '_5y';
|
||||
const groups = [];
|
||||
const labor = result.value.labor_disputes;
|
||||
if (labor) {
|
||||
const keys = ['labor_disputes', 'labor_relation', 'wage_claim', 'compensation', 'collective_contract', 'dispatch_contract', 'part_time', 'non_compete'];
|
||||
const labels = ['劳动争议', '劳动关系', '追索劳动报酬', '经济补偿金', '集体合同', '劳务派遣', '非全日制用工', '竞业限制'];
|
||||
const rows = keys.map((k, i) => ({ label: labels[i], value: labor[k + suffix] })).filter((r) => r.value === 2).map((r) => ({ label: r.label, value: 2 }));
|
||||
if (rows.length) groups.push({ key: 'labor', title: '劳动争议', rows });
|
||||
}
|
||||
const social = result.value.social_insurance;
|
||||
if (social) {
|
||||
const keys = ['pension', 'injury_insurance', 'medical_insurance', 'maternity_insurance', 'commercial_insurance'];
|
||||
const labels = ['养老保险', '工伤保险', '医疗保险', '生育保险', '商业保险'];
|
||||
const rows = keys.map((k, i) => ({ label: labels[i], value: social[k + suffix] })).filter((r) => r.value === 2).map((r) => ({ label: r.label, value: 2 }));
|
||||
if (rows.length) groups.push({ key: 'social', title: '社会保险', rows });
|
||||
}
|
||||
const personnel = result.value.personnel_disputes;
|
||||
if (personnel) {
|
||||
const keys = ['resignation_dispute', 'dismissal_dispute', 'employment_contract'];
|
||||
const labels = ['辞职争议', '辞退争议', '聘用合同'];
|
||||
const rows = keys.map((k, i) => ({ label: labels[i], value: personnel[k + suffix] })).filter((r) => r.value === 2).map((r) => ({ label: r.label, value: 2 }));
|
||||
if (rows.length) groups.push({ key: 'personnel', title: '人事争议', rows });
|
||||
}
|
||||
const arb = result.value.arbitration;
|
||||
if (arb) {
|
||||
const rows = [];
|
||||
if (arb[`arbitration_confirmation${suffix}`] === 2) rows.push({ label: '申请仲裁确认', value: 2 });
|
||||
if (arb[`arbitration_revocation${suffix}`] === 2) rows.push({ label: '撤销仲裁裁决', value: 2 });
|
||||
if (rows.length) groups.push({ key: 'arbitration', title: '仲裁流程', rows });
|
||||
}
|
||||
return groups;
|
||||
});
|
||||
|
||||
const periodRows = computed(() => periodGroups.value.flatMap((g) => g.rows));
|
||||
|
||||
// 用于 riskScore:需要近三年+近五年全部数据
|
||||
const recentThreeYearsRows = computed(() => {
|
||||
const r = result.value;
|
||||
const rows = [];
|
||||
const labor = r.labor_disputes;
|
||||
if (labor) {
|
||||
[['labor_disputes_3y'], ['labor_relation_3y'], ['wage_claim_3y'], ['compensation_3y'], ['collective_contract_3y'], ['dispatch_contract_3y'], ['part_time_3y'], ['non_compete_3y']].forEach(([k]) => { if (labor[k] === 2) rows.push({ value: 2 }); });
|
||||
}
|
||||
const social = r.social_insurance;
|
||||
if (social) {
|
||||
['pension_3y', 'injury_insurance_3y', 'medical_insurance_3y', 'maternity_insurance_3y', 'commercial_insurance_3y'].forEach((k) => { if (social[k] === 2) rows.push({ value: 2 }); });
|
||||
}
|
||||
const personnel = r.personnel_disputes;
|
||||
if (personnel) {
|
||||
['resignation_dispute_3y', 'dismissal_dispute_3y', 'employment_contract_3y'].forEach((k) => { if (personnel[k] === 2) rows.push({ value: 2 }); });
|
||||
}
|
||||
const arb = r.arbitration;
|
||||
if (arb) {
|
||||
if (arb.arbitration_confirmation_3y === 2) rows.push({ value: 2 });
|
||||
if (arb.arbitration_revocation_3y === 2) rows.push({ value: 2 });
|
||||
}
|
||||
return rows;
|
||||
});
|
||||
const recentFiveYearsRows = computed(() => {
|
||||
const r = result.value;
|
||||
const rows = [];
|
||||
const labor = r.labor_disputes;
|
||||
if (labor) {
|
||||
[['labor_disputes_5y'], ['labor_relation_5y'], ['wage_claim_5y'], ['compensation_5y'], ['collective_contract_5y'], ['dispatch_contract_5y'], ['part_time_5y'], ['non_compete_5y']].forEach(([k]) => { if (labor[k] === 2) rows.push({ value: 2 }); });
|
||||
}
|
||||
const social = r.social_insurance;
|
||||
if (social) {
|
||||
['pension_5y', 'injury_insurance_5y', 'medical_insurance_5y', 'maternity_insurance_5y', 'commercial_insurance_5y'].forEach((k) => { if (social[k] === 2) rows.push({ value: 2 }); });
|
||||
}
|
||||
const personnel = r.personnel_disputes;
|
||||
if (personnel) {
|
||||
['resignation_dispute_5y', 'dismissal_dispute_5y', 'employment_contract_5y'].forEach((k) => { if (personnel[k] === 2) rows.push({ value: 2 }); });
|
||||
}
|
||||
const arb = r.arbitration;
|
||||
if (arb) {
|
||||
if (arb.arbitration_confirmation_5y === 2) rows.push({ value: 2 });
|
||||
if (arb.arbitration_revocation_5y === 2) rows.push({ value: 2 });
|
||||
}
|
||||
return rows;
|
||||
});
|
||||
|
||||
// 头部风险总结:风险类型、建议、命中统计(仅真正的风险项)
|
||||
const riskSummary = computed(() => {
|
||||
const basic = result.value.basic_info;
|
||||
const hasRisk = basic?.risk_flag === 2;
|
||||
|
||||
// 真正的风险项:总项数、命中数(文档:失信限高、劳动争议、社会保险、福利待遇、人事争议、仲裁流程、通知函触达)
|
||||
const totalItems = riskItemRows.value.length;
|
||||
const hitItems = riskItemRows.value.filter((r) => r.value === 2).length;
|
||||
|
||||
// 命中的风险分类(汇总中 value=2 的 group)
|
||||
const riskCategories = summaryGroups.value
|
||||
.filter((g) => g.key !== 'basic' && g.rows.some((r) => r.value === 2))
|
||||
.map((g) => g.title);
|
||||
|
||||
// 精简建议(取主要类型合并为一句)
|
||||
const suggestionMap = {
|
||||
'失信限高': '征信修复与限高事项',
|
||||
'劳动争议': '劳动纠纷与薪酬离职',
|
||||
'社会保险': '社保缴纳与补缴',
|
||||
'福利待遇': '福利待遇合规',
|
||||
'人事争议': '辞职辞退与聘用合同',
|
||||
'仲裁流程': '仲裁案件进展',
|
||||
'通知函触达': '仲裁调解涉诉通知',
|
||||
};
|
||||
const suggestionParts = riskCategories.map((c) => suggestionMap[c]).filter(Boolean);
|
||||
const suggestion = suggestionParts.length ? `建议关注${suggestionParts.slice(0, 3).join('、')}。` : '';
|
||||
|
||||
return {
|
||||
hasRisk,
|
||||
label: hasRisk ? '有风险' : '无风险',
|
||||
riskCategories,
|
||||
suggestion,
|
||||
totalItems,
|
||||
hitItems,
|
||||
};
|
||||
});
|
||||
|
||||
// 风险评分 0-100,越高越安全(供 BaseReport 分析指数)
|
||||
// 基于真正的风险项(riskItemRows),与展示逻辑一致,通过 useRiskNotifier 递交 BaseReport
|
||||
const riskScore = computed(() => {
|
||||
const basic = result.value.basic_info;
|
||||
if (!basic || basic.risk_flag === 1) return 100;
|
||||
const hitItems = riskItemRows.value.filter((r) => r.value === 2).length;
|
||||
const score = 100 - hitItems * 2; // 每命中 1 项扣 2 分
|
||||
return Math.max(0, Math.min(100, score));
|
||||
});
|
||||
useRiskNotifier(props, riskScore);
|
||||
defineExpose({ riskScore });
|
||||
|
||||
// 借鉴司法涉诉概览:风险图标与背景样式
|
||||
const getRiskIcon = () => {
|
||||
if (riskSummary.value.hasRisk) return new URL('@/assets/images/report/gfx.png', import.meta.url).href;
|
||||
return new URL('@/assets/images/report/zq.png', import.meta.url).href;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="report-wrap">
|
||||
<!-- 头部风险总结(底色固定白色,命中项用内嵌 card 展现) -->
|
||||
<div v-if="hasAnyData" class="risk-summary card">
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="w-12 h-12 mr-3 flex-shrink-0">
|
||||
<img :src="getRiskIcon()" alt="风险" class="w-12 h-12 object-contain" />
|
||||
</div>
|
||||
<div class="text-gray-700 text-[15px] leading-relaxed">
|
||||
<template v-if="riskSummary.hasRisk">
|
||||
<span v-if="riskSummary.riskCategories.length">涉及{{ riskSummary.riskCategories.join('、')
|
||||
}};</span>
|
||||
<span v-if="riskSummary.suggestion">{{ riskSummary.suggestion }}</span>
|
||||
</template>
|
||||
<template v-else>未检测到相关风险</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 命中项:仅显示总项数 / 命中数(真正的风险项:失信限高、劳动争议、社会保险、福利待遇、人事争议、仲裁流程、通知函触达) -->
|
||||
<div v-if="riskSummary.totalItems > 0" class="inner-card p-4 rounded-xl text-center"
|
||||
:class="riskSummary.hitItems > 0 ? 'inner-card-risk' : 'inner-card-safe'">
|
||||
<div class="text-2xl font-bold mb-1"
|
||||
:class="riskSummary.hitItems > 0 ? 'text-[#EB3C3C]' : 'text-[#10b981]'">
|
||||
{{ riskSummary.hitItems }}/{{ riskSummary.totalItems }}
|
||||
</div>
|
||||
<div class="text-sm font-medium text-gray-800">命中项</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 1: 汇总 -->
|
||||
<section class="card">
|
||||
<header class="card-header">
|
||||
<span class="card-title">风险概览</span>
|
||||
<span class="card-subtitle">综合评估结果</span>
|
||||
</header>
|
||||
<div v-if="hasAnyData" class="group-list">
|
||||
<div v-for="(group, gi) in summaryGroups" :key="group.key" class="group-box">
|
||||
<div class="group-header">
|
||||
<span class="group-title">{{ group.title }}</span>
|
||||
</div>
|
||||
<div class="group-body">
|
||||
<div v-for="(row, ri) in group.rows" :key="ri" class="data-row">
|
||||
<span class="data-label">{{ row.label }}</span>
|
||||
<span v-if="row.period !== undefined" class="data-value data-value-text">{{
|
||||
getNoticeLetterPeriodText(row.period) }}</span>
|
||||
<span v-else
|
||||
:class="['data-value', 'data-badge', row.value === 2 ? 'badge-risk' : 'badge-safe']">
|
||||
<span class="badge-dot" :class="row.value === 2 ? 'dot-risk' : 'dot-safe'" />
|
||||
{{ getStatusText(row.value) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-state">
|
||||
<span class="empty-icon">—</span>
|
||||
<span class="empty-text">暂无相关风险数据</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Card 2: 近三年 / 近五年 -->
|
||||
<section class="card">
|
||||
<header class="card-header">
|
||||
<span class="card-title">时间维度</span>
|
||||
<span class="card-subtitle">按周期查看命中情况</span>
|
||||
</header>
|
||||
<div class="period-tabs">
|
||||
<button type="button" :class="['period-tab', periodTab === 'threeYears' && 'active']"
|
||||
@click="periodTab = 'threeYears'">近三年</button>
|
||||
<button type="button" :class="['period-tab', periodTab === 'fiveYears' && 'active']"
|
||||
@click="periodTab = 'fiveYears'">近五年</button>
|
||||
</div>
|
||||
<div v-if="periodGroups.length" class="group-list">
|
||||
<div v-for="(group, gi) in periodGroups" :key="group.key" class="group-box">
|
||||
<div class="group-header">
|
||||
<span class="group-title">{{ group.title }}</span>
|
||||
</div>
|
||||
<div class="group-body">
|
||||
<div v-for="(row, ri) in group.rows" :key="ri" class="data-row">
|
||||
<span class="data-label">{{ row.label }}</span>
|
||||
<span class="data-value data-badge badge-risk">
|
||||
<span class="badge-dot dot-risk" />
|
||||
{{ getStatusText(row.value) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-state">
|
||||
<span class="empty-icon">—</span>
|
||||
<span class="empty-text">暂无{{ periodTab === 'threeYears' ? '近三年' : '近五年' }}命中数据</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.report-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.inner-card {
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.inner-card-risk {
|
||||
background: rgba(235, 60, 60, 0.1);
|
||||
border-color: rgba(235, 60, 60, 0.3);
|
||||
}
|
||||
|
||||
.inner-card-safe {
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
border-color: rgba(16, 185, 129, 0.3);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
margin-bottom: 14px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.card-subtitle {
|
||||
font-size: 13px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.period-tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
padding: 4px;
|
||||
background: #f8fafc;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.period-tab {
|
||||
flex: 1;
|
||||
padding: 10px 16px;
|
||||
font-size: 15px;
|
||||
color: #64748b;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.period-tab.active {
|
||||
color: #1e293b;
|
||||
font-weight: 500;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.group-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.group-box {
|
||||
background: #fff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.group-header {
|
||||
padding: 12px 16px;
|
||||
background: #f8fafc;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.group-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.group-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.data-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.data-row:not(:last-child) {
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.data-label {
|
||||
color: #475569;
|
||||
flex: 1;
|
||||
margin-right: 12px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.data-value {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.data-value-text {
|
||||
color: #64748b;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.data-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.badge-risk {
|
||||
background: #fff1f2;
|
||||
color: #be123c;
|
||||
}
|
||||
|
||||
.dot-risk {
|
||||
background: #e11d48;
|
||||
}
|
||||
|
||||
.badge-safe {
|
||||
background: #f0fdf4;
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.dot-safe {
|
||||
background: #10b981;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 28px 16px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 20px;
|
||||
color: #cbd5e1;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 15px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
</style>
|
||||
@@ -31,19 +31,26 @@
|
||||
<span class="text-gray-800">{{
|
||||
paymentType === "agent_upgrade"
|
||||
? "代理升级"
|
||||
: "查询服务"
|
||||
: paymentType === "whitelist"
|
||||
? "模块下架"
|
||||
: "查询服务"
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="paymentType === 'agent_upgrade'" class="text-center text-gray-600 mb-4">恭喜你升级代理等级成功,享受更多权益
|
||||
</div>
|
||||
<div v-else-if="paymentType === 'whitelist'" class="text-center text-gray-600 mb-4">
|
||||
模块下架成功,该身份证号查询时将不显示此模块的数据
|
||||
</div>
|
||||
|
||||
<div class="action-buttons grid grid-cols-1 gap-4">
|
||||
<van-button block type="primary" class="rounded-lg" @click="handleNavigation">
|
||||
{{
|
||||
paymentType === "agent_upgrade"
|
||||
? "查看代理信息"
|
||||
: "查看查询结果"
|
||||
: paymentType === "whitelist"
|
||||
? "返回报告"
|
||||
: "查看查询结果"
|
||||
}}
|
||||
</van-button>
|
||||
</div>
|
||||
@@ -74,7 +81,9 @@
|
||||
<span class="text-gray-800">{{
|
||||
paymentType === "agent_upgrade"
|
||||
? "代理升级"
|
||||
: "查询服务"
|
||||
: paymentType === "whitelist"
|
||||
? "模块下架"
|
||||
: "查询服务"
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
@@ -137,7 +146,9 @@
|
||||
<span class="text-gray-800">{{
|
||||
paymentType === "agent_upgrade"
|
||||
? "代理升级"
|
||||
: "查询服务"
|
||||
: paymentType === "whitelist"
|
||||
? "模块下架"
|
||||
: "查询服务"
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
@@ -329,6 +340,20 @@ const checkPaymentStatus = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 对于白名单类型,如果状态是已支付,跳转回报告页
|
||||
if (paymentType.value === "whitelist" && newStatus === "paid") {
|
||||
stopPolling();
|
||||
const returnUrl = route.query.returnUrl;
|
||||
if (returnUrl) {
|
||||
router.replace(returnUrl);
|
||||
} else if (window.history.length > 1) {
|
||||
router.go(-1);
|
||||
} else {
|
||||
router.replace("/");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果状态不是 pending,停止轮询
|
||||
if (newStatus !== "pending") {
|
||||
stopPolling();
|
||||
@@ -414,6 +439,16 @@ function handleNavigation() {
|
||||
router.replace("/agent");
|
||||
agentStore.fetchAgentStatus();
|
||||
userStore.fetchUserInfo();
|
||||
} else if (paymentType.value === "whitelist") {
|
||||
// 白名单支付:优先使用 returnUrl,否则返回上一页
|
||||
const returnUrl = route.query.returnUrl;
|
||||
if (returnUrl) {
|
||||
router.replace(returnUrl);
|
||||
} else if (window.history.length > 1) {
|
||||
router.go(-1);
|
||||
} else {
|
||||
router.replace("/");
|
||||
}
|
||||
} else {
|
||||
// 跳转到查询结果页面
|
||||
router.replace({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<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" />
|
||||
<BaseReport v-if="queryState === 'success'" :order-id="orderId" :order-no="orderNo" :query-id="queryId"
|
||||
: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>
|
||||
@@ -27,6 +27,7 @@ const isEmpty = ref(false);
|
||||
const isDone = ref(false);
|
||||
const orderId = ref(null);
|
||||
const orderNo = ref("");
|
||||
const queryId = ref("");
|
||||
const queryState = ref("");
|
||||
const pollingInterval = ref(null);
|
||||
|
||||
@@ -98,6 +99,7 @@ const getReport = async () => {
|
||||
queryState.value = decryptedData.query_state;
|
||||
if (queryState.value === "success") {
|
||||
feature.value = decryptedData.product || "";
|
||||
queryId.value = decryptedData.id || decryptedData.query_id || "";
|
||||
|
||||
const sortedQueryData = Array.isArray(decryptedData.query_data)
|
||||
? [...decryptedData.query_data].sort((a, b) => {
|
||||
|
||||
Reference in New Issue
Block a user