From 70f0f98cf91a21bbac22eb27bc6aeb6fef7ebe7a Mon Sep 17 00:00:00 2001
From: liangzai <2440983361@qq.com>
Date: Mon, 2 Mar 2026 14:32:58 +0800
Subject: [PATCH] f
---
src/api/agent.js | 64 +++++++++++
src/components/BaseReport.vue | 204 ++++++++++++++++++++++++++++++++++
src/views/PaymentResult.vue | 28 +++--
src/views/Report.vue | 10 +-
4 files changed, 293 insertions(+), 13 deletions(-)
diff --git a/src/api/agent.js b/src/api/agent.js
index 14391a4..474543d 100644
--- a/src/api/agent.js
+++ b/src/api/agent.js
@@ -278,3 +278,67 @@ 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 列表
+ * @param {string} params.order_id - 关联的查询订单 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.query_id - 查询记录 ID
+ * @param {string} params.feature_api_id - Feature 的 API 标识
+ */
+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();
+}
diff --git a/src/components/BaseReport.vue b/src/components/BaseReport.vue
index b11a9d0..5359ac9 100644
--- a/src/components/BaseReport.vue
+++ b/src/components/BaseReport.vue
@@ -3,12 +3,15 @@ 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 { showFailToast } from "vant";
+import { checkFeatureWhitelistStatus, offlineFeature, checkOrderAgent } from "@/api/agent";
// 动态导入产品背景图片的函数
const loadProductBackground = async (productType) => {
@@ -53,6 +56,11 @@ const props = defineProps({
type: String,
default: "",
},
+ queryId: {
+ type: String,
+ required: false,
+ default: "",
+ },
feature: {
type: String,
required: true,
@@ -98,8 +106,163 @@ const {
isEmpty,
isDone,
isExample,
+ orderId,
+ orderNo,
+ queryId,
} = toRefs(props);
+// 订单是否属于当前代理推广(仅代理订单才显示模块下架)
+const isAgentOrder = ref(false);
+const idCard = computed(() => reportParams.value?.id_card || "");
+
+// 模块下架状态映射:主模块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 mainApiIds = [...new Set(processedReportData.value.map((item) => getMainApiId(item.data.apiID)))];
+ 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 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,无法下架");
+ featureOfflineStatus.value.set(mainApiId, { ...getFeatureStatus(mainApiId), isSubmitting: false });
+ 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 || "下架失败");
+ featureOfflineStatus.value.set(mainApiId, { ...getFeatureStatus(mainApiId), isSubmitting: false });
+ return;
+ }
+ const resp = data.value.data || {};
+ if (resp.need_pay) {
+ const currentStatus = getFeatureStatus(mainApiId);
+ currentStatus.isSubmitting = false;
+ currentStatus.whitelistPrice = resp.amount || 0;
+ featureOfflineStatus.value.set(mainApiId, { ...currentStatus });
+ whitelistPaymentData.value = { product_name: `${featureName || "模块"} 下架`, sell_price: resp.amount || 0 };
+ whitelistPaymentId.value = `${idCard.value}|${mainApiId}`;
+ whitelistPaymentType.value = "whitelist";
+ showWhitelistPayment.value = true;
+ return;
+ }
+ showFailToast("下架成功");
+ const updatedStatus = getFeatureStatus(mainApiId);
+ updatedStatus.isSubmitting = false;
+ updatedStatus.isOfflined = true;
+ featureOfflineStatus.value.set(mainApiId, { ...updatedStatus });
+ if (queryId.value || orderId.value) window.location.reload();
+ } catch (err) {
+ console.error("下架模块失败:", err);
+ showFailToast("下架模块失败");
+ featureOfflineStatus.value.set(mainApiId, { ...getFeatureStatus(mainApiId), isSubmitting: false });
+ }
+};
+const confirmOffline = async () => {
+ if (!currentOfflineFeature.value) return;
+ const mainApiId = currentOfflineFeature.value.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 || "下架失败");
+ featureOfflineStatus.value.set(mainApiId, { ...getFeatureStatus(mainApiId), isSubmitting: false });
+ 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;
+ featureOfflineStatus.value.set(mainApiId, { ...getFeatureStatus(mainApiId), isSubmitting: false });
+ return;
+ }
+ showFailToast("下架成功");
+ showOfflineConfirmDialog.value = false;
+ currentOfflineFeature.value = null;
+ const updatedStatus = getFeatureStatus(mainApiId);
+ updatedStatus.isSubmitting = false;
+ updatedStatus.isOfflined = true;
+ featureOfflineStatus.value.set(mainApiId, { ...updatedStatus });
+ if (queryId.value || orderId.value) window.location.reload();
+ } catch (err) {
+ console.error("下架模块失败:", err);
+ showFailToast("下架模块失败");
+ featureOfflineStatus.value.set(mainApiId, { ...getFeatureStatus(mainApiId), isSubmitting: false });
+ }
+};
+
const active = ref(null);
const backgroundContainerRef = ref(null); // 背景容器的引用
@@ -153,8 +316,29 @@ 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 || false;
+ }
+ } catch (err) {
+ console.error("检查订单代理状态失败:", err);
+ }
+ }
+ if (isAgentOrder.value && idCard.value && !isExample.value) {
+ checkAllFeaturesStatus();
+ }
});
+watch([() => isAgentOrder.value, idCard, processedReportData], () => {
+ if (isAgentOrder.value && idCard.value && !isExample.value) {
+ checkAllFeaturesStatus();
+ }
+}, { deep: true });
+
// 处理窗口大小变化(带防抖)
const handleResize = () => {
if (resizeTimer) {
@@ -892,6 +1076,16 @@ const showPublicSecurityRecord = import.meta.env.VITE_SHOW_PUBLIC_SECURITY_RECOR
报告生成中,请稍候...
@@ -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,9 @@ const getReport = async () => { queryState.value = decryptedData.query_state; if (queryState.value === "success") { feature.value = decryptedData.product || ""; + // 查询记录 ID,供报告页模块下架使用 + const rawId = decryptedData.id ?? decryptedData.query_id; + queryId.value = rawId != null ? String(rawId) : ""; const sortedQueryData = Array.isArray(decryptedData.query_data) ? [...decryptedData.query_data].sort((a, b) => {