This commit is contained in:
2025-11-13 22:27:54 +08:00
parent 75590a0062
commit 3135250b1e
210 changed files with 36854 additions and 16 deletions

View File

@@ -107,7 +107,7 @@
/* ===== 业务特定颜色 ===== */
--color-service-personal: #5d7eeb; /* 个人大数据 */
--color-service-company: #6b9df9; /* 小微企业 */
--color-service-loan: #e1a0e4; /* 贷前背调 */
--color-service-loan: #e1a0e4; /* 贷前风险 */
/* ===== 渐变色彩 ===== */
--gradient-primary: linear-gradient(

View File

@@ -9,12 +9,12 @@
<p class="indent-[2em]">
本人<span class="font-bold">
{{ signature ? props.name : "____________" }}</span>
拟向贵司申请大数据分析报告查询业务贵司需要了解本人相关状况用于查询大数据分析报告因此本人同意向贵司提供本人的姓名和手机号等个人信息并同意贵司向第三方包括但不限于西部数据交易有限公司传送上述信息第三方将使用上述信息核实信息真实情况查询信用记录并生成报告
拟向贵司申请大数据分析报告查询业务贵司需要了解本人相关状况用于查询大数据分析报告因此本人同意向贵司提供本人的姓名和手机号等个人信息并同意贵司向第三方传送上述信息第三方将使用上述信息核实信息真实情况查询信用记录并生成报告
</p>
<p class="mt-2 font-bold">授权内容如下</p>
<ol class="list-decimal pl-6">
<li>
贵司向依法成立的第三方服务商包括但不限于西部数据交易有限公司根据本人提交的信息进行核实并有权通过前述第三方服务机构查询使用本人的身份信息设备信息运营商信息等查询本人信息包括但不限于学历婚姻资产状况及对信息主体产生负面影响的不良信息出具相关报告
贵司向依法成立的第三方服务商根据本人提交的信息进行核实并有权通过前述第三方服务机构查询使用本人的身份信息设备信息运营商信息等查询本人信息包括但不限于学历婚姻资产状况及对信息主体产生负面影响的不良信息出具相关报告
</li>
<li>
依法成立的第三方服务商查询或核实搜集保存处理共享使用含合法业务应用本人相关数据且不再另行告知本人但法律法规监管政策禁止的除外

View File

@@ -336,6 +336,11 @@ const featureMap = {
name: "学历信息",
component: defineAsyncComponent(() => import("@/ui/CIVYZ7F3A.vue")),
},
IVYZ3P9M: {
name: "学历信息",
component: defineAsyncComponent(() => import("@/ui/IVYZ3P9M.vue")),
remark: '学历信息展示学生姓名、身份证号、学校、专业、入学与毕业时间、学历层次以及学习形式等字段,可结合字典编码了解具体含义。',
},
DWBG8B4D: {
name: "谛听多维报告",
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/index.vue")),
@@ -579,6 +584,7 @@ const featureRiskLevels = {
// 🔵 低风险类 - 权重 3
'IVYZ5733': 3, // 婚姻状态
'IVYZ9A2B': 3, // 学历信息
'IVYZ3P9M': 3, // 学历信息查询(实时版)
// 📊 复合报告类 - 按子模块动态计算
'DWBG8B4D': 0, // 谛听多维报告(由子模块计算)

View File

@@ -15,7 +15,7 @@
<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-sm">示例报告</span>
<span class="">示例报告</span>
</div>
</div>
<!-- 表单输入区域 -->
@@ -42,9 +42,9 @@
<button class="text-primary font-medium text-nowrap"
:disabled="isCountingDown || !isPhoneNumberValid" @click="sendVerificationCode">
{{
isCountingDown
? `${countdown}s重新获取`
: "获取验证码"
isCountingDown
? `${countdown}s重新获取`
: "获取验证码"
}}
</button>
</div>
@@ -66,10 +66,10 @@
class="w-full bg-primary 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 || '88.8' }}</span>
<span class="ml-4">¥{{ featureData.sell_price }}</span>
</button>
<div class="text-xs text-gray-500 leading-relaxed mt-8" v-html="featureData.description">
</div>
<!-- <div class="text-xs 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">
为保证用户的隐私及数据安全查询结果生成30天后将自动删除

File diff suppressed because it is too large Load Diff

696
src/ui/IVYZ3P9M.vue Normal file
View File

@@ -0,0 +1,696 @@
<script setup>
import { computed } from 'vue';
import { useRiskNotifier } from '@/composables/useRiskNotifier';
import xlIcon from '@/assets/images/report/xl.png';
import zymcIcon from '@/assets/images/report/zymc.png';
import xxxsIcon from '@/assets/images/report/xxxs.png';
import xxlxIcon from '@/assets/images/report/xxlx.png';
import bysjIcon from '@/assets/images/report/bysj.png';
import dictionaries from '@/data/ivyz3p9m-dictionary.json';
const props = defineProps({
data: {
type: [Array, Object],
default: () => [],
},
apiId: {
type: String,
default: '',
},
index: {
type: Number,
default: 0,
},
notifyRiskStatus: {
type: Function,
default: () => { },
},
});
const riskScore = computed(() => 100);
useRiskNotifier(props, riskScore);
defineExpose({ riskScore });
const educationLevelMap = dictionaries.educationLevel ?? {};
const learningFormMap = dictionaries.learningForm ?? {};
const schoolDictionary = dictionaries.schools ?? {};
const specialtyDictionary = dictionaries.specialties ?? {};
const educationTagColorMap = {
'1': 'bg-emerald-50 text-emerald-700 border-emerald-200',
'2': 'bg-blue-50 text-blue-700 border-blue-200',
'3': 'bg-indigo-50 text-indigo-700 border-indigo-200',
'4': 'bg-purple-50 text-purple-700 border-purple-200',
'5': 'bg-amber-50 text-amber-700 border-amber-200',
};
const learningFormColorMap = {
'1': 'bg-sky-50 text-sky-700 border-sky-200',
'2': 'bg-blue-50 text-blue-700 border-blue-200',
'3': 'bg-blue-50 text-blue-700 border-blue-200',
'4': 'bg-cyan-50 text-cyan-700 border-cyan-200',
'5': 'bg-orange-50 text-orange-700 border-orange-200',
'6': 'bg-lime-50 text-lime-700 border-lime-200',
'7': 'bg-indigo-50 text-indigo-700 border-indigo-200',
'8': 'bg-violet-50 text-violet-700 border-violet-200',
'9': 'bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200',
};
const normalizeCode = (value) => {
if (value === null || value === undefined) return '';
return String(value).trim();
};
const getEducationLevelText = (code) => {
const normalized = normalizeCode(code);
if (!normalized) return '未知';
return educationLevelMap[normalized] || '未知';
};
const getLearningFormText = (code) => {
const normalized = normalizeCode(code);
if (!normalized) return '未知';
return learningFormMap[normalized] || '未知';
};
const getSchoolNameText = (code, fallback) => {
const normalized = normalizeCode(code);
if (!normalized) return fallback || '未知学校';
return schoolDictionary[normalized] || fallback || '未知学校';
};
const getSpecialtyNameText = (code, fallback) => {
const normalized = normalizeCode(code);
if (!normalized) return fallback || '未知专业';
return specialtyDictionary[normalized] || fallback || '未知专业';
};
const getEducationLevelClass = (code) => {
const normalized = normalizeCode(code);
return educationTagColorMap[normalized] || 'bg-gray-50 text-gray-700 border-gray-200';
};
const getLearningFormClass = (code) => {
const normalized = normalizeCode(code);
return learningFormColorMap[normalized] || 'bg-gray-50 text-gray-700 border-gray-200';
};
const maskIdNumber = (idNumber) => {
if (!idNumber) return '未知';
const normalized = String(idNumber).trim();
if (normalized.length <= 6) {
return `${normalized.slice(0, 1)}****${normalized.slice(-1)}`;
}
return `${normalized.slice(0, 3)}********${normalized.slice(-4)}`;
};
const formatDate = (dateStr) => {
if (!dateStr) return '未知';
const normalized = String(dateStr).trim();
if (!/^\d+$/.test(normalized)) return '未知';
if (normalized.length === 8) {
const year = normalized.substring(0, 4);
const month = normalized.substring(4, 6);
const day = normalized.substring(6, 8);
return `${year}${month}${day}`;
}
if (normalized.length === 6) {
const year = normalized.substring(0, 4);
const month = normalized.substring(4, 6);
return `${year}${month}`;
}
if (normalized.length === 4) {
const shortYear = normalized.substring(0, 2);
const month = normalized.substring(2, 4);
return `20${shortYear}${month}`;
}
return '未知';
};
const parseDate = (value) => {
if (!value) return null;
const normalized = String(value).trim();
if (!/^\d+$/.test(normalized)) return null;
let year;
let month;
let day = 1;
if (normalized.length === 8) {
year = Number(normalized.substring(0, 4));
month = Number(normalized.substring(4, 6));
day = Number(normalized.substring(6, 8));
} else if (normalized.length === 6) {
year = Number(normalized.substring(0, 4));
month = Number(normalized.substring(4, 6));
} else if (normalized.length === 4) {
year = Number(`20${normalized.substring(0, 2)}`);
month = Number(normalized.substring(2, 4));
} else {
return null;
}
if (!year || !month) return null;
return new Date(year, month - 1, day);
};
const calculateStudyDuration = (start, end) => {
const startDate = parseDate(start);
const endDate = parseDate(end);
if (!startDate || !endDate || endDate < startDate) {
return '时长未知';
}
const totalMonths =
(endDate.getFullYear() - startDate.getFullYear()) * 12 +
(endDate.getMonth() - startDate.getMonth());
if (totalMonths <= 0) {
return '不足 1 个月';
}
const years = Math.floor(totalMonths / 12);
const months = totalMonths % 12;
const parts = [];
if (years > 0) parts.push(`${years}`);
if (months > 0) parts.push(`${months}个月`);
return parts.length > 0 ? `${parts.join('')}` : '约 1 个月';
};
const educationRecords = computed(() => {
const source = props.data;
if (Array.isArray(source)) return source;
if (Array.isArray(source?.data)) return source.data;
if (Array.isArray(source?.records)) return source.records;
if (Array.isArray(source?.list)) return source.list;
return [];
});
const enhancedRecords = computed(() =>
educationRecords.value.map((record, index) => {
const educationLevelCode = normalizeCode(record.educationLevel);
const learningFormCode = normalizeCode(record.learningForm);
const schoolCode = normalizeCode(record.schoolName);
const specialtyCode = normalizeCode(record.specialtyName);
const schoolName = getSchoolNameText(schoolCode, record.schoolName);
const specialtyName = getSpecialtyNameText(specialtyCode, record.specialtyName);
return {
index: index + 1,
studentName: record.studentName || '未知',
idNumber: record.idNumber || '',
maskedIdNumber: maskIdNumber(record.idNumber),
schoolName,
specialtyName,
isUnknownSchool: schoolName === '未知学校' || (!schoolCode && !record.schoolName),
isUnknownSpecialty: specialtyName === '未知专业' || (!specialtyCode && !record.specialtyName),
educationLevelCode,
educationLevel: getEducationLevelText(educationLevelCode),
learningFormCode,
learningForm: getLearningFormText(learningFormCode),
enrollmentDate: formatDate(record.enrollmentDate),
graduationDate: formatDate(record.graduationDate),
rawEnrollmentDate: record.enrollmentDate || '',
rawGraduationDate: record.graduationDate || '',
studyDuration: calculateStudyDuration(record.enrollmentDate, record.graduationDate),
};
})
);
const getTimestamp = (value) => {
const date = parseDate(value);
return date ? date.getTime() : null;
};
const orderedRecords = computed(() => {
if (enhancedRecords.value.length <= 1) return enhancedRecords.value;
return [...enhancedRecords.value].sort((a, b) => {
const startA =
getTimestamp(a.rawEnrollmentDate) ??
getTimestamp(a.rawGraduationDate) ??
Number.MAX_SAFE_INTEGER;
const startB =
getTimestamp(b.rawEnrollmentDate) ??
getTimestamp(b.rawGraduationDate) ??
Number.MAX_SAFE_INTEGER;
if (startA === startB) {
const endA = getTimestamp(a.rawGraduationDate) ?? Number.MAX_SAFE_INTEGER;
const endB = getTimestamp(b.rawGraduationDate) ?? Number.MAX_SAFE_INTEGER;
return endA - endB;
}
return startA - startB;
});
});
const educationRankMap = {
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 2.5,
};
const getEducationRank = (code) => {
const normalized = normalizeCode(code);
return educationRankMap[normalized] ?? 0;
};
const summaryRecord = computed(() => {
if (orderedRecords.value.length === 0) return null;
return orderedRecords.value.reduce((best, current) => {
if (!best) return current;
const currentRank = getEducationRank(current.educationLevelCode);
const bestRank = getEducationRank(best.educationLevelCode);
if (currentRank > bestRank) return current;
if (currentRank < bestRank) return best;
const currentGrad = getTimestamp(current.rawGraduationDate) ?? Number.NEGATIVE_INFINITY;
const bestGrad = getTimestamp(best.rawGraduationDate) ?? Number.NEGATIVE_INFINITY;
return currentGrad >= bestGrad
? current
: best;
}, null);
});
const latestGraduationText = computed(() => {
if (orderedRecords.value.length === 0) return '未知';
const latest = orderedRecords.value.reduce((latestRecord, current) => {
if (!latestRecord) return current;
const currentGrad = getTimestamp(current.rawGraduationDate) ?? Number.NEGATIVE_INFINITY;
const latestGrad = getTimestamp(latestRecord.rawGraduationDate) ?? Number.NEGATIVE_INFINITY;
return currentGrad >= latestGrad
? current
: latestRecord;
}, null);
return latest?.graduationDate || '未知';
});
const hasData = computed(() => orderedRecords.value.length > 0);
</script>
<template>
<div v-if="hasData" class="card max-w-4xl mx-auto">
<div class="flex flex-col gap-6">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div class="flex items-center gap-3">
<div class="w-12 h-12 flex items-center justify-center">
<img :src="xlIcon" alt="学历信息" class="w-12 h-12" />
</div>
<div>
<h2 class="text-2xl font-bold text-gray-900">学历信息查询</h2>
</div>
</div>
<div class="flex flex-col items-start md:items-end gap-1">
<div class="text-lg font-semibold text-blue-600">
{{ orderedRecords.length }} 条记录
</div>
<div v-if="summaryRecord" class="summary-meta text-sm text-gray-500">
<span class="summary-meta__item">最高学历{{ summaryRecord.educationLevel }}</span>
<span v-if="latestGraduationText" class="summary-meta__divider">·</span>
<span class="summary-meta__item">最新毕业时间{{ latestGraduationText }}</span>
</div>
</div>
</div>
<div v-if="summaryRecord" class="summary-banner">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-6">
<div class="flex items-center gap-4">
<div class="w-14 h-14 rounded-full bg-white/80 flex items-center justify-center shadow-inner">
<img :src="xlIcon" alt="学历图标" class="w-10 h-10" />
</div>
<div>
<div class="text-xl font-semibold text-gray-900">{{ summaryRecord.studentName }}</div>
<div class="text-sm text-slate-600">身份证{{ summaryRecord.maskedIdNumber }}</div>
<div class="summary-highlight">
<span class="summary-highlight__badge">{{ summaryRecord.educationLevel }}</span>
<div class="summary-highlight__text flex flex-col gap-1">
<span class="flex items-center gap-2">
{{ summaryRecord.schoolName }}
<span v-if="summaryRecord.isUnknownSchool" class="unknown-hint">
<svg class="unknown-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
</span>
<span v-if="summaryRecord.isUnknownSchool" class="unknown-text">该学校名称信息未找到可能是学校已改名</span>
</div>
</div>
</div>
</div>
<!-- <div class="flex flex-wrap items-center gap-3">
<div class="summary-chip">
<span class="chip-label">入学时间</span>
<span class="chip-value">{{ summaryRecord.enrollmentDate }}</span>
</div>
<div class="summary-chip">
<span class="chip-label">毕业时间</span>
<span class="chip-value">{{ summaryRecord.graduationDate }}</span>
</div>
<div class="summary-chip">
<span class="chip-label">学习时长</span>
<span class="chip-value">{{ summaryRecord.studyDuration }}</span>
</div>
</div> -->
</div>
</div>
<div class="space-y-5">
<div v-for="record in orderedRecords" :key="record.index" class="record-card">
<div class="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4">
<div class="record-header">
<div class="record-index">
{{ record.index }}
</div>
<div class="record-title">
<div class="record-title__name flex flex-col gap-1">
<span class="flex items-center gap-2">
{{ record.schoolName }}
<span v-if="record.isUnknownSchool" class="unknown-hint">
<svg class="unknown-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
</span>
<span v-if="record.isUnknownSchool" class="unknown-text">该学校名称信息未找到可能是学校已改名</span>
</div>
<div class="record-title__meta" v-if="record.enrollmentDate !== '未知' || record.graduationDate !== '未知'">
<span v-if="record.enrollmentDate !== '未知'">{{ record.enrollmentDate }}</span>
<span v-if="record.enrollmentDate !== '未知' && record.graduationDate !== '未知'"> - </span>
<span v-if="record.graduationDate !== '未知'">{{ record.graduationDate }}</span>
</div>
</div>
</div>
<div class="flex flex-wrap items-center gap-3">
<span :class="['tag', getEducationLevelClass(record.educationLevelCode)]">
{{ record.educationLevel }}学历
</span>
<span :class="['tag', getLearningFormClass(record.learningFormCode)]">
学习形式{{ record.learningForm }}
</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6">
<div class="info-block">
<div class="info-icon">
<img :src="zymcIcon" alt="专业名称" class="w-7 h-7" />
</div>
<div>
<div class="info-label">专业名称</div>
<div class="info-value flex flex-col gap-1">
<span class="flex items-center gap-2">
{{ record.specialtyName }}
<span v-if="record.isUnknownSpecialty" class="unknown-hint">
<svg class="unknown-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
</span>
<span v-if="record.isUnknownSpecialty" class="unknown-text">该专业名称信息未找到可能是该学校专业已受到变动</span>
</div>
</div>
</div>
<div class="info-block">
<div class="info-icon">
<img :src="xxxsIcon" alt="学习形式" class="w-7 h-7" />
</div>
<div>
<div class="info-label">学习形式</div>
<div class="info-value">
{{ record.learningForm }}
</div>
</div>
</div>
<div class="info-block">
<div class="info-icon">
<img :src="xxlxIcon" alt="入学时间" class="w-7 h-7" />
</div>
<div>
<div class="info-label">入学时间</div>
<div class="info-value">{{ record.enrollmentDate }}</div>
</div>
</div>
<div class="info-block">
<div class="info-icon">
<img :src="bysjIcon" alt="毕业时间" class="w-7 h-7" />
</div>
<div>
<div class="info-label">毕业时间</div>
<div class="info-value">{{ record.graduationDate }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else class="card max-w-3xl mx-auto">
<div class="flex flex-col items-center py-12 text-center">
<div class="w-20 h-20 flex items-center justify-center mb-4">
<img :src="xlIcon" alt="学历图标" class="w-20 h-20 opacity-40" />
</div>
<h3 class="text-lg font-medium text-gray-900 mb-2">暂无学历记录</h3>
<p class="text-sm text-gray-500 max-w-md">
未查询到相关的学历信息可能是数据正在更新或尚未录入建议稍后重试或联系数据提供方确认
</p>
</div>
</div>
</template>
<style lang="scss" scoped>
.card {
padding: 1.5rem;
box-shadow: 0px 0px 24px 0px #3f3f3f0f;
border-radius: 12px;
background: white;
}
.summary-banner {
border-radius: 16px;
padding: 1.5rem;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(79, 70, 229, 0.12));
border: 1px solid rgba(59, 130, 246, 0.25);
}
.summary-chip {
display: inline-flex;
flex-direction: column;
gap: 0.15rem;
padding: 0.5rem 0.75rem;
border-radius: 0.75rem;
background-color: rgba(255, 255, 255, 0.9);
border: 1px solid rgba(148, 163, 184, 0.3);
}
.chip-label {
font-size: 0.7rem;
color: #64748b;
letter-spacing: 0.02em;
text-transform: uppercase;
}
.chip-value {
font-size: 0.95rem;
font-weight: 600;
color: #0f172a;
}
.summary-meta {
display: inline-flex;
align-items: center;
gap: 0.35rem;
flex-wrap: wrap;
}
.summary-meta__divider {
color: #94a3b8;
}
.summary-highlight {
margin-top: 0.35rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.summary-highlight__badge {
padding: 0.2rem 0.6rem;
border-radius: 9999px;
background: rgba(59, 130, 246, 0.12);
color: #2563eb;
font-size: 0.75rem;
font-weight: 600;
}
.summary-highlight__text {
font-size: 0.9rem;
color: #1e293b;
font-weight: 500;
}
.record-card {
position: relative;
padding: 1.5rem;
border-radius: 16px;
border: 1px solid rgba(226, 232, 240, 0.9);
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
box-shadow: 0 10px 25px rgba(15, 23, 42, 0.06);
transition: all 0.25s ease;
}
.record-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: linear-gradient(90deg, rgba(59, 130, 246, 0.75), rgba(129, 140, 248, 0.75));
border-radius: 12px 12px 0 0;
}
.record-card:hover {
transform: translateY(-4px);
box-shadow: 0 16px 35px rgba(59, 130, 246, 0.16);
}
.record-header {
display: flex;
align-items: flex-start;
gap: 1rem;
}
.record-index {
width: 3rem;
height: 3rem;
border-radius: 999px;
background: rgba(59, 130, 246, 0.18);
color: #2563eb;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.05rem;
flex-shrink: 0;
}
.record-title {
display: flex;
flex-direction: column;
gap: 0.2rem;
}
.record-title__name {
font-size: 1.125rem;
font-weight: 600;
color: #0f172a;
}
.record-title__meta {
font-size: 0.85rem;
color: #64748b;
}
.tag {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.4rem 0.85rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 600;
border-width: 1px;
border-style: solid;
}
.info-block {
display: flex;
gap: 0.75rem;
padding: 1rem;
border-radius: 12px;
background-color: rgba(248, 250, 252, 0.9);
border: 1px solid rgba(226, 232, 240, 0.8);
transition: border-color 0.2s ease, transform 0.2s ease;
}
.info-block:hover {
border-color: rgba(59, 130, 246, 0.3);
transform: translateY(-2px);
}
.info-icon {
width: 2.5rem;
height: 2.5rem;
border-radius: 0.75rem;
background: rgba(59, 130, 246, 0.12);
display: flex;
align-items: center;
justify-content: center;
}
.info-label {
font-size: 0.75rem;
color: #64748b;
margin-bottom: 0.25rem;
}
.info-value {
font-size: 1rem;
font-weight: 500;
color: #0f172a;
display: flex;
align-items: center;
gap: 0.5rem;
}
.unknown-hint {
display: inline-flex;
align-items: center;
}
.unknown-icon {
width: 1rem;
height: 1rem;
color: #f59e0b;
flex-shrink: 0;
}
.unknown-text {
font-size: 0.75rem;
color: #f59e0b;
line-height: 1.4;
margin-top: 0.125rem;
}
@media (max-width: 768px) {
.record-card {
padding: 1.25rem;
}
.info-block {
padding: 0.85rem;
}
}
</style>

View File

@@ -4,12 +4,12 @@
<p class="my-2">海南天远大数据科技有限公司</p>
<p class="indent-[2em]">
<!-- <span class="font-bold"> {{ signature ? userData.name : "____________" }}</span> -->
本人________拟向贵司申请大数据分析报告查询业务贵司需要了解本人相关状况用于查询大数据分析报告因此本人同意向贵司提供本人的姓名和手机号等个人信息并同意贵司向第三方包括但不限于西部数据交易有限公司传送上述信息第三方将使用上述信息核实信息真实情况查询信用记录并生成报告
本人________拟向贵司申请大数据分析报告查询业务贵司需要了解本人相关状况用于查询大数据分析报告因此本人同意向贵司提供本人的姓名和手机号等个人信息并同意贵司向第三方传送上述信息第三方将使用上述信息核实信息真实情况查询信用记录并生成报告
</p>
<p class="mt-2 font-bold">授权内容如下</p>
<ol class="list-decimal pl-6">
<li>
贵司向依法成立的第三方服务商包括但不限于西部数据交易有限公司根据本人提交的信息进行核实并有权通过前述第三方服务机构查询使用本人的身份信息设备信息运营商信息等查询本人信息包括但不限于学历婚姻资产状况及对信息主体产生负面影响的不良信息出具相关报告
贵司向依法成立的第三方服务商根据本人提交的信息进行核实并有权通过前述第三方服务机构查询使用本人的身份信息设备信息运营商信息等查询本人信息包括但不限于学历婚姻资产状况及对信息主体产生负面影响的不良信息出具相关报告
</li>
<li>
依法成立的第三方服务商查询或核实搜集保存处理共享使用含合法业务应用本人相关数据且不再另行告知本人但法律法规监管政策禁止的除外

View File

@@ -1,6 +1,7 @@
<script setup>
const router = useRouter();
import { storeToRefs } from "pinia";
import { showConfirmDialog } from "vant";
import SectionTitle from "@/components/SectionTitle.vue";
const agentStore = useAgentStore();
@@ -11,7 +12,25 @@ import loanCheckIcon from "@/assets/images/index/loan_check_bg.png";
import marriageRiskIcon from "@/assets/images/index/marriage_risk_bg.png";
import housekeepingRiskIcon from "@/assets/images/index/housekeeping_risk_bg.png";
import preLoanRiskIcon from "@/assets/images/index/preloan_risk_bg.png";
function toInquire(name) {
if (name === "marriage") {
showConfirmDialog({
title: "婚恋风险查询",
message: "是否进入天远查进行婚恋查询?",
confirmButtonText: "进入",
cancelButtonText: "取消",
})
.then(() => {
// 在当前标签页打开不新开tab
window.location.href = "https://www.tianyuancha.cn";
})
.catch(() => {
// 取消则继续后续逻辑
router.push(`/inquire/marriage`);
});
return; // 阻止继续跳转,等待 dialog 回调
}
router.push(`/inquire/${name}`);
}
function toInvitation() {
@@ -76,7 +95,7 @@ const riskServices = ref([
goColor: "#66cccc",
},
{
title: "贷前背调",
title: "贷前风险",
name: "preloanbackgroundcheck",
subtitle: "信用评估,放款无忧",
bg: loanCheckIcon,
@@ -143,7 +162,7 @@ const toBigData = () => {
:style="`background: url(${service.bg}) no-repeat; background-size: cover; background-position: center;`"
@click=" toInquire(service.name)">
<div class="min-h-18 flex flex-col items-start px-1">
<div class="mt-1 max-w-max text-left text-gray-600 font-bold text-md">
<div class="mt-1 max-w-max text-left text-gray-600 font-bold">
{{ service.title }}
</div>
<!-- <div class="max-w-max text-left text-xs text-gray-600">
@@ -165,7 +184,7 @@ const toBigData = () => {
:style="`background: url(${service.bg}) no-repeat; background-size: cover; background-position: center;`"
@click="toInquire(service.name)">
<div class="min-h-18 flex flex-col items-start px-1">
<div class="mt-1 max-w-max text-left text-gray-600 font-bold text-sm">
<div class="mt-1 max-w-max text-left text-gray-600 font-bold">
{{ service.title }}
</div>
<!-- <div class="max-w-max text-left text-xs text-gray-600">