2025-11-27 13:19:45 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="inquire-bg min-h-screen relative pt-60" :style="backgroundStyle">
|
|
|
|
|
|
<!-- 主要内容区域 - 覆盖背景图片 -->
|
|
|
|
|
|
<div class="min-h-screen relative mx-4 pb-12">
|
|
|
|
|
|
<!-- 产品卡片牌匾效果 - 使用背景图片 -->
|
|
|
|
|
|
<div class="absolute -top-[12px] left-1/2 transform -translate-x-1/2 w-[140px]">
|
|
|
|
|
|
<div class="trapezoid-bg-image flex items-center justify-center" :style="trapezoidBgStyle">
|
|
|
|
|
|
<div class="text-xl whitespace-nowrap text-white" :style="trapezoidTextStyle">{{
|
|
|
|
|
|
featureData.product_name }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-container">
|
|
|
|
|
|
<!-- 基本信息标题 -->
|
|
|
|
|
|
<div class="mb-6 flex items-center">
|
|
|
|
|
|
<SectionTitle title="基本信息" />
|
|
|
|
|
|
<div class="ml-auto flex items-center text-gray-600 cursor-pointer" @click="toExample">
|
|
|
|
|
|
<img src="@/assets/images/report/slbg_inquire_icon.png" alt="示例报告" class="w-4 h-4 mr-1" />
|
|
|
|
|
|
<span class="text-md">示例报告</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 表单输入区域 -->
|
|
|
|
|
|
<div class="space-y-4 mb-6">
|
|
|
|
|
|
<div class="flex items-center py-3 border-b border-gray-100">
|
|
|
|
|
|
<label for="name" class="w-20 font-medium text-gray-700">姓名</label>
|
|
|
|
|
|
<input v-model="formData.name" id="name" type="text" placeholder="请输入正确的姓名"
|
|
|
|
|
|
class="flex-1 border-none outline-none" @click="handleInputClick" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center py-3 border-b border-gray-100">
|
|
|
|
|
|
<label for="idCard" class="w-20 font-medium text-gray-700">身份证号</label>
|
|
|
|
|
|
<input v-model="formData.idCard" id="idCard" type="text" placeholder="请输入准确的身份证号"
|
|
|
|
|
|
class="flex-1 border-none outline-none" @click="handleInputClick" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center py-3 border-b border-gray-100">
|
|
|
|
|
|
<label for="mobile" class="w-20 font-medium text-gray-700">手机号</label>
|
|
|
|
|
|
<input v-model="formData.mobile" id="mobile" type="tel" placeholder="请输入手机号"
|
|
|
|
|
|
class="flex-1 border-none outline-none" @click="handleInputClick" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center py-3 border-b border-gray-100">
|
|
|
|
|
|
<label for="verificationCode" class="w-20 font-medium text-gray-700">验证码</label>
|
|
|
|
|
|
<input v-model="formData.verificationCode" id="verificationCode" placeholder="请输入验证码"
|
|
|
|
|
|
maxlength="6" class="flex-1 border-none outline-none" @click="handleInputClick" />
|
|
|
|
|
|
<button class="text-primary font-medium text-nowrap"
|
|
|
|
|
|
:disabled="isCountingDown || !isPhoneNumberValid" @click="sendVerificationCode">
|
|
|
|
|
|
{{
|
|
|
|
|
|
isCountingDown
|
|
|
|
|
|
? `${countdown}s重新获取`
|
|
|
|
|
|
: "获取验证码"
|
|
|
|
|
|
}}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 协议同意 -->
|
|
|
|
|
|
<div class="flex items-center mb-6">
|
|
|
|
|
|
<input type="checkbox" v-model="formData.agreeToTerms" class="mr-3 accent-primary" />
|
|
|
|
|
|
<span class="text-sm text-gray-500">
|
|
|
|
|
|
我已阅读并同意
|
|
|
|
|
|
<span @click="toUserAgreement" class="text-primary cursor-pointer">《用户协议》</span>
|
|
|
|
|
|
<span @click="toPrivacyPolicy" class="text-primary cursor-pointer">《隐私政策》</span>
|
|
|
|
|
|
<span @click="toAuthorization" class="text-primary cursor-pointer">《授权书》</span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 查询按钮 -->
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="w-full bg-primary-second text-white py-4 rounded-[48px] text-lg font-medium mb-4 flex items-center justify-center mt-10"
|
|
|
|
|
|
@click="handleSubmit">
|
|
|
|
|
|
<span>{{ buttonText }}</span>
|
|
|
|
|
|
<span class="ml-4">¥{{ featureData.sell_price }}</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<!-- <div class="text-gray-500 leading-relaxed mt-8" v-html="featureData.description">
|
|
|
|
|
|
</div> -->
|
|
|
|
|
|
<!-- 免责声明 -->
|
|
|
|
|
|
<div class="text-xs text-center text-gray-500 leading-relaxed mt-2">
|
2025-12-16 19:27:20 +08:00
|
|
|
|
为保证用户的隐私及数据安全,查询结果生成{{ appStore.queryRetentionDays || 30 }}天后将自动删除
|
2025-11-27 13:19:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 报告包含内容 -->
|
|
|
|
|
|
<div class="card mt-3" v-if="featureData.features && featureData.features.length > 0">
|
|
|
|
|
|
<ReportFeatures :features="featureData.features" :title-style="{ color: 'var(--van-text-color)' }" />
|
|
|
|
|
|
<div class="mt-3 text-center">
|
|
|
|
|
|
<div class="inline-flex items-center px-3 py-1.5 rounded-full border transition-all"
|
|
|
|
|
|
style="background: linear-gradient(135deg, var(--van-theme-primary-light), rgba(255,255,255,0.8)); border-color: var(--van-theme-primary);">
|
|
|
|
|
|
<div class="w-1.5 h-1.5 rounded-full mr-1.5"
|
|
|
|
|
|
style="background-color: var(--van-theme-primary);">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="text-xs font-medium" style="color: var(--van-theme-primary);">更多信息请解锁报告</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 产品详情卡片 -->
|
|
|
|
|
|
<div class="card mt-4">
|
|
|
|
|
|
<div class="mb-4 text-xl font-bold" style="color: var(--van-text-color);">
|
|
|
|
|
|
{{ featureData.product_name }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="mb-4 flex items-start justify-between">
|
|
|
|
|
|
<div class="text-lg" style="color: var(--van-text-color-2);">价格:</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="text-2xl font-semibold text-danger">
|
|
|
|
|
|
¥{{ featureData.sell_price }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mb-4 leading-relaxed" style="color: var(--van-text-color-2);"
|
|
|
|
|
|
v-html="featureData.description">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="mb-2 text-xs italic text-danger">
|
2025-12-16 19:27:20 +08:00
|
|
|
|
为保证用户的隐私以及数据安全,查询的结果生成{{ appStore.queryRetentionDays || 30 }}天之后将自动清除。
|
2025-11-27 13:19:45 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 支付组件 -->
|
|
|
|
|
|
<Payment v-model="showPayment" :data="featureData" :id="queryId" type="query" @close="showPayment = false" />
|
2025-12-16 19:27:20 +08:00
|
|
|
|
<BindPhoneOnlyDialog @bind-success="handleBindSuccess" />
|
2025-11-27 13:19:45 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 历史查询按钮 - 仅推广查询显示 -->
|
|
|
|
|
|
<div v-if="props.type === 'promotion'" @click="toHistory"
|
|
|
|
|
|
class="fixed right-2 top-3/4 px-4 py-2 text-sm bg-primary rounded-xl cursor-pointer text-white font-bold shadow active:bg-blue-500">
|
|
|
|
|
|
历史查询
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-12-16 19:27:20 +08:00
|
|
|
|
import { ref, reactive, computed, onMounted, onUnmounted, nextTick, watch } from "vue";
|
2025-11-27 13:19:45 +08:00
|
|
|
|
import { aesEncrypt } from "@/utils/crypto";
|
|
|
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
|
|
import { useUserStore } from "@/stores/userStore";
|
|
|
|
|
|
import { useDialogStore } from "@/stores/dialogStore";
|
|
|
|
|
|
import { useEnv } from "@/composables/useEnv";
|
|
|
|
|
|
import { showConfirmDialog } from "vant";
|
|
|
|
|
|
|
|
|
|
|
|
import Payment from "@/components/Payment.vue";
|
2025-12-16 19:27:20 +08:00
|
|
|
|
import BindPhoneOnlyDialog from "@/components/BindPhoneOnlyDialog.vue";
|
2025-11-27 13:19:45 +08:00
|
|
|
|
import SectionTitle from "@/components/SectionTitle.vue";
|
|
|
|
|
|
import ReportFeatures from "@/components/ReportFeatures.vue";
|
2025-12-16 19:27:20 +08:00
|
|
|
|
import { useAppStore } from "@/stores/appStore";
|
2025-11-27 13:19:45 +08:00
|
|
|
|
|
|
|
|
|
|
// Props
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
// 查询类型:'normal' | 'promotion'
|
|
|
|
|
|
type: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
default: 'normal'
|
|
|
|
|
|
},
|
|
|
|
|
|
// 产品特征
|
|
|
|
|
|
feature: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
required: true
|
|
|
|
|
|
},
|
|
|
|
|
|
// 推广链接标识符(仅推广查询需要)
|
|
|
|
|
|
linkIdentifier: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
default: ''
|
|
|
|
|
|
},
|
|
|
|
|
|
// 产品数据(从外部传入)
|
|
|
|
|
|
featureData: {
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => ({})
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Emits
|
|
|
|
|
|
const emit = defineEmits(['submit-success']);
|
|
|
|
|
|
|
|
|
|
|
|
// 动态导入产品背景图片的函数
|
|
|
|
|
|
const loadProductBackground = async (productType) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
switch (productType) {
|
|
|
|
|
|
case 'companyinfo':
|
|
|
|
|
|
return (await import("@/assets/images/report/xwqy_inquire_bg.png")).default;
|
|
|
|
|
|
case 'preloanbackgroundcheck':
|
|
|
|
|
|
return (await import("@/assets/images/report/dqfx_inquire_bg.png")).default;
|
2025-12-16 19:27:20 +08:00
|
|
|
|
case 'riskassessment':
|
2025-11-27 13:19:45 +08:00
|
|
|
|
return (await import("@/assets/images/report/grdsj_inquire_bg.png")).default;
|
|
|
|
|
|
case 'marriage':
|
|
|
|
|
|
return (await import("@/assets/images/report/marriage_inquire_bg.png")).default;
|
|
|
|
|
|
case 'homeservice':
|
|
|
|
|
|
return (await import("@/assets/images/report/homeservice_inquire_bg.png")).default;
|
|
|
|
|
|
case 'backgroundcheck':
|
|
|
|
|
|
return (await import("@/assets/images/report/backgroundcheck_inquire_bg.png")).default;
|
|
|
|
|
|
case 'consumerFinanceReport':
|
|
|
|
|
|
return (await import("@/assets/images/report/xjbg_inquire_bg.png")).default;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.warn(`Failed to load background image for ${productType}:`, error);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
const dialogStore = useDialogStore();
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
const { isWeChat } = useEnv();
|
2025-12-16 19:27:20 +08:00
|
|
|
|
const appStore = useAppStore();
|
2025-11-27 13:19:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 响应式数据
|
|
|
|
|
|
const showPayment = ref(false);
|
|
|
|
|
|
const pendingPayment = ref(false);
|
|
|
|
|
|
const queryId = ref(null);
|
|
|
|
|
|
const productBackground = ref('');
|
|
|
|
|
|
const trapezoidBgImage = ref('');
|
|
|
|
|
|
const isCountingDown = ref(false);
|
|
|
|
|
|
const countdown = ref(60);
|
|
|
|
|
|
|
|
|
|
|
|
// 使用传入的featureData或创建响应式引用
|
|
|
|
|
|
const featureData = computed(() => props.featureData || {});
|
|
|
|
|
|
|
|
|
|
|
|
// 表单数据
|
|
|
|
|
|
const formData = reactive({
|
|
|
|
|
|
name: "",
|
|
|
|
|
|
idCard: "",
|
|
|
|
|
|
mobile: "",
|
|
|
|
|
|
verificationCode: "",
|
|
|
|
|
|
agreeToTerms: false
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 计算属性
|
|
|
|
|
|
const isPhoneNumberValid = computed(() => {
|
|
|
|
|
|
return /^1[3-9]\d{9}$/.test(formData.mobile);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const isIdCardValid = computed(() => /^\d{17}[\dX]$/i.test(formData.idCard));
|
|
|
|
|
|
|
|
|
|
|
|
const isLoggedIn = computed(() => userStore.isLoggedIn);
|
|
|
|
|
|
|
|
|
|
|
|
const buttonText = computed(() => {
|
|
|
|
|
|
return isLoggedIn.value ? '立即查询' : '前往登录';
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 获取产品背景图片
|
|
|
|
|
|
const getProductBackground = computed(() => productBackground.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 背景图片样式
|
|
|
|
|
|
const backgroundStyle = computed(() => {
|
|
|
|
|
|
if (getProductBackground.value) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
backgroundImage: `url(${getProductBackground.value})`,
|
|
|
|
|
|
backgroundSize: 'contain',
|
|
|
|
|
|
backgroundPosition: 'center -40px',
|
|
|
|
|
|
backgroundRepeat: 'no-repeat',
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
return {};
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 动态加载牌匾背景图片
|
|
|
|
|
|
const loadTrapezoidBackground = async () => {
|
2025-12-16 19:27:20 +08:00
|
|
|
|
if (!props.feature) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-11-27 13:19:45 +08:00
|
|
|
|
try {
|
|
|
|
|
|
let bgModule;
|
|
|
|
|
|
if (props.feature === 'marriage') {
|
|
|
|
|
|
bgModule = await import("@/assets/images/report/title_inquire_bg_red.png");
|
|
|
|
|
|
} else if (props.feature === 'homeservice') {
|
|
|
|
|
|
bgModule = await import("@/assets/images/report/title_inquire_bg_green.png");
|
|
|
|
|
|
} else if (props.feature === 'consumerFinanceReport' || props.feature === 'companyinfo') {
|
|
|
|
|
|
bgModule = await import("@/assets/images/report/title_inquire_bg_yellow.png");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
bgModule = await import("@/assets/images/report/title_inquire_bg.png");
|
|
|
|
|
|
}
|
|
|
|
|
|
trapezoidBgImage.value = bgModule.default;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.warn(`Failed to load trapezoid background image:`, error);
|
|
|
|
|
|
// 回退到默认图片
|
|
|
|
|
|
try {
|
|
|
|
|
|
const defaultModule = await import("@/assets/images/report/title_inquire_bg.png");
|
|
|
|
|
|
trapezoidBgImage.value = defaultModule.default;
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('Failed to load default trapezoid background:', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 牌匾背景图片样式
|
|
|
|
|
|
const trapezoidBgStyle = computed(() => {
|
|
|
|
|
|
if (trapezoidBgImage.value) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
backgroundImage: `url(${trapezoidBgImage.value})`,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
return {};
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 牌匾文字样式
|
|
|
|
|
|
const trapezoidTextStyle = computed(() => {
|
|
|
|
|
|
// homeservice 和 marriage 使用白色文字
|
|
|
|
|
|
// 其他情况使用默认字体色(不设置 color,使用浏览器默认或继承)
|
|
|
|
|
|
return {};
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 方法
|
|
|
|
|
|
const validateField = (field, value, validationFn, errorMessage) => {
|
|
|
|
|
|
if (isHasInput(field) && !validationFn(value)) {
|
|
|
|
|
|
showToast({ message: errorMessage });
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const defaultInput = ["name", "idCard", "mobile", "verificationCode"];
|
|
|
|
|
|
const isHasInput = (input) => {
|
|
|
|
|
|
return defaultInput.includes(input);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 处理绑定手机号成功的回调
|
|
|
|
|
|
function handleBindSuccess() {
|
|
|
|
|
|
if (pendingPayment.value) {
|
|
|
|
|
|
pendingPayment.value = false;
|
|
|
|
|
|
submitRequest();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理输入框点击事件
|
|
|
|
|
|
const handleInputClick = async () => {
|
|
|
|
|
|
if (!isLoggedIn.value) {
|
2025-12-16 19:27:20 +08:00
|
|
|
|
if (!isWeChat.value && props.type !== 'promotion') {
|
2025-11-27 13:19:45 +08:00
|
|
|
|
try {
|
|
|
|
|
|
await showConfirmDialog({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
message: '您需要登录后才能进行查询,是否前往登录?',
|
|
|
|
|
|
confirmButtonText: '前往登录',
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
});
|
|
|
|
|
|
router.push('/login');
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
// 用户点击取消,什么都不做
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-12-16 19:27:20 +08:00
|
|
|
|
if (isWeChat.value && !userStore.mobile && props.type !== 'promotion') {
|
2025-11-27 13:19:45 +08:00
|
|
|
|
dialogStore.openBindPhone();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function handleSubmit() {
|
2025-12-16 19:27:20 +08:00
|
|
|
|
if (!isWeChat.value && !isLoggedIn.value && props.type !== 'promotion') {
|
2025-11-27 13:19:45 +08:00
|
|
|
|
router.push('/login');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 基本协议验证
|
|
|
|
|
|
if (!formData.agreeToTerms) {
|
|
|
|
|
|
showToast({ message: `请阅读并同意用户协议和隐私政策` });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
!validateField("name", formData.name, (v) => v, "请输入姓名") ||
|
|
|
|
|
|
!validateField(
|
|
|
|
|
|
"mobile",
|
|
|
|
|
|
formData.mobile,
|
|
|
|
|
|
(v) => isPhoneNumberValid.value,
|
|
|
|
|
|
"请输入有效的手机号"
|
|
|
|
|
|
) ||
|
|
|
|
|
|
!validateField(
|
|
|
|
|
|
"idCard",
|
|
|
|
|
|
formData.idCard,
|
|
|
|
|
|
(v) => isIdCardValid.value,
|
|
|
|
|
|
"请输入有效的身份证号码"
|
|
|
|
|
|
) ||
|
|
|
|
|
|
!validateField(
|
|
|
|
|
|
"verificationCode",
|
|
|
|
|
|
formData.verificationCode,
|
|
|
|
|
|
(v) => v,
|
|
|
|
|
|
"请输入验证码"
|
|
|
|
|
|
)
|
|
|
|
|
|
) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否需要绑定手机号
|
2025-12-16 19:27:20 +08:00
|
|
|
|
if (!userStore.mobile && props.type !== 'promotion') {
|
2025-11-27 13:19:45 +08:00
|
|
|
|
pendingPayment.value = true;
|
|
|
|
|
|
dialogStore.openBindPhone();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
submitRequest();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function submitRequest() {
|
|
|
|
|
|
const req = {
|
|
|
|
|
|
name: formData.name,
|
|
|
|
|
|
id_card: formData.idCard,
|
|
|
|
|
|
mobile: formData.mobile,
|
|
|
|
|
|
code: formData.verificationCode
|
|
|
|
|
|
};
|
|
|
|
|
|
const reqStr = JSON.stringify(req);
|
|
|
|
|
|
const encodeData = aesEncrypt(
|
|
|
|
|
|
reqStr,
|
|
|
|
|
|
import.meta.env.VITE_INQUIRE_AES_KEY
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
let apiUrl = '';
|
|
|
|
|
|
let requestData = { data: encodeData };
|
|
|
|
|
|
|
|
|
|
|
|
if (props.type === 'promotion') {
|
|
|
|
|
|
apiUrl = `/query/service_agent/${props.feature}`;
|
|
|
|
|
|
requestData.agent_identifier = props.linkIdentifier;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
apiUrl = `/query/service/${props.feature}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { data, error } = await useApiFetch(apiUrl)
|
|
|
|
|
|
.post(requestData)
|
|
|
|
|
|
.json();
|
|
|
|
|
|
|
|
|
|
|
|
if (data.value.code === 200) {
|
|
|
|
|
|
queryId.value = data.value.data.id;
|
|
|
|
|
|
|
|
|
|
|
|
// 推广查询需要保存token
|
|
|
|
|
|
if (props.type === 'promotion') {
|
|
|
|
|
|
localStorage.setItem("token", data.value.data.accessToken);
|
|
|
|
|
|
localStorage.setItem("refreshAfter", data.value.data.refreshAfter);
|
|
|
|
|
|
localStorage.setItem("accessExpire", data.value.data.accessExpire);
|
2025-12-16 19:27:20 +08:00
|
|
|
|
// ⚠️ 重要:保存 token 后立即设置 tokenVersion,防止被 checkTokenVersion 清除
|
|
|
|
|
|
const tokenVersion = import.meta.env.VITE_TOKEN_VERSION || "1.1";
|
|
|
|
|
|
localStorage.setItem("tokenVersion", tokenVersion);
|
2025-11-27 13:19:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
showPayment.value = true;
|
|
|
|
|
|
emit('submit-success', data.value.data);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function sendVerificationCode() {
|
|
|
|
|
|
if (isCountingDown.value || !isPhoneNumberValid.value) return;
|
|
|
|
|
|
if (!isPhoneNumberValid.value) {
|
|
|
|
|
|
showToast({ message: "请输入有效的手机号" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { data, error } = await useApiFetch("/auth/sendSms")
|
|
|
|
|
|
.post({ mobile: formData.mobile, actionType: "query" })
|
|
|
|
|
|
.json();
|
|
|
|
|
|
|
|
|
|
|
|
if (!error.value && data.value.code === 200) {
|
|
|
|
|
|
showToast({ message: "验证码发送成功", type: "success" });
|
|
|
|
|
|
startCountdown();
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
const verificationCodeInput = document.getElementById('verificationCode');
|
|
|
|
|
|
if (verificationCodeInput) {
|
|
|
|
|
|
verificationCodeInput.focus();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
showToast({ message: "验证码发送失败,请重试" });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let timer = null;
|
|
|
|
|
|
|
|
|
|
|
|
function startCountdown() {
|
|
|
|
|
|
isCountingDown.value = true;
|
|
|
|
|
|
countdown.value = 60;
|
|
|
|
|
|
timer = setInterval(() => {
|
|
|
|
|
|
if (countdown.value > 0) {
|
|
|
|
|
|
countdown.value--;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
|
isCountingDown.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function toUserAgreement() {
|
|
|
|
|
|
router.push(`/userAgreement`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function toPrivacyPolicy() {
|
|
|
|
|
|
router.push(`/privacyPolicy`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function toAuthorization() {
|
|
|
|
|
|
router.push(`/authorization`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const toExample = () => {
|
|
|
|
|
|
router.push(`/example?feature=${props.feature}`);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const toHistory = () => {
|
|
|
|
|
|
router.push("/historyQuery");
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 加载背景图片
|
|
|
|
|
|
const loadBackgroundImage = async () => {
|
2025-12-16 19:27:20 +08:00
|
|
|
|
if (!props.feature) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-11-27 13:19:45 +08:00
|
|
|
|
const background = await loadProductBackground(props.feature);
|
|
|
|
|
|
productBackground.value = background || '';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-12-16 19:27:20 +08:00
|
|
|
|
// 监听 feature 变化,重新加载背景图
|
|
|
|
|
|
watch(() => props.feature, async (newFeature) => {
|
|
|
|
|
|
if (newFeature) {
|
|
|
|
|
|
await loadBackgroundImage();
|
|
|
|
|
|
await loadTrapezoidBackground();
|
|
|
|
|
|
}
|
|
|
|
|
|
}, { immediate: true });
|
|
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
await loadBackgroundImage();
|
|
|
|
|
|
await loadTrapezoidBackground();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-27 13:19:45 +08:00
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
if (timer) {
|
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
/* 背景样式 */
|
|
|
|
|
|
.inquire-bg {
|
|
|
|
|
|
background-color: var(--color-primary-50);
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 卡片样式优化 */
|
|
|
|
|
|
.card {
|
|
|
|
|
|
@apply shadow-lg rounded-xl p-6 transition-all hover:shadow-xl;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.95);
|
|
|
|
|
|
backdrop-filter: blur(10px);
|
|
|
|
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
|
|
|
box-shadow:
|
|
|
|
|
|
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
|
|
|
|
0 2px 4px -1px rgba(0, 0, 0, 0.06),
|
|
|
|
|
|
0 0 0 1px rgba(255, 255, 255, 0.05);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 按钮悬停效果 */
|
|
|
|
|
|
button:hover {
|
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
button:active {
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 梯形背景图片样式 */
|
|
|
|
|
|
.trapezoid-bg-image {
|
|
|
|
|
|
background-size: contain;
|
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
|
background-position: center;
|
|
|
|
|
|
height: 44px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 卡片容器样式 */
|
|
|
|
|
|
.card-container {
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 32px 16px;
|
|
|
|
|
|
box-shadow: 0px 0px 24px 0px #3F3F3F0F;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.card-container input::placeholder {
|
|
|
|
|
|
color: #DDDDDD;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 功能标签样式 */
|
|
|
|
|
|
.feature-tag {
|
|
|
|
|
|
background-color: var(--color-primary-light);
|
|
|
|
|
|
color: var(--color-primary);
|
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
|
border-radius: 9999px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 功能标签圆点 */
|
|
|
|
|
|
.feature-dot {
|
|
|
|
|
|
width: 6px;
|
|
|
|
|
|
height: 6px;
|
|
|
|
|
|
background-color: var(--color-primary);
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
}
|
2025-12-16 19:27:20 +08:00
|
|
|
|
</style>
|