1
@ -16,7 +16,7 @@
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="婚恋评估, 司法涉诉查询, 判决书查询, 婚姻状态查询, 失信人, 司法涉诉查询, 企业涉诉查询, 名下车辆核验, 车辆核验, 婚姻报告, 法律风险, 信用风险, 银行卡黑名单, 手机身份证核验, 学历核验, AI律师"
|
||||
content="婚恋评估, 司法涉诉查询, 判决书查询, 婚姻状态查询, 失信人, 司法涉诉查询, 企业涉诉查询, 名下车辆核验, 车辆核验, 婚姻报告, 法律风险, 信用风险, 银行卡黑名单, 手机身份证核验, 学历核验, 智能助手"
|
||||
/>
|
||||
<meta name="author" content="天远数据" />
|
||||
<meta
|
||||
|
BIN
public/image/help/13.jpg
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
public/image/help/14.jpg
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
public/image/help/15.jpg
Normal file
After Width: | Height: | Size: 204 KiB |
BIN
public/image/help/18.jpg
Normal file
After Width: | Height: | Size: 864 KiB |
BIN
public/image/help/19.jpg
Normal file
After Width: | Height: | Size: 619 KiB |
BIN
public/image/help/20.jpg
Normal file
After Width: | Height: | Size: 558 KiB |
BIN
public/image/help/21.jpg
Normal file
After Width: | Height: | Size: 719 KiB |
BIN
public/image/help/22.jpg
Normal file
After Width: | Height: | Size: 878 KiB |
BIN
public/image/help/23.jpg
Normal file
After Width: | Height: | Size: 929 KiB |
BIN
public/image/help/24.jpg
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
public/image/help/25.jpg
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
public/image/help/invite-earnings.jpg
Normal file
After Width: | Height: | Size: 886 KiB |
BIN
public/image/help/invite-step1.jpg
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
public/image/help/invite-step2.jpg
Normal file
After Width: | Height: | Size: 258 KiB |
BIN
public/image/help/invite-step3.jpg
Normal file
After Width: | Height: | Size: 213 KiB |
BIN
public/image/help/report-calculation.jpg
Normal file
After Width: | Height: | Size: 367 KiB |
BIN
public/image/help/report-cost.jpg
Normal file
After Width: | Height: | Size: 307 KiB |
BIN
public/image/help/report-efficiency.jpg
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
public/image/help/report-push.jpg
Normal file
After Width: | Height: | Size: 940 KiB |
BIN
public/image/help/report-secret-1.jpg
Normal file
After Width: | Height: | Size: 2.1 MiB |
BIN
public/image/help/report-secret-2.jpg
Normal file
After Width: | Height: | Size: 1.7 MiB |
BIN
public/image/help/report-step1.jpg
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
public/image/help/report-step2.jpg
Normal file
After Width: | Height: | Size: 194 KiB |
BIN
public/image/help/report-step3.jpg
Normal file
After Width: | Height: | Size: 179 KiB |
BIN
public/image/help/report-step4.jpg
Normal file
After Width: | Height: | Size: 194 KiB |
BIN
public/image/help/report-step5.jpg
Normal file
After Width: | Height: | Size: 175 KiB |
BIN
public/image/help/report-types.jpg
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
public/image/help/vip-guide.jpg
Normal file
After Width: | Height: | Size: 257 KiB |
BIN
public/image/shot_nonal.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
public/image/shot_svip.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
public/image/shot_vip.png
Normal file
After Width: | Height: | Size: 21 KiB |
15
src/api/user.js
Normal file
@ -0,0 +1,15 @@
|
||||
import axios from "axios";
|
||||
|
||||
// 获取API基础URL
|
||||
const baseURL = import.meta.env.VITE_API_BASE_URL || "";
|
||||
|
||||
// 注销账号API
|
||||
export function cancelAccount() {
|
||||
return axios({
|
||||
method: "post",
|
||||
url: `${baseURL}/api/user/cancel`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
||||
},
|
||||
});
|
||||
}
|
BIN
src/assets/images/ai_qinggan.png
Normal file
After Width: | Height: | Size: 59 KiB |
@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1740754612192" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="39491" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M887.456923 331.598922C867.952667 146.308492 707.042557 2.464607 516.876064 0.026575 307.205315-2.411457 134.105045 163.374716 134.105045 368.169401c0 134.091758 73.140959 253.555324 190.166494 319.382188l7.314096 75.578991c2.438032 14.628192 14.628192 24.38032 29.256383 24.380319h299.877932c14.628192 0 26.818352-12.19016 29.256383-24.380319l7.314096-75.578991c131.653726-70.702927 204.794685-207.232717 190.166494-355.952667zM321.833507 360.855305c0 17.066224-14.628192 29.256384-29.256384 29.256384s-29.256384-12.19016-29.256383-29.256384c0-9.752128 0-17.066224 2.438031-26.818351 2.438032-17.066224 17.066224-26.818352 34.132448-26.818352 17.066224 2.438032 29.256384 17.066224 26.818352 31.694416-2.438032 9.752128-4.876064 14.628192-4.876064 21.942287z m190.166493-185.290429c-70.702927 0-134.091758 36.570479-165.786174 97.521279-4.876064 9.752128-14.628192 14.628192-26.818351 14.628191-4.876064 0-9.752128 0-14.628192-2.438032-14.628192-7.314096-19.504256-24.38032-12.19016-39.008511 43.884575-78.017023 126.777662-126.777662 219.422877-126.777662 17.066224 0 29.256384 12.19016 29.256384 29.256383s-12.19016 26.818352-29.256384 26.818352zM343.775794 833.833507c-2.438032 9.752128-2.438032 17.066224-2.438032 26.818351 0 90.207183 75.578991 163.348142 168.224206 163.348142 92.645215 0 168.224206-73.140959 168.224206-163.348142 0-9.752128 0-19.504256-2.438032-26.818351H343.775794z" fill="#F5B53A" p-id="39492"></path></svg>
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1741855510780" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2636" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M853.64224 76.7488H155.25888c-49.03424 0-88.75008 40.14592-88.75008 89.18528l-0.41472 766.18752c-0.00512 13.45024 16.256 20.18816 25.76384 10.68032l148.16256-148.16256a15.09376 15.09376 0 0 1 10.6752-4.41856h602.94656c57.34912 0 104.26368-46.9248 104.26368-104.2688V181.02784c0-57.35424-46.91456-104.27904-104.26368-104.27904z m-299.33056 544.1792a15.09376 15.09376 0 0 1-15.08864 15.08864H472.73472a15.09376 15.09376 0 0 1-15.09376-15.08864v-60.5696a15.09376 15.09376 0 0 1 15.09376-15.08864h66.4832a15.09376 15.09376 0 0 1 15.08864 15.08864v60.5696h0.00512z m39.45984-199.94112c-35.16928 24.76032-51.65056 48.84992-49.39776 72.30464 0.05632 0.4608 0.08704 0.9216 0.08704 1.3824a15.08864 15.08864 0 0 1-15.09376 15.08864h-48.73216a15.08352 15.08352 0 0 1-15.08864-15.08864v-6.60992c-1.32608-40.61184 15.6672-72.77056 50.92352-96.41984 0.24064-0.16384 0.49152-0.33792 0.72704-0.51712 32.6144-24.86784 48.2816-48.45056 46.99136-70.74816-2.62144-27.33056-18.0992-42.40896-46.4384-45.29152a16.45568 16.45568 0 0 0-1.81248-0.08192c-31.42144 0.3584-52.42368 19.4816-62.98112 57.3696a15.13472 15.13472 0 0 1-17.4592 10.85952L374.1696 331.23328a15.11424 15.11424 0 0 1-11.70944-18.61632c20.54144-80.15872 76.60032-118.99392 168.17152-116.5312 81.30048 5.25312 126.0032 41.89696 134.08256 109.88544 0.0512 0.38912 0.08192 0.78848 0.10752 1.1776 2.3808 44.47744-21.2992 82.41152-71.05024 113.83808z" fill="#397B8B" p-id="2637"></path></svg>
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
src/assets/images/index_b_banner.png
Normal file
After Width: | Height: | Size: 480 KiB |
BIN
src/assets/images/tg_qrcode_2.jpg
Normal file
After Width: | Height: | Size: 619 KiB |
BIN
src/assets/images/tg_qrcode_3.jpg
Normal file
After Width: | Height: | Size: 558 KiB |
BIN
src/assets/images/tg_qrcode_4.jpg
Normal file
After Width: | Height: | Size: 719 KiB |
BIN
src/assets/images/tg_qrcode_5.jpg
Normal file
After Width: | Height: | Size: 878 KiB |
BIN
src/assets/images/tg_qrcode_6.jpg
Normal file
After Width: | Height: | Size: 929 KiB |
BIN
src/assets/images/tg_qrcode_7.jpg
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
src/assets/images/tg_qrcode_8.jpg
Normal file
After Width: | Height: | Size: 297 KiB |
@ -2,20 +2,16 @@
|
||||
<van-popup v-model:show="show" round position="bottom">
|
||||
<div class="max-h-[calc(100vh-100px)] m-4 ">
|
||||
<div class="p-4">
|
||||
<canvas ref="posterCanvas" class="rounded-xl shadow h-[500px] m-auto"></canvas>
|
||||
<van-swipe class="poster-swiper rounded-xl shadow" indicator-color="white" @change="onSwipeChange">
|
||||
<van-swipe-item v-for="(_, index) in posterImages" :key="index">
|
||||
<canvas :ref="el => posterCanvasRefs[index] = el"
|
||||
class="poster-canvas rounded-xl h-[800px] m-auto"></canvas>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</div>
|
||||
<!-- <div class="m-2"></div> -->
|
||||
<van-divider>分享到好友</van-divider>
|
||||
|
||||
<div class="flex items-center justify-around">
|
||||
<!-- <div class="flex flex-col items-center justify-center" @click="toPromote">
|
||||
<img src="@/assets/images/icon_share_wechat.svg" class="w-12 h-12 rounded-full" />
|
||||
<div class="text-center mt-1">微信好友</div>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<img src="@/assets/images/icon_share_friends.svg" class="w-12 h-12 rounded-full" />
|
||||
<div class="text-center mt-1">微信朋友圈</div>
|
||||
</div> -->
|
||||
<div class="flex flex-col items-center justify-center" @click="savePoster">
|
||||
<img src="@/assets/images/icon_share_img.svg" class="w-10 h-10 rounded-full" />
|
||||
<div class="text-center mt-1 text-gray-600 text-xs">保存图片</div>
|
||||
@ -30,8 +26,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, nextTick } from 'vue';
|
||||
import { ref, watch, nextTick, computed, onMounted, toRefs } from 'vue';
|
||||
import QRCode from 'qrcode';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
const props = defineProps({
|
||||
linkIdentifier: {
|
||||
type: String,
|
||||
@ -43,9 +41,10 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
const { linkIdentifier, mode } = toRefs(props);
|
||||
const posterCanvas = ref(null); // 用于绘制海报的canvas
|
||||
let posterGenerated = ref(false); // 标记海报是否已经生成过
|
||||
const show = defineModel('show')
|
||||
const posterCanvasRefs = ref([]); // 用于绘制海报的canvas数组
|
||||
const currentIndex = ref(0); // 当前显示的海报索引
|
||||
const postersGenerated = ref([]); // 标记海报是否已经生成过,将在onMounted中初始化
|
||||
const show = defineModel('show');
|
||||
const url = computed(() => {
|
||||
const baseUrl = window.location.origin; // 获取当前站点的域名
|
||||
return mode.value === "promote"
|
||||
@ -53,35 +52,98 @@ const url = computed(() => {
|
||||
: `${baseUrl}/agent/invitationAgentApply/`;
|
||||
});
|
||||
|
||||
const qrcodeImage = ref(null);
|
||||
const loadPosterImage = async () => {
|
||||
if (mode.value === "promote") {
|
||||
const module = await import("@/assets/images/tg_qrcode_1.png");
|
||||
return module.default;
|
||||
} else {
|
||||
const module = await import("@/assets/images/yq_qrcode_1.png");
|
||||
return module.default;
|
||||
// 海报图片数组
|
||||
const posterImages = ref([]);
|
||||
|
||||
// QR码位置配置(为每个海报单独配置)
|
||||
const qrCodePositions = ref({
|
||||
// promote模式的配置 (tg_qrcode)
|
||||
promote: [
|
||||
{ x: 180, y: 1440, size: 300 }, // tg_qrcode_1.png
|
||||
{ x: 525, y: 1955, size: 500 }, // tg_qrcode_2.jpg
|
||||
{ x: 525, y: 1955, size: 500 }, // tg_qrcode_3.jpg
|
||||
{ x: 525, y: 1955, size: 500 }, // tg_qrcode_4.jpg
|
||||
{ x: 525, y: 1955, size: 500 }, // tg_qrcode_5.jpg
|
||||
{ x: 525, y: 1955, size: 500 }, // tg_qrcode_6.jpg
|
||||
{ x: 255, y: 940, size: 250 }, // tg_qrcode_7.jpg
|
||||
{ x: 255, y: 940, size: 250 }, // tg_qrcode_8.jpg
|
||||
],
|
||||
// invitation模式的配置 (yq_qrcode)
|
||||
invitation: [
|
||||
{ x: 360, y: -1370, size: 360 }, // yq_qrcode_1.png
|
||||
]
|
||||
});
|
||||
|
||||
// 处理轮播图切换事件
|
||||
const onSwipeChange = (index) => {
|
||||
currentIndex.value = index;
|
||||
if (!postersGenerated.value[index]) {
|
||||
generatePoster(index);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载海报图片
|
||||
const loadPosterImages = async () => {
|
||||
const images = [];
|
||||
const basePrefix = mode.value === "promote" ? "tg_qrcode_" : "yq_qrcode_";
|
||||
|
||||
// 根据模式确定要加载的图片数量
|
||||
const imageCount = mode.value === "promote" ? 8 : 1;
|
||||
|
||||
// 加载图片
|
||||
for (let i = 1; i <= imageCount; i++) {
|
||||
// 尝试加载 .png 文件
|
||||
try {
|
||||
const module = await import(`@/assets/images/${basePrefix}${i}.png`);
|
||||
images.push(module.default);
|
||||
continue; // 如果成功加载了 png,则跳过后续的 jpg 尝试
|
||||
} catch (error) {
|
||||
console.warn(`Image ${basePrefix}${i}.png not found, trying jpg...`);
|
||||
}
|
||||
|
||||
// 如果 .png 不存在,尝试加载 .jpg 文件
|
||||
try {
|
||||
const module = await import(`@/assets/images/${basePrefix}${i}.jpg`);
|
||||
images.push(module.default);
|
||||
} catch (error) {
|
||||
console.warn(`Image ${basePrefix}${i}.jpg not found either, using fallback.`);
|
||||
if (i === 1) {
|
||||
// 如果第一张也不存在,创建一个空白图片
|
||||
const emptyImg = new Image();
|
||||
emptyImg.width = 600;
|
||||
emptyImg.height = 800;
|
||||
images.push(emptyImg.src);
|
||||
} else if (images.length > 0) {
|
||||
images.push(images[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return images;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
qrcodeImage.value = await loadPosterImage()
|
||||
posterImages.value = await loadPosterImages();
|
||||
// 根据加载的图片数量初始化postersGenerated数组
|
||||
postersGenerated.value = Array(posterImages.value.length).fill(false);
|
||||
});
|
||||
|
||||
// 生成海报并合成二维码
|
||||
const generatePoster = async () => {
|
||||
const generatePoster = async (index) => {
|
||||
// 如果已经生成过海报,就直接返回
|
||||
if (posterGenerated.value) return;
|
||||
if (postersGenerated.value[index]) return;
|
||||
|
||||
// 确保 DOM 已经渲染完成
|
||||
await nextTick();
|
||||
|
||||
const canvas = posterCanvas.value;
|
||||
const canvas = posterCanvasRefs.value[index];
|
||||
if (!canvas) return; // 如果 canvas 元素为空则直接返回
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// 1. 加载海报图片
|
||||
const posterImg = new Image();
|
||||
posterImg.src = qrcodeImage.value;
|
||||
posterImg.src = posterImages.value[index];
|
||||
|
||||
posterImg.onload = () => {
|
||||
// 设置 canvas 尺寸与海报图一致
|
||||
@ -102,13 +164,18 @@ const generatePoster = async () => {
|
||||
const qrCodeImg = new Image();
|
||||
qrCodeImg.src = qrCodeUrl;
|
||||
qrCodeImg.onload = () => {
|
||||
const qrX = mode.value === "promote" ? 180 : 360; // **根据模式调整二维码位置**
|
||||
const qrY = mode.value === "promote" ? posterImg.height - 480 : posterImg.height - 1370;
|
||||
const qrSize = mode.value === "promote" ? 300 : 360
|
||||
ctx.drawImage(qrCodeImg, qrX, qrY, qrSize, qrSize);
|
||||
// 获取当前海报的二维码位置配置
|
||||
const positions = qrCodePositions.value[mode.value];
|
||||
const position = positions[index] || positions[0]; // 如果没有对应索引的配置,则使用第一个配置
|
||||
|
||||
// 计算Y坐标(负值表示从底部算起的位置)
|
||||
const qrY = position.y < 0 ? posterImg.height + position.y : position.y;
|
||||
|
||||
// 绘制二维码
|
||||
ctx.drawImage(qrCodeImg, position.x, qrY, position.size, position.size);
|
||||
|
||||
// 标记海报已生成
|
||||
posterGenerated.value = true;
|
||||
postersGenerated.value[index] = true;
|
||||
};
|
||||
});
|
||||
};
|
||||
@ -116,8 +183,8 @@ const generatePoster = async () => {
|
||||
|
||||
// 监听 show 变化,show 为 true 时生成海报
|
||||
watch(show, (newVal) => {
|
||||
if (newVal && !posterGenerated.value) {
|
||||
generatePoster(); // 当弹窗显示且海报未生成时生成海报
|
||||
if (newVal && !postersGenerated.value[currentIndex.value]) {
|
||||
generatePoster(currentIndex.value); // 当弹窗显示且当前海报未生成时生成海报
|
||||
}
|
||||
});
|
||||
|
||||
@ -129,19 +196,22 @@ const toPromote = () => {
|
||||
|
||||
// 保存海报图片
|
||||
const savePoster = () => {
|
||||
const canvas = posterCanvas.value;
|
||||
const canvas = posterCanvasRefs.value[currentIndex.value];
|
||||
const dataURL = canvas.toDataURL('image/png'); // 获取 canvas 内容为图片
|
||||
const a = document.createElement('a');
|
||||
a.href = dataURL;
|
||||
a.download = '天远数据查询.png';
|
||||
a.click();
|
||||
};
|
||||
|
||||
const generalUrl = () => {
|
||||
return url.value + encodeURIComponent(linkIdentifier.value)
|
||||
return url.value + encodeURIComponent(linkIdentifier.value);
|
||||
}
|
||||
|
||||
const copyUrl = () => {
|
||||
copyToClipboard(generalUrl())
|
||||
copyToClipboard(generalUrl());
|
||||
}
|
||||
|
||||
// 复制链接
|
||||
const copyToClipboard = (text) => {
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
@ -170,5 +240,14 @@ const copyToClipboard = (text) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 这里是你自定义的样式 */
|
||||
.poster-swiper {
|
||||
height: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.poster-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,13 +1,10 @@
|
||||
// src/composables/useEnv.js
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, computed } from "vue";
|
||||
|
||||
export function useEnv() {
|
||||
const isWeChat = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
// 检测是否是微信环境
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
isWeChat.value = userAgent.includes("micromessenger");
|
||||
});
|
||||
const isWeChat = /micromessenger/i.test(userAgent);
|
||||
|
||||
return {
|
||||
isWeChat,
|
||||
|
@ -54,8 +54,8 @@ const route = useRoute();
|
||||
const tabbar = ref('index');
|
||||
const menu = reactive([
|
||||
{ title: '首页', icon: 'home-o', name: 'index' },
|
||||
{ title: '推广', icon: 'balance-o', name: 'agent' },
|
||||
{ title: 'AI律师', icon: 'chat-o', name: 'ai' },
|
||||
{ title: '资产', icon: 'gold-coin-o', name: 'agent' },
|
||||
{ title: '智能助手', icon: 'chat-o', name: 'ai' },
|
||||
{ title: '我的', icon: 'user-o', name: 'me' },
|
||||
]);
|
||||
|
||||
@ -73,7 +73,7 @@ const tabChange = (name) => {
|
||||
|
||||
// 跳转到投诉页面
|
||||
const toComplaint = () => {
|
||||
window.location.href = 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9' // 跳转到客服页面
|
||||
window.location.href = 'https://work.weixin.qq.com/kfid/kfc8a32720024833f57' // 跳转到客服页面
|
||||
// router.push({ name: 'complaint' }); // 使用 Vue Router 进行跳转
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,18 @@ const router = createRouter({
|
||||
component: () => import("@/views/Help.vue"),
|
||||
meta: { title: "帮助中心" },
|
||||
},
|
||||
|
||||
{
|
||||
path: "/help/detail",
|
||||
name: "helpDetail",
|
||||
component: () => import("@/views/HelpDetail.vue"),
|
||||
meta: { title: "帮助中心" },
|
||||
},
|
||||
{
|
||||
path: "/help/guide",
|
||||
name: "helpGuide",
|
||||
component: () => import("@/views/HelpGuide.vue"),
|
||||
meta: { title: "引导指南" },
|
||||
},
|
||||
{
|
||||
path: "/service",
|
||||
name: "service",
|
||||
|
@ -23,11 +23,46 @@ export const useAgentStore = defineStore("agent", {
|
||||
this.status = data.value.data.status; // 获取代理状态 0=待审核,1=审核通过,2=审核未通过,3=未申请
|
||||
this.agentID = data.value.data.agent_id;
|
||||
this.mobile = data.value.data.mobile;
|
||||
|
||||
// 保存到localStorage
|
||||
localStorage.setItem(
|
||||
"agentInfo",
|
||||
JSON.stringify({
|
||||
isAgent: this.isAgent,
|
||||
level: this.level,
|
||||
status: this.status,
|
||||
agentID: this.agentID,
|
||||
mobile: this.mobile,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
console.log("Error fetching agent info", data.value);
|
||||
}
|
||||
}
|
||||
this.isLoaded = true;
|
||||
},
|
||||
|
||||
// 更新代理信息
|
||||
updateAgentInfo(agentInfo) {
|
||||
if (agentInfo) {
|
||||
this.isAgent = agentInfo.isAgent || false;
|
||||
this.level = agentInfo.level || "";
|
||||
this.status = agentInfo.status || 3;
|
||||
this.agentID = agentInfo.agentID || null;
|
||||
this.mobile = agentInfo.mobile || "";
|
||||
this.isLoaded = true;
|
||||
}
|
||||
},
|
||||
|
||||
// 重置代理信息
|
||||
resetAgent() {
|
||||
this.isLoaded = false;
|
||||
this.level = "";
|
||||
this.status = 3;
|
||||
this.isAgent = false;
|
||||
this.ancestorID = null;
|
||||
this.agentID = null;
|
||||
this.mobile = "";
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -17,8 +17,33 @@ export const useUserStore = defineStore("user", {
|
||||
this.userName = userinfo.nickName || "";
|
||||
this.userAvatar = userinfo.userAvatar;
|
||||
this.isLoggedIn = true;
|
||||
|
||||
// 保存到localStorage
|
||||
localStorage.setItem(
|
||||
"userInfo",
|
||||
JSON.stringify({
|
||||
nickName: this.userName,
|
||||
avatar: this.userAvatar,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 更新用户信息
|
||||
updateUserInfo(userInfo) {
|
||||
if (userInfo) {
|
||||
this.userName = userInfo.nickName || "";
|
||||
this.userAvatar = userInfo.avatar || "";
|
||||
this.isLoggedIn = true;
|
||||
}
|
||||
},
|
||||
|
||||
// 重置用户信息
|
||||
resetUser() {
|
||||
this.userName = "";
|
||||
this.userAvatar = "";
|
||||
this.isLoggedIn = false;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
87
src/ui/CIDV044.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<script setup>
|
||||
import LTitle from "@/components/LTitle.vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const { data } = props;
|
||||
|
||||
// 状态映射,包括显示的文字和样式
|
||||
const statusMap = {
|
||||
0: {
|
||||
text: "未婚或尚未登记结婚",
|
||||
bgClass: "bg-yellow-100",
|
||||
textClass: "text-yellow-700",
|
||||
description: "未进行民政登记婚姻",
|
||||
},
|
||||
1: {
|
||||
text: "已婚",
|
||||
bgClass: "bg-green-100",
|
||||
textClass: "text-green-700",
|
||||
description: "已登记婚姻,家庭幸福美满",
|
||||
},
|
||||
2: {
|
||||
text: "离异",
|
||||
bgClass: "bg-red-100",
|
||||
textClass: "text-red-700",
|
||||
description: "离异状态,未来生活可期",
|
||||
},
|
||||
3: {
|
||||
text: "离婚冷静期",
|
||||
bgClass: "bg-blue-100",
|
||||
textClass: "text-blue-700",
|
||||
description: "目前处于离婚冷静期,请谨慎决策",
|
||||
},
|
||||
};
|
||||
|
||||
// 根据 `data.status` 确定当前状态,默认值为 “无相关记录”
|
||||
const currentStatus =
|
||||
data.status !== undefined
|
||||
? statusMap[data.status] || statusMap["0"]
|
||||
: {
|
||||
text: "无相关记录",
|
||||
bgClass: "bg-gray-200",
|
||||
textClass: "text-gray-500",
|
||||
description: "暂无婚姻相关记录",
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card">
|
||||
<div class="status-info flex flex-col items-center ">
|
||||
<div
|
||||
:class="`status-label rounded-full px-6 py-3 text-center font-bold shadow-md ${currentStatus.bgClass} ${currentStatus.textClass}`">
|
||||
{{ currentStatus.text }}
|
||||
</div>
|
||||
<p class="status-description mt-3 text-sm text-gray-600">
|
||||
{{ currentStatus.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.status-info {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: 1.25rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 9999px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.status-description {
|
||||
color: #4a5568;
|
||||
margin-top: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.additional-info p {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
</style>
|
@ -14,7 +14,7 @@
|
||||
<script setup>
|
||||
function toService() {
|
||||
// window.location.href = '/service' // 跳转到客服页面
|
||||
window.location.href = 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9' // 跳转到客服页面
|
||||
window.location.href = 'https://work.weixin.qq.com/kfid/kfc8a32720024833f57' // 跳转到客服页面
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,5 +1,16 @@
|
||||
<template>
|
||||
<div class="flex flex-col box-border from-blue-100 to-white bg-gradient-to-b pt-4 flex-1 pb-4">
|
||||
<!-- 顶部标题 -->
|
||||
<div class="flex border-blue-300 mx-4 p-3 bg-blue-300 text-white rounded-xl mb-4 justify-between items-center">
|
||||
<div class="flex items-center">
|
||||
<img src="@/assets/images/ai_qinggan.png" class="w-10 h-10 rounded-xl mr-2" alt="智能助手" />
|
||||
<span class="text-lg font-medium">智能助手</span>
|
||||
</div>
|
||||
<div @click="contactCustomerService"
|
||||
class="flex items-center px-3 py-1 bg-green-500 rounded-lg cursor-pointer shadow-sm">
|
||||
<span class="text-white text-sm">联系人工客服</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx-4 flex flex-col flex-1 rounded-xl shadow-lg">
|
||||
<!-- Chat Window -->
|
||||
<div class="w-full text-center py-2 text-slate-800 font-bold text-xl bg-white rounded-t-xl">AI律师</div>
|
||||
@ -8,7 +19,7 @@
|
||||
<div class=" flex-1 overflow-y-auto">
|
||||
<div v-for="(message, index) in messages" :key="index" class="mb-4">
|
||||
<div v-if="message.sender === 'ai'" class="flex justify-start items-start">
|
||||
<img class="w-10 h-10 rounded-xl mr-2" src="@/assets/images/ai_picture.webp" alt="AI律师">
|
||||
<img class="w-10 h-10 rounded-xl mr-2" src="@/assets/images/ai_qinggan.png" alt="AI律师">
|
||||
<div
|
||||
class="inline-block max-w-max rounded-xl bg-white p-2 text-left text-green-600 font-medium shadow-md">
|
||||
<!-- If AI message, show loading or text -->
|
||||
@ -78,7 +89,7 @@ async function sendMessage() {
|
||||
body: JSON.stringify({
|
||||
prompt: userMessage.value,
|
||||
platform_id: 2,
|
||||
roleid: 1,
|
||||
role_id: 2,
|
||||
openid: 'openid' + localStorage.getItem("token"),
|
||||
userid: 'userid' + localStorage.getItem("token"),
|
||||
sessionid: sessionID.value // 可以在请求中添加 sessionID
|
||||
@ -150,7 +161,9 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const contactCustomerService = () => {
|
||||
window.location.href = 'https://work.weixin.qq.com/kfid/kfc8a32720024833f57' // 跳转到客服页面
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -86,7 +86,12 @@ const featureMap = {
|
||||
CAR061: {
|
||||
name: '名下车辆',
|
||||
component: defineAsyncComponent(() => import('@/ui/CCAR061.vue')),
|
||||
}
|
||||
},
|
||||
IDV044: {
|
||||
name: '婚姻状态',
|
||||
component: defineAsyncComponent(() => import('@/ui/CIDV044.vue')),
|
||||
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异、离异冷静期。如您对查询结果有疑问,请联系客服反馈。'
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -97,7 +102,7 @@ import GaugeChart from "@/components/GaugeChart.vue";
|
||||
|
||||
|
||||
const productId = ref(null);
|
||||
const isDone = ref(true);
|
||||
const isDone = ref(false);
|
||||
const active = ref(null)
|
||||
|
||||
const reportData = ref([])
|
||||
@ -106,9 +111,9 @@ const reportName = ref("")
|
||||
const reportDateTime = ref(null)
|
||||
const feature = ref("")
|
||||
const isEmpty = ref(false)
|
||||
const reportScore = ref(75); // 默认分数
|
||||
const reportScore = ref(0); // 默认分数
|
||||
|
||||
onMounted(() => {
|
||||
onBeforeMount(() => {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
feature.value = query.get("feature");
|
||||
console.log("feature", feature.value)
|
||||
@ -138,17 +143,17 @@ const getReport = async () => {
|
||||
} else if (data.value.code === 200003) {
|
||||
isEmpty.value = true
|
||||
}
|
||||
isDone.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 计算综合评分的函数
|
||||
const calculateScore = (reportData) => {
|
||||
// 从0分开始
|
||||
// 从0分开始(0分表示无风险)
|
||||
let score = 0;
|
||||
// 最高分为90分
|
||||
// 最高分为90分(90分表示最高风险)
|
||||
const maxScore = 90;
|
||||
|
||||
// 定义各接口的相对权重比例(而非固定分值)
|
||||
// 定义各接口的相对风险权重比例
|
||||
const relativeWeights = {
|
||||
// 关键风险指标(高优先级)
|
||||
'G34BJ03': 250, // 不良记录
|
||||
@ -179,7 +184,7 @@ const calculateScore = (reportData) => {
|
||||
const availableAPIs = reportData.map(item => item.data.apiID).filter(id => relativeWeights[id]);
|
||||
|
||||
// 如果没有可评分的接口,返回默认分数
|
||||
if (availableAPIs.length === 0) return 60; // 默认60分
|
||||
if (availableAPIs.length === 0) return 30; // 默认30分(中等风险)
|
||||
|
||||
// 计算当前报告中所有接口的相对权重总和
|
||||
let totalWeight = 0;
|
||||
@ -197,7 +202,7 @@ const calculateScore = (reportData) => {
|
||||
actualWeights[apiID] = relativeWeights[apiID] * pointValue;
|
||||
});
|
||||
|
||||
// 遍历报告数据进行评分
|
||||
// 遍历报告数据进行评分 - 风险越高分数越高
|
||||
reportData.forEach(item => {
|
||||
const apiID = item.data.apiID;
|
||||
const data = item.data.data;
|
||||
@ -205,7 +210,7 @@ const calculateScore = (reportData) => {
|
||||
// 如果没有定义权重,跳过
|
||||
if (!actualWeights[apiID]) return;
|
||||
|
||||
// 根据不同的API ID计算分数(只有没有风险或风险低时加分)
|
||||
// 根据不同的API ID计算分数(有风险时加分)
|
||||
switch (apiID) {
|
||||
case 'G09SC02': // 婚姻状态
|
||||
// 不计入风险
|
||||
@ -213,61 +218,58 @@ const calculateScore = (reportData) => {
|
||||
|
||||
case 'G27BJ05': // 借贷申请记录
|
||||
if (data) {
|
||||
// 检查所有字段是否都为0(没有风险)
|
||||
let noRisk = true;
|
||||
// 检查是否有申请记录(有则表示风险)
|
||||
let hasRisk = false;
|
||||
for (const key in data) {
|
||||
if (data[key] !== 0 && data[key] !== '0') {
|
||||
noRisk = false;
|
||||
if (data[key] !== 0 && data[key] !== '0' &&
|
||||
key.indexOf('allnum') > -1 &&
|
||||
!isNaN(parseInt(data[key])) &&
|
||||
parseInt(data[key]) > 0) {
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (noRisk || !Object.keys(data).length) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G28BJ05': // 借贷行为记录
|
||||
if (data) {
|
||||
// 检查所有字段是否都为0(没有风险)
|
||||
let noRisk = true;
|
||||
// 检查是否有借贷记录(有则表示风险)
|
||||
let hasRisk = false;
|
||||
for (const key in data) {
|
||||
if (data[key] !== 0 && data[key] !== '0') {
|
||||
noRisk = false;
|
||||
if (data[key] !== 0 && data[key] !== '0' &&
|
||||
(key.indexOf('lendamt') > -1 || key.indexOf('num') > -1) &&
|
||||
!isNaN(parseInt(data[key])) &&
|
||||
parseInt(data[key]) > 0) {
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (noRisk || !Object.keys(data).length) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G26BJ05': // 违约异常
|
||||
if (data) {
|
||||
// 检查除特定字段外的其他字段是否都为0(没有风险)
|
||||
// 检查除特定字段外的其他字段是否有异常值(有异常则表示风险)
|
||||
const excludeFields = ['swift_number', 'code', 'flag_specialList_c'];
|
||||
let noRisk = true;
|
||||
let hasRisk = false;
|
||||
|
||||
for (const key in data) {
|
||||
if (!excludeFields.includes(key) && data[key] !== 0 && data[key] !== '0') {
|
||||
noRisk = false;
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (noRisk || !Object.keys(data).length) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -276,23 +278,20 @@ const calculateScore = (reportData) => {
|
||||
// 根据风险等级加分
|
||||
switch (data.risk_level) {
|
||||
case 'A': // 无风险
|
||||
score += actualWeights[apiID];
|
||||
// 不加分
|
||||
break;
|
||||
case 'F': // 低风险
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case 'C': // 中风险
|
||||
case 'D': // 中风险
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case 'B': // 高风险
|
||||
case 'E': // 高风险
|
||||
// 不加分
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -327,12 +326,9 @@ const calculateScore = (reportData) => {
|
||||
hasRisk = true;
|
||||
}
|
||||
|
||||
if (!hasRisk) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -341,38 +337,29 @@ const calculateScore = (reportData) => {
|
||||
// 根据filterType判断风险等级
|
||||
switch (data.filterType) {
|
||||
case '0': // 安全
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
case '3': // 低危
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case '2': // 中危
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case '1': // 高危
|
||||
// 不加分
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
case '3': // 低危
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case '2': // 中危
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case '1': // 高危
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G19BJ02': // 手机二次卡
|
||||
if (data && data.is_second_card === false) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.is_second_card === true) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G02BJ02': // 手机在网时长
|
||||
if (data && data.online_months >= 6) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.online_months < 6) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
@ -381,19 +368,13 @@ const calculateScore = (reportData) => {
|
||||
case 'G17BJ02': // 手机号二要素
|
||||
case 'KZEYS': // 身份证二要素
|
||||
case 'G20GZ01': // 银行卡四要素核验
|
||||
if (data && data.is_consistent) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.is_consistent === false) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'FIN019': // 银行卡黑名单
|
||||
if (data && data.is_blacklisted === false) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.is_blacklisted === true) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
@ -580,7 +561,7 @@ const maskValue = computed(() => {
|
||||
<div class="text-sm text-gray-600">身份证信息核验通过</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
|
||||
<!-- <div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
|
||||
<div
|
||||
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
|
||||
✔</div>
|
||||
@ -589,7 +570,7 @@ const maskValue = computed(() => {
|
||||
<div class="text-sm text-gray-600">被查询人姓名与运营商提供的一致</div>
|
||||
<div class="text-sm text-gray-600">被查询人身份证与运营商提供的一致</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -597,13 +578,14 @@ const maskValue = computed(() => {
|
||||
</div>
|
||||
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
|
||||
</van-tab>
|
||||
<van-tab v-for="(item, index) in reportData" :key="index" :title="featureMap[item.data.apiID].name">
|
||||
<div id="lawsuit" class="title mb-4">{{ featureMap[item.data.apiID].name }}</div>
|
||||
<component :is="featureMap[item.data.apiID].component" :data="item.data.data"
|
||||
<van-tab v-for="(item, index) in reportData" :key="index"
|
||||
:title="featureMap[item.data.apiID]?.name">
|
||||
<div id="lawsuit" class="title mb-4">{{ featureMap[item.data.apiID]?.name }}</div>
|
||||
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
|
||||
:params="reportParams">
|
||||
</component>
|
||||
<LRemark v-if="featureMap[item.data.apiID].remark"
|
||||
:content="featureMap[item.data.apiID].remark" />
|
||||
<LRemark v-if="featureMap[item.data.apiID]?.remark"
|
||||
:content="featureMap[item.data.apiID]?.remark" />
|
||||
</van-tab>
|
||||
<div class="card">
|
||||
<div>
|
||||
|
@ -1,11 +1,114 @@
|
||||
<template>
|
||||
<div>
|
||||
帮助中心
|
||||
<div class="help-center">
|
||||
<van-tabs v-model:active="activeTab" sticky :offset-top="46">
|
||||
<van-tab v-for="(category, index) in categories" :key="index" :title="category.title" :name="category.name">
|
||||
<van-cell-group inset class="help-list" size="large">
|
||||
<van-cell v-for="item in category.items" :key="item.id" :title="item.title" is-link
|
||||
@click="goToDetail(item.id, item.type)" class="help-item">
|
||||
<template #label>
|
||||
<van-tag v-if="item.type === 'guide'" type="primary" size="small"
|
||||
class="guide-tag">引导指南</van-tag>
|
||||
</template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const activeTab = ref('report')
|
||||
|
||||
const categories = [
|
||||
{
|
||||
title: '推广报告',
|
||||
name: 'report',
|
||||
items: [
|
||||
{ id: 'report_guide', title: '直推报告页面引导', type: 'guide' },
|
||||
{ id: 'invite_guide', title: '邀请下级页面引导', type: 'guide' },
|
||||
{ id: 'report_push', title: '如何推广报告' },
|
||||
{ id: 'report_efficiency', title: '报告推广效率飙升指南' },
|
||||
{ id: 'report_calculation', title: '推广报告的收益是如何计算的?' },
|
||||
{ id: 'report_cost', title: '推广报告的成本是如何计算的?' },
|
||||
{ id: 'report_secret', title: '报告推广秘籍大公开' },
|
||||
{ id: 'report_types', title: '天远数据有哪些大数据报告类型' },
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '邀请下级',
|
||||
name: 'invite',
|
||||
items: [
|
||||
{ id: 'invite_earnings', title: '邀请下级赚取收益' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '其他',
|
||||
name: 'other',
|
||||
items: [
|
||||
{ id: 'vip_guide', title: '如何成为VIP代理和SVIP代理?' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const goToDetail = (id, type) => {
|
||||
if (type === 'guide') {
|
||||
router.push({
|
||||
path: '/help/guide',
|
||||
query: { id }
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
path: '/help/detail',
|
||||
query: { id }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.help-center {
|
||||
min-height: 100vh;
|
||||
background-color: #f7f8fa;
|
||||
|
||||
.help-list {
|
||||
margin-top: 12px;
|
||||
|
||||
.guide-tag {
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.help-item) {
|
||||
.van-cell__title {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.help-detail {
|
||||
padding: 20px;
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
white-space: pre-line;
|
||||
line-height: 1.6;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
</style>
|
80
src/views/HelpDetail.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="help-detail">
|
||||
<h2>{{ currentHelp.title }}</h2>
|
||||
<template v-if="Array.isArray(currentHelp.images)">
|
||||
<img v-for="(image, index) in currentHelp.images" :key="index" :src="image" :alt="currentHelp.title"
|
||||
class="help-image">
|
||||
</template>
|
||||
<img v-else-if="currentHelp.image" :src="currentHelp.image" :alt="currentHelp.title" class="help-image">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const currentHelp = ref({
|
||||
title: '',
|
||||
image: '',
|
||||
images: null
|
||||
})
|
||||
|
||||
// 图片路径映射
|
||||
const imageMap = {
|
||||
report_calculation: '/image/help/report-calculation.jpg',
|
||||
report_efficiency: '/image/help/report-efficiency.jpg',
|
||||
report_cost: '/image/help/report-cost.jpg',
|
||||
report_types: '/image/help/report-types.jpg',
|
||||
report_push: '/image/help/report-push.jpg',
|
||||
report_secret: ['/image/help/report-secret-1.jpg', '/image/help/report-secret-2.jpg'],
|
||||
invite_earnings: '/image/help/invite-earnings.jpg',
|
||||
direct_earnings: '/image/help/direct-earnings.jpg',
|
||||
vip_guide: '/image/help/vip-guide.jpg'
|
||||
}
|
||||
|
||||
// 标题映射
|
||||
const titleMap = {
|
||||
report_calculation: '推广报告的收益是如何计算的?',
|
||||
report_efficiency: '报告推广效率飙升指南',
|
||||
report_cost: '推广报告的成本是如何计算的?',
|
||||
report_types: '天远数据有哪些大数据报告类型',
|
||||
report_push: '如何推广报告',
|
||||
report_secret: '报告推广秘籍大公开',
|
||||
invite_earnings: '邀请下级赚取收益',
|
||||
direct_earnings: '直推报告赚取收益',
|
||||
vip_guide: '如何成为VIP代理和SVIP代理?'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const id = route.query.id
|
||||
if (id && titleMap[id]) {
|
||||
currentHelp.value = {
|
||||
title: titleMap[id],
|
||||
image: Array.isArray(imageMap[id]) ? null : imageMap[id],
|
||||
images: Array.isArray(imageMap[id]) ? imageMap[id] : null
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.help-detail {
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
|
||||
h2 {
|
||||
margin: 0 0 20px;
|
||||
font-size: 22px;
|
||||
color: #323233;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.help-image {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
103
src/views/HelpGuide.vue
Normal file
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="help-guide">
|
||||
<div class="guide-content" @click="handleImageClick">
|
||||
<img :src="currentStep.image" :alt="currentStep.title" class="guide-image">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const currentStepIndex = ref(0)
|
||||
|
||||
// 引导步骤数据
|
||||
const guideSteps = {
|
||||
report_guide: [
|
||||
{
|
||||
title: '第一步:进入直推报告页面',
|
||||
image: '/image/help/report-step1.jpg'
|
||||
},
|
||||
{
|
||||
title: '第二步:选择报告类型',
|
||||
image: '/image/help/report-step2.jpg'
|
||||
},
|
||||
{
|
||||
title: '第三步:填写推广信息',
|
||||
image: '/image/help/report-step3.jpg'
|
||||
},
|
||||
{
|
||||
title: '第四步:完成推广',
|
||||
image: '/image/help/report-step4.jpg'
|
||||
}
|
||||
],
|
||||
invite_guide: [
|
||||
{
|
||||
title: '第一步:进入邀请页面',
|
||||
image: '/image/help/invite-step1.jpg'
|
||||
},
|
||||
{
|
||||
title: '第二步:获取邀请码',
|
||||
image: '/image/help/invite-step2.jpg'
|
||||
},
|
||||
{
|
||||
title: '第三步:分享邀请链接',
|
||||
image: '/image/help/invite-step3.jpg'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
const currentGuide = computed(() => {
|
||||
const id = route.query.id
|
||||
return guideSteps[id] || []
|
||||
})
|
||||
|
||||
const totalSteps = computed(() => currentGuide.value.length)
|
||||
|
||||
const currentStep = computed(() => currentGuide.value[currentStepIndex.value])
|
||||
|
||||
const handleImageClick = () => {
|
||||
if (currentStepIndex.value < totalSteps.value - 1) {
|
||||
currentStepIndex.value++
|
||||
} else {
|
||||
// 最后一步,返回列表页
|
||||
router.back()
|
||||
}
|
||||
}
|
||||
|
||||
const onClickLeft = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const id = route.query.id
|
||||
if (!guideSteps[id]) {
|
||||
router.back()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.help-guide {
|
||||
background-color: #666666;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 46px);
|
||||
|
||||
.guide-content {
|
||||
flex: 1;
|
||||
height: calc(100vh - 46px);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.guide-image {
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
127
src/views/Me.vue
@ -7,7 +7,7 @@
|
||||
<div class="relative">
|
||||
<!-- 头像容器添加overflow-hidden解决边框问题 -->
|
||||
<div class="overflow-hidden rounded-full p-0.5" :class="levelGradient.border">
|
||||
<img :src="userAvatar || headShot" alt="User Avatar"
|
||||
<img :src="userAvatar || getDefaultAvatar()" alt="User Avatar"
|
||||
class="h-24 w-24 rounded-full border-4 border-white">
|
||||
</div>
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<VipBanner v-if="isAgent && level === 'normal'" />
|
||||
<VipBanner v-if="isAgent && (level === 'normal' || level === '')" />
|
||||
<!-- 功能菜单 -->
|
||||
<div class="features-section space-y-3">
|
||||
<template v-if="isAgent && ['VIP', 'SVIP'].includes(level)">
|
||||
@ -45,10 +45,18 @@
|
||||
<button class="feature-item hover:bg-blue-50" @click="toUserAgreement">
|
||||
📜 用户协议
|
||||
</button>
|
||||
<button class="feature-item hover:bg-blue-50" @click="toService">
|
||||
💬 联系客服
|
||||
<button class="feature-item hover:bg-blue-50" @click="toPrivacyPolicy">
|
||||
🔒 隐私政策
|
||||
</button>
|
||||
<button v-if="!isWeChat" class="feature-item hover:bg-red-50 text-red-600" @click="handleLogout">
|
||||
<button class="feature-item hover:bg-blue-50" @click="toAi">
|
||||
💬 智能客服
|
||||
</button>
|
||||
<button v-if="isLoggedIn" class="feature-item hover:bg-red-50 text-red-600"
|
||||
@click="handleCancelAccount">
|
||||
📴 注销账号
|
||||
</button>
|
||||
<button v-if="isLoggedIn && !isWeChat" class="feature-item hover:bg-red-50 text-red-600"
|
||||
@click="handleLogout">
|
||||
⏏️ 退出登录
|
||||
</button>
|
||||
</div>
|
||||
@ -58,23 +66,29 @@
|
||||
|
||||
<script setup>
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { ref, computed, onBeforeMount } from 'vue'
|
||||
const router = useRouter()
|
||||
import headShot from "@/assets/images/head_shot.webp"
|
||||
import { useAgentStore } from '@/stores/agentStore'
|
||||
import { useUserStore } from '@/stores/userStore'
|
||||
import { useEnv } from '@/composables/useEnv'
|
||||
import useApiFetch from '@/composables/useApiFetch'
|
||||
const agentStore = useAgentStore()
|
||||
const userStore = useUserStore()
|
||||
const { isAgent, level } = storeToRefs(agentStore)
|
||||
const { userName, userAvatar, isLoggedIn } = storeToRefs(userStore)
|
||||
const { isWeChat } = useEnv()
|
||||
|
||||
const levelNames = {
|
||||
normal: '普通代理',
|
||||
'': '普通代理',
|
||||
VIP: 'VIP代理',
|
||||
SVIP: 'SVIP代理'
|
||||
}
|
||||
|
||||
const levelText = {
|
||||
normal: '基础代理特权',
|
||||
'': '基础代理特权',
|
||||
VIP: '高级代理特权',
|
||||
SVIP: '尊享代理特权'
|
||||
}
|
||||
@ -82,27 +96,31 @@ const levelText = {
|
||||
const levelGradient = computed(() => ({
|
||||
border: {
|
||||
'normal': 'bg-green-300',
|
||||
'': 'bg-green-300',
|
||||
'VIP': 'bg-gradient-to-r from-yellow-400 to-amber-500',
|
||||
'SVIP': 'bg-gradient-to-r from-purple-400 to-pink-400 shadow-[0_0_15px_rgba(163,51,200,0.2)]'
|
||||
}[level.value],
|
||||
|
||||
badge: {
|
||||
'normal': 'bg-green-500',
|
||||
'': 'bg-green-500',
|
||||
'VIP': 'bg-gradient-to-r from-yellow-500 to-amber-600',
|
||||
'SVIP': 'bg-gradient-to-r from-purple-500 to-pink-500'
|
||||
}[level.value],
|
||||
|
||||
text: {
|
||||
'normal': 'text-green-600',
|
||||
'': 'text-green-600',
|
||||
'VIP': 'text-amber-600',
|
||||
'SVIP': 'text-purple-600'
|
||||
}[level.value]
|
||||
}))
|
||||
const maskName = computed(() => {
|
||||
return (name) => {
|
||||
return name.substring(0, 3) + "****" + name.substring(7);
|
||||
}
|
||||
})
|
||||
|
||||
const maskName = (name) => {
|
||||
if (!name || name.length < 11) return name
|
||||
return name.substring(0, 3) + "****" + name.substring(7)
|
||||
}
|
||||
|
||||
function toHistory() {
|
||||
router.push(`/historyQuery`)
|
||||
}
|
||||
@ -111,33 +129,97 @@ function toUserAgreement() {
|
||||
router.push(`/userAgreement`)
|
||||
}
|
||||
|
||||
function toPrivacyPolicy() {
|
||||
router.push(`/privacyPolicy`) // 新增隐私政策路由
|
||||
}
|
||||
|
||||
function toAi() {
|
||||
router.push(`/ai`) // 新增AI智能客服路由
|
||||
}
|
||||
|
||||
function redirectToLogin() {
|
||||
router.push(`/login`)
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
// 改进的存储管理
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refreshAfter')
|
||||
localStorage.removeItem('accessExpire')
|
||||
localStorage.removeItem('userInfo')
|
||||
localStorage.removeItem('agentInfo')
|
||||
|
||||
// 重置状态
|
||||
userStore.resetUser()
|
||||
agentStore.resetAgent()
|
||||
|
||||
location.reload()
|
||||
}
|
||||
|
||||
function toService() {
|
||||
// window.location.href = '/service' // 跳转到客服页面
|
||||
window.location.href = 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9' // 跳转到客服页面
|
||||
function handleCancelAccount() {
|
||||
// 账号注销功能
|
||||
if (confirm('注销账号后,您的所有数据将被清除且无法恢复,确定要继续吗?')) {
|
||||
useApiFetch("/user/cancelOut")
|
||||
.post()
|
||||
.json()
|
||||
.then(({ data, error }) => {
|
||||
if (!error && data.value && data.value.code === 200) {
|
||||
alert('账号已注销')
|
||||
handleLogout()
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('注销账号失败:', error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function toService() {
|
||||
window.location.href = 'https://work.weixin.qq.com/kfid/kfc8a32720024833f57' // 跳转到客服页面
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
// const token = localStorage.getItem('token') // 使用 localStorage 获取 token
|
||||
// if (token) {
|
||||
// fetchUserInfo()
|
||||
// agentStore.fetchAgentStatus()
|
||||
// }
|
||||
})
|
||||
const toVipConfig = () => {
|
||||
router.push({ name: "agentVipConfig" })
|
||||
}
|
||||
|
||||
const getDefaultAvatar = () => {
|
||||
if (!isAgent.value) return headShot
|
||||
|
||||
switch (level.value) {
|
||||
case 'normal':
|
||||
case '':
|
||||
return '/image/shot_nonal.png'
|
||||
case 'VIP':
|
||||
return '/image/shot_vip.png'
|
||||
case 'SVIP':
|
||||
return '/image/shot_svip.png'
|
||||
default:
|
||||
return headShot
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
// 获取存储的用户和代理信息
|
||||
const userInfo = localStorage.getItem('userInfo')
|
||||
if (userInfo) {
|
||||
try {
|
||||
const parsedUserInfo = JSON.parse(userInfo)
|
||||
userStore.updateUserInfo(parsedUserInfo)
|
||||
} catch (e) {
|
||||
console.error('解析用户信息失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
const agentInfo = localStorage.getItem('agentInfo')
|
||||
if (agentInfo) {
|
||||
try {
|
||||
const parsedAgentInfo = JSON.parse(agentInfo)
|
||||
agentStore.updateAgentInfo(parsedAgentInfo)
|
||||
} catch (e) {
|
||||
console.error('解析代理信息失败', e)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -159,6 +241,11 @@ const toVipConfig = () => {
|
||||
@apply flex w-full items-center shadow space-x-3 rounded-xl bg-white px-6 py-4 text-left text-gray-700 transition-all duration-300 hover:scale-[1.02] hover:shadow-md focus:outline-none;
|
||||
}
|
||||
|
||||
.feature-item:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.border-gradient-to-r {
|
||||
border-image: linear-gradient(to right, var(--tw-gradient-from), var(--tw-gradient-to)) 1;
|
||||
}
|
||||
|
@ -91,13 +91,18 @@ const featureMap = {
|
||||
CAR061: {
|
||||
name: '名下车辆',
|
||||
component: defineAsyncComponent(() => import('@/ui/CCAR061.vue')),
|
||||
}
|
||||
},
|
||||
IDV044: {
|
||||
name: '婚姻状态',
|
||||
component: defineAsyncComponent(() => import('@/ui/CIDV044.vue')),
|
||||
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异、离异冷静期。如您对查询结果有疑问,请联系客服反馈。'
|
||||
},
|
||||
};
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const productId = ref(null);
|
||||
const isDone = ref(true);
|
||||
const isDone = ref(false);
|
||||
const active = ref(null)
|
||||
const reportData = ref([])
|
||||
const reportParams = ref({})
|
||||
@ -107,9 +112,9 @@ const orderId = ref(null);
|
||||
const orderNo = ref("")
|
||||
const isEmpty = ref(false)
|
||||
const isPending = ref(false)
|
||||
const reportScore = ref(75); // 默认分数
|
||||
const reportScore = ref(0); // 默认分数
|
||||
|
||||
onMounted(() => {
|
||||
onBeforeMount(() => {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
orderNo.value = query.get("out_trade_no");
|
||||
orderId.value = query.get("order_id");
|
||||
@ -152,18 +157,18 @@ const getReport = async () => {
|
||||
} else if (data.value.code === 200002) {
|
||||
isPending.value = true
|
||||
}
|
||||
|
||||
isDone.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 计算综合评分的函数
|
||||
const calculateScore = (reportData) => {
|
||||
// 从0分开始
|
||||
// 从0分开始(0分表示无风险)
|
||||
let score = 0;
|
||||
// 最高分为90分
|
||||
// 最高分为90分(90分表示最高风险)
|
||||
const maxScore = 90;
|
||||
|
||||
// 定义各接口的相对权重比例(而非固定分值)
|
||||
// 定义各接口的相对风险权重比例
|
||||
const relativeWeights = {
|
||||
// 关键风险指标(高优先级)
|
||||
'G34BJ03': 250, // 不良记录
|
||||
@ -194,7 +199,7 @@ const calculateScore = (reportData) => {
|
||||
const availableAPIs = reportData.map(item => item.data.apiID).filter(id => relativeWeights[id]);
|
||||
|
||||
// 如果没有可评分的接口,返回默认分数
|
||||
if (availableAPIs.length === 0) return 60; // 默认60分
|
||||
if (availableAPIs.length === 0) return 30; // 默认30分(中等风险)
|
||||
|
||||
// 计算当前报告中所有接口的相对权重总和
|
||||
let totalWeight = 0;
|
||||
@ -212,7 +217,7 @@ const calculateScore = (reportData) => {
|
||||
actualWeights[apiID] = relativeWeights[apiID] * pointValue;
|
||||
});
|
||||
|
||||
// 遍历报告数据进行评分
|
||||
// 遍历报告数据进行评分 - 风险越高分数越高
|
||||
reportData.forEach(item => {
|
||||
const apiID = item.data.apiID;
|
||||
const data = item.data.data;
|
||||
@ -220,7 +225,7 @@ const calculateScore = (reportData) => {
|
||||
// 如果没有定义权重,跳过
|
||||
if (!actualWeights[apiID]) return;
|
||||
|
||||
// 根据不同的API ID计算分数(只有没有风险或风险低时加分)
|
||||
// 根据不同的API ID计算分数(有风险时加分)
|
||||
switch (apiID) {
|
||||
case 'G09SC02': // 婚姻状态
|
||||
// 不计入风险
|
||||
@ -228,61 +233,58 @@ const calculateScore = (reportData) => {
|
||||
|
||||
case 'G27BJ05': // 借贷申请记录
|
||||
if (data) {
|
||||
// 检查所有字段是否都为0(没有风险)
|
||||
let noRisk = true;
|
||||
// 检查是否有申请记录(有则表示风险)
|
||||
let hasRisk = false;
|
||||
for (const key in data) {
|
||||
if (data[key] !== 0 && data[key] !== '0') {
|
||||
noRisk = false;
|
||||
if (data[key] !== 0 && data[key] !== '0' &&
|
||||
key.indexOf('allnum') > -1 &&
|
||||
!isNaN(parseInt(data[key])) &&
|
||||
parseInt(data[key]) > 0) {
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (noRisk || !Object.keys(data).length) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G28BJ05': // 借贷行为记录
|
||||
if (data) {
|
||||
// 检查所有字段是否都为0(没有风险)
|
||||
let noRisk = true;
|
||||
// 检查是否有借贷记录(有则表示风险)
|
||||
let hasRisk = false;
|
||||
for (const key in data) {
|
||||
if (data[key] !== 0 && data[key] !== '0') {
|
||||
noRisk = false;
|
||||
if (data[key] !== 0 && data[key] !== '0' &&
|
||||
(key.indexOf('lendamt') > -1 || key.indexOf('num') > -1) &&
|
||||
!isNaN(parseInt(data[key])) &&
|
||||
parseInt(data[key]) > 0) {
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (noRisk || !Object.keys(data).length) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G26BJ05': // 违约异常
|
||||
if (data) {
|
||||
// 检查除特定字段外的其他字段是否都为0(没有风险)
|
||||
// 检查除特定字段外的其他字段是否有异常值(有异常则表示风险)
|
||||
const excludeFields = ['swift_number', 'code', 'flag_specialList_c'];
|
||||
let noRisk = true;
|
||||
let hasRisk = false;
|
||||
|
||||
for (const key in data) {
|
||||
if (!excludeFields.includes(key) && data[key] !== 0 && data[key] !== '0') {
|
||||
noRisk = false;
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (noRisk || !Object.keys(data).length) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -291,23 +293,20 @@ const calculateScore = (reportData) => {
|
||||
// 根据风险等级加分
|
||||
switch (data.risk_level) {
|
||||
case 'A': // 无风险
|
||||
score += actualWeights[apiID];
|
||||
// 不加分
|
||||
break;
|
||||
case 'F': // 低风险
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case 'C': // 中风险
|
||||
case 'D': // 中风险
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case 'B': // 高风险
|
||||
case 'E': // 高风险
|
||||
// 不加分
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -342,12 +341,9 @@ const calculateScore = (reportData) => {
|
||||
hasRisk = true;
|
||||
}
|
||||
|
||||
if (!hasRisk) {
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -356,38 +352,29 @@ const calculateScore = (reportData) => {
|
||||
// 根据filterType判断风险等级
|
||||
switch (data.filterType) {
|
||||
case '0': // 安全
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
case '3': // 低危
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case '2': // 中危
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case '1': // 高危
|
||||
// 不加分
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 无数据视为无风险
|
||||
case '3': // 低危
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case '2': // 中危
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case '1': // 高危
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G19BJ02': // 手机二次卡
|
||||
if (data && data.is_second_card === false) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.is_second_card === true) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G02BJ02': // 手机在网时长
|
||||
if (data && data.online_months >= 6) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.online_months < 6) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
@ -396,19 +383,13 @@ const calculateScore = (reportData) => {
|
||||
case 'G17BJ02': // 手机号二要素
|
||||
case 'KZEYS': // 身份证二要素
|
||||
case 'G20GZ01': // 银行卡四要素核验
|
||||
if (data && data.is_consistent) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.is_consistent === false) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'FIN019': // 银行卡黑名单
|
||||
if (data && data.is_blacklisted === false) {
|
||||
score += actualWeights[apiID];
|
||||
} else if (!data) {
|
||||
// 无数据视为无风险
|
||||
if (data && data.is_blacklisted === true) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
@ -603,7 +584,7 @@ const maskValue = computed(() => {
|
||||
<div class="text-sm text-gray-600">身份证信息核验通过</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
|
||||
<!-- <div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
|
||||
<div
|
||||
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
|
||||
✔</div>
|
||||
@ -612,7 +593,7 @@ const maskValue = computed(() => {
|
||||
<div class="text-sm text-gray-600">被查询人姓名与运营商提供的一致</div>
|
||||
<div class="text-sm text-gray-600">被查询人身份证与运营商提供的一致</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -627,11 +608,11 @@ const maskValue = computed(() => {
|
||||
<van-tab v-for="(item, index) in reportData" :key="index"
|
||||
:title="featureMap[item.data.apiID]?.name">
|
||||
<div id="lawsuit" class="title mb-4">{{ featureMap[item.data.apiID]?.name }}</div>
|
||||
<component :is="featureMap[item.data.apiID].component" :data="item.data.data"
|
||||
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
|
||||
:params="reportParams">
|
||||
</component>
|
||||
<LRemark v-if="featureMap[item.data.apiID].remark"
|
||||
:content="featureMap[item.data.apiID].remark" />
|
||||
<LRemark v-if="featureMap[item.data.apiID]?.remark"
|
||||
:content="featureMap[item.data.apiID]?.remark" />
|
||||
</van-tab>
|
||||
<div class="card">
|
||||
<div>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<script setup>
|
||||
|
||||
onMounted(() => {
|
||||
// 插入客服脚本
|
||||
(function (d, t) {
|
||||
const BASE_URL = "https://service.quannengcha.com";
|
||||
const g = d.createElement(t),
|
||||
|
@ -1,5 +1,9 @@
|
||||
<script setup>
|
||||
const router = useRouter()
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const agentStore = useAgentStore()
|
||||
const { isAgent } = storeToRefs(agentStore)
|
||||
import indexIcon1 from '@/assets/images/index_icon_1.png'
|
||||
import indexIcon2 from '@/assets/images/index_icon_2.png'
|
||||
import indexIcon3 from '@/assets/images/index_icon_3.png'
|
||||
@ -17,6 +21,9 @@ function toInvitation() {
|
||||
const toPromote = () => {
|
||||
router.push({ name: "promote" })
|
||||
}
|
||||
function toAgentApply() {
|
||||
router.push({ name: "invitationAgentApplySelf" })
|
||||
}
|
||||
const toHelp = () => {
|
||||
router.push("/help")
|
||||
}
|
||||
@ -110,13 +117,13 @@ function toHistory() {
|
||||
</div>
|
||||
<div class="text-center mt-1 font-bold">邀请下级</div>
|
||||
</div>
|
||||
<!-- <div class="" @click="toHelp">
|
||||
<div class="" @click="toHelp">
|
||||
<div
|
||||
class="h-16 w-16 p-2 bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
|
||||
<img src="@/assets/images/icon_bz.svg" alt="帮助中心" class="w-12 h-12" />
|
||||
</div>
|
||||
<div class="text-center mt-1 font-bold">帮助中心</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="" @click="toHistory">
|
||||
<div
|
||||
class="h-16 w-16 p-2 bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
|
||||
@ -151,6 +158,9 @@ function toHistory() {
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="!isAgent" class="mt-4 rounded-2xl overflow-hidden" @click="toAgentApply">
|
||||
<img src="@/assets/images/index_b_banner.png" class="w-full h-full" mode="widthFix" />
|
||||
</div>
|
||||
<div class="mt-4 box-border h-14 w-full flex items-center rounded-xl bg-white px-4 text-gray-700 shadow-xl"
|
||||
@click="toHistory">
|
||||
<img class="mr-4 h-10 w-10" src="@/assets/images/bg_icon.png" mode="widthFix" />
|
||||
|