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 + +
+ + 下架该模块 + +
+
该模块已下架
@@ -918,6 +1112,16 @@ const showPublicSecurityRecord = import.meta.env.VITE_SHOW_PUBLIC_SECURITY_RECOR + + +
+ 下架该模块需支付 ¥{{ currentOfflineFeature?.whitelistPrice ?? 0 }},是否继续? +
+
+ +
diff --git a/src/views/PaymentResult.vue b/src/views/PaymentResult.vue index 621b483..8de8e01 100644 --- a/src/views/PaymentResult.vue +++ b/src/views/PaymentResult.vue @@ -31,19 +31,24 @@ {{ paymentType === "agent_upgrade" ? "代理升级" - : "查询服务" + : paymentType === "whitelist" + ? "模块下架" + : "查询服务" }}
恭喜你升级代理等级成功,享受更多权益
+
模块已下架,报告将不再展示该模块内容
{{ paymentType === "agent_upgrade" ? "查看代理信息" - : "查看查询结果" + : paymentType === "whitelist" + ? "返回报告" + : "查看查询结果" }}
@@ -74,7 +79,9 @@ {{ paymentType === "agent_upgrade" ? "代理升级" - : "查询服务" + : paymentType === "whitelist" + ? "模块下架" + : "查询服务" }}
@@ -83,9 +90,9 @@
-
+
- 查看查询结果 + {{ paymentType === "whitelist" ? "返回报告" : "查看查询结果" }}
@@ -137,7 +144,9 @@ {{ paymentType === "agent_upgrade" ? "代理升级" - : "查询服务" + : paymentType === "whitelist" + ? "模块下架" + : "查询服务" }}
@@ -316,9 +325,9 @@ const checkPaymentStatus = async () => { if (paymentStatus.value !== newStatus) { paymentStatus.value = newStatus; - // 对于查询类型,如果状态是已支付或已退款,直接跳转 + // 对于查询或白名单类型,如果状态是已支付或已退款,直接跳转 if ( - paymentType.value === "query" && + (paymentType.value === "query" || paymentType.value === "whitelist") && (newStatus === "paid" || newStatus === "refunded") ) { stopPolling(); @@ -410,12 +419,11 @@ onBeforeUnmount(() => { // 处理导航逻辑 function handleNavigation() { if (paymentType.value === "agent_upgrade") { - // 跳转到代理主页 router.replace("/agent"); agentStore.fetchAgentStatus(); userStore.fetchUserInfo(); } else { - // 跳转到查询结果页面 + // 查询服务或白名单下架:跳转到报告页 router.replace({ path: "/report", query: { orderNo: orderNo.value }, diff --git a/src/views/Report.vue b/src/views/Report.vue index 3f85288..31612c6 100644 --- a/src/views/Report.vue +++ b/src/views/Report.vue @@ -1,7 +1,7 @@