This commit is contained in:
liangzai 2025-06-03 20:44:50 +08:00
parent 1eaf3e810e
commit 526370bb41
12 changed files with 421 additions and 245 deletions

View File

@ -8,13 +8,14 @@
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<title>天远查 - 婚恋评估、司法涉诉查询、婚姻状态、判决书查询工具</title>
<meta
name="description"
content="天远查依托大数据技术,精准查询司法涉诉风险!AI律师智能分析企业/个人司法风险,支持婚姻状况/婚姻状态/判决书/被执行人/老赖/失信人/限高查询,并提供身份/银行卡/手机号码一键核验!AI律师在线咨询+风险报告。多维防控财产/信用/身份风险!"
content="天远查依托大数据技术,精准查询司法涉诉风险!个人司法风险,支持婚姻状况/婚姻状态/判决书/被执行人/老赖/失信人/限高查询,并提供身份/银行卡/手机号码一键核验!多维防控财产/信用/身份风险!"
/>
<meta
name="keywords"
content="婚恋评估, 司法涉诉查询, 判决书查询, 婚姻状态查询, 老赖, 被执行人, 限高, 失信人, 个人涉诉查询, 企业涉诉查询, 名下车辆核验, 车辆核验, 婚姻状况, 风险报告, 法律风险, 信用风险, 银行卡黑名单, 手机身份证核验, 学历核验, AI律师, 在线查询"
content="婚恋评估, 司法涉诉查询, 判决书查询, 婚姻状态查询, 老赖, 被执行人, 限高, 失信人, 个人涉诉查询, 企业涉诉查询, 名下车辆核验, 车辆核验, 婚姻状况, 风险报告, 法律风险, 信用风险, 银行卡黑名单, 手机身份证核验, 学历核验, 在线查询"
/>
<meta name="author" content="天远查" />
<meta

View File

@ -11,6 +11,7 @@ declare global {
const VanTabbarItem: typeof import('vant/es')['TabbarItem']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const clearPromotionSession: typeof import('./composables/usePromotion.js')['clearPromotionSession']
const closeToast: typeof import('vant/es')['closeToast']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
@ -38,7 +39,9 @@ declare global {
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const getPromotionSession: typeof import('./composables/usePromotion.js')['getPromotionSession']
const h: typeof import('vue')['h']
const handlePromotionLink: typeof import('./composables/usePromotion.js')['handlePromotionLink']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const injectLocal: typeof import('@vueuse/core')['injectLocal']

View File

@ -19,6 +19,8 @@ const useApiFetch = createFetch({
// 在请求前添加通用的 Header例如 Authorization
const token = localStorage.getItem("token");
const webviewEnv = localStorage.getItem("webview_env");
const promoteKey = sessionStorage.getItem("promote_key");
if (webviewEnv) {
platform = webviewEnv;
}
@ -33,6 +35,13 @@ const useApiFetch = createFetch({
Authorization: `${token}`,
};
}
// 如果有推广key添加到请求头
if (promoteKey) {
options.headers = {
...options.headers,
"X-Promote-Key": promoteKey,
};
}
return { options };
},
async afterFetch({ data, response }) {

View File

@ -0,0 +1,79 @@
// 记录推广链接访问
async function recordPromotionVisit(shortUrl) {
try {
const { data, error } = await useApiFetch(`/admin/promotion/link/record/${shortUrl}`)
.get()
.json();
if (error.value) {
throw new Error(error.value);
}
return data.value;
} catch (error) {
console.error("记录推广访问失败:", error);
throw error;
}
}
// 处理会话存储
function handleSessionStorage(promoteKey) {
if (!promoteKey) return;
try {
// 存储推广key
sessionStorage.setItem('promote_key', promoteKey);
// 存储时间戳,用于判断会话是否过期
sessionStorage.setItem('promote_timestamp', Date.now().toString());
} catch (error) {
console.error("存储会话信息失败:", error);
throw error;
}
}
// 统一的入口函数
export function handlePromotionLink(shortUrl) {
// 使用 Promise.resolve().then 确保异步执行
Promise.resolve().then(async () => {
try {
const response = await recordPromotionVisit(shortUrl);
console.log(response);
if (response.code === 200 && response.data.success) {
handleSessionStorage(shortUrl);
}
} catch (error) {
// 错误已经在各自的函数中处理,这里只做日志记录
console.error("推广链接处理失败:", error);
}
});
}
// 获取会话数据
export function getPromotionSession() {
try {
const promoteKey = sessionStorage.getItem('promote_key');
const timestamp = sessionStorage.getItem('promote_timestamp');
// 检查会话是否过期30天过期
const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000;
if (timestamp && Date.now() - parseInt(timestamp) > THIRTY_DAYS) {
clearPromotionSession();
return null;
}
return promoteKey;
} catch (error) {
console.error("获取会话信息失败:", error);
return null;
}
}
// 清除会话数据
export function clearPromotionSession() {
try {
sessionStorage.removeItem('promote_key');
sessionStorage.removeItem('promote_timestamp');
} catch (error) {
console.error("清除会话信息失败:", error);
}
}

View File

@ -43,6 +43,14 @@
<div>广西福铭网络科技有限公司版权所有</div>
</div>
</div>
<!-- <meta
name="description"
content="天远查依托大数据技术精准查询司法涉诉风险AI律师智能分析企业/个人司法风险,支持婚姻状况/婚姻状态/判决书/被执行人/老赖/失信人/限高查询,并提供身份/银行卡/手机号码一键核验AI律师在线咨询+风险报告。多维防控财产/信用/身份风险!"
/>
<meta
name="keywords"
content="婚恋评估, 司法涉诉查询, 判决书查询, 婚姻状态查询, 老赖, 被执行人, 限高, 失信人, 个人涉诉查询, 企业涉诉查询, 名下车辆核验, 车辆核验, 婚姻状况, 风险报告, 法律风险, 信用风险, 银行卡黑名单, 手机身份证核验, 学历核验, AI律师, 在线查询"
/> -->
</template>
<script setup>
@ -54,7 +62,7 @@ const route = useRoute();
const tabbar = ref("index");
const menu = reactive([
{ title: "首页", icon: "home-o", name: "index" },
{ title: "AI律师", icon: "chat-o", name: "ai" },
// { title: "AI", icon: "chat-o", name: "ai" },
{ title: "我的", icon: "user-o", name: "me" },
{ title: "推广代理", icon: "balance-o", name: "promote" },
]);

View File

@ -4,9 +4,22 @@ import GlobalLayout from "@/layouts/GlobalLayout.vue";
import HomeLayout from "@/layouts/HomeLayout.vue";
import PageLayout from "@/layouts/PageLayout.vue";
import index from "@/views/index.vue";
import { handlePromotionLink } from "@/composables/usePromotion";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/p/:url",
name: "promotionLink",
component: () => import("@/views/PromotionLink.vue"),
beforeEnter: (to, from, next) => {
// 调用处理函数,不等待其完成
handlePromotionLink(to.params.url);
// 直接跳转到首页
next('/');
}
},
{
path: "/",
component: GlobalLayout, // 使用 Layout 作为父组件

View File

@ -58,15 +58,25 @@ const getReferenceDate = computed(() => {
//
function getActualMonthYear(monthsBack) {
const refDate = new Date(getReferenceDate.value);
refDate.setMonth(refDate.getMonth() - monthsBack);
const month = monthsBack.replace("m", "");
if (month === "12") {
return "近1年";
}
return `${month}`;
// const refDate = new Date(getReferenceDate.value);
// refDate.setMonth(refDate.getMonth() - monthsBack);
const year = refDate.getFullYear();
const month = refDate.getMonth() + 1; // JavaScript0
// const year = refDate.getFullYear();
// const month = refDate.getMonth() + 1; // JavaScript0
return `${year}${month}`;
// return `${year}${month}`;
}
function getActualMonthYearT(monthsBack) {
if (monthsBack === "t0") {
return "1年内";
}
return `${monthsBack.replace("t", "")}`;
}
//
function getLevelAmount(level) {
const levelNum = Number(level) || 1;
@ -85,28 +95,17 @@ function getLevelRange(level) {
//
const monthlyBorrowData = computed(() => {
const months = [
"t0",
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7",
"t8",
"t9",
"t10",
"t11",
];
const months = ["m1", "m3", "m6", "m9", "m12"];
const prefix = `tl_${dataType.value}`;
return months
.map((month, index) => {
const borrowKey = `${prefix}_${month}_nbank_lendamt`;
const borrowKey = `${prefix}_${month}_nbank_passlendamt`;
const borrowAmount = getLevelAmount(data[borrowKey]);
console.log(borrowKey, borrowAmount);
return {
month: getActualMonthYear(index),
month: getActualMonthYear(month),
amount: borrowAmount,
displayAmount: formatAmount(borrowAmount),
level: data[borrowKey] || "0",
@ -115,23 +114,9 @@ const monthlyBorrowData = computed(() => {
})
.reverse();
});
//
//
const monthlyRepayData = computed(() => {
const months = [
"t0",
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7",
"t8",
"t9",
"t10",
"t11",
];
const months = ["m1", "m3", "m6", "m9", "m12"];
const prefix = `tl_${dataType.value}`;
return months
@ -139,7 +124,7 @@ const monthlyRepayData = computed(() => {
const repayKey = `${prefix}_${month}_nbank_reamt`;
const repayAmount = getLevelAmount(data[repayKey]);
return {
month: getActualMonthYear(index),
month: getActualMonthYear(month),
amount: repayAmount,
displayAmount: formatAmount(repayAmount),
level: data[repayKey] || "0",
@ -151,20 +136,41 @@ const monthlyRepayData = computed(() => {
//
const monthlyInstitutionData = computed(() => {
const months = [
"t0",
"t1",
"t2",
"t3",
"t4",
"t5",
"t6",
"t7",
"t8",
"t9",
"t10",
"t11",
];
const months = ["m1", "m3", "m6", "m9", "m12"];
const prefix = `tl_${dataType.value}`;
return months
.map((month, index) => {
const orgKey = `${prefix}_${month}_nbank_passorg`;
const numKey = `${prefix}_${month}_nbank_passnum`;
const borrowKey = `${prefix}_${month}_nbank_passlendamt`;
const repayKey = `${prefix}_${month}_nbank_reamt`;
const orgCount = Number(data[orgKey] || 0);
const loanCount = Number(data[numKey] || 0);
const borrowAmount = getLevelAmount(data[borrowKey]);
const repayAmount = getLevelAmount(data[repayKey]);
let ratio = 0;
if (borrowAmount > 0) {
ratio = ((repayAmount / borrowAmount) * 100).toFixed(2);
}
return {
month: getActualMonthYear(month),
orgCount,
loanCount,
borrowAmount: formatAmount(borrowAmount),
repayAmount: formatAmount(repayAmount),
ratio: `${ratio}%`,
};
})
.reverse();
});
// 36912
const recentBorrowTrends = computed(() => {
const months = ["t0"];
const prefix = `tl_${dataType.value}`;
return months
@ -181,14 +187,11 @@ const monthlyInstitutionData = computed(() => {
let ratio = 0;
if (borrowAmount > 0) {
ratio = (
((borrowAmount - repayAmount) / borrowAmount) *
100
).toFixed(2);
ratio = ((repayAmount / borrowAmount) * 100).toFixed(2);
}
return {
month: getActualMonthYear(index),
month: getActualMonthYearT(month),
orgCount,
loanCount,
borrowAmount: formatAmount(borrowAmount),
@ -199,37 +202,6 @@ const monthlyInstitutionData = computed(() => {
.reverse();
});
// 36912
const recentBorrowTrends = computed(() => {
const periods = ["m3", "m6", "m9", "m12"];
const prefix = `tl_${dataType.value}`;
return periods.map((period) => {
const amountKey = `${prefix}_${period}_nbank_passlendamt`;
const numKey = `${prefix}_${period}_nbank_passnum`;
const orgKey = `${prefix}_${period}_nbank_passorg`;
//
const monthsBack = Number(period.replace("m", ""));
const startDate = new Date(getReferenceDate.value);
startDate.setMonth(startDate.getMonth() - monthsBack);
const startYear = startDate.getFullYear();
const startMonth = startDate.getMonth() + 1;
//
const periodDesc = `${startYear}${startMonth}月至今`;
return {
period: periodDesc,
amount: getLevelAmount(data[amountKey]),
level: data[amountKey] || "0",
levelRange: getLevelRange(data[amountKey]),
loanCount: Number(data[numKey] || 0),
orgCount: Number(data[orgKey] || 0),
};
});
});
//
const lastLoanInfo = computed(() => {
const prefix = `tl_${dataType.value}`;
@ -265,71 +237,59 @@ function formatAmount(amount) {
const behaviorSummary = computed(() => {
const prefix = `tl_${dataType.value}`;
//
const totalBorrowAmount = monthlyBorrowData.value.reduce(
(sum, item) => sum + item.amount,
0
);
const avgBorrowAmount = totalBorrowAmount / 12;
//
const yearData = recentBorrowTrends.value[0];
//
const totalRepayAmount = monthlyRepayData.value.reduce(
(sum, item) => sum + item.amount,
0
);
const avgRepayAmount = totalRepayAmount / 12;
//
const avgMonthlyApplications = (yearData.loanCount / 12).toFixed(1);
//
const maxBorrowAmount = Math.max(
...monthlyBorrowData.value.map((item) => item.amount)
);
const maxRepayAmount = Math.max(
...monthlyRepayData.value.map((item) => item.amount)
);
//
const totalBorrowAmount = Number(yearData.borrowAmount.replace(/,/g, ""));
const avgMonthlyAmount = (totalBorrowAmount / 12).toFixed(0);
//
const totalOrgCount = monthlyInstitutionData.value.reduce(
(sum, item) => sum + item.orgCount,
0
);
const avgOrgCount = (totalOrgCount / 12).toFixed(1);
//
const totalRepayAmount = Number(yearData.repayAmount.replace(/,/g, ""));
const avgMonthlyRepay = (totalRepayAmount / 12).toFixed(0);
//
const repayRatio = avgRepayAmount / avgBorrowAmount;
//
const repayRatio =
totalBorrowAmount > 0
? ((totalRepayAmount / totalBorrowAmount) * 100).toFixed(1)
: 0;
//
const borrowTrend = recentBorrowTrends.value.map((item) => item.amount);
const isBorrowIncreasing = borrowTrend[3] > borrowTrend[0];
//
//
let riskLevel = "低";
let riskDesc = "借贷行为健康,按时还款,借贷金额合理";
let riskDesc = "借贷行为健康,借贷金额合理";
if (repayRatio < 0.5) {
//
if (yearData.orgCount > 5) {
riskLevel = "高";
riskDesc = "还款比例低,可能存在较大的贷款负担";
} else if (repayRatio < 0.8) {
riskDesc = "多头借贷风险较高,借贷机构过多";
} else if (yearData.orgCount > 3) {
riskLevel = "中";
riskDesc = "存在一定的贷款负担,还款压力中等";
riskDesc = "存在多头借贷风险,借贷机构较多";
}
if (Number(data[`${prefix}_m12_nbank_passorg`]) > 3) {
//
if (avgMonthlyApplications > 3) {
riskLevel = riskLevel === "低" ? "中" : "高";
riskDesc += ",借贷机构较多,可能存在多头借贷风险";
riskDesc += ",月均申请次数较多";
}
//
if (repayRatio < 50) {
riskLevel = riskLevel === "低" ? "中" : "高";
riskDesc += ",还款比例较低";
}
return {
avgBorrowAmount: formatAmount(avgBorrowAmount.toFixed(0)),
avgRepayAmount: formatAmount(avgRepayAmount.toFixed(0)),
maxBorrowAmount: formatAmount(maxBorrowAmount),
maxRepayAmount: formatAmount(maxRepayAmount),
totalBorrowAmount: formatAmount(totalBorrowAmount),
totalRepayAmount: formatAmount(totalRepayAmount),
avgOrgCount,
repayRatio: (repayRatio * 100).toFixed(1) + "%",
trendDesc: isBorrowIncreasing
? "借贷金额呈上升趋势"
: "借贷金额呈下降趋势",
totalApplications: yearData.loanCount,
totalOrgs: yearData.orgCount,
totalAmount: formatAmount(totalBorrowAmount),
avgMonthlyApplications,
avgMonthlyAmount: formatAmount(avgMonthlyAmount),
avgMonthlyRepay: formatAmount(avgMonthlyRepay),
repayRatio: `${repayRatio}%`,
riskLevel,
riskDesc,
};
@ -346,7 +306,7 @@ function drawBorrowChart() {
const chartData = monthlyBorrowData.value;
const option = {
title: {
text: "月度借贷金额(元)",
text: "月度审批额度(元)",
left: "center",
textStyle: {
fontWeight: "bold",
@ -378,8 +338,10 @@ function drawBorrowChart() {
type: "category",
data: chartData.map((item) => item.month),
axisLabel: {
rotate: 45, //
interval: 0,
rotate: 45,
fontWeight: "bold",
margin: 15,
},
axisLine: {
lineStyle: {
@ -402,7 +364,7 @@ function drawBorrowChart() {
},
series: [
{
name: "借贷金额",
name: "审批额度",
type: "bar",
data: chartData.map((item) => ({
value: item.amount,
@ -440,7 +402,7 @@ function drawBorrowChart() {
borrowChartInstance.value.setOption(option);
}
//
//
function drawRepayChart() {
if (!repayChartRef.value) return;
@ -451,7 +413,7 @@ function drawRepayChart() {
const chartData = monthlyRepayData.value;
const option = {
title: {
text: "月度金额(元)",
text: "月度还金额(元)",
left: "center",
textStyle: {
fontWeight: "bold",
@ -476,15 +438,17 @@ function drawRepayChart() {
grid: {
left: "5%",
right: "5%",
bottom: "0%",
bottom: "15%",
containLabel: true,
},
xAxis: {
type: "category",
data: chartData.map((item) => item.month),
axisLabel: {
rotate: 45, //
interval: 0,
rotate: 45,
fontWeight: "bold",
margin: 15,
},
axisLine: {
lineStyle: {
@ -507,7 +471,7 @@ function drawRepayChart() {
},
series: [
{
name: "金额",
name: "还金额",
type: "bar",
data: chartData.map((item) => ({
value: item.amount,
@ -545,7 +509,7 @@ function drawRepayChart() {
repayChartInstance.value.setOption(option);
}
//
//
function drawTrendChart() {
if (!trendChartRef.value) return;
@ -558,7 +522,7 @@ function drawTrendChart() {
const option = {
title: {
text: "借贷与还款金额趋势对比",
text: "审批额度与应还金额趋势对比",
left: "center",
textStyle: {
fontWeight: "bold",
@ -577,7 +541,7 @@ function drawTrendChart() {
shadowColor: "rgba(0, 0, 0, 0.2)",
},
legend: {
data: ["借贷金额", "还款金额"],
data: ["审批额度", "应还金额"],
top: 30,
textStyle: {
fontWeight: "bold",
@ -586,15 +550,17 @@ function drawTrendChart() {
grid: {
left: "5%",
right: "5%",
bottom: "0%",
bottom: "15%",
containLabel: true,
},
xAxis: {
type: "category",
data: borrowData.map((item) => item.month),
axisLabel: {
rotate: 45, //
interval: 0,
rotate: 45,
fontWeight: "bold",
margin: 15,
},
axisLine: {
lineStyle: {
@ -617,7 +583,7 @@ function drawTrendChart() {
},
series: [
{
name: "借贷金额",
name: "审批额度",
type: "line",
data: borrowData.map((item) => item.amount),
smooth: true,
@ -641,7 +607,7 @@ function drawTrendChart() {
},
},
{
name: "金额",
name: "还金额",
type: "line",
data: repayData.map((item) => item.amount),
smooth: true,
@ -727,7 +693,7 @@ onUnmounted(() => {
借贷行为分析报告
</h2>
<p class="text-sm text-gray-600 ml-6">
本报告统计借贷金额与还款情况帮助评估信贷风险
本报告统计审批额度与应还情况帮助评估信贷风险
</p>
</div>
<div
@ -855,19 +821,19 @@ onUnmounted(() => {
</div>
<!-- 借贷金额图表 -->
<LTitle title="月度借贷金额" type="blue-green" />
<LTitle title="近期审批额度" type="blue-green" />
<div ref="borrowChartRef" class="chart-container"></div>
<!-- 金额图表 -->
<LTitle title="月度金额" type="blue-green" />
<div ref="repayChartRef" class="chart-container"></div>
<!-- 还金额图表 -->
<!--<LTitle title="月度还金额" type="blue-green" />
<div ref="repayChartRef" class="chart-container"></div> -->
<!-- 借贷趋势对比 -->
<LTitle title="借贷与还款趋势对比" type="blue-green" />
<div ref="trendChartRef" class="chart-container"></div>
<!-- 借贷还趋势对比 -->
<!--<LTitle title="审批额度与应还金额趋势对比" type="blue-green" />
<div ref="trendChartRef" class="chart-container"></div> -->
<!-- 借贷机构数和借还差值比例表格 -->
<LTitle title="月度借贷机构数与借还比例" type="blue-green" />
<LTitle title="近期通过借贷审批情况" type="blue-green" />
<div class="overflow-x-auto">
<LTable :data="monthlyInstitutionData" type="blue-green">
<template #header>
@ -881,13 +847,60 @@ onUnmounted(() => {
借贷次数
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
借贷金额
审批额度
</th>
<!-- <th class="border px-1 py-2 text-xs min-w-[15%]">
应还金额
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
还款金额
应还比例
</th> -->
</template>
<template #default="{ row }">
<td class="border px-1 py-2 text-xs">
{{ row.month }}
</td>
<td class="border px-1 py-2 text-xs text-center">
{{ row.orgCount }}
</td>
<td class="border px-1 py-2 text-xs text-center">
{{ row.loanCount }}
</td>
<td class="border px-1 py-2 text-xs text-center">
{{ row.borrowAmount }}
</td>
<!-- <td class="border px-1 py-2 text-xs text-center">
{{ row.repayAmount }}
</td>
<td class="border px-1 py-2 text-xs text-center">
{{ row.ratio }}
</td> -->
</template>
</LTable>
</div>
<!-- 近期借贷趋势表格 -->
<LTitle title="近1年借贷情况" type="blue-green" />
<div class="overflow-x-auto">
<LTable :data="recentBorrowTrends" type="blue-green">
<template #header>
<th class="border px-1 py-2 text-xs min-w-[25%]">
时间
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
还款比例
借贷机构数
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
借贷次数
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
审批额度
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
应还金额
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
审批与应还比例
</th>
</template>
<template #default="{ row }">
@ -913,76 +926,35 @@ onUnmounted(() => {
</LTable>
</div>
<!-- 近期借贷趋势表格 -->
<LTitle title="近期借贷趋势" type="blue-green" />
<div class="overflow-x-auto">
<LTable :data="recentBorrowTrends" type="blue-green">
<template #header>
<th class="border px-1 py-2 text-xs min-w-[25%]">
时间段
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
借贷金额
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
借贷次数
</th>
<th class="border px-1 py-2 text-xs min-w-[15%]">
借贷机构数
</th>
</template>
<template #default="{ row }">
<td class="border px-1 py-2 text-xs">
{{ row.period }}
</td>
<td class="border px-1 py-2 text-xs">
{{ row.levelRange }}
</td>
<td class="border px-1 py-2 text-xs text-center">
{{ row.loanCount }}
</td>
<td class="border px-1 py-2 text-xs text-center">
{{ row.orgCount }}
</td>
</template>
</LTable>
</div>
<!-- 借贷行为总结 -->
<LTitle title="借贷行为总结分析" type="blue-green" />
<div class="summary-container bg-blue-50 p-4 rounded-md">
<div class="text-xs text-gray-500 mb-2">
数据时间范围:
{{
monthlyBorrowData[monthlyBorrowData.length - 1]
?.month || "未知"
}}
-
{{ monthlyBorrowData[0]?.month || "未知" }}
数据时间范围: 近1年
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
<div class="info-card p-3 bg-white rounded shadow-sm">
<div class="text-sm text-gray-500">平均月借贷金额</div>
<div class="text-sm text-gray-500">总申请次数</div>
<div class="text-lg font-semibold">
{{ behaviorSummary.avgBorrowAmount }}
{{ behaviorSummary.totalApplications }}
</div>
</div>
<div class="info-card p-3 bg-white rounded shadow-sm">
<div class="text-sm text-gray-500">平均月还款金额</div>
<div class="text-sm text-gray-500">借贷机构数</div>
<div class="text-lg font-semibold">
{{ behaviorSummary.avgRepayAmount }}
{{ behaviorSummary.totalOrgs }}
</div>
</div>
<div class="info-card p-3 bg-white rounded shadow-sm">
<div class="text-sm text-gray-500">借贷金额</div>
<div class="text-sm text-gray-500">总审批额度</div>
<div class="text-lg font-semibold">
{{ behaviorSummary.totalBorrowAmount }}
{{ behaviorSummary.totalAmount }}
</div>
</div>
<div class="info-card p-3 bg-white rounded shadow-sm">
<div class="text-sm text-gray-500">平均借贷机构</div>
<div class="text-sm text-gray-500">月均申请次数</div>
<div class="text-lg font-semibold">
{{ behaviorSummary.avgOrgCount }}
{{ behaviorSummary.avgMonthlyApplications }}
</div>
</div>
</div>
@ -1003,7 +975,14 @@ onUnmounted(() => {
>
</div>
<div class="text-gray-700">
<p>· 借贷趋势: {{ behaviorSummary.trendDesc }}</p>
<p>
· 月均审批额度:
{{ behaviorSummary.avgMonthlyAmount }}
</p>
<p>
· 月均应还金额:
{{ behaviorSummary.avgMonthlyRepay }}
</p>
<p>· 还款比例: {{ behaviorSummary.repayRatio }}</p>
<p>· {{ behaviorSummary.riskDesc }}</p>
</div>

View File

@ -9,6 +9,11 @@ const featureMap = {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIDV044.vue")),
},
G09XM02: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIDV044.vue")),
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
G27BJ05: {
name: "借贷申请记录",
component: defineAsyncComponent(() =>

View File

@ -0,0 +1,42 @@
<template>
<div></div>
</template>
<script setup>
//
</script>
<style scoped>
.promotion-link-container {
min-height: 100vh;
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
}
.loading-wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid #f3f3f3;
border-top: 3px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -9,7 +9,12 @@ const featureMap = {
IDV044: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIDV044.vue")),
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异、离异冷静期。如您对查询结果有疑问,请联系客服反馈。',
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
G09XM02: {
name: "婚姻状态",
component: defineAsyncComponent(() => import("@/ui/CIDV044.vue")),
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
G27BJ05: {
name: "借贷申请记录",

View File

@ -1,19 +1,40 @@
<template>
<div class="bg-gradient-to-b from-[#aeceff] to-white min-h-screen relative">
<!-- banner -->
<div class="w-full flex justify-center" style="clip-path: ellipse(100% 95% at 50% 0%)">
<img src="@/assets/images/hygj_banner.png" alt="核验工具" class="w-full h-auto" />
<div
class="w-full flex justify-center"
style="clip-path: ellipse(100% 95% at 50% 0%)"
>
<img
src="@/assets/images/hygj_banner.png"
alt="核验工具"
class="w-full h-auto"
/>
</div>
<div class="p-6 -my-24 z-1000 absolute">
<!-- 分类功能菜单 -->
<van-skeleton :row="5" :loading="isFetching">
<div v-for="(items, category) in categorizedMenuItems" :key="category" class="card mb-4">
<h2 class="text-lg font-bold text-blue-500 mb-3">{{ category }}</h2>
<div
v-for="(items, category) in categorizedMenuItems"
:key="category"
class="card mb-4"
>
<h2 class="text-lg font-bold text-blue-500 mb-3">
{{ category }}
</h2>
<div class="grid grid-cols-4 gap-4">
<div v-for="(item, index) in items" :key="index" class="flex flex-col items-center"
@click="toInquire(item.product)">
<div
v-for="(item, index) in items"
:key="index"
class="flex flex-col items-center"
@click="toInquire(item.product)"
>
<div class="bg-slate-100 rounded-full p-4">
<img :src="item.icon" :alt="item.title" class="w-10 h-10" />
<img
:src="item.icon"
:alt="item.title"
class="w-10 h-10"
/>
</div>
<p class="mt-2 text-sm text-center font-semibold">
{{ item.title }}
@ -24,7 +45,10 @@
</van-skeleton>
<!-- 详情文本 -->
<div class="card mt-4" v-if="Object.keys(categorizedMenuItems).length !== 0">
<div
class="card mt-4"
v-if="Object.keys(categorizedMenuItems).length !== 0"
>
<h2 class="text-lg font-bold text-blue-500 mb-4">
核验工具服务
</h2>
@ -32,9 +56,17 @@
本平台提供全方位核验工具服务助您全面防范风险功能包括
</p>
<van-skeleton :row="3" :loading="isFetching">
<div v-for="(items, category) in categorizedMenuItems" :key="category" class="mt-4">
<h3 class="font-bold text-md text-gray-700 mb-2">{{ category }}</h3>
<ul class="list-disc list-inside space-y-2 text-gray-600">
<div
v-for="(items, category) in categorizedMenuItems"
:key="category"
class="mt-4"
>
<h3 class="font-bold text-md text-gray-700 mb-2">
{{ category }}
</h3>
<ul
class="list-disc list-inside space-y-2 text-gray-600"
>
<li v-for="(item, index) in items" :key="index">
<strong>{{ item.title }}</strong>
{{ item.description }}
@ -56,16 +88,16 @@ const { fetchRenderData, categorizedMenuItems, isFetching } = useMenuItems();
const toInquire = (product) => {
router.push("/inquire/" + product);
};
const webviewEnv = localStorage.getItem('webview_env')
const webviewEnv = localStorage.getItem("webview_env");
onMounted(() => {
if (webviewEnv) {
router.replace("/ai"); // 使 router.push("/target-page");
}
// if (webviewEnv) {
// router.replace("/ai"); // 使 router.push("/target-page");
// }
fetchRenderData("verify");
});
const show = ref(false)
const show = ref(false);
</script>
<style scoped></style>

View File

@ -14,10 +14,10 @@ export default defineConfig({
port: 5678, // 自定义端口号,可选
strictPort: true, // 如果端口被占用则抛出错误而不是使用下一个可用端口
proxy: {
'/api/v1': {
target: 'https://www.tianyuancha.cn', // 本地接口地址
changeOrigin: true,
},
// '/api/v1': {
// target: 'https://www.tianyuancha.cn', // 本地接口地址
// changeOrigin: true,
// },
"/api/v1/chat": {
target: "https://www.tianyuancha.cn", // 本地接口地址
@ -25,10 +25,10 @@ export default defineConfig({
// rewrite: (path) => path.replace(/^\/api\/v1\/chat/, '/chat')
},
// "/api/v1": {
// target: "https://6m4685017o.goho.co", // 本地接口地址
// changeOrigin: true,
// },
"/api/v1": {
target: "https://6m4685017o.goho.co", // 本地接口地址
changeOrigin: true,
},
},
},
plugins: [