base
158
src/App.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<script setup>
|
||||
import { RouterLink, RouterView } from "vue-router";
|
||||
const { isWeChat } = useEnv();
|
||||
import { useAgentStore } from "@/stores/agentStore";
|
||||
import { useUserStore } from "@/stores/userStore";
|
||||
import { useDialogStore } from "@/stores/dialogStore";
|
||||
|
||||
const agentStore = useAgentStore();
|
||||
const userStore = useUserStore();
|
||||
const dialogStore = useDialogStore();
|
||||
|
||||
onMounted(() => {
|
||||
// 检查token版本,如果版本不匹配则清除旧token
|
||||
checkTokenVersion()
|
||||
RefreshToken();
|
||||
const token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
agentStore.fetchAgentStatus();
|
||||
userStore.fetchUserInfo();
|
||||
}
|
||||
});
|
||||
|
||||
const checkTokenVersion = () => {
|
||||
// 设置新的token版本号(当后端token格式改变时,修改这个版本号)
|
||||
const CURRENT_TOKEN_VERSION = '2.1'
|
||||
const storedTokenVersion = localStorage.getItem('tokenVersion')
|
||||
|
||||
if (!storedTokenVersion || storedTokenVersion !== CURRENT_TOKEN_VERSION) {
|
||||
// 清除所有旧的认证信息
|
||||
clearAuthData()
|
||||
|
||||
// 设置新的token版本
|
||||
localStorage.setItem('tokenVersion', CURRENT_TOKEN_VERSION)
|
||||
|
||||
console.log('Token version updated, cleared old authentication data')
|
||||
}
|
||||
}
|
||||
|
||||
// 统一清除认证数据的工具函数
|
||||
const clearAuthData = () => {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refreshAfter')
|
||||
localStorage.removeItem('accessExpire')
|
||||
localStorage.removeItem('userInfo')
|
||||
localStorage.removeItem('agentInfo')
|
||||
}
|
||||
|
||||
const RefreshToken = async () => {
|
||||
if (isWeChat.value) {
|
||||
h5WeixinLogin();
|
||||
return;
|
||||
}
|
||||
const token = localStorage.getItem("token");
|
||||
const refreshAfter = localStorage.getItem("refreshAfter");
|
||||
const accessExpire = localStorage.getItem("accessExpire");
|
||||
const currentTime = new Date().getTime();
|
||||
|
||||
if (accessExpire) {
|
||||
const accessExpireInMilliseconds = parseInt(accessExpire) * 1000; // 转换为毫秒级
|
||||
if (currentTime > accessExpireInMilliseconds) {
|
||||
if (isWeChat.value) {
|
||||
h5WeixinLogin();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 1. 如果没有 token,直接返回
|
||||
if (!token) {
|
||||
if (isWeChat.value) {
|
||||
h5WeixinLogin();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 如果有 refreshAfter,检查当前时间是否超过 refreshAfter(refreshAfter 是秒级,需要转换为毫秒级)
|
||||
if (refreshAfter) {
|
||||
const refreshAfterInMilliseconds = parseInt(refreshAfter) * 1000; // 转换为毫秒级
|
||||
if (currentTime < refreshAfterInMilliseconds) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 3. 如果没有 refreshAfter 或者时间超过 refreshAfter,执行刷新 token 的请求
|
||||
refreshToken();
|
||||
};
|
||||
|
||||
const mpWeixinLogin = () => { };
|
||||
|
||||
const refreshToken = async () => {
|
||||
const { data, error } = await useApiFetch("/user/getToken").post().json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
localStorage.setItem("token", data.value.data.accessToken);
|
||||
localStorage.setItem("refreshAfter", data.value.data.refreshAfter);
|
||||
localStorage.setItem("accessExpire", data.value.data.accessExpire);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const h5WeixinLogin = async () => {
|
||||
// 获取当前URL
|
||||
const url = new URL(window.location.href);
|
||||
// 获取参数
|
||||
const params = new URLSearchParams(url.search);
|
||||
// 获取特定参数值
|
||||
const code = params.get("code");
|
||||
const state = params.get("state");
|
||||
if (code && state) {
|
||||
const { data, error } = await useApiFetch("/user/wxh5Auth")
|
||||
.post({ code })
|
||||
.json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
localStorage.setItem("token", data.value.data.accessToken);
|
||||
localStorage.setItem(
|
||||
"refreshAfter",
|
||||
data.value.data.refreshAfter
|
||||
);
|
||||
localStorage.setItem(
|
||||
"accessExpire",
|
||||
data.value.data.accessExpire
|
||||
);
|
||||
|
||||
params.delete("code");
|
||||
params.delete("state");
|
||||
|
||||
// 更新 URL(不刷新页面)
|
||||
const newUrl = `${url.origin}${url.pathname
|
||||
}?${params.toString()}`;
|
||||
window.history.replaceState({}, "", newUrl);
|
||||
|
||||
agentStore.fetchAgentStatus();
|
||||
userStore.fetchUserInfo();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
h5WeixinGetCode();
|
||||
}
|
||||
};
|
||||
const h5WeixinGetCode = () => {
|
||||
const currentUrl = window.location.href;
|
||||
let redirectUri = encodeURIComponent(currentUrl);
|
||||
let appId = "wxa581992dc74d860e";
|
||||
let state = "snsapi_base";
|
||||
let scope = "snsapi_base";
|
||||
let authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`;
|
||||
// 跳转到授权URL
|
||||
window.location.href = authUrl;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
<BindPhoneDialog />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
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")}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
26
src/assets/base.css
Normal file
@@ -0,0 +1,26 @@
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
html {
|
||||
margin: auto !important;
|
||||
@apply max-w-lg;
|
||||
/* 确保在缩放时保持响应式 */
|
||||
min-width: 320px;
|
||||
}
|
||||
body {
|
||||
background-color: #f8f8f8;
|
||||
min-height: 100vh;
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
BIN
src/assets/images/banner.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
src/assets/images/bg_2.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
src/assets/images/bg_icon.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/images/company_bg.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
75
src/assets/images/empty.svg
Normal file
@@ -0,0 +1,75 @@
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024" height="1024px" width="1024px">
|
||||
<title>空空如也</title>
|
||||
<defs>
|
||||
<rect rx="22.1405405" height="1024" width="1024" y="0" x="0" id="path-1"></rect>
|
||||
<linearGradient id="linearGradient-3" y2="64.8840762%" x2="50%" y1="-33.7184979%" x1="115.913479%">
|
||||
<stop offset="0%" stop-color="#6CADFF"></stop>
|
||||
<stop offset="100%" stop-opacity="0" stop-color="#FFFFFF"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient-4" y2="100%" x2="70.4980572%" y1="-20.569195%" x1="10.5031837%">
|
||||
<stop offset="0%" stop-color="#6CADFF"></stop>
|
||||
<stop offset="100%" stop-opacity="0" stop-color="#FFFFFF"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient-5" y2="104.73608%" x2="38.801584%" y1="-97.78046%" x1="100.191761%">
|
||||
<stop offset="0%" stop-color="#6CADFF"></stop>
|
||||
<stop offset="100%" stop-color="#FFFFFF"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient-6" y2="100%" x2="50%" y1="-27.9013949%" x1="50%">
|
||||
<stop offset="0%" stop-color="#6CADFF"></stop>
|
||||
<stop offset="100%" stop-opacity="0" stop-color="#FFFFFF"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient-7" y2="100%" x2="50%" y1="-27.9013949%" x1="50%">
|
||||
<stop offset="0%" stop-color="#6CADFF"></stop>
|
||||
<stop offset="100%" stop-opacity="0" stop-color="#FFFFFF"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient-8" y2="100%" x2="50%" y1="-221.1569%" x1="50%">
|
||||
<stop offset="0%" stop-color="#D2D2D2"></stop>
|
||||
<stop offset="100%" stop-opacity="0" stop-color="#D2D2D2"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient-9" y2="53.7335012%" x2="73.0360423%" y1="48.1527472%" x1="67.5652976%">
|
||||
<stop offset="0%" stop-opacity="0" stop-color="#858585"></stop>
|
||||
<stop offset="100%" stop-opacity="0.5" stop-color="#616161"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g fill-rule="evenodd" fill="none" stroke-width="1" stroke="none" id="空空如也">
|
||||
<g>
|
||||
<mask fill="white" id="mask-2">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<g id="蒙版"></g>
|
||||
<g mask="url(#mask-2)" id="编组-3">
|
||||
<g transform="translate(0, 238.0108)">
|
||||
<g fill-rule="evenodd" fill="none" stroke-width="1" stroke="none" id="编组-2">
|
||||
<g fill-rule="nonzero" transform="translate(162.5599, 0)" id="编组">
|
||||
<polygon points="592.450826 498.100707 589.3555 489.432325 587.255101 479.632083 586.398359 469.500567 586.868185 459.341443 588.001295 452.660716 589.852963 446.421689 592.367915 440.541544 595.711972 435.158313 599.857498 430.520452 604.887401 426.517537 606.932527 428.091097 608.342006 430.133964 609.060564 432.508107 609.032927 435.075494 608.286732 439.989418 607.070711 451.308006 606.794343 463.813666 607.540538 469.25211 608.894743 472.371623 610.248947 473.448269 612.072979 473.393057 614.864299 471.791891 619.037461 467.319668 626.084854 456.884481 638.963619 434.136879 651.870021 411.527309 659.000324 400.705634 667.015006 390.325661 673.758394 383.451689 680.225413 378.42734 686.471338 374.921338 693.159452 372.491982 699.156645 371.470549 704.628738 371.691399 709.8521 373.126928 714.191083 375.639102 717.783871 379.283135 720.32646 383.755358 721.818849 389.331833 722.150491 396.343837 721.155565 403.328234 718.530066 411.610128 713.942351 421.493188 708.884811 429.471413 700.400302 443.19175 696.006046 451.031943 692.219799 458.706498 689.345568 466.270628 688.212458 472.09556 688.46119 475.601562 689.760121 477.920492 692.109252 479.438839 695.232214 479.714902 698.299903 479.052351 705.070927 476.540176 711.924862 473.393057 718.778797 470.383969 725.384001 468.258282 729.805894 467.595731 734.144877 467.8994 738.511497 469.224503 741.966102 471.377796 744.702148 474.055608 746.857821 477.368366 748.985858 483.000054 750.008421 489.349506 750.036057 495.864596 749.206952 502.158835 746.526179 511.40695 742.104286 520.737884 736.21764 529.406266 728.866242 537.16364 723.283601 541.608256 717.203498 545.25229 710.570657 548.123346 703.606175 550.000575 696.199503 550.745946 688.212458 550.359458 675.554788 548.09574 661.238907 544.396494 646.923027 539.537783 632.855878 533.464394 623.76336 528.688502 615.582857 523.526121 608.203822 517.977252 601.543344 511.683013 596.375256 505.140317 592.533736 498.349164" fill="url(#linearGradient-3)" id="路径"></polygon>
|
||||
<polygon points="39.9075893 440.458725 31.7823599 436.096928 23.6571305 430.216783 16.222822 423.287598 9.75580266 415.447406 4.58771456 406.834236 1.21602073 397.834578 0.0552736694 391.623157 0 385.411737 1.05019972 379.117498 3.59278851 378.896647 5.99719313 379.421167 8.12522941 380.635845 9.83871316 382.54068 12.6023966 386.654021 19.2905106 395.87453 27.4986505 405.315889 31.6994494 408.849497 34.7947749 410.257419 36.5082587 410.146993 37.8348267 408.877103 38.8297528 405.840409 38.9403001 399.711807 37.1439059 387.26136 31.3401706 361.863552 25.7022563 336.465744 23.7676779 323.601202 22.8003886 310.488203 23.242578 300.881206 24.6520566 292.820163 26.9459139 286.056616 30.2899709 279.789983 34.0762172 275.014091 38.2770161 271.508089 43.1134622 269.078734 48.0051819 268.0573 53.1179963 268.333363 57.9820792 269.934529 62.8185253 273.081649 67.7655187 278.050785 71.6899493 283.903324 75.3103746 291.798729 78.5162474 302.206309 80.1191838 311.509637 83.0210515 327.383267 85.0385404 336.134468 87.4153082 344.361149 90.3448127 351.870067 93.4125013 356.977234 95.9550901 359.378984 98.4700421 360.234779 101.206089 359.765472 103.748678 357.888243 105.572709 355.320856 108.916766 348.916191 111.873907 342.014613 114.913959 335.195853 118.368563 329.23289 121.215157 325.782101 124.642125 323.159501 128.78765 321.254665 132.794991 320.509295 136.636511 320.674933 140.450394 321.696366 145.81194 324.429391 150.841844 328.459913 155.236101 333.291018 158.856526 338.508611 162.670409 345.575827 166.788298 354.823942 170.381086 364.762215 173.448775 375.639102 175.604448 386.764446 176.5441 397.641334 176.378279 404.874188 175.41099 411.499703 173.697506 417.628304 171.04437 423.315205 167.396308 428.173916 162.642772 432.314863 157.032495 435.62762 150.344381 438.691921 142.440246 441.424946 130.058944 444.572066 116.2958 446.835784 102.173378 448.160887 87.9956817 448.547375 74.0390802 447.967642 61.3537731 446.504508 49.4422973 443.964727 40.1563208 440.707182" fill="url(#linearGradient-4)" id="路径"></polygon>
|
||||
<path fill="url(#linearGradient-5)" id="形状结合" d="M648.498327,284.510663 L644.71208,289.9215 L641.589118,295.939676 L639.350534,302.344341 L638.217424,308.914643 L638.355608,315.567765 L640.013818,322.165674 L642.224765,326.058164 L644.988449,328.92922 L647.94559,331.579426 L650.571089,334.505696 L652.284573,338.039304 L652.83731,343.588173 L651.648926,349.689168 L649.576163,355.458887 L646.619022,360.952544 L640.428371,370.780391 L633.408615,379.945687 L625.615028,388.53125 L630.092195,393.086292 L633.159883,398.524736 L634.735183,404.570518 L634.707546,410.947577 L633.215157,417.186603 L630.755479,423.066748 L627.411422,428.477585 L623.210623,433.336296 L620.115297,436.234959 L616.384325,438.25022 L612.459894,438.691921 L608.535464,438.25022 L595.960704,435.517195 L583.77286,431.624705 L571.944295,426.57275 L566.555112,423.729299 L561.608118,420.250904 L557.545504,416.027138 L554.864731,410.91997 L554.035626,406.723811 L554.25672,403.769935 L555.251646,401.699462 L557.877146,399.049256 L561.41466,396.895963 L562.685955,396.178199 L566.30638,393.886875 L569.180611,390.822574 L571.253374,386.129501 L572.524668,380.939514 L574.127604,370.55954 L575.150167,359.075314 L575.896362,352.781075 L577.444025,347.121781 L579.212782,343.864236 L581.783008,341.352061 L585.292886,339.557651 L592.533736,338.260154 L599.74695,336.935051 L604.389938,334.754152 L608.176185,331.827883 L611.243873,328.128637 L614.974846,321.696366 L618.180719,314.518725 L618.899277,312.751921 L622.630249,304.663271 L624.785922,300.908813 L627.273238,297.568449 L630.313289,294.86303 L634.292994,292.461281 L642.611681,288.430759 L646.28738,286.387892 L648.498327,284.510663 Z M619.009824,341.73855 L615.195941,346.514442 L606.158696,359.323771 L600.935334,367.854122 L595.463241,378.013245 L590.626795,388.807313 L586.702364,400.346752 L584.795423,408.269764 L583.717586,416.192776 L583.468855,424.115788 L595.325057,424.115788 L596.319983,416.109957 L599.912771,395.929742 L602.925186,383.313657 L607.153622,369.234437 L612.432257,355.238037 L619.009824,341.73855 Z"></path>
|
||||
<polygon points="125.250135 60.7614951 125.250135 60.7614951 124.559214 54.3016178 122.431178 48.4214731 119.059484 43.2314863 114.55468 38.9249014 109.165497 35.7777818 102.947209 33.9005525 96.4525532 33.5416704 90.3171759 34.7011355 84.6239879 37.21331 79.6769945 40.9677686 75.6972903 45.7712671 72.8783332 51.6238055 66.8258663 52.3415696 61.3537731 54.5500746 56.6278743 58.111289 52.9245385 62.9147875 50.658318 68.5464754 49.9673972 74.3990138 50.8517759 80.2515521 53.3114542 85.8004211 57.1529742 90.4934943 61.9894203 93.8890708 67.5444241 95.931938 73.569254 96.4564579 123.011551 96.4564579 127.626903 95.7663001 131.634244 94.1375276 135.171759 91.5149279 137.963079 88.1193514 139.78711 84.1992549 140.699126 79.6442132 140.367484 74.9787463 139.013279 70.8654057 136.664148 67.1661597 133.513549 64.1294653 129.727302 62.0037792" fill="url(#linearGradient-6)" id="路径"></polygon>
|
||||
<polygon points="329.569254 33.7073083 329.569254 33.5416704 329.127065 28.130833 327.911044 23.0788777 325.921192 18.3305919 321.665119 11.9259273 316.054842 6.65312145 311.715859 3.89249014 306.934686 1.84962298 301.656051 0.496913635 296.266868 0 291.071143 0.35888207 286.041239 1.49074091 278.993846 4.61025428 272.858469 9.22050857 269.376228 13.0301798 266.557271 17.3643709 264.318687 22.305901 259.205873 22.8856335 254.507611 24.2383429 250.196265 26.364029 246.299471 29.2074792 243.010688 32.6030557 240.302278 36.5783648 238.284789 40.9677686 237.096405 45.6608418 236.681853 50.7956161 237.234589 55.902784 238.588794 60.5682509 240.744467 64.8748357 243.591061 68.7673259 246.990392 72.0524771 250.970096 74.7855021 255.364353 76.7731567 260.062615 77.9878345 265.203066 78.3743228 326.612113 78.3743228 332.360574 77.6565587 337.501026 75.5860852 341.950556 72.3285403 345.488071 68.1047744 347.892475 63.1080317 348.997949 57.4211312 348.611033 51.6514118 346.842276 46.378606 343.885134 41.7683517 339.877793 37.9862868 335.041347 35.2808681 329.403433 33.8453398" fill="url(#linearGradient-7)" id="路径"></polygon>
|
||||
</g>
|
||||
<polygon points="1024 550.359458 999.596675 534.403009 973.839145 519.164324 946.672136 504.615797 918.040376 490.785034 889.159883 478.224161 859.118644 466.491478 827.833747 455.669804 795.305193 445.703925 762.693728 437.007936 729.114974 429.360987 694.541293 422.735472 658.917413 417.186603 623.348807 412.880018 587.034006 409.760505 549.945374 407.883276 512 407.193118 474.054626 407.883276 436.965994 409.760505 400.623556 412.880018 365.082587 417.186603 329.458707 422.735472 294.885026 429.360987 261.306272 437.007936 228.694807 445.703925 196.166253 455.669804 164.881356 466.491478 134.840117 478.224161 105.931987 490.785034 77.3278635 504.615797 50.160855 519.164324 24.4033251 534.403009 0 550.359458" fill-rule="nonzero" fill="url(#linearGradient-8)" id="路径"></polygon>
|
||||
</g>
|
||||
<polygon points="168.585366 389.215532 314.612039 389.215532 461.536985 469.266954 317.214646 465.594981" fill-rule="nonzero" fill="url(#linearGradient-9)" stroke="none" id="矩形"></polygon>
|
||||
<polygon points="481.155803 208.25638 479.722777 299.451613 688.569371 236.303345" fill-rule="nonzero" fill="#B8D6FF" stroke="none" id="路径"></polygon>
|
||||
<polygon points="314.788219 244.959395 481.155803 208.631248 481.155803 264.00952" fill-rule="nonzero" fill="#9CC6FF" stroke="none" id="路径"></polygon>
|
||||
<polygon points="314.788219 244.959395 511.147006 264.384388 511.147006 512.547202 314.788219 465.075243" fill-rule="nonzero" fill="#64ADFF" stroke="none" id="路径"></polygon>
|
||||
<polygon points="314.788219 244.959395 511.283486 263.617612 489.889892 383.428742 314.788219 346.994453" fill-rule="nonzero" fill="#429BFF" stroke="none" id="矩形"></polygon>
|
||||
<polygon points="511.147006 264.384388 688.569371 236.303345 688.569371 458.600245 511.147006 512.547202" opacity="0.99" fill-rule="nonzero" fill="#9CC5FF" stroke="none" id="路径"></polygon>
|
||||
<polygon points="511.283486 264.997809 671.897967 239.34913 688.569371 344.292902 535.025228 383.428742" fill-rule="nonzero" fill="#64ADFF" stroke="none" id="矩形"></polygon>
|
||||
<polygon points="314.788219 244.959395 267.566573 324.806343 465.801946 362.565804 511.147006 264.384388" fill-rule="nonzero" fill="#9CC6FF" stroke="none" id="路径"></polygon>
|
||||
<polygon points="511.147006 264.384388 566.898574 362.565804 745.583366 317.786082 688.569371 236.303345" opacity="0.99" fill-rule="nonzero" fill="#9DC6FF" stroke="none" id="路径"></polygon>
|
||||
<path stroke-dasharray="11.05477807439905,8.29108355579929" fill="none" stroke-width="5.52738904" stroke="#9DC6FF" id="路径-19" d="M583.139543,151.843183 C532.695151,184.875351 501.824507,214.257045 511.001904,232.450753 C523.475834,257.179661 544.659409,246.913618 547.874,236.537816 C551.088588,226.162013 542.242035,205.908265 523.475834,216.933951 C504.709635,227.959637 484.261479,247.732311 479.722777,267.098145"></path>
|
||||
<g transform="translate(555.0939, 41.4059)" fill-rule="evenodd" fill="none" stroke-width="1" stroke="none" id="飞机">
|
||||
<polygon points="163.057977 9.09494702e-13 0 30.854292 41.4554178 58.3378535" fill-rule="nonzero" fill="#9DC6FF" id="路径-16备份"></polygon>
|
||||
<polygon points="163.057977 0 41.4554178 58.3378535 41.4554178 104.894966" fill-rule="nonzero" fill="#64ADFF" id="路径-16备份-2"></polygon>
|
||||
<polygon points="163.057977 0 41.4554178 58.3378535 65.4910753 84.1769753" fill-rule="nonzero" fill="#429BFF" id="路径-16备份-2"></polygon>
|
||||
<polygon points="163.057977 0 58.9237102 70.0692202 108.951745 102.134572" fill-rule="nonzero" fill="#9DC6FF" id="路径-16备份"></polygon>
|
||||
<line stroke-linecap="round" stroke-width="2.76369452" stroke="#429BFF" id="路径-16" y2="32.1173295" x2="0.501635492" y1="58.3378535" x1="41.4554178"></line>
|
||||
<line stroke-linecap="round" stroke-width="2.76369452" stroke="#429BFF" id="路径-17" y2="101.744072" x2="107.648858" y1="71.0666294" x1="59.7211085"></line>
|
||||
<line stroke-linecap="round" stroke-width="2.76369452" stroke="#429BFF" id="路径-18" y2="103.502333" x2="41.4554178" y1="58.3378535" x1="41.4554178"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
1
src/assets/images/gdrqgx_icon.svg
Normal file
@@ -0,0 +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="1733324501181" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6340" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M339.162366 1023.729653c-95.973119 0-127.972351-435.012601-127.97235-518.254842 0-63.900156 121.557758-115.167743 121.557758-115.167743h127.972351s6.390016 51.193856 31.950078 63.900156C466.962679 479.865595 441.476347 742.224889 460.670971 799.759606a214.974871 214.974871 0 0 0 51.193856 95.973119 227.681171 227.681171 0 0 0 63.900156-95.973119c6.414593-51.193856 0-307.212288-25.58464-345.503228a90.394144 90.394144 0 0 0 25.58464-63.900156h127.97235s115.143166 44.80384 108.753151 115.167743c0 76.778495-44.80384 505.450234-140.776959 518.254842z m511.864827-204.750846c12.780031-51.193856 19.170047-319.918589-19.194624-390.307068s-147.166975-89.558526-147.166974-102.363135c0-6.390016 25.584639-12.780031 44.80384-12.780031h211.140861a84.692284 84.692284 0 0 1 83.193088 83.168511l-25.682947 351.893244c-6.414593 51.193856-44.779263 70.38848-102.387712 70.388479z m-729.395704 0c-57.583871 0-89.583103-19.194624-102.363134-70.388479L0 396.697084a84.692284 84.692284 0 0 1 83.168511-83.168511h204.750846c19.170047 0 44.80384 0 44.80384 12.780031s-108.777727 31.950078-147.166975 102.363135-31.950078 339.162366-19.194624 390.307068z m230.261755-652.617209A169.384567 169.384567 0 0 1 518.254842 0a169.581183 169.581183 0 0 1 0 339.162366 170.785455 170.785455 0 0 1-166.361598-172.800768z m377.50246 12.780032a101.060554 101.060554 0 0 1 102.363134-102.363135 95.850234 95.850234 0 0 1 102.363135 95.973119 101.060554 101.060554 0 0 1-102.363135 102.363135 99.635089 99.635089 0 0 1-102.363134-95.973119z m-639.812601 0A101.060554 101.060554 0 0 1 191.946238 76.778495a99.659666 99.659666 0 0 1 102.363134 95.973119 101.060554 101.060554 0 0 1-102.363134 102.363135 95.850234 95.850234 0 0 1-102.363135-95.973119z" fill="#4B64FA" p-id="6341"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
src/assets/images/grbl_icon.svg
Normal file
@@ -0,0 +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="1733326573199" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9341" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M390.063158 950.649263a104.286316 104.286316 0 0 0-10.644211 50.149053H26.947368v-150.042948c0-220.779789 177.259789-400.410947 395.290948-400.410947 68.985263 0 133.820632 18.081684 190.383158 49.744842l-222.558316 450.56z m32.175158-550.346105c-109.029053 0-197.658947-89.869474-197.658948-200.218947C224.579368 89.788632 313.236211 0 422.265263 0s197.632 89.734737 197.632 200.218947c0 110.322526-88.656842 200.084211-197.632 200.084211z m571.930947 583.895579c8.973474 18.270316-4.149895 39.801263-24.306526 39.801263H480.741053c-20.156632 0-33.306947-21.530947-24.306527-39.801263l244.601263-495.400421a27.028211 27.028211 0 0 1 48.613053 0l244.493474 495.400421z m-296.016842-42.738526h54.298947v-55.080422h-54.298947v55.080422z m0-110.133895h54.298947v-137.620211h-54.298947v137.620211z" fill="#4B64FA" p-id="9342"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/images/grss_icon.svg
Normal file
@@ -0,0 +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="1733326791000" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="28866" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M425.3 245.5c80.1 0 126.4 50.8 126.4 147.4 0 55.2-19 102.2-47.9 132.4-9.1 15.2-13.9 37.5-13.9 47.4 0 5.9 4.6 13.7 13 21.9-20.1 9.4-32.7 29-32.5 50.5v22.8c0 24.7 16 45.4 38.5 52.9-8.7 19.1-6.1 41.1 6.7 57.9h-339c-12.7 0-23-10.1-23-24 0-30.9 4.6-51.4 13.7-61.4 22.5-24.7 70.7-46.4 118.3-62.9 47.6-16.4 74.5-42.8 74.5-57.6 0-10.2-5-33.6-14.6-48.8-28.2-30.2-46.6-76.7-46.6-131 0.1-96.8 46.4-147.5 126.4-147.5z m241 266.7l66.9 68.4-9.8 8.6 15.4 16.6-10.3 9 128.3 125.3c6.6 6.3 22.4 21.6 7.1 33.8-15.4 12.2-29.4-4.9-36-11.2l-125.6-124-12.2 10.8-15.4-16.6-8.9 7.6-66.4-68.4 66.9-59.9z m50.8 205.9c7.9 0 14.5 6.3 14.5 14l0.5 3.6c11.7 0 21 9 21 20.2v18h-201v-18c0-11.2 9.3-20.2 21-20.2h1.4v-3.6c0-7.7 6.6-14 14.5-14h128.1zM593.3 578.4l65.5 67.5c6.6 6.7 6.6 18-1 24.3l-10.3 9c-7 6.3-18.7 5.8-25.2-1l-65.5-67.5c-6.6-6.7-6.6-18 1-24.3l10.3-9c7-6.2 18.7-6.2 25.2 1z m116.5-104l65.5 67.5c6.6 6.7 6.6 18-1 24.3l-10.3 9c-7 6.3-18.7 6.3-25.2-0.9l-65.5-67.4c-6.6-6.7-6.6-18 1-24.3l10.3-9c6.9-6.4 18.1-5.9 25.2 0.8z" fill="#4B64FA" p-id="28867"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/images/head_shot.webp
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/assets/images/icon_1.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
src/assets/images/icon_2.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
src/assets/images/icon_3.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
src/assets/images/icon_4.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
1
src/assets/images/icon_bg.svg
Normal file
@@ -0,0 +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="1740754594473" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="36608" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M102.4 256a102.4 102.4 0 0 1 102.4-102.4h340.2752a102.4 102.4 0 0 1 95.0784 64.3584L665.6 281.6c3.3792 8.3968 5.4272 17.0496 6.2464 25.6H819.2a51.2 51.2 0 0 1 51.2 51.2v512a51.2 51.2 0 0 1-51.2 51.2H153.6a51.2 51.2 0 0 1-51.2-51.2V256z" fill="#2357DF" opacity=".5" p-id="36609"></path><path d="M238.592 409.6h681.8304a51.2 51.2 0 0 1 50.176 61.44l-83.8656 409.6a51.2 51.2 0 0 1-50.176 40.96H154.7776a51.2 51.2 0 0 1-50.176-61.44l83.8656-409.6a51.2 51.2 0 0 1 50.176-40.96z" fill="#2357DF" p-id="36610"></path><path d="M358.4 640m25.6 0l307.2 0q25.6 0 25.6 25.6l0 0q0 25.6-25.6 25.6l-307.2 0q-25.6 0-25.6-25.6l0 0q0-25.6 25.6-25.6Z" fill="#FFFFFF" p-id="36611"></path></svg>
|
||||
|
After Width: | Height: | Size: 1007 B |
1
src/assets/images/icon_bz.svg
Normal file
@@ -0,0 +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="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>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/images/icon_cwhy.svg
Normal file
@@ -0,0 +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="1757768265875" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12302" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 1024C229.233778 1024 0 794.766222 0 512S229.233778 0 512 0s512 229.233778 512 512-229.233778 512-512 512z m284.444444-595.228444a72.490667 72.490667 0 0 0-20.807111-50.432 71.253333 71.253333 0 0 0-100.892444 0 66.816 66.816 0 0 0-20.807111 50.432 68.707556 68.707556 0 0 0 20.807111 50.432c2.474667 3.015111 5.461333 5.575111 8.817778 7.566222a78.833778 78.833778 0 0 1-93.312 13.866666 104.661333 104.661333 0 0 1-49.180445-58.638222 189.084444 189.084444 0 0 1 5.034667-51.057778 71.864889 71.864889 0 0 0 37.205333-63.047111 70.599111 70.599111 0 0 0-20.807111-50.432 70.001778 70.001778 0 0 0-100.892444 0 71.864889 71.864889 0 0 0-20.807111 50.432 72.490667 72.490667 0 0 0 20.807111 50.446223c5.632 5.304889 12.003556 9.770667 18.915555 13.226666a131.100444 131.100444 0 0 1 3.797334 48.554667 105.287111 105.287111 0 0 1-49.820445 59.875555 81.351111 81.351111 0 0 1-95.217778-14.492444 71.864889 71.864889 0 0 0 30.264889-58.624 71.253333 71.253333 0 0 0-70.613333-69.347556 72.533333 72.533333 0 0 0-50.446222 20.807112 71.224889 71.224889 0 0 0 0 100.864 70.627556 70.627556 0 0 0 30.890666 18.275555l59.278223 247.125333a28.373333 28.373333 0 0 0 27.107555 21.432889H658.346667a27.733333 27.733333 0 0 0 27.121777-21.432889l59.264-247.125333A71.864889 71.864889 0 0 0 796.444444 428.771556z" fill="#D7A26A" p-id="12303"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
1
src/assets/images/icon_index_apistore.svg
Normal file
@@ -0,0 +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="1739431145867" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1589" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M795.442 73a38 38 0 0 1 35.204 23.693L951.218 393.37c7.042 17.326 0.43 37.2-15.589 46.854l-2.63 1.583L933 860c0 52.49-42.125 95.14-94.412 95.987L837 956H198c-52.49 0-95.14-42.125-95.987-94.412L102 860V450.436l-16.391-10.474c-15.605-9.972-21.727-29.72-14.57-46.741l0.22-0.515L201.222 95.764A38 38 0 0 1 236.034 73z m-77.406 373.306l-37.677 22.708c-41.905 25.255-94.4 24.824-135.854-1.01l-1.252-0.79-32.717-20.908-37.677 22.708c-41.905 25.255-94.4 24.824-135.854-1.01l-1.252-0.79-32.717-20.908-39.657 23.901c-30.927 18.64-67.792 22.875-101.38 12.828L162 860c0 19.683 15.797 35.677 35.405 35.995L198 896h639c19.683 0 35.677-15.797 35.995-35.405L873 860V476.714c-39.43 17.315-85.348 14.08-122.247-9.5l-32.717-20.908z m62.598-313.307H250.42L133.766 399.531l28.744 18.37a66.275 66.275 0 0 0 69.25 1.303l0.648-0.386 71.555-43.124 64.099 40.962a70 70 0 0 0 73.827 0.969l69.574-41.931 64.099 40.962a70 70 0 0 0 73.827 0.969l69.574-41.931 64.099 40.962a70 70 0 0 0 73.827 0.969l31.665-19.084-107.92-265.542z" fill="#1296db" p-id="1590"></path><path d="M335.81 565.173l54.876 0.41 82.301 190-55.056 23.85-16.649-38.434h-78.957l-17.52 38.844-54.693-24.67 85.699-190z m26.792 86.529l-13.215 29.297h25.905l-12.69-29.297zM502.395 561.66l60 0.11v0.236l0.492 0.005c45.692 0.736 82.613 37.772 82.613 83.489 0 45.717-36.92 82.753-82.613 83.489l-0.803 0.005-0.084 46.061-60-0.11 0.395-213.286z m59.888 60.352l-0.087 46.978c12.991-0.36 23.304-10.8 23.304-23.49 0-12.662-10.267-23.083-23.217-23.488zM691.697 561.66l60 0.11-0.394 213.285-60-0.11z" fill="#1296db" p-id="1591"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
1
src/assets/images/icon_index_chacheliang.svg
Normal file
@@ -0,0 +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="1736930506398" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18562" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M997.307733 535.210667A353.09568 353.09568 0 0 1 791.893333 600.746667c-59.255467 0-115.0976-14.609067-164.2496-40.277334-149.9136 11.0592-300.987733 1.024-448.7168-30.378666 24.712533-67.9936 46.011733-131.549867 74.205867-193.262934a57.685333 57.685333 0 0 1 37.205333-25.463466l152.234667-2.389334C438.954667 288.426667 436.906667 267.332267 436.906667 245.76c0-8.055467 0.341333-16.042667 0.887466-23.9616-62.805333 0.6144-110.523733 3.345067-121.105066 5.3248-71.8848 5.870933-132.369067 56.1152-151.483734 125.610667-14.472533 47.104-31.470933 93.3888-50.926933 138.717866-3.549867 9.216-15.223467 21.367467-21.2992 21.367467C40.96 508.040533 20.548267 539.716267 5.3248 580.471467a61.269333 61.269333 0 0 0 0 24.917333l53.6576 13.789867c-3.072 74.205867-3.072 147.933867-3.072 221.5936 0 39.7312 0 78.301867 3.072 119.057066 0.136533 19.456 6.485333 38.2976 18.158933 53.8624a477.934933 477.934933 0 0 0 166.0928 0c11.127467-4.096 16.725333-61.986133 26.350934-96.597333h492.1344c12.0832 32.494933-11.195733 72.635733 26.282666 96.597333a475.436373 475.436373 0 0 0 162.133334-3.072 80.827733 80.827733 0 0 0 17.2032-46.557866V682.3936c-1.092267-20.48-3.4816-40.891733-7.031467-61.098667l57.7536-15.496533c2.594133-10.376533 2.594133-21.162667 0-31.5392-2.935467-15.428267-10.4448-28.808533-20.753067-39.048533z m-688.128 206.848a50.223787 50.223787 0 0 1-32.836266 24.917333c-17.885867 3.072-36.0448 4.096-54.203734 3.072l2.389334-1.160533c-28.330667-2.594133-53.179733-3.549867-79.0528-8.669867-32.904533-7.031467-43.281067-31.470933-32.904534-75.639467 5.051733-30.037333 29.422933-31.5392 50.722134-24.507733a1187.089067 1187.089067 0 0 1 126.634666 50.926933c10.103467 4.642133 21.845333 23.483733 19.2512 31.061334z m576.375467 17.681066c-26.282667 4.9152-52.8384 8.3968-79.530667 10.376534h-0.273066v-0.546134c-22.9376-0.6144-45.738667-2.594133-68.4032-6.075733-25.326933-5.597867-33.3824-35.157333-11.127467-45.806933 49.152-23.074133 99.9424-42.461867 152.029867-57.9584 20.753067-6.075733 34.542933 6.621867 35.976533 33.518933 1.4336 26.965333 9.216 58.026667-28.672 66.491733z" p-id="18563" fill="#1296db"></path><path d="M589.073067 230.263467h7.645866c0 88.064 72.772267 160.836267 160.836267 160.836266s160.836267-72.772267 160.836267-160.836266-72.772267-160.836267-160.836267-160.836267-160.836267 72.704-160.836267 160.836267h-7.645866z m421.205333 210.5344c11.4688 11.4688 11.4688 30.651733 0 42.120533s-30.651733 11.4688-42.120533 0L891.562667 406.3232c-38.2976 30.651733-84.241067 45.943467-134.075734 45.943467-122.538667 0-222.0032-99.601067-222.0032-222.0032 0-122.538667 99.601067-222.0032 222.0032-222.0032 122.538667 0 222.0032 99.601067 222.0032 222.0032 0 49.7664-15.291733 95.778133-45.943466 134.075733l76.731733 76.458667z" p-id="18564" fill="#1296db"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
1
src/assets/images/icon_lxkf.svg
Normal file
@@ -0,0 +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="1757768310883" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16196" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 0c282.779826 0 512 229.220174 512 512S794.779826 1024 512 1024 0 794.779826 0 512 229.220174 0 512 0z m-1.135304 225.925565c-138.017391 0-250.278957 114.287304-250.278957 255.777392 0 1.157565 0.089043 2.29287 0.222609 3.428173-0.222609 1.825391-0.222609 3.695304-0.222609 5.565218v71.858087c-1.914435 37.62087 28.360348 69.654261 67.82887 71.746782h16.962782c39.535304-2.070261 69.854609-34.170435 67.895652-71.835826v-71.791304c1.936696-37.62087-28.338087-69.676522-67.806608-71.791304h-16.985044a64.111304 64.111304 0 0 0-7.234782 0.400695c17.92-65.313391 71.457391-116.335304 140.020869-133.431652 104.759652-26.112 211.878957 33.613913 239.304348 133.431652a64.155826 64.155826 0 0 0-7.279304-0.400695h-16.962783c-39.513043 2.048-69.832348 34.148174-67.895652 71.791304v71.902609c-1.958957 37.64313 28.382609 69.765565 67.895652 71.813565h12.510609a186.479304 186.479304 0 0 1-88.909913 80.428522 36.59687 36.59687 0 0 0-36.173913-9.728l-49.196522 13.935304c-20.992 7.346087-32.589913 28.805565-26.713043 49.374609l0.512 2.159304c5.030957 19.389217 25.6 31.254261 45.990956 26.445913l49.174261-13.935304c15.805217-5.075478 26.86887-18.69913 28.048696-34.504348 57.032348-25.132522 100.886261-71.257043 121.36626-127.799652a73.104696 73.104696 0 0 0 28.204522-58.278957v-71.813565l-0.222609-5.565217c0.155826-1.113043 0.222609-2.270609 0.222609-3.405913 0-141.490087-112.261565-255.777391-250.278956-255.777392z" fill="#2196F3" p-id="16197"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
src/assets/images/icon_share_friends.svg
Normal file
@@ -0,0 +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="1739523534229" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14507" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M491.52 0c-20.48 0-40.96 2.275556-59.164444 4.551111-47.786667 4.551111-93.297778 15.928889-136.533334 31.857778 0 0 354.986667 336.782222 364.088889 350.435555V27.306667c-11.377778-4.551111-20.48-6.826667-31.857778-9.102223-43.235556-11.377778-88.746667-18.204444-136.533333-18.204444z" fill="#F26848" p-id="14508"></path><path d="M853.333333 118.328889c-13.653333-15.928889-29.582222-29.582222-45.511111-40.96C769.137778 45.511111 728.177778 20.48 682.666667 0c0 0 2.275556 530.204444 0 546.133333l273.066666-279.893333c-4.551111-11.377778-11.377778-20.48-15.928889-31.857778-22.755556-40.96-52.337778-79.644444-86.471111-116.053333z" fill="#5D62D4" p-id="14509"></path><path d="M987.591111 295.822222S650.808889 650.808889 637.155556 659.911111h359.537777c4.551111-11.377778 6.826667-20.48 9.102223-31.857778 11.377778-43.235556 18.204444-88.746667 18.204444-136.533333 0-20.48-2.275556-40.96-4.551111-59.164444-4.551111-47.786667-15.928889-93.297778-31.857778-136.533334z" fill="#4694E9" p-id="14510"></path><path d="M757.76 955.733333c9.102222-4.551111 20.48-11.377778 29.582222-15.928889 38.684444-22.755556 75.093333-52.337778 106.951111-86.471111 13.653333-13.653333 27.306667-29.582222 38.684445-45.511111 27.306667-38.684444 52.337778-79.644444 70.542222-125.155555 0 0-484.693333 2.275556-500.622222 0l254.862222 273.066666z" fill="#69DEF0" p-id="14511"></path><path d="M364.088889 637.155556v359.537777c11.377778 4.551111 20.48 6.826667 31.857778 9.102223 43.235556 11.377778 88.746667 18.204444 136.533333 18.204444 20.48 0 40.96-2.275556 59.164444-4.551111 47.786667-4.551111 93.297778-15.928889 136.533334-34.133333C728.177778 987.591111 373.191111 650.808889 364.088889 637.155556z" fill="#83E45A" p-id="14512"></path><path d="M341.333333 455.111111L68.266667 735.004444c4.551111 11.377778 11.377778 20.48 15.928889 31.857778 22.755556 43.235556 52.337778 81.92 86.471111 116.053334 13.653333 15.928889 29.582222 29.582222 45.511111 40.96C254.862222 955.733333 298.097778 983.04 341.333333 1001.244444c0 0-2.275556-530.204444 0-546.133333z" fill="#BBDC64" p-id="14513"></path><path d="M18.204444 395.946667c-11.377778 43.235556-18.204444 88.746667-18.204444 136.533333 0 20.48 2.275556 40.96 4.551111 59.164444 4.551111 47.786667 15.928889 93.297778 34.133333 136.533334 0 0 336.782222-354.986667 350.435556-364.088889H27.306667c-4.551111 11.377778-6.826667 20.48-9.102223 31.857778z" fill="#F3DF68" p-id="14514"></path><path d="M248.035556 84.195556C207.075556 106.951111 170.666667 136.533333 136.533333 170.666667c-13.653333 13.653333-27.306667 29.582222-40.96 45.511111C65.991111 254.862222 40.96 295.822222 22.755556 341.333333c0 0 507.448889-2.275556 523.377777 0L277.617778 68.266667c-11.377778 4.551111-20.48 11.377778-29.582222 15.928889z" fill="#F7B964" p-id="14515"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
1
src/assets/images/icon_share_img.svg
Normal file
@@ -0,0 +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="1739523547121" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15535" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M1024 512c0 282.794667-229.205333 512-512 512S0 794.794667 0 512 229.205333 0 512 0s512 229.205333 512 512" fill="#FA7268" p-id="15536"></path><path d="M685.226667 355.157333h-27.374934a20.616533 20.616533 0 0 0-20.6848 20.718934c0 11.434667 9.216 20.650667 20.6848 20.650666h27.374934c5.051733 0 9.216 4.130133 9.216 9.216v305.732267a9.216 9.216 0 0 1-9.216 9.216H339.114667a9.216 9.216 0 0 1-9.216-9.216v-305.732267c0-5.085867 4.096-9.216 9.216-9.216h27.989333c11.4688 0 20.6848-9.216 20.6848-20.6848a20.616533 20.616533 0 0 0-20.6848-20.650666h-27.989333a50.517333 50.517333 0 0 0-50.5856 50.551466v305.732267c0 27.989333 22.562133 50.5856 50.551466 50.5856h345.8048a50.517333 50.517333 0 0 0 50.5856-50.5856v-305.732267a50.005333 50.005333 0 0 0-50.244266-50.5856" fill="#FFFFFF" p-id="15537"></path><path d="M480.6656 500.565333a20.923733 20.923733 0 0 0-29.2864 0l-86.8352 86.8352a20.923733 20.923733 0 0 0 0 29.2864c4.130133 4.096 9.216 6.007467 14.6432 6.007467a20.241067 20.241067 0 0 0 14.6432-6.007467l72.192-72.226133 72.226133 72.226133a4.949333 4.949333 0 0 0 1.604267 1.262934 20.241067 20.241067 0 0 0 13.0048 4.437333 18.944 18.944 0 0 0 9.250133-2.218667 20.514133 20.514133 0 0 0 5.393067-3.822933l86.8352-86.869333a20.855467 20.855467 0 0 0 0-29.252267 20.923733 20.923733 0 0 0-29.218133 0l-72.260267 72.226133-72.192-71.8848zM497.834667 440.763733c4.130133 4.130133 9.216 6.0416 14.6432 6.0416a20.206933 20.206933 0 0 0 14.6432-6.0416l87.7568-87.825066a20.855467 20.855467 0 0 0 0-29.252267 20.8896 20.8896 0 0 0-29.218134 0L532.821333 376.490667V231.424a20.616533 20.616533 0 0 0-20.650666-20.650667 20.616533 20.616533 0 0 0-20.6848 20.650667v144.418133l-52.189867-51.882666a20.957867 20.957867 0 0 0-29.252267 0 20.923733 20.923733 0 0 0 0 29.320533l87.790934 87.483733z" fill="#FFFFFF" p-id="15538"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
1
src/assets/images/icon_share_url.svg
Normal file
@@ -0,0 +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="1739523560037" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16553" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M512 0C229.376 0 0 229.376 0 512s229.376 512 512 512 512-229.376 512-512S794.624 0 512 0z" fill="#0087FF" p-id="16554"></path><path d="M575.8976 449.536l-11.264-11.264c-5.7344-5.7344-11.264-5.7344-16.9984-5.7344-14.1312 0-25.6 11.264-25.6 25.6 0 5.7344 2.8672 11.264 5.7344 16.9984 0 0 2.8672 2.8672 5.7344 2.8672 2.8672 2.8672 5.7344 2.8672 5.7344 5.7344l2.8672 2.8672c25.6 25.6 16.9984 70.8608-8.6016 96.256l-110.592 110.592c-25.6 25.6-67.9936 25.6-93.5936 0l-2.8672-2.8672c-25.6-25.6-25.6-67.9936 0-93.5936l48.128-48.128c5.7344-5.7344 11.264-11.264 11.264-22.7328 0-14.1312-11.264-28.2624-28.2624-28.2624-5.7344 2.8672-11.264 5.7344-14.1312 8.6016-2.8672 0-2.8672 2.8672-5.7344 5.7344L286.72 560.3328c-48.128 48.128-48.128 127.5904 0 175.7184l2.8672 2.8672c48.128 48.128 127.5904 48.128 175.7184 0l110.592-110.592c48.128-51.4048 50.9952-127.7952 0-178.7904z m0 0" fill="#FFFFFF" p-id="16555"></path><path d="M737.4848 287.9488c-50.9952-50.9952-130.4576-50.9952-175.7184-2.8672l-113.2544 110.592c-48.128 48.128-50.9952 116.1216-2.8672 167.1168h2.8672l11.264 11.264c2.8672 2.8672 8.6016 2.8672 11.264 2.8672 14.1312 0 22.7328-11.264 22.7328-22.7328 0-2.8672 0-8.6016-2.8672-11.264 0-5.7344-5.7344-11.264-8.6016-14.1312l-2.8672-2.8672c-25.6-25.6-16.9984-62.2592 8.6016-90.7264l110.592-110.592c25.6-25.6 67.9936-25.6 93.5936 0l2.8672 2.8672c25.6 25.6 25.6 67.9936 0 93.5936l-48.128 48.128c-5.7344 5.7344-11.264 14.1312-11.264 22.7328 0 14.1312 11.264 28.2624 28.2624 28.2624 5.7344 0 11.264 0 14.1312-2.8672 2.8672-2.8672 5.7344-2.8672 5.7344-5.7344l50.9952-48.128c50.7904-50.7904 50.7904-127.3856 2.6624-175.5136z m0 0" fill="#FFFFFF" p-id="16556"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
1
src/assets/images/icon_share_wechat.svg
Normal file
@@ -0,0 +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="1739523523170" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13404" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#15C521" p-id="13405"></path><path d="M665.00608 409.47712c3.66592 0 7.24992 0.06144 10.83392 0.24576-18.96448-104.448-125.68576-184.44288-254.50496-184.44288C279.10144 225.28 163.84 322.7648 163.84 443.02336c0 70.51264 39.6288 133.20192 101.0688 172.99456l2.37568 1.49504L242.3808 696.32l93.10208-47.9232 4.38272 1.24928a300.8512 300.8512 0 0 0 98.77504 10.56768 170.63936 170.63936 0 0 1-8.192-51.93728c0-109.7728 105.0624-198.79936 234.55744-198.79936z m-154.07104-76.84096c19.968 0 36.1472 15.83104 36.1472 35.40992 0 19.51744-16.1792 35.38944-36.1472 35.38944-19.98848 0-36.1472-15.872-36.1472-35.38944 0-19.57888 16.1792-35.40992 36.1472-35.40992z m-179.2 70.79936c-19.968 0-36.1472-15.872-36.1472-35.38944 0-19.57888 16.1792-35.40992 36.1472-35.40992 19.98848 0 36.18816 15.83104 36.18816 35.40992 0 19.51744-16.19968 35.38944-36.18816 35.38944z" fill="#FFFFFF" p-id="13406"></path><path d="M450.56 609.93536c0 99.34848 96.29696 179.89632 215.08096 179.89632a253.07136 253.07136 0 0 0 71.68-10.26048L815.02208 819.2l-20.76672-65.1264 1.98656-1.2288C847.52384 719.9744 880.64 668.20096 880.64 609.93536 880.64 510.60736 784.384 430.08 665.64096 430.08 546.85696 430.08 450.56 510.60736 450.56 609.93536z m259.6864-61.952c0-16.13824 13.49632-29.20448 30.16704-29.20448 16.71168 0 30.22848 13.06624 30.22848 29.20448 0 16.1792-13.5168 29.26592-30.22848 29.26592-16.67072 0-30.16704-13.1072-30.16704-29.26592z m-149.66784 0c0-16.13824 13.5168-29.20448 30.208-29.20448 16.6912 0 30.208 13.06624 30.208 29.20448 0 16.1792-13.5168 29.26592-30.208 29.26592-16.6912 0-30.208-13.1072-30.208-29.26592z" fill="#FFFFFF" p-id="13407"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
src/assets/images/icon_srmx.svg
Normal file
@@ -0,0 +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="1757768389400" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="26577" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M165.376 37.376c-58.368 0-110.08 51.712-110.08 110.08v660.48c0 58.368 51.712 110.08 110.08 110.08h401.408c-26.112-38.912-38.912-83.968-38.912-129.536 0-129.536 110.08-239.616 239.616-239.616 26.112 0 45.568 6.656 65.024 12.8v-414.72c0-58.368-51.712-110.08-110.08-110.08H165.376z m110.08 278.528h336.896c12.8 0 26.112 12.8 26.112 26.112s-12.8 26.112-26.112 26.112H275.456c-12.8 0-26.112-12.8-26.112-26.112s13.312-26.112 26.112-26.112z m0 136.192h336.896c12.8 0 26.112 12.8 26.112 26.112s-12.8 26.112-26.112 26.112H275.456c-12.8 0-26.112-12.8-26.112-26.112s13.312-26.112 26.112-26.112zM502.272 640H275.456c-12.8 0-26.112-12.8-26.112-26.112 0-12.8 12.8-26.112 26.112-26.112h220.16c19.456 0 32.256 6.656 32.256 26.112S515.072 640 502.272 640z" fill="#66CC00" p-id="26578"></path><path d="M774.144 598.016c-107.52 0-194.56 87.04-194.56 194.56s87.04 194.56 194.56 194.56 194.56-87.04 194.56-194.56-87.04-194.56-194.56-194.56z m71.168 188.928v23.552H785.92v31.232h59.392v23.552H785.92v64h-23.552v-64h-59.392v-23.552h59.392v-31.232h-59.392v-23.552h43.008l-69.12-112.128h31.744l65.024 112.128 66.048-112.128h31.744l-69.12 112.128h43.008z" fill="#66CC00" p-id="26579"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/assets/images/icon_tg.svg
Normal file
@@ -0,0 +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="1739502172305" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4607" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M569.2 788.4H215.8c-77.8 0-141.5-63.7-141.5-141.5V207.5C74.3 129.6 137.9 66 215.8 66h353.4c77.8 0 141.5 63.7 141.5 141.5v439.4c0 77.8-63.7 141.5-141.5 141.5z" fill="#D6F3FA" p-id="4608"></path><path d="M678.8 276.5v42.7c0 0.6-0.5 1.1-1.1 1.1h-418c-0.6 0-1.1-0.5-1.1-1.1v-42.7c0-0.6 0.5-1.1 1.1-1.1h418c0.6 0 1.1 0.5 1.1 1.1zM677.6 463h-418c-0.6 0-1.1 0.5-1.1 1.1v42.7c0 0.6 0.5 1.1 1.1 1.1h418c0.6 0 1.1-0.5 1.1-1.1v-42.7c0.1-0.6-0.4-1.1-1.1-1.1zM485 650.7H259.6c-0.6 0-1.1 0.5-1.1 1.1v42.7c0 0.6 0.5 1.1 1.1 1.1H485c0.6 0 1.1-0.5 1.1-1.1v-42.7c0-0.6-0.5-1.1-1.1-1.1z m466.5-24.1c0-59.1-48.1-107.3-107.3-107.3-59.1 0-107.3 48.1-107.3 107.3 0 59.1 48.1 107.3 107.3 107.3 59.2-0.1 107.3-48.2 107.3-107.3z m-34.4 0c0 40.2-32.7 72.9-72.9 72.9s-72.9-32.7-72.9-72.9 32.7-72.9 72.9-72.9 72.9 32.7 72.9 72.9zM706 759.5c0-50.9-41.4-92.3-92.3-92.3s-92.3 41.4-92.3 92.3 41.4 92.3 92.3 92.3c50.9-0.1 92.3-41.4 92.3-92.3z m-34.4 0c0 31.9-26 57.9-57.9 57.9s-57.9-26-57.9-57.9 26-57.9 57.9-57.9 57.9 26 57.9 57.9z m135.1 80.4c-33.2 0-60 26.9-60 60 0 33.2 26.9 60 60 60s60-26.9 60-60c0-33.2-26.8-60-60-60z m-27.2-148.1L755 649.3l-83.5 48.2L696 740l83.5-48.2z m-105.7 99.9L650.5 832 787 910.8l23.3-40.3-136.5-78.8z m-135.1 95.4c0-12.4-10.1-22.5-22.5-22.5H246c-41.5 0-75.1-33.6-75.1-75.1V234.1c0-41.5 33.6-75.1 75.1-75.1h52.5c12.4 0 22.5-10.1 22.5-22.5S310.9 114 298.5 114H246c-66.3 0-120.1 53.8-120.1 120.1v555.4c0 66.3 53.8 120.1 120.1 120.1h270.2c12.4 0 22.5-10.1 22.5-22.5z m277.7-488.3V234.1c0-66.3-53.8-120.1-120.1-120.1H448.6c-12.4 0-22.5 10.1-22.5 22.5s10.1 22.5 22.5 22.5h247.7c41.5 0 75.1 33.6 75.1 75.1v164.7c0 12.4 10.1 22.5 22.5 22.5s22.5-10.1 22.5-22.5zM408.1 157.9v-42.7c0-0.6-0.5-1.1-1.1-1.1h-65.3c-0.6 0-1.1 0.5-1.1 1.1v42.7c0 0.6 0.5 1.1 1.1 1.1H407c0.6 0 1.1-0.5 1.1-1.1z" fill="#18BAE5" p-id="4609"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
1
src/assets/images/icon_wytx.svg
Normal file
@@ -0,0 +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="1757768568193" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="28711" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M0 0h1024v1024H0V0z" fill="#202425" opacity=".01" p-id="28712"></path><path d="M955.733333 443.733333c0 226.2016-183.3984 409.6-409.6 409.6S136.533333 669.934933 136.533333 443.733333 319.931733 34.133333 546.133333 34.133333s409.6 183.3984 409.6 409.6z" fill="#FFAA44" p-id="28713"></path><path d="M703.829333 212.309333l3.1744 2.901334 3.140267 3.208533a34.133333 34.133333 0 0 1 2.730667 44.305067l-2.730667 3.1744-73.352533 75.776h47.342933a34.133333 34.133333 0 1 1 0 68.266666h-102.434133v68.266667h102.4a34.133333 34.133333 0 1 1 0 68.266667h-102.4v68.266666a34.133333 34.133333 0 1 1-68.266667 0v-68.266666h-102.4a34.133333 34.133333 0 0 1 0-68.266667h102.4v-68.266667h-102.4a34.133333 34.133333 0 0 1 0-68.266666h47.342933l-73.3184-75.776a34.133333 34.133333 0 0 1 0-47.445334l3.140267-3.242666a34.133333 34.133333 0 0 1 48.264533-0.8192l111.138134 114.824533 111.138133-114.824533a34.133333 34.133333 0 0 1 45.090133-2.082134z" fill="#FFFFFF" p-id="28714"></path><path d="M34.133333 750.933333a68.266667 68.266667 0 0 1 68.266667-68.266666h136.533333a68.266667 68.266667 0 0 1 68.266667 68.266666v170.666667a68.266667 68.266667 0 0 1-68.266667 68.266667H102.4a68.266667 68.266667 0 0 1-68.266667-68.266667v-170.666667z" fill="#FFAA44" p-id="28715"></path><path d="M204.8 989.866667a34.133333 34.133333 0 0 1-34.133333-34.133334v-258.935466a34.133333 34.133333 0 0 1 10.001066-24.132267l18.261334-18.261333A136.533333 136.533333 0 0 1 295.492267 614.4H597.333333a85.333333 85.333333 0 0 1 0 170.666667h-170.666666a17.066667 17.066667 0 0 0 0 34.133333h198.007466l260.676267-77.380267a85.333333 85.333333 0 1 1 44.168533 164.864l-268.834133 78.404267c-12.219733 3.2768-21.2992 4.8128-43.349333 4.8128H204.8z" fill="#FF7744" p-id="28716"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
src/assets/images/icon_xj.svg
Normal file
@@ -0,0 +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="1739502235932" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12319" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m177.3 336.7c51 0 92.7 44.7 92.7 99.8s-41.4 99.8-92.7 99.8c-43.6 0-80.5-32.3-90.2-76.2 15.5-20 24.4-45.9 24.4-73.9 0-6.4-0.7-12.4-1.5-18.4 17.1-19.1 40.7-31.1 67.3-31.1zM515 282.1c53.6 0 96.8 46.7 96.8 104.2s-43.6 104.2-97.2 104.2-96.8-46.7-96.8-104.2 43.6-104.2 97.2-104.2z m-181.1 54.6c29.2 0 55.4 14.4 72.4 37.1-0.4 4-0.7 8-0.7 12 0 25.1 7.4 48.3 19.9 67.5-7.4 47.1-45.8 83-91.6 83-51.4 0-92.7-44.7-92.7-99.8 0-55 41.4-99.8 92.7-99.8zM179.5 741.9c0-99.8 69.5-180.4 154.8-180.4 16.6 0 33.3 3.2 49.1 9.2-42.5 41.5-70.9 102.6-74.3 171.3l-129.6-0.1z m153.7 0c0-117 81.3-212 181.8-212s181.8 95 182.2 212h-364z m387.6-0.4c-3.7-69.5-32.5-131.3-76.1-172.5 14.4-4.8 29.9-7.6 45.1-7.6 85.3 0 154.8 80.6 154.8 180l-123.8 0.1z" fill="#2ACE4D" p-id="12320"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/images/index_icon_1.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
src/assets/images/index_icon_2.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
src/assets/images/index_icon_3.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
src/assets/images/index_icon_4.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/images/index_icon_4_1.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/images/index_icon_6.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
src/assets/images/invitation.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
src/assets/images/invitation_agent_apply.png
Normal file
|
After Width: | Height: | Size: 369 KiB |
BIN
src/assets/images/llqdk.jpg
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
src/assets/images/loan_check_bg.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
src/assets/images/login_bg.png
Normal file
|
After Width: | Height: | Size: 507 KiB |
BIN
src/assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 319 KiB |
1
src/assets/images/mxcl_icon.svg
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
87
src/assets/images/pendding.svg
Normal file
@@ -0,0 +1,87 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 1024 1024" height="1024" width="1024">
|
||||
<g clip-path="url(#clip0_1513_110780)">
|
||||
<ellipse fill="url(#paint0_linear_1513_110780)" ry="127.5" rx="467" cy="762.5" cx="506"></ellipse>
|
||||
<path fill="url(#paint1_linear_1513_110780)" d="M230.457 615.502C230.457 615.502 230.233 614.922 229.928 615.542C227.184 621.122 202.334 681.566 200.362 728.218C200.362 728.218 196.215 755.02 230.965 754.665C259.973 754.37 259.2 729.662 259.099 721.337C258.702 687.573 230.457 615.502 230.457 615.502Z"></path>
|
||||
<path fill="url(#paint2_linear_1513_110780)" d="M229.664 784.343C229.105 784.343 228.647 783.886 228.647 783.327V631.754C228.647 631.195 229.105 630.737 229.664 630.737C230.223 630.737 230.68 631.195 230.68 631.754V783.327C230.68 783.896 230.223 784.343 229.664 784.343Z"></path>
|
||||
<path fill="url(#paint3_linear_1513_110780)" d="M869.35 810.661C876.541 808.4 883.517 805.446 889.874 797.176C891.178 795.482 892.404 793.311 891.689 791.283C891.151 789.757 889.594 788.778 888.013 788.529C887.424 788.442 886.827 788.426 886.234 788.48H886.228C885.316 788.574 884.415 788.754 883.536 789.015L883.285 789.089C879.09 790.299 875.093 792.13 871.425 794.524C871.093 794.738 870.698 794.833 870.306 794.792C869.914 794.75 869.548 794.576 869.266 794.296C868.984 794.017 868.804 793.649 868.754 793.252C868.704 792.855 868.789 792.453 868.993 792.111C869.367 791.491 869.803 790.911 870.292 790.38C871.015 789.613 871.807 788.916 872.657 788.299C873.788 787.462 874.994 786.715 876.174 785.951C880.562 783.116 884.719 779.929 888.605 776.42C891.378 773.913 894.091 771.131 895.409 767.607C896.015 765.986 896.291 764.117 895.568 762.547C894.376 759.968 890.999 759.245 888.237 759.78C883.398 760.721 879.532 764.32 876.104 767.908C873.261 770.889 870.075 774.189 865.99 774.372C865.294 774.439 864.594 774.296 863.977 773.963C862.812 773.247 862.512 771.588 862.927 770.271C863.343 768.953 864.304 767.901 865.231 766.89C870.623 761.021 875.928 754.916 879.429 747.725C882.93 740.534 884.481 732.044 882.048 724.409C881.335 722.177 880.263 720.005 878.591 718.383C876.919 716.762 874.575 715.745 872.28 716.056C869.153 716.473 866.798 719.15 865.213 721.915C859.768 731.401 860.101 743.025 858.567 753.891C858.138 756.933 857.514 760.053 855.728 762.557C855.563 762.798 855.35 763 855.101 763.15C853.632 764.013 852.313 762.272 851.761 760.795C849.583 754.95 849.038 748.265 845.139 743.427C843.65 741.585 841.544 740.046 839.197 740.061C836.331 740.081 833.877 742.51 833.04 745.292C832.204 748.074 832.705 751.096 833.601 753.858C835.264 758.98 838.245 763.582 841.759 767.627C843.61 769.763 845.705 771.92 846.261 774.706C846.431 775.653 846.36 776.628 846.054 777.539C845.748 778.45 845.218 779.267 844.513 779.912C844.184 780.202 843.801 780.423 843.386 780.561C842.971 780.699 842.533 780.75 842.098 780.713C841.157 780.626 840.306 780.139 839.484 779.666C839.139 779.467 838.794 779.265 838.447 779.067C837.077 778.276 835.707 777.483 834.336 776.69C830.851 774.674 826.646 772.614 823.018 774.35C821.167 775.238 819.954 776.983 819.383 778.986C818.872 780.804 818.872 782.73 819.383 784.548C820.464 788.328 827.276 798.848 830.086 801.561C833.368 804.729 844.748 818.398 869.35 810.661Z"></path>
|
||||
<path fill="url(#paint4_linear_1513_110780)" d="M649.638 740.684C650.38 738.632 650.88 736.312 651.021 733.581C651.097 732.138 650.946 730.46 649.772 729.604C648.888 728.959 647.648 729.008 646.674 729.474C646.314 729.65 645.975 729.869 645.667 730.126L645.663 730.129C645.193 730.529 644.761 730.974 644.373 731.455L644.261 731.592C642.394 733.869 640.875 736.417 639.754 739.152C639.651 739.399 639.468 739.602 639.235 739.729C639.001 739.856 638.73 739.899 638.467 739.851C638.203 739.802 637.962 739.666 637.782 739.464C637.603 739.262 637.495 739.006 637.478 738.737C637.448 738.249 637.468 737.759 637.537 737.276C637.644 736.573 637.817 735.882 638.053 735.213C638.302 734.488 638.6 733.776 638.897 733.067C638.968 732.898 639.038 732.73 639.108 732.561C640.46 729.305 641.548 725.941 642.363 722.501C642.944 720.045 643.385 717.458 642.767 714.99C642.483 713.856 641.92 712.709 640.917 712.11C639.267 711.129 637.113 712.017 635.783 713.37C633.455 715.744 632.686 719.226 632.155 722.535C631.718 725.282 631.212 728.339 629.013 730.001C628.651 730.304 628.208 730.492 627.737 730.543C626.815 730.589 626.013 729.779 625.739 728.886C625.465 727.994 625.596 727.04 625.724 726.122C626.471 720.792 627.08 715.364 626.27 710.019C625.46 704.675 623.069 699.352 618.792 696.028C617.541 695.056 616.113 694.256 614.563 693.991C613.012 693.727 611.32 694.056 610.164 695.106C608.586 696.534 608.303 698.925 608.482 701.071C608.942 706.634 611.7 711.617 614.449 716.583C615.34 718.193 616.23 719.801 617.041 721.426C617.968 723.285 618.816 725.262 618.783 727.34C618.784 727.537 618.743 727.731 618.662 727.909C618.177 728.952 616.777 728.486 615.904 727.874C614.781 727.084 613.72 726.179 612.661 725.276C610.467 723.405 608.281 721.54 605.57 720.728C604.037 720.27 602.277 720.217 600.979 721.122C599.394 722.229 598.961 724.52 599.562 726.389C600.163 728.259 601.599 729.751 603.155 730.948C606.042 733.166 609.462 734.591 612.964 735.502C613.144 735.549 613.325 735.595 613.507 735.641C615.193 736.072 616.935 736.516 618.178 737.726C618.635 738.189 618.969 738.759 619.148 739.384C619.328 740.008 619.346 740.666 619.201 741.294C619.13 741.582 619.001 741.852 618.824 742.087C618.646 742.322 618.422 742.518 618.166 742.664C617.61 742.975 616.95 743.029 616.312 743.079C616.226 743.086 616.14 743.092 616.053 743.099C615.871 743.113 615.689 743.126 615.507 743.142C614.442 743.224 613.378 743.306 612.312 743.388C609.603 743.596 606.477 744.055 605.127 746.409C604.438 747.611 604.433 749.047 604.883 750.381C605.296 751.589 606.034 752.662 607.014 753.48C608.305 754.547 611.561 756.243 614.443 757.461C618.506 760.98 630.194 760.946 644.502 760.905C646.078 760.9 647.685 760.896 649.318 760.896C650.95 760.896 652.558 760.9 654.133 760.905C671.968 760.956 685.732 760.996 685.732 754.158C685.732 746.756 669.602 740.748 649.638 740.684Z" clip-rule="evenodd" fill-rule="evenodd"></path>
|
||||
<path fill="#E0EFFB" d="M398.378 606.003C398.378 552.319 432.932 506.743 480.916 490.497C432.932 474.257 398.378 428.681 398.378 374.997V340.028H370.877C361.556 340.028 354 332.438 354 323.074V320.955C354 311.591 361.556 304 370.877 304H668.935C678.256 304 685.812 311.591 685.812 320.954V323.074C685.812 332.438 678.256 340.028 668.935 340.028H640.982V374.997C640.982 428.681 606.427 474.257 558.444 490.503C606.427 506.743 640.982 552.319 640.982 606.003V640.972H669.123C678.444 640.972 686 648.562 686 657.926V660.045C686 669.409 678.444 677 669.123 677H371.065C361.744 677 354.189 669.409 354.189 660.046V657.926C354.189 648.562 361.744 640.972 371.065 640.972H398.378V606.003Z"></path>
|
||||
<path fill="#81C2FA" d="M613 637C613 673.451 565.362 656 514 656C462.638 656 427 673.451 427 637C427 600.549 467.638 557 519 557C570.362 557 613 600.549 613 637Z"></path>
|
||||
<path fill="url(#paint5_linear_1513_110780)" d="M668.668 304C678.011 304 685.585 311.591 685.585 320.954V323.074C685.585 332.438 678.011 340.028 668.668 340.028H369.916C360.574 340.028 353 332.438 353 323.074V320.955C353 311.591 360.574 304 369.916 304H668.668V304ZM669.084 640.972C678.426 640.972 686 648.562 686 657.926V660.045C686 669.409 678.426 677 669.084 677H370.331C360.989 677 353.415 669.409 353.415 660.046V657.926C353.415 648.562 360.989 640.972 370.331 640.972H669.084V640.972Z"></path>
|
||||
<ellipse fill-opacity="0.1" fill="#7D7D7D" ry="15.5" rx="56.5" cy="744.5" cx="380.5"></ellipse>
|
||||
<path fill="url(#paint6_linear_1513_110780)" d="M388.138 590.092H362.863V615.366H388.138V590.092Z"></path>
|
||||
<path fill="#FEE0BC" d="M402.423 582.636C404.608 583.518 407.573 581.276 409.047 577.628C410.521 573.98 409.946 570.307 407.761 569.424C405.577 568.542 402.611 570.784 401.137 574.432C399.663 578.08 400.239 581.753 402.423 582.636Z"></path>
|
||||
<path fill="#FEE0BC" d="M348.175 582.595C346.006 583.516 343.001 581.326 341.464 577.704C339.926 574.082 340.438 570.4 342.607 569.479C344.776 568.559 347.78 570.749 349.318 574.37C350.855 577.992 350.343 581.675 348.175 582.595Z"></path>
|
||||
<path fill="url(#paint7_linear_1513_110780)" d="M376.181 600.131C392.089 600.131 404.984 587.403 404.984 571.702C404.984 556.001 392.089 543.272 376.181 543.272C360.274 543.272 347.378 556.001 347.378 571.702C347.378 587.403 360.274 600.131 376.181 600.131Z"></path>
|
||||
<path fill="url(#paint8_linear_1513_110780)" d="M404.119 573.743C414.43 559.996 409.275 525.629 374.907 525.629C340.54 525.629 333.667 561.714 347.414 573.743C352.568 558.278 398.964 558.278 404.119 573.743Z"></path>
|
||||
<path fill="#585449" d="M410.191 557.658C409.554 572.537 393.77 555.533 374.3 555.533C354.829 555.533 337.984 574.237 338.408 555.533C338.408 535.812 355.466 521.95 374.937 521.95C394.407 521.95 411.034 537.955 410.191 557.658Z"></path>
|
||||
<path fill="#747169" d="M408.724 562.119C408.724 565.75 393.233 564.876 374.123 564.876C355.013 564.876 339.521 565.75 339.521 562.119C339.521 558.487 355.013 552.998 374.123 552.998C393.233 552.998 408.724 558.487 408.724 562.119Z"></path>
|
||||
<path fill="url(#paint9_linear_1513_110780)" d="M386.491 606.175C387.05 605.65 387.608 605.068 388.164 604.428L388.174 604.432C388.384 604.433 388.64 604.475 389.128 604.824C391.595 605.916 393.875 607.539 395.959 609.51C419.437 620.293 448.133 651.929 449.682 659.957C451.485 669.295 447.834 674.286 444.137 676.077C442.286 676.974 429.317 681.461 415.201 685.27C416.83 704.65 418.718 723.386 420.606 728.15C421.865 731.327 412.177 732.54 398.561 732.695C371.08 735.371 324.372 734.768 326.993 728.154C328.875 723.404 330.757 704.767 332.382 685.448C320.048 682.577 309.039 679.178 307.296 678.307C303.692 676.505 296.482 669.295 298.285 658.481C299.675 650.138 334.524 615.04 357.975 605.055C358.455 604.827 358.941 604.619 359.435 604.432L359.454 604.453C359.491 604.439 359.528 604.425 359.564 604.411C359.567 604.426 359.57 604.441 359.572 604.455C361.418 603.115 362.636 602.608 362.931 602.608C365.835 606.378 371.949 611.363 378.778 610.25C381.883 609.361 384.592 607.826 386.491 606.175ZM334.655 656.861C334.874 654.069 335.081 651.452 335.276 649.074C332.93 650.984 330.236 652.93 327.122 654.877C329.488 655.215 332.023 655.912 334.655 656.861ZM413.042 658.12C412.851 655.675 412.669 653.353 412.495 651.194C414.72 652.904 417.239 654.639 420.105 656.375C417.878 656.683 415.505 657.292 413.042 658.12Z" clip-rule="evenodd" fill-rule="evenodd"></path>
|
||||
<path fill="#FB955B" d="M391.434 605.947C391.434 605.947 389.643 604.093 387.853 604.093C378.206 614.08 367.28 607.14 362.782 602.24C362.613 602.048 360.991 602.238 359.2 604.093C374.959 618.925 387.256 611.509 391.434 605.947Z"></path>
|
||||
<path fill="#FEE4C3" d="M334.332 746.796L331.538 734.637L317.4 737.47L319.526 748.074L334.332 746.796Z"></path>
|
||||
<path fill="#7B7B7B" d="M321.766 736.133C318.964 740.512 320.757 746.368 322.003 748.748C318.467 752.42 303.692 755.992 303.692 746.802C303.691 737.784 312.722 734.501 321.766 736.133Z"></path>
|
||||
<path fill="#FEE4C3" d="M415.233 746.796L418.027 734.637L432.165 737.47L430.04 748.074L415.233 746.796Z"></path>
|
||||
<path fill="#7B7B7B" d="M427.798 736.133C430.6 740.512 428.808 746.368 427.561 748.748C431.097 752.42 445.872 755.992 445.873 746.802C445.873 737.784 436.842 734.501 427.798 736.133Z"></path>
|
||||
<path fill="#DCDCDC" d="M426.623 696.181C426.623 696.181 446.29 692.531 452.543 706.678C457.11 723.22 440.502 727.377 440.502 727.377L427.51 729.924L421.852 749.064L375.903 740.046L329.917 749.064L324.251 729.908L311.397 727.387C311.397 727.387 293 720.449 299.37 706.697C307.428 689.3 325.262 696.204 325.262 696.204L375.881 710.561L426.623 696.181Z"></path>
|
||||
<path fill="url(#paint10_linear_1513_110780)" d="M330.263 637.979C330.263 637.426 330.71 636.979 331.263 636.979H415.708C416.26 636.979 416.708 637.426 416.708 637.979V698.15H330.263V637.979Z"></path>
|
||||
<rect fill="url(#paint11_linear_1513_110780)" rx="2" height="5.49441" width="94.1376" y="698.149" x="326.967"></rect>
|
||||
<path fill="url(#paint12_linear_1513_110780)" d="M774.5 291.455C776.513 291.455 778.444 292.254 779.868 293.678C781.291 295.101 782.091 297.032 782.091 299.045V329.409C782.091 331.422 781.291 333.353 779.868 334.777C778.444 336.2 776.513 337 774.5 337C772.487 337 770.556 336.2 769.132 334.777C767.709 333.353 766.909 331.422 766.909 329.409V299.045C766.909 297.032 767.709 295.101 769.132 293.678C770.556 292.254 772.487 291.455 774.5 291.455V291.455ZM747.659 280.341C749.082 281.765 749.881 283.695 749.881 285.708C749.881 287.721 749.082 289.651 747.659 291.075L726.191 312.542C725.491 313.267 724.654 313.845 723.727 314.243C722.801 314.641 721.805 314.85 720.797 314.859C719.789 314.868 718.79 314.676 717.857 314.294C716.924 313.913 716.077 313.349 715.364 312.636C714.651 311.923 714.087 311.076 713.706 310.143C713.324 309.21 713.132 308.211 713.141 307.203C713.15 306.195 713.359 305.199 713.757 304.273C714.155 303.346 714.733 302.509 715.458 301.809L736.925 280.341C738.349 278.918 740.279 278.119 742.292 278.119C744.305 278.119 746.235 278.918 747.659 280.341V280.341ZM812.075 280.341L833.542 301.809C834.925 303.24 835.69 305.158 835.673 307.148C835.655 309.138 834.857 311.042 833.45 312.45C832.042 313.857 830.138 314.655 828.148 314.673C826.158 314.69 824.24 313.925 822.809 312.542L801.341 291.075C799.959 289.643 799.194 287.726 799.211 285.736C799.228 283.745 800.027 281.841 801.434 280.434C802.841 279.027 804.745 278.228 806.736 278.211C808.726 278.194 810.643 278.959 812.075 280.341ZM728.955 245.909C730.968 245.909 732.899 246.709 734.322 248.132C735.746 249.556 736.545 251.487 736.545 253.5C736.545 255.513 735.746 257.444 734.322 258.868C732.899 260.291 730.968 261.091 728.955 261.091H698.591C696.578 261.091 694.647 260.291 693.223 258.868C691.8 257.444 691 255.513 691 253.5C691 251.487 691.8 249.556 693.223 248.132C694.647 246.709 696.578 245.909 698.591 245.909H728.955ZM850.409 245.909C852.422 245.909 854.353 246.709 855.777 248.132C857.2 249.556 858 251.487 858 253.5C858 255.513 857.2 257.444 855.777 258.868C854.353 260.291 852.422 261.091 850.409 261.091H820.045C818.032 261.091 816.101 260.291 814.678 258.868C813.254 257.444 812.455 255.513 812.455 253.5C812.455 251.487 813.254 249.556 814.678 248.132C816.101 246.709 818.032 245.909 820.045 245.909H850.409ZM833.542 194.458C834.965 195.881 835.765 197.812 835.765 199.825C835.765 201.838 834.965 203.768 833.542 205.191L812.075 226.659C810.643 228.041 808.726 228.806 806.736 228.789C804.745 228.772 802.841 227.973 801.434 226.566C800.027 225.159 799.228 223.255 799.211 221.264C799.194 219.274 799.959 217.357 801.341 215.925L822.809 194.458C824.232 193.035 826.162 192.235 828.175 192.235C830.188 192.235 832.119 193.035 833.542 194.458V194.458ZM726.191 194.458L747.659 215.925C748.384 216.625 748.962 217.463 749.36 218.389C749.758 219.315 749.967 220.311 749.976 221.319C749.984 222.327 749.792 223.327 749.411 224.259C749.029 225.192 748.465 226.04 747.753 226.753C747.04 227.465 746.192 228.029 745.259 228.411C744.327 228.792 743.327 228.984 742.319 228.976C741.311 228.967 740.315 228.758 739.389 228.36C738.463 227.962 737.625 227.384 736.925 226.659L715.458 205.191C714.075 203.76 713.31 201.842 713.327 199.852C713.345 197.862 714.143 195.958 715.55 194.55C716.958 193.143 718.862 192.345 720.852 192.327C722.842 192.31 724.76 193.075 726.191 194.458V194.458ZM774.5 170C776.513 170 778.444 170.8 779.868 172.223C781.291 173.647 782.091 175.578 782.091 177.591V207.955C782.091 209.968 781.291 211.899 779.868 213.322C778.444 214.746 776.513 215.545 774.5 215.545C772.487 215.545 770.556 214.746 769.132 213.322C767.709 211.899 766.909 209.968 766.909 207.955V177.591C766.909 175.578 767.709 173.647 769.132 172.223C770.556 170.8 772.487 170 774.5 170Z"></path>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="890" x2="506" y1="635" x1="506" id="paint0_linear_1513_110780">
|
||||
<stop stop-color="#BDDFFF"></stop>
|
||||
<stop stop-opacity="0" stop-color="white" offset="0.95892"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="615.257" x2="229.66" y1="754.678" x1="229.66" id="paint1_linear_1513_110780">
|
||||
<stop stop-color="#5FB2FF"></stop>
|
||||
<stop stop-color="#DFF0FF" offset="0.7893"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="784.347" x2="229.661" y1="630.738" x1="229.661" id="paint2_linear_1513_110780">
|
||||
<stop stop-color="#DFF0FF"></stop>
|
||||
<stop stop-color="#A2D2FF" offset="0.818"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="802.968" x2="847.534" y1="720.042" x1="883.842" id="paint3_linear_1513_110780">
|
||||
<stop stop-color="#C4E3FF" offset="0.365159"></stop>
|
||||
<stop stop-color="#5FB2FF" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="696.911" x2="605.494" y1="778.74" x1="649.318" id="paint4_linear_1513_110780">
|
||||
<stop stop-color="#97CDFF" offset="0.568288"></stop>
|
||||
<stop stop-color="#5FB2FF" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="646.727" x2="206.755" y1="200" x1="686" id="paint5_linear_1513_110780">
|
||||
<stop stop-color="#6CB8FF"></stop>
|
||||
<stop stop-color="#B1D9FF" offset="0.865168"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="615.366" x2="375.5" y1="593.358" x1="375.5" id="paint6_linear_1513_110780">
|
||||
<stop stop-color="#FFCDA5"></stop>
|
||||
<stop stop-color="#FFE8D1" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="600.131" x2="376.181" y1="543.272" x1="376.181" id="paint7_linear_1513_110780">
|
||||
<stop stop-color="#FFF2DF"></stop>
|
||||
<stop stop-color="#FEE0BC" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="579.657" x2="358.148" y1="540.753" x1="396.189" id="paint8_linear_1513_110780">
|
||||
<stop stop-color="#777CA7"></stop>
|
||||
<stop stop-color="#636681" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="749.353" x2="384.874" y1="591.568" x1="425.773" id="paint9_linear_1513_110780">
|
||||
<stop stop-color="#FFE194"></stop>
|
||||
<stop stop-color="#FFBF84" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="690.962" x2="358.001" y1="640.104" x1="392.552" id="paint10_linear_1513_110780">
|
||||
<stop stop-color="#94CBFF"></stop>
|
||||
<stop stop-color="#DCEEFF" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="703.644" x2="374.036" y1="698.149" x1="374.036" id="paint11_linear_1513_110780">
|
||||
<stop stop-color="#94CBFF"></stop>
|
||||
<stop stop-color="#DCEEFF" offset="1"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" y2="304.871" x2="701.011" y1="178.533" x1="811.334" id="paint12_linear_1513_110780">
|
||||
<stop stop-color="#6CB8FF"></stop>
|
||||
<stop stop-color="#BDDFFF" offset="0.781833"></stop>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_1513_110780">
|
||||
<rect fill="white" height="1024" width="1024"></rect>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/images/personal_data_bg.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
src/assets/images/promote_bg.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
src/assets/images/public_security_record_icon.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
1
src/assets/images/qyss_icon.svg
Normal file
@@ -0,0 +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="1733326801081" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="29986" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M928 832 896 832 896 384c0-70.4-57.6-128-128-128L576 256l0 544C576 817.92 561.92 832 544 832S512 817.92 512 800L512 192c0-70.4-57.6-128-128-128L192 64C121.6 64 64 121.6 64 192l0 640L32 832C14.08 832 0 846.08 0 864 0 881.92 14.08 896 32 896l896 0c17.92 0 32-14.08 32-32C960 846.08 945.92 832 928 832zM352 704l-128 0C206.08 704 192 689.92 192 672S206.08 640 224 640l128 0C369.92 640 384 654.08 384 672S369.92 704 352 704zM352 512l-128 0C206.08 512 192 497.92 192 480 192 462.08 206.08 448 224 448l128 0C369.92 448 384 462.08 384 480 384 497.92 369.92 512 352 512zM352 320l-128 0C206.08 320 192 305.92 192 288 192 270.08 206.08 256 224 256l128 0C369.92 256 384 270.08 384 288 384 305.92 369.92 320 352 320zM800 704l-128 0c-17.92 0-32-14.08-32-32s14.08-32 32-32l128 0c17.92 0 32 14.08 32 32S817.92 704 800 704zM800 512l-128 0C654.08 512 640 497.92 640 480 640 462.08 654.08 448 672 448l128 0C817.92 448 832 462.08 832 480 832 497.92 817.92 512 800 512z" p-id="29987" fill="#4B64FA"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
src/assets/images/rchy_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M179.2 665.6c0 46.933333 38.4 85.333333 85.333333 85.333333s85.333333-38.4 85.333334-85.333333-38.4-85.333333-85.333334-85.333333-85.333333 38.4-85.333333 85.333333z m110.933333 0c0 12.8-8.533333 21.333333-21.333333 21.333333s-21.333333-8.533333-21.333333-21.333333 8.533333-21.333333 21.333333-21.333333 21.333333 8.533333 21.333333 21.333333zM610.133333 290.133333c25.6 0 42.666667-17.066667 42.666667-42.666666s-17.066667-42.666667-42.666667-42.666667H371.2c-38.4 0-72.533333 25.6-81.066667 59.733333L256 405.333333c0 12.8 0 25.6 8.533333 38.4s21.333333 17.066667 34.133334 17.066667h221.866666c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666666h-170.666666l21.333333-85.333334h238.933333zM384 810.666667c-25.6 0-42.666667 17.066667-42.666667 42.666666s-17.066667 42.666667-42.666666 42.666667-42.666667-17.066667-42.666667-42.666667-17.066667-42.666667-42.666667-42.666666H128c-21.333333 0-42.666667-17.066667-42.666667-42.666667v-268.8c0-17.066667 8.533333-29.866667 25.6-38.4l46.933334-21.333333c12.8-4.266667 21.333333-17.066667 21.333333-29.866667l46.933333-213.333333c8.533333-38.4 42.666667-68.266667 85.333334-68.266667h362.666666c38.4 0 76.8 29.866667 85.333334 68.266667 4.266667 21.333333 29.866667 38.4 51.2 34.133333 21.333333-4.266667 38.4-25.6 34.133333-51.2-17.066667-76.8-85.333333-136.533333-166.4-136.533333H311.466667C230.4 42.666667 162.133333 98.133333 145.066667 174.933333l-42.666667 192-29.866667 17.066667C25.6 405.333333 0 448 0 499.2V768c0 72.533333 55.466667 128 128 128h51.2c17.066667 51.2 64 85.333333 119.466667 85.333333 72.533333 0 128-55.466667 128-128 0-25.6-17.066667-42.666667-42.666667-42.666666zM785.066667 691.2c68.266667-12.8 119.466667-76.8 119.466666-149.333333 0-85.333333-68.266667-149.333333-149.333333-149.333334s-149.333333 68.266667-149.333333 149.333334c0 72.533333 51.2 132.266667 119.466666 149.333333-136.533333 12.8-238.933333 119.466667-238.933333 247.466667 0 25.6 17.066667 42.666667 42.666667 42.666666s42.666667-17.066667 42.666666-42.666666c0-89.6 85.333333-162.133333 187.733334-162.133334S938.666667 849.066667 938.666667 938.666667c0 25.6 17.066667 42.666667 42.666666 42.666666s42.666667-17.066667 42.666667-42.666666c0-128-106.666667-230.4-238.933333-247.466667z m-98.133334-149.333333c0-38.4 29.866667-64 64-64s64 29.866667 64 64-29.866667 64-64 64-64-25.6-64-64z" /></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
1
src/assets/images/sfzeys_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="29.56px" viewBox="0 0 1663 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M1624.062335 1024H39.123025A39.265143 39.265143 0 0 1 0 984.856673V39.123025A39.265143 39.265143 0 0 1 39.123025 0h1584.93931a39.24484 39.24484 0 0 1 39.123025 39.123025v945.733648a39.24484 39.24484 0 0 1-39.123025 39.143327zM570.70484 163.049825H179.352777a32.626207 32.626207 0 0 0 0 65.232111H570.70484a32.626207 32.626207 0 0 0 0-65.232111zM635.916648 306.568591H179.352777a32.626207 32.626207 0 0 0 0 65.232111h456.563871a32.626207 32.626207 0 0 0 0-65.232111z m0 143.47816H179.352777a32.626207 32.626207 0 0 0 0 65.232112h456.563871a32.626207 32.626207 0 0 0 0-65.232112z m130.443921 143.498464H179.352777a32.626207 32.626207 0 0 0 0 65.232111h587.007792a32.626207 32.626207 0 1 0 0-65.232111z m750.077919-6.517121c0-44.361084-77.61667-87.727343-146.422032-110.547415-3.268711-0.994825-23.165216-10.151278-10.435513-47.934334h-0.324841c32.281064-33.60073 57.050181-87.422805 57.050181-140.554593 0-81.880207-54.126613-124.596784-116.739695-124.596784-62.937923 0-116.414854 42.635367-116.414854 124.596784 0 53.476932 24.363067 107.603545 57.070484 140.879434 12.7094 33.580427-10.151278 45.985289-14.678748 47.609493-65.881793 23.794595-142.848782 67.505998-142.848782 110.547415V602.985903c0 58.694688 112.841604 72.074073 217.521582 72.074073s216.222218-13.379384 216.222218-72.074073zM1483.812281 828.344271H179.352777a32.626207 32.626207 0 0 0 0 65.232111h1304.459504a32.626207 32.626207 0 1 0 0-65.232111z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/images/sjeck_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M716.096 0c32.384 0 59.136 23.936 62.784 54.784l0.448 7.232-0.128 153.28c-29.696-13.76-46.464-24.448-46.464-24.448l-14.784-7.296v-18.88h-528.64v666.24h528.64v-16.256c10.304-2.368 33.344-13.184 61.248-29.888l0.128 177.216a62.464 62.464 0 0 1-55.872 61.568l-7.36 0.448H191.232a62.784 62.784 0 0 1-62.784-54.784L128 961.92V62.016c0-31.808 24.384-58.048 55.872-61.568L191.232 0h524.8z m-262.4 873.6a51.392 51.392 0 0 0-51.84 50.88c0 28.096 23.168 50.816 51.84 50.816 28.608 0 51.84-22.72 51.84-50.816a51.392 51.392 0 0 0-51.84-50.88z m260.16-644.864l15.616 7.68s33.28 21.184 88 40.448c50.88 19.264 82.176 19.264 82.176 19.264l23.424 1.92v265.92c0 98.304-187.712 204.224-209.216 204.224-23.488 0-209.28-105.92-209.28-204.16V297.984l25.472-1.92s29.312-1.92 82.112-19.2a585.024 585.024 0 0 0 83.904-38.144l3.648-2.112 0.448-0.256 13.696-7.68z m97.792 159.872L694.272 533.12l-62.528-55.872-29.376 36.608 97.792 88.64 146.688-181.12-35.2-32.768z m-299.456-311.04h-117.12a16.576 16.576 0 0 0-16.64 16.384c0 7.744 5.44 14.272 12.8 16l3.84 0.384h117.12a16.576 16.576 0 0 0 16.768-16.384 16.576 16.576 0 0 0-16.768-16.384z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
src/assets/images/sjeys_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M909.824 457.728H738.816V60.416C738.304 27.136 711.68 0 678.4 0H116.736C83.456 0 56.32 27.136 56.32 60.416v782.336c0 33.28 27.136 60.416 60.416 60.416h485.376v62.464c0 32.256 26.112 57.856 57.856 57.856h249.344c32.256 0 57.856-26.112 57.856-57.856V515.584c0.512-31.744-25.6-57.856-57.344-57.856zM397.312 866.816c-19.968 0-36.352-16.384-36.352-36.352 0-19.968 16.384-36.352 36.352-36.352 19.968 0 36.352 16.384 36.352 36.352 0.512 19.968-15.872 36.352-36.352 36.352z m204.8-351.232v241.152H143.36c-18.944 0-34.816-15.872-34.816-34.816V87.04c0-18.944 15.872-34.816 34.816-34.816h508.416c18.944 0 34.816 15.872 34.816 34.816v370.688H660.48c-32.256 0-58.368 26.112-58.368 57.856zM915.456 939.52c0 17.92-14.336 32.256-32.256 32.256H686.592c-17.92 0-32.256-14.336-32.256-32.256V541.696c0-17.92 14.336-32.256 32.256-32.256H883.2c17.92 0 32.256 14.336 32.256 32.256V939.52z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/images/sjhmfx_icon.svg
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
1
src/assets/images/sjsys_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M1023.842304 997.558272c-3.960832-128.258048-92.628992-235.188224-212.025344-266.9056 56.522752-27.35104 95.500288-85.18656 95.500288-152.119296 0-93.298688-75.743232-168.92928-169.187328-168.92928s-169.183232 75.630592-169.183232 168.92928c0 66.934784 38.975488 124.768256 95.49824 152.119296-119.3984 31.715328-208.06656 138.647552-212.025344 266.9056h-0.1536v26.425344h151.68512v-26.425344H478.9248c5.072896-134.557696 123.65824-250.073088 259.207168-250.073088s254.134272 115.515392 259.20512 250.073088h-125.022208v26.425344h151.683072v-26.425344h-0.155648zM595.412992 578.531328c0-73.996288 68.608-142.526464 142.716928-142.526464s142.716928 68.530176 142.716928 142.526464c0 74.008576-68.608 142.528512-142.716928 142.528512s-142.716928-68.519936-142.716928-142.528512z m-173.819904 343.062528H59.74016a17.065984 17.065984 0 0 1-17.068032-17.068032V85.331968a17.055744 17.055744 0 0 1 17.068032-17.057792h494.923776c9.424896 0 17.068032 7.634944 17.068032 17.057792v358.373376a214.53824 214.53824 0 0 1 42.65984-42.653696V85.331968C614.391808 38.203392 576.188416 0 529.05984 0H85.331968C38.213632 0 0 38.203392 0 85.331968v853.32992c0 47.118336 38.213632 85.321728 85.331968 85.321728h337.69472c-3.155968-18.024448-4.888576-36.538368-4.888576-55.451648 0-15.955968 1.200128-31.614976 3.454976-46.938112zM255.995904 29.87008c0-2.3552 1.910784-4.265984 4.265984-4.265984h93.868032c2.3552 0 4.268032 1.910784 4.268032 4.265984v8.534016c0 2.3552-1.912832 4.265984-4.268032 4.265984h-93.868032a4.268032 4.268032 0 0 1-4.265984-4.265984v-8.534016z m85.331968 959.987712c0 9.422848-7.634944 17.068032-17.057792 17.068032h-34.136064a17.072128 17.072128 0 0 1-17.068032-17.068032v-34.125824a17.072128 17.072128 0 0 1 17.068032-17.07008h34.136064c9.424896 0 17.057792 7.645184 17.057792 17.07008v34.125824z m20.946944-496.023552c15.214592-7.000064 26.691584-16.42496 34.44736-28.291072 7.757824-11.86816 11.636736-25.014272 11.636736-39.460864 0-15.212544-4.077568-29.591552-12.212224-43.116544-8.136704-13.545472-19.879936-24.225792-35.237888-32.059392-15.37024-7.835648-32.169984-11.757568-50.427904-11.757568-26.458112 0-48.582656 7.5776-66.38592 22.71232-17.790976 15.12448-29.192192 36.460544-34.213888 63.985664l41.060352 7.29088c3.045376-20.068352 9.889792-35.125248 20.533248-45.160448 10.647552-10.04544 23.959552-15.058944 39.927808-15.058944 16.111616 0 29.270016 4.94592 39.460864 14.835712s15.292416 22.358016 15.292416 37.404672c0 19.023872-7.002112 33.091584-20.992 42.203136-13.991936 9.13408-29.73696 13.69088-47.21664 13.69088-1.67936 0-3.889152-0.155648-6.623232-0.444416l-4.56704 36.038656c11.558912-3.043328 21.225472-4.56704 28.981248-4.56704 19.001344 0 34.670592 6.135808 46.993408 18.356224 12.324864 12.25728 18.479104 27.8016 18.479104 46.671872 0 19.769344-6.656 36.337664-19.95776 49.727488-13.32224 13.377536-29.626368 20.08064-48.939008 20.08064-16.279552 0-30.081024-5.134336-41.404416-15.403008-11.33568-10.268672-19.359744-27.035648-24.082432-50.305024l-41.050112 5.476352c2.736128 27.826176 13.80352 50.495488 33.193984 67.987456 19.390464 17.48992 43.759616 26.22464 73.107456 26.22464 32.548864 0 59.47392-10.145792 80.766976-30.447616 21.291008-20.314112 31.936512-45.049856 31.936512-74.252288 0-21.604352-5.480448-39.583744-16.42496-53.9648-10.944512-14.372864-26.312704-23.842816-46.082048-28.397568z" /></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
1
src/assets/images/sjzwsc_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M722.6624 108.928a86.6048 86.6048 0 0 1 86.6048 86.6048v245.76a21.6576 21.6576 0 0 1-43.3152 0v-245.76a43.2896 43.2896 0 0 0-43.2896-43.2896H246.3744a43.2896 43.2896 0 0 0-43.3152 43.2896v621.7728a43.2896 43.2896 0 0 0 43.3152 43.2896h297.0624a21.6576 21.6576 0 1 1 0 43.3152H246.3744a86.6048 86.6048 0 0 1-86.6048-86.6048V195.5328a86.6048 86.6048 0 0 1 86.6048-86.6048h476.288z m-106.24 213.3248c10.24 6.144 13.568 19.456 7.424 29.696l-158.72 274.7648a21.6576 21.6576 0 1 1-37.12-22.3232l158.72-274.7392c6.144-10.24 19.456-13.568 29.696-7.424z m-108.8512 1.9456c10.24 6.144 13.568 19.456 7.424 29.696l-102.8096 173.824a21.6576 21.6576 0 1 1-37.12-22.2976l102.8096-173.824c6.144-10.24 19.456-13.568 29.696-7.424z m-103.424-11.8528c10.24 6.144 13.568 19.456 7.3984 29.696l-66.8928 111.36a21.6576 21.6576 0 1 1-37.12-22.2976l66.8928-111.36c6.144-10.24 19.456-13.568 29.696-7.3984z" fill="#3B424C" /><path d="M489.088 809.9328a43.5712 43.5712 0 1 0 0-87.168 43.5712 43.5712 0 0 0 0 87.168zM742.4768 498.6368a194.8416 194.8416 0 0 1 194.0736 194.816 195.3024 195.3024 0 0 1-197.12 194.8416 194.8416 194.8416 0 0 1 3.0464-389.6576z m-3.072 45.824a148.992 148.992 0 1 0 4.608 297.984 148.992 148.992 0 0 0-4.608-297.984z m2.304 36.608c11.5968 0 21.0944 9.088 21.76 20.5312l0.0256 1.28v99.1744l56.1664 30.4896a21.7856 21.7856 0 0 1 9.344 28.3648l-0.5888 1.1776a21.7856 21.7856 0 0 1-28.3648 9.3696l-1.1776-0.6144-67.584-36.6592a21.7856 21.7856 0 0 1-11.3152-17.7664l-0.0512-1.3824V602.88c0-12.032 9.7536-21.7856 21.7856-21.7856z" fill="#4B7EFE" /></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
src/assets/images/srhy_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="44.77px" viewBox="0 0 1098 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M545.501953 292.942155l3.101943 3.101942 85.082433-82.423481a337.670781 337.670781 0 0 0 25.258535-24.816543l11.078796-11.520788 14.62273-14.623731a97.933196 97.933196 0 0 0 32.792396-74.003637 79.321539 79.321539 0 0 0-19.497641-60.26689 92.172302 92.172302 0 0 0-147.12229 19.054649A88.627368 88.627368 0 0 0 471.054324 0.028549a91.286319 91.286319 0 0 0-91.286319 91.286319 97.047213 97.047213 0 0 0 32.792396 70.901694z m441.363871 453.32865a35.451347 35.451347 0 0 0-22.156592-8.419845 32.349404 32.349404 0 0 0-22.599584 55.835972 300.004475 300.004475 0 0 1 88.627368 192.76445 33.67838 33.67838 0 1 0 66.913768 0 396.164703 396.164703 0 0 0-110.78496-240.180577z" /><path fill="#4B64FA" d="M761.308978 287.624253a214.921042 214.921042 0 0 0-214.035058 209.604139 217.137001 217.137001 0 0 0-214.035058-209.604139 215.365033 215.365033 0 0 0-125.40769 390.402809 272.085989 272.085989 0 0 0-97.490204 68.243743A381.097981 381.097981 0 0 0 0 988.667341a35.894339 35.894339 0 0 0 33.235388 33.679379 35.894339 35.894339 0 0 0 33.67838-33.679379 310.196287 310.196287 0 0 1 88.627367-192.76445 255.247299 255.247299 0 0 1 170.606858-73.560645h7.090869A214.921042 214.921042 0 0 0 547.27492 515.396057a215.808025 215.808025 0 0 0 88.626368 162.632005 278.732866 278.732866 0 0 0-88.627368 61.152874h-8.862836a32.349404 32.349404 0 0 0-22.599584 8.419845 33.235388 33.235388 0 0 0-10.191812 23.485567 26.58851 26.58851 0 0 0 3.101942 13.294755 363.815299 363.815299 0 0 0-78.878547 205.615213 35.894339 35.894339 0 0 0 33.235388 33.67838 36.337331 36.337331 0 0 0 33.67838-33.67838 279.61985 279.61985 0 0 1 55.834971-150.667225 274.301948 274.301948 0 0 1 53.619013 148.451266 33.67838 33.67838 0 0 0 66.914767 0 364.702283 364.702283 0 0 0-76.663588-197.63836 254.803307 254.803307 0 0 1 156.871111-67.800751h7.08987A215.365033 215.365033 0 0 0 974.902044 507.420204a218.022984 218.022984 0 0 0-213.592066-219.795951zM914.193162 502.545294a151.110217 151.110217 0 0 1-145.792314 150.223233h-11.521788a149.33725 149.33725 0 1 1 157.314102-150.666225z m-430.286075 0A151.110217 151.110217 0 0 1 338.113773 652.768527h-11.96478a149.33725 149.33725 0 1 1 157.757094-150.666225z" /></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/assets/images/tg_qrcode_1.png
Normal file
|
After Width: | Height: | Size: 846 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 |
BIN
src/assets/images/vip_banner.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
src/assets/images/vip_bg.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
1
src/assets/images/xlhy_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M938.666667 398.506667a45.653333 45.653333 0 0 0-19.626667-35.84L539.733333 95.573333a45.226667 45.226667 0 0 0-52.693333 0L106.666667 362.666667a42.666667 42.666667 0 0 0 0 75.733333l149.333333 104.533333V682.666667a256 256 0 0 0 512 0v-137.813334l85.333333-60.16V661.333333a42.666667 42.666667 0 0 0 85.333334 0V405.333333v-6.826666zM682.666667 682.666667a170.666667 170.666667 0 0 1-341.333334 0v-79.573334l145.706667 102.613334a45.866667 45.866667 0 0 0 52.693333 0l142.933334-100.693334z m0-190.506667l-169.386667 119.253333L341.333333 490.666667l-85.333333-60.16-42.666667-29.44 44.8-31.573334L513.28 189.866667 758.826667 362.666667H512a42.666667 42.666667 0 0 0 0 85.333333h233.173333z" /></svg>
|
||||
|
After Width: | Height: | Size: 983 B |
1
src/assets/images/xunihaoma_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M716.096 0c32.384 0 59.136 23.936 62.784 54.784l0.448 7.232-0.128 153.28c-29.696-13.76-46.464-24.448-46.464-24.448l-14.784-7.296v-18.88h-528.64v666.24h528.64v-16.256c10.304-2.368 33.344-13.184 61.248-29.888l0.128 177.216a62.464 62.464 0 0 1-55.872 61.568l-7.36 0.448H191.232a62.784 62.784 0 0 1-62.784-54.784L128 961.92V62.016c0-31.808 24.384-58.048 55.872-61.568L191.232 0h524.8z m-262.4 873.6a51.392 51.392 0 0 0-51.84 50.88c0 28.096 23.168 50.816 51.84 50.816 28.608 0 51.84-22.72 51.84-50.816a51.392 51.392 0 0 0-51.84-50.88z m260.16-644.864l15.616 7.68s33.28 21.184 88 40.448c50.88 19.264 82.176 19.264 82.176 19.264l23.424 1.92v265.92c0 98.304-187.712 204.224-209.216 204.224-23.488 0-209.28-105.92-209.28-204.16V297.984l25.472-1.92s29.312-1.92 82.112-19.2a585.024 585.024 0 0 0 83.904-38.144l3.648-2.112 0.448-0.256 13.696-7.68z m97.792 159.872L694.272 533.12l-62.528-55.872-29.376 36.608 97.792 88.64 146.688-181.12-35.2-32.768z m-299.456-311.04h-117.12a16.576 16.576 0 0 0-16.64 16.384c0 7.744 5.44 14.272 12.8 16l3.84 0.384h117.12a16.576 16.576 0 0 0 16.768-16.384 16.576 16.576 0 0 0-16.768-16.384z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
src/assets/images/yhk4ys_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M137.2622 508.74077l38.936801 0 0 218.511689-38.936801 0L137.2622 508.74077 137.2622 508.74077zM137.2622 508.74077" /><path fill="#4B64FA" d="M215.137849 508.74077l38.939871 0 0 218.511689-38.939871 0L215.137849 508.74077 215.137849 508.74077zM215.137849 508.74077" /><path fill="#4B64FA" d="M293.016567 508.74077l38.936801 0 0 218.511689-38.936801 0L293.016567 508.74077 293.016567 508.74077zM293.016567 508.74077" /><path fill="#4B64FA" d="M124.163881 783.822872c-25.908066-2.705622-46.272883-24.810059-46.272883-51.440579L77.890998 232.474702c0-28.441772 23.233144-49.553603 51.632961-49.553603l755.787352 0c28.399817 0 53.800323 21.112853 53.800323 49.553603l0 310.202994c12.725836 9.861602 24.509207 20.857027 35.21606 32.8205L974.327694 214.801181c0-38.150902-34.065863-66.464761-72.161506-66.464761L111.927185 148.33642c-38.089503 0-69.252247 28.313859-69.252247 66.464761l0 534.608927c0 35.719526 27.316136 65.36573 62.065568 68.997444l415.806147 0c-3.078105-11.249205-5.426593-22.791076-6.978948-34.58468L124.163881 783.822872 124.163881 783.822872zM124.163881 783.822872" /><path fill="#4B64FA" d="M65.239863 325.343833l873.871771 0 0 119.525234-873.871771 0 0-119.525234Z" /><path fill="#4B64FA" d="M768.32183 691.604564c-1.24741 3.070942-3.071965 6.478552-5.470595 10.221806l-50.103118 77.17059 58.741869 0 0-73.138764c0-6.239098 0.192382-13.389962 0.576121-21.452591l-0.86367 0C770.433934 686.23016 769.474073 688.629813 768.32183 691.604564z" /><path fill="#4B64FA" d="M776.145006 551.10053c-110.596887 0-200.25386 88.847537-200.25386 198.456934s89.656973 198.452841 200.25386 198.452841 200.251813-88.842421 200.251813-198.452841S886.741893 551.10053 776.145006 551.10053zM841.029782 812.399721 813.96231 812.399721l0 48.663326-42.472324 0 0-48.663326-98.04706 0 0-29.658484 94.15952-144.694473 46.359864 0 0 140.951219 27.067472 0L841.029782 812.399721z" /></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
1
src/assets/images/yhkhmd_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M992 96H32a32 32 0 0 0-32 32v704a32 32 0 0 0 32 32h416v-64H64v-288h384v-64H64v-128h896v96h64V128a32 32 0 0 0-32-32zM64 256V160h896v96zM128 608h64v64H128zM256 608h64v64H256zM768 416a256 256 0 1 0 256 256 256 256 0 0 0-256-256z m0 448a192 192 0 1 1 192-192 192 192 0 0 1-192 192zM841.28 553.28L768 626.88l-73.28-73.6-45.44 45.44 73.6 73.28-73.6 73.28 45.44 45.44 73.28-73.6 73.28 73.6 45.44-45.44-73.6-73.28 73.6-73.28-45.44-45.44z" /></svg>
|
||||
|
After Width: | Height: | Size: 719 B |
1
src/assets/images/yhksys_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M225.8 491h30.8v173h-30.8zM287.4 491h30.8v173h-30.8zM349.1 491h30.8v173h-30.8zM215.4 708.8c-20.5-2.1-36.6-19.6-36.6-40.7V440.4h681.9v77.4c10.1 7.8 19.4 16.5 27.9 26V258.3c0-30.2-27-52.6-57.1-52.6H205.7c-30.2 0-54.8 22.4-54.8 52.6v423.3c0 28.3 21.6 51.8 49.1 54.6h329.2c-2.4-8.9-4.3-18-5.5-27.4H215.4z m4.2-475.8h598.5c22.5 0 42.6 16.7 42.6 39.2v73.5H178.8v-73.5c0-22.5 18.4-39.2 40.8-39.2z m0 0M731.7 524.6c-87.6 0-158.6 70.4-158.6 157.1s71 157.1 158.6 157.1 158.6-70.3 158.6-157.1-71.1-157.1-158.6-157.1z m42.9 234.3c-12.3 9.4-28.6 14.1-49.1 14.1-18.2 0-32.8-3-43.9-9v-32.5c11.8 8.8 25.5 13.2 41.3 13.2 10 0 17.9-2.2 23.7-6.6 5.9-4.4 8.8-10.7 8.8-18.8 0-8.4-3.5-14.7-10.4-19.2-7-4.4-16.7-6.6-29.2-6.6H700v-28.4h14.5c23.7 0 35.6-8 35.6-23.9 0-15-9.1-22.6-27.2-22.6-11.9 0-23.4 3.9-34.5 11.6v-30.4c12.2-6.3 26.5-9.5 43-9.5 16.7 0 30.3 3.9 40.7 11.6 10.4 7.7 15.6 18.4 15.6 32.1 0 23.1-11.7 37.6-35.1 43.5v0.6c12.3 1.4 22.2 5.9 29.5 13.5 7.4 7.6 11.1 16.9 11.1 27.9-0.2 16.9-6.3 30-18.6 39.4z m0 0" /></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/images/yq_qrcode_1.png
Normal file
|
After Width: | Height: | Size: 585 KiB |
1
src/assets/images/zrrsczt_icon.svg
Normal file
@@ -0,0 +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 class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#4B64FA" d="M800.53 643.11L662.89 505.46l-11.12-11.12-33.66-33.66-0.41-0.42h-0.01l-246.8-246.8c-2.06-2.06-4.38-3.64-6.79-5.02 0.25-0.35 0.46-0.72 0.71-1.07l-45.18-45.19c-32.72 41.63-52.42 93.95-52.42 150.89 0 65.45 25.96 124.84 67.94 168.8-102.62 91.7-167.41 259.88-167.41 442.15 0 17.49 14.18 31.67 31.67 31.67h625.17c17.49 0 31.67-14.18 31.67-31.67 0.01-101.58-20.16-198.8-55.72-280.91zM330.55 313.09c0-15.44 2.02-30.39 5.7-44.68l220.43 220.44c-14.3 3.67-29.24 5.69-44.68 5.69-100.05 0-181.45-81.4-181.45-181.45z m-98.76 579.28c6.93-157.25 65.11-297.71 153.39-370.29 37.03 22.57 80.36 35.81 126.82 35.81 33.52 0 65.36-6.98 94.44-19.27l138.61 138.62c0.72 0.72 1.54 1.25 2.3 1.88 25.58 63.07 41.45 136.08 44.85 213.26H231.79zM512 131.63c100.05 0 181.44 81.4 181.44 181.45 0 37.76-11.61 72.85-31.44 101.92l45.18 45.19c30.99-41.01 49.6-91.86 49.6-147.11 0-134.99-109.81-244.8-244.79-244.8-55.24 0-106.11 18.61-147.11 49.6l45.19 45.19c29.08-19.82 64.17-31.44 101.93-31.44z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
30
src/assets/main.css
Normal file
@@ -0,0 +1,30 @@
|
||||
@import "./base.css";
|
||||
@import "./nprogress.css";
|
||||
@import "./vant-theme.css";
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
#app {
|
||||
margin: 0 auto;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
.card {
|
||||
@apply shadow rounded-xl bg-white p-6;
|
||||
}
|
||||
.ltitle {
|
||||
@apply mx-auto mt-2 w-64 border rounded-3xl bg-gradient-to-r from-blue-400 via-green-500 to-teal-500 py-2 text-center text-white font-bold;
|
||||
}
|
||||
10
src/assets/nprogress.css
Normal file
@@ -0,0 +1,10 @@
|
||||
/* 进度条颜色 */
|
||||
#nprogress .bar {
|
||||
background: #a22525; /* 主题色 */
|
||||
height: 4px; /* 修改高度 */
|
||||
}
|
||||
|
||||
/* 圆圈颜色 */
|
||||
#nprogress .peg {
|
||||
box-shadow: 0 0 10px #a22525, 0 0 5px #a22525;
|
||||
}
|
||||
1
src/assets/uni-webview.js
Normal file
434
src/assets/vant-theme.css
Normal file
@@ -0,0 +1,434 @@
|
||||
/* Vant 主题色配置 - 使用 CSS 变量统一管理主题色 */
|
||||
|
||||
/* 定义主题色变量 */
|
||||
:root {
|
||||
/* 主色调 - 可以根据需要修改这个变量来改变整个主题 */
|
||||
--van-theme-primary: #a22525;
|
||||
--van-theme-primary-light: rgba(162, 37, 37, 0.1);
|
||||
--van-theme-primary-dark: rgba(162, 37, 37, 0.8);
|
||||
--van-theme-primary-alpha: rgba(162, 37, 37, 0.15);
|
||||
|
||||
/* 覆盖 Vant 默认的主色调变量 */
|
||||
--van-primary-color: var(--van-theme-primary);
|
||||
--van-success-color: #07c160;
|
||||
--van-warning-color: #ff976a;
|
||||
--van-danger-color: #ee0a24;
|
||||
|
||||
/* 文本颜色 */
|
||||
--van-text-color: #323233;
|
||||
--van-text-color-2: #646566;
|
||||
--van-text-color-3: #969799;
|
||||
|
||||
/* 背景色 */
|
||||
--van-background-color: #ffffff;
|
||||
--van-background-color-light: #fafafa;
|
||||
|
||||
/* 边框色 */
|
||||
--van-border-color: #ebedf0;
|
||||
|
||||
/* 活跃状态颜色 */
|
||||
--van-active-color: #f2f3f5;
|
||||
}
|
||||
|
||||
/* 使用 CSS 变量覆盖组件样式 */
|
||||
|
||||
/* 按钮组件 */
|
||||
.van-button--primary {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
border-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-button--primary:active {
|
||||
background-color: var(--van-theme-primary-dark) !important;
|
||||
}
|
||||
|
||||
/* 导航栏组件 */
|
||||
.van-nav-bar {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-nav-bar__title {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-nav-bar__left,
|
||||
.van-nav-bar__right {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-nav-bar__arrow {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
.van-nav-bar__text {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
/* 标签栏组件 */
|
||||
.van-tabbar-item--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 标签页组件 */
|
||||
.van-tabs__line {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-tab--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-tabs__wrap {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 开关组件 */
|
||||
.van-switch--on {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 复选框组件 */
|
||||
/* 取消复选框主题色配置,使用默认样式 */
|
||||
|
||||
/* 单选框组件 */
|
||||
/* 取消单选框主题色配置,使用默认样式 */
|
||||
|
||||
/* 滑动条组件 */
|
||||
.van-slider__bar {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-slider__button {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
border-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 进度条组件 */
|
||||
.van-progress__portion {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 评分组件 */
|
||||
.van-rate__icon--full {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 步进器组件 */
|
||||
.van-stepper__plus,
|
||||
.van-stepper__minus {
|
||||
color: var(--van-theme-primary) !important;
|
||||
border-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 步骤条组件 */
|
||||
.van-steps__item--active .van-steps__item__circle {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
border-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 标签组件 */
|
||||
.van-tag--primary {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 徽章组件 */
|
||||
.van-badge--primary {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 通知栏组件 */
|
||||
.van-notice-bar--primary {
|
||||
background-color: var(--van-theme-primary-light) !important;
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 轮播图指示器 */
|
||||
.van-swipe__indicator--active {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 加载组件 */
|
||||
.van-loading__spinner {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 弹窗组件 */
|
||||
.van-popup {
|
||||
background-color: var(--van-background-color) !important;
|
||||
}
|
||||
|
||||
/* 选择器组件 */
|
||||
.van-picker {
|
||||
background-color: var(--van-background-color) !important;
|
||||
}
|
||||
|
||||
.van-picker__toolbar {
|
||||
background-color: var(--van-background-color) !important;
|
||||
}
|
||||
|
||||
.van-picker__confirm {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-picker__cancel {
|
||||
color: var(--van-text-color-2) !important;
|
||||
}
|
||||
|
||||
/* 日期选择器组件 */
|
||||
.van-date-picker {
|
||||
background-color: var(--van-background-color) !important;
|
||||
}
|
||||
|
||||
.van-date-picker__toolbar {
|
||||
background-color: var(--van-background-color) !important;
|
||||
}
|
||||
|
||||
.van-date-picker__confirm {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-date-picker__cancel {
|
||||
color: var(--van-text-color-2) !important;
|
||||
}
|
||||
|
||||
/* 字段组件 */
|
||||
.van-field__control {
|
||||
color: var(--van-text-color) !important;
|
||||
}
|
||||
|
||||
.van-field__placeholder {
|
||||
color: var(--van-text-color-3) !important;
|
||||
}
|
||||
|
||||
.van-field__right-icon {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 动作面板组件 */
|
||||
.van-action-sheet__item--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 选择器组件 */
|
||||
.van-picker__confirm {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 日期选择器组件 */
|
||||
.van-datetime-picker__confirm {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 地区选择器组件 */
|
||||
.van-area__confirm {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 搜索组件 */
|
||||
.van-search__action {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 日历组件 */
|
||||
.van-calendar__day--selected {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-calendar__day--start,
|
||||
.van-calendar__day--end {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 时间选择器组件 */
|
||||
.van-time-picker__confirm {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 商品卡片组件 */
|
||||
.van-card__price {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 优惠券组件 */
|
||||
.van-coupon__discount {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 地址编辑组件 */
|
||||
.van-address-edit__default {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 商品规格选择器组件 */
|
||||
.van-sku-item--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
border-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 购物车组件 */
|
||||
.van-submit-bar__price {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 提交订单栏组件 */
|
||||
.van-submit-bar__button--primary {
|
||||
background-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 侧边栏组件 */
|
||||
.van-sidebar-item--select {
|
||||
color: var(--van-theme-primary) !important;
|
||||
border-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 树形选择器组件 */
|
||||
.van-tree-select__item--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 联系人列表组件 */
|
||||
.van-contact-list__item--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 密码输入框组件 */
|
||||
.van-password-input__item--focus {
|
||||
border-color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 下拉菜单组件 */
|
||||
.van-dropdown-menu__title--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.van-dropdown-menu__option--active {
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 索引组件 */
|
||||
.van-index-anchor--active {
|
||||
background-color: var(--van-background-color) !important;
|
||||
color: var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
/* 水印组件 */
|
||||
.van-water-mark {
|
||||
color: var(--van-theme-primary-alpha) !important;
|
||||
}
|
||||
|
||||
/* 分割线组件 */
|
||||
.van-divider {
|
||||
color: var(--van-text-color-3) !important;
|
||||
}
|
||||
|
||||
/* 分享组件 */
|
||||
.van-share-sheet__option-name {
|
||||
color: var(--van-text-color) !important;
|
||||
}
|
||||
|
||||
/* 骨架屏组件 */
|
||||
.van-skeleton__content {
|
||||
background-color: var(--van-background-color-light) !important;
|
||||
}
|
||||
|
||||
/* 空状态组件 */
|
||||
.van-empty__description {
|
||||
color: var(--van-text-color-2) !important;
|
||||
}
|
||||
|
||||
/* 倒计时组件 */
|
||||
.van-count-down {
|
||||
color: var(--van-text-color) !important;
|
||||
}
|
||||
|
||||
/* 签名组件 */
|
||||
.van-signature {
|
||||
background-color: var(--van-background-color) !important;
|
||||
border-color: var(--van-border-color) !important;
|
||||
}
|
||||
|
||||
/* 上传组件 */
|
||||
.van-uploader__upload {
|
||||
background-color: var(--van-background-color-light) !important;
|
||||
}
|
||||
|
||||
/* 列表组件 */
|
||||
.van-list__loading,
|
||||
.van-list__finished-text {
|
||||
color: var(--van-text-color-2) !important;
|
||||
}
|
||||
|
||||
/* 下拉刷新组件 */
|
||||
.van-pull-refresh__text {
|
||||
color: var(--van-text-color-2) !important;
|
||||
}
|
||||
|
||||
/* 懒加载组件 */
|
||||
.van-lazyload {
|
||||
background-color: var(--van-background-color-light) !important;
|
||||
}
|
||||
|
||||
/* 图片预览组件 */
|
||||
.van-image-preview__index {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 索引组件 */
|
||||
.van-index-anchor {
|
||||
background-color: var(--van-background-color-light) !important;
|
||||
color: var(--van-text-color-2) !important;
|
||||
}
|
||||
|
||||
/* 弹出层遮罩 */
|
||||
.van-overlay {
|
||||
background-color: rgba(0, 0, 0, 0.5) !important;
|
||||
}
|
||||
|
||||
/* Toast 组件 */
|
||||
.van-toast {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-toast--success {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-toast--fail {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-toast--loading {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-toast__text {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-toast__icon {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* Loading Toast 特殊处理 */
|
||||
.van-loading-toast {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-loading-toast .van-loading__spinner {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.van-loading-toast .van-toast__text {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 数字键盘组件 */
|
||||
.van-number-keyboard__key--active {
|
||||
background-color: var(--van-active-color) !important;
|
||||
}
|
||||
315
src/auto-imports.d.ts
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const VanTabbar: typeof import('vant/es')['Tabbar']
|
||||
const VanTabbarItem: typeof import('vant/es')['TabbarItem']
|
||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
|
||||
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
|
||||
const closeToast: typeof import('vant/es')['closeToast']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const computedAsync: typeof import('@vueuse/core')['computedAsync']
|
||||
const computedEager: typeof import('@vueuse/core')['computedEager']
|
||||
const computedInject: typeof import('@vueuse/core')['computedInject']
|
||||
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
|
||||
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
|
||||
const controlledRef: typeof import('@vueuse/core')['controlledRef']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const createEventHook: typeof import('@vueuse/core')['createEventHook']
|
||||
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
|
||||
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
|
||||
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
|
||||
const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate']
|
||||
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
|
||||
const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise']
|
||||
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
|
||||
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
|
||||
const onLongPress: typeof import('@vueuse/core')['onLongPress']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
||||
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const provideLocal: typeof import('@vueuse/core')['provideLocal']
|
||||
const reactify: typeof import('@vueuse/core')['reactify']
|
||||
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
|
||||
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
|
||||
const reactivePick: typeof import('@vueuse/core')['reactivePick']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
|
||||
const refDebounced: typeof import('@vueuse/core')['refDebounced']
|
||||
const refDefault: typeof import('@vueuse/core')['refDefault']
|
||||
const refThrottled: typeof import('@vueuse/core')['refThrottled']
|
||||
const refWithControl: typeof import('@vueuse/core')['refWithControl']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const resolveRef: typeof import('@vueuse/core')['resolveRef']
|
||||
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const showLoadingToast: typeof import('vant/es')['showLoadingToast']
|
||||
const showToast: typeof import('vant/es')['showToast']
|
||||
const syncRef: typeof import('@vueuse/core')['syncRef']
|
||||
const syncRefs: typeof import('@vueuse/core')['syncRefs']
|
||||
const templateRef: typeof import('@vueuse/core')['templateRef']
|
||||
const throttledRef: typeof import('@vueuse/core')['throttledRef']
|
||||
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toReactive: typeof import('@vueuse/core')['toReactive']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
|
||||
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
|
||||
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
|
||||
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
|
||||
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const unrefElement: typeof import('@vueuse/core')['unrefElement']
|
||||
const until: typeof import('@vueuse/core')['until']
|
||||
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
|
||||
const useAgent: typeof import('./composables/useAgent.js')['useAgent']
|
||||
const useAgentStore: typeof import('./stores/agentStore.js')['useAgentStore']
|
||||
const useAnimate: typeof import('@vueuse/core')['useAnimate']
|
||||
const useApiFetch: typeof import('./composables/useApiFetch.js')['default']
|
||||
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
|
||||
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
|
||||
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
|
||||
const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
|
||||
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
|
||||
const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast']
|
||||
const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes']
|
||||
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
|
||||
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
|
||||
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
|
||||
const useArraySome: typeof import('@vueuse/core')['useArraySome']
|
||||
const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique']
|
||||
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
|
||||
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useBase64: typeof import('@vueuse/core')['useBase64']
|
||||
const useBattery: typeof import('@vueuse/core')['useBattery']
|
||||
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
|
||||
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
|
||||
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
|
||||
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
|
||||
const useCached: typeof import('@vueuse/core')['useCached']
|
||||
const useClipboard: typeof import('@vueuse/core')['useClipboard']
|
||||
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
|
||||
const useCloned: typeof import('@vueuse/core')['useCloned']
|
||||
const useColorMode: typeof import('@vueuse/core')['useColorMode']
|
||||
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
|
||||
const useCounter: typeof import('@vueuse/core')['useCounter']
|
||||
const useCounterStore: typeof import('./stores/counter.js')['useCounterStore']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVar: typeof import('@vueuse/core')['useCssVar']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
|
||||
const useCycleList: typeof import('@vueuse/core')['useCycleList']
|
||||
const useDark: typeof import('@vueuse/core')['useDark']
|
||||
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
|
||||
const useDebounce: typeof import('@vueuse/core')['useDebounce']
|
||||
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
|
||||
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
|
||||
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
|
||||
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
|
||||
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
|
||||
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
|
||||
const useDialogStore: typeof import('./stores/dialogStore.js')['useDialogStore']
|
||||
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
|
||||
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
|
||||
const useDraggable: typeof import('@vueuse/core')['useDraggable']
|
||||
const useDropZone: typeof import('@vueuse/core')['useDropZone']
|
||||
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
|
||||
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
|
||||
const useElementHover: typeof import('@vueuse/core')['useElementHover']
|
||||
const useElementSize: typeof import('@vueuse/core')['useElementSize']
|
||||
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
|
||||
const useEnv: typeof import('./composables/useEnv.js')['useEnv']
|
||||
const useEnvironment: typeof import('./composables/useEnvironment.js')['useEnvironment']
|
||||
const useEventBus: typeof import('@vueuse/core')['useEventBus']
|
||||
const useEventListener: typeof import('@vueuse/core')['useEventListener']
|
||||
const useEventSource: typeof import('@vueuse/core')['useEventSource']
|
||||
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
|
||||
const useFavicon: typeof import('@vueuse/core')['useFavicon']
|
||||
const useFetch: typeof import('@vueuse/core')['useFetch']
|
||||
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
|
||||
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
|
||||
const useFocus: typeof import('@vueuse/core')['useFocus']
|
||||
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
|
||||
const useFps: typeof import('@vueuse/core')['useFps']
|
||||
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
|
||||
const useGamepad: typeof import('@vueuse/core')['useGamepad']
|
||||
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
|
||||
const useHttp: typeof import('./composables/useHttp.js')['useHttp']
|
||||
const useId: typeof import('vue')['useId']
|
||||
const useIdle: typeof import('@vueuse/core')['useIdle']
|
||||
const useImage: typeof import('@vueuse/core')['useImage']
|
||||
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
|
||||
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
|
||||
const useInterval: typeof import('@vueuse/core')['useInterval']
|
||||
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
|
||||
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
|
||||
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
|
||||
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
|
||||
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
|
||||
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
|
||||
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
|
||||
const useMemoize: typeof import('@vueuse/core')['useMemoize']
|
||||
const useMemory: typeof import('@vueuse/core')['useMemory']
|
||||
const useModel: typeof import('vue')['useModel']
|
||||
const useMounted: typeof import('@vueuse/core')['useMounted']
|
||||
const useMouse: typeof import('@vueuse/core')['useMouse']
|
||||
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
|
||||
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
|
||||
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
|
||||
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
|
||||
const useNetwork: typeof import('@vueuse/core')['useNetwork']
|
||||
const useNow: typeof import('@vueuse/core')['useNow']
|
||||
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
|
||||
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
|
||||
const useOnline: typeof import('@vueuse/core')['useOnline']
|
||||
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
|
||||
const useParallax: typeof import('@vueuse/core')['useParallax']
|
||||
const useParentElement: typeof import('@vueuse/core')['useParentElement']
|
||||
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
|
||||
const usePermission: typeof import('@vueuse/core')['usePermission']
|
||||
const usePointer: typeof import('@vueuse/core')['usePointer']
|
||||
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
|
||||
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
|
||||
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
|
||||
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
|
||||
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
|
||||
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
|
||||
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
|
||||
const usePrevious: typeof import('@vueuse/core')['usePrevious']
|
||||
const useRafFn: typeof import('@vueuse/core')['useRafFn']
|
||||
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
|
||||
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSEO: typeof import('./composables/useSEO.js')['useSEO']
|
||||
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
|
||||
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
|
||||
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
|
||||
const useScroll: typeof import('@vueuse/core')['useScroll']
|
||||
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
|
||||
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
|
||||
const useShare: typeof import('@vueuse/core')['useShare']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useSorted: typeof import('@vueuse/core')['useSorted']
|
||||
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
|
||||
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
|
||||
const useStepper: typeof import('@vueuse/core')['useStepper']
|
||||
const useStorage: typeof import('@vueuse/core')['useStorage']
|
||||
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
|
||||
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
|
||||
const useSupported: typeof import('@vueuse/core')['useSupported']
|
||||
const useSwipe: typeof import('@vueuse/core')['useSwipe']
|
||||
const useTemplateRef: typeof import('vue')['useTemplateRef']
|
||||
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
|
||||
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
|
||||
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
|
||||
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
|
||||
const useThrottle: typeof import('@vueuse/core')['useThrottle']
|
||||
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
|
||||
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
|
||||
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
|
||||
const useTimeout: typeof import('@vueuse/core')['useTimeout']
|
||||
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
|
||||
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
|
||||
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
|
||||
const useTitle: typeof import('@vueuse/core')['useTitle']
|
||||
const useToNumber: typeof import('@vueuse/core')['useToNumber']
|
||||
const useToString: typeof import('@vueuse/core')['useToString']
|
||||
const useToggle: typeof import('@vueuse/core')['useToggle']
|
||||
const useTransition: typeof import('@vueuse/core')['useTransition']
|
||||
const useUni: typeof import('./composables/useUni.js')['useUni']
|
||||
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
|
||||
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
|
||||
const useUserStore: typeof import('./stores/userStore.js')['useUserStore']
|
||||
const useVModel: typeof import('@vueuse/core')['useVModel']
|
||||
const useVModels: typeof import('@vueuse/core')['useVModels']
|
||||
const useVibrate: typeof import('@vueuse/core')['useVibrate']
|
||||
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
|
||||
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
|
||||
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
|
||||
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
|
||||
const useWebView: typeof import('./composables/useWebView.js')['useWebView']
|
||||
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
|
||||
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
|
||||
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
|
||||
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
|
||||
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
|
||||
const useZoomAdapter: typeof import('./composables/useZoomAdapter.js')['useZoomAdapter']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchArray: typeof import('@vueuse/core')['watchArray']
|
||||
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
|
||||
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
|
||||
const watchDeep: typeof import('@vueuse/core')['watchDeep']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
|
||||
const watchImmediate: typeof import('@vueuse/core')['watchImmediate']
|
||||
const watchOnce: typeof import('@vueuse/core')['watchOnce']
|
||||
const watchPausable: typeof import('@vueuse/core')['watchPausable']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
|
||||
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
|
||||
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
|
||||
const whenever: typeof import('@vueuse/core')['whenever']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
263
src/components/AgentApplicationForm.vue
Normal file
@@ -0,0 +1,263 @@
|
||||
<template>
|
||||
<van-popup v-model:show="show" destroy-on-close round position="bottom">
|
||||
<div
|
||||
class="h-12 flex items-center justify-center font-semibold"
|
||||
style="background-color: var(--van-theme-primary-light); color: var(--van-theme-primary);"
|
||||
>
|
||||
成为代理
|
||||
</div>
|
||||
<div v-if="ancestor" class="text-center text-xs my-2" style="color: var(--van-text-color-2);">
|
||||
{{ maskName(ancestor) }}邀您成为天远数据代理方
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<van-field
|
||||
label-width="56"
|
||||
v-model="form.region"
|
||||
is-link
|
||||
readonly
|
||||
label="地区"
|
||||
placeholder="请选择地区"
|
||||
@click="showCascader = true"
|
||||
/>
|
||||
<van-popup v-model:show="showCascader" round position="bottom">
|
||||
<van-cascader
|
||||
v-model="cascaderValue"
|
||||
title="请选择所在地区"
|
||||
:options="options"
|
||||
@close="showCascader = false"
|
||||
@finish="onFinish"
|
||||
/>
|
||||
</van-popup>
|
||||
<van-field
|
||||
label-width="56"
|
||||
v-model="form.mobile"
|
||||
label="手机号"
|
||||
name="mobile"
|
||||
placeholder="请输入手机号"
|
||||
:readonly="isSelf"
|
||||
:disabled="isSelf"
|
||||
/>
|
||||
|
||||
<!-- 获取验证码按钮 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<van-field
|
||||
label-width="56"
|
||||
v-model="form.code"
|
||||
label="验证码"
|
||||
name="code"
|
||||
placeholder="请输入验证码"
|
||||
/>
|
||||
<button
|
||||
class="px-2 py-1 text-sm font-bold flex-shrink-0 rounded-lg transition duration-300"
|
||||
:class="
|
||||
isCountingDown || !isPhoneNumberValid
|
||||
? 'cursor-not-allowed bg-gray-300 text-gray-500'
|
||||
: 'text-white hover:opacity-90'
|
||||
"
|
||||
:style="isCountingDown || !isPhoneNumberValid
|
||||
? ''
|
||||
: 'background-color: var(--van-theme-primary);'"
|
||||
@click="getSmsCode"
|
||||
:disabled="isCountingDown || !isPhoneNumberValid"
|
||||
>
|
||||
{{
|
||||
isCountingDown ? `${countdown}s重新获取` : "获取验证码"
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
<!-- 同意条款的复选框 -->
|
||||
<div class="p-4">
|
||||
<div class="flex items-start">
|
||||
<van-checkbox
|
||||
v-model="isAgreed"
|
||||
name="agree"
|
||||
icon-size="16px"
|
||||
class="flex-shrink-0 mr-2"
|
||||
>
|
||||
</van-checkbox>
|
||||
<div class="text-xs leading-tight" style="color: var(--van-text-color-2);">
|
||||
我已阅读并同意
|
||||
<a
|
||||
class="cursor-pointer hover:underline"
|
||||
style="color: var(--van-theme-primary);"
|
||||
@click="toUserAgreement"
|
||||
>《用户协议》</a
|
||||
><a
|
||||
class="cursor-pointer hover:underline"
|
||||
style="color: var(--van-theme-primary);"
|
||||
@click="toServiceAgreement"
|
||||
>《信息技术服务合同》</a
|
||||
><a
|
||||
class="cursor-pointer hover:underline"
|
||||
style="color: var(--van-theme-primary);"
|
||||
@click="toAgentManageAgreement"
|
||||
>《推广方管理制度协议》</a
|
||||
>
|
||||
<div class="text-xs mt-1" style="color: var(--van-text-color-2);">
|
||||
点击勾选即代表您同意上述法律文书的相关条款并签署上述法律文书
|
||||
</div>
|
||||
<div class="text-xs mt-1" style="color: var(--van-text-color-2);">
|
||||
手机号未在本平台注册账号则申请后将自动生成账号
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<van-button type="primary" round block @click="submit"
|
||||
>提交申请</van-button
|
||||
>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<van-button type="default" round block @click="closePopup"
|
||||
>取消</van-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const router = useRouter();
|
||||
const show = defineModel("show");
|
||||
import { useCascaderAreaData } from "@vant/area-data";
|
||||
import { showToast } from "vant"; // 引入 showToast 方法
|
||||
const emit = defineEmits(); // 确保 emit 可以正确使用
|
||||
const props = defineProps({
|
||||
ancestor: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isSelf: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
userName: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
const { ancestor, isSelf, userName } = toRefs(props);
|
||||
const form = ref({
|
||||
region: "",
|
||||
mobile: "",
|
||||
code: "", // 增加验证码字段
|
||||
});
|
||||
const showCascader = ref(false);
|
||||
const cascaderValue = ref("");
|
||||
const options = useCascaderAreaData();
|
||||
const loadingSms = ref(false); // 控制验证码按钮的loading状态
|
||||
const isCountingDown = ref(false);
|
||||
const isAgreed = ref(false);
|
||||
const countdown = ref(60);
|
||||
const onFinish = ({ selectedOptions }) => {
|
||||
showCascader.value = false;
|
||||
form.value.region = selectedOptions.map((option) => option.text).join("/");
|
||||
};
|
||||
const isPhoneNumberValid = computed(() => {
|
||||
return /^1[3-9]\d{9}$/.test(form.value.mobile);
|
||||
});
|
||||
|
||||
const getSmsCode = async () => {
|
||||
if (!form.value.mobile) {
|
||||
showToast({ message: "请输入手机号" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "手机号格式不正确" });
|
||||
return;
|
||||
}
|
||||
|
||||
loadingSms.value = true;
|
||||
|
||||
const { data, error } = await useApiFetch("auth/sendSms")
|
||||
.post({ mobile: form.value.mobile, actionType: "agentApply" })
|
||||
.json();
|
||||
|
||||
loadingSms.value = false;
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
showToast({ message: "获取成功" });
|
||||
startCountdown(); // 启动倒计时
|
||||
} else {
|
||||
showToast(data.value.msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
let timer = null;
|
||||
|
||||
function startCountdown() {
|
||||
isCountingDown.value = true;
|
||||
countdown.value = 60;
|
||||
timer = setInterval(() => {
|
||||
if (countdown.value > 0) {
|
||||
countdown.value--;
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
isCountingDown.value = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
const submit = () => {
|
||||
// 校验表单字段
|
||||
if (!form.value.region) {
|
||||
showToast({ message: "请选择地区" });
|
||||
return;
|
||||
}
|
||||
if (!form.value.mobile) {
|
||||
showToast({ message: "请输入手机号" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "手机号格式不正确" });
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果不是自己申请,则需要验证码
|
||||
if (!isSelf.value && !form.value.code) {
|
||||
showToast({ message: "请输入验证码" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAgreed.value) {
|
||||
showToast({ message: "请先阅读并同意用户协议及相关条款" });
|
||||
return;
|
||||
}
|
||||
console.log("form", form.value);
|
||||
// 触发父组件提交申请
|
||||
emit("submit", form.value);
|
||||
};
|
||||
const maskName = computed(() => {
|
||||
return (name) => {
|
||||
return name.substring(0, 3) + "****" + name.substring(7);
|
||||
};
|
||||
});
|
||||
const closePopup = () => {
|
||||
emit("close");
|
||||
};
|
||||
|
||||
const toUserAgreement = () => {
|
||||
router.push({ name: "userAgreement" });
|
||||
};
|
||||
const toServiceAgreement = () => {
|
||||
router.push({ name: "agentSerivceAgreement" });
|
||||
};
|
||||
const toAgentManageAgreement = () => {
|
||||
router.push({ name: "agentManageAgreement" });
|
||||
};
|
||||
|
||||
// 如果是自己申请,则预填并锁定手机号
|
||||
onMounted(() => {
|
||||
if (isSelf.value && userName.value) {
|
||||
form.value.mobile = userName.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
175
src/components/Authorization.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div class=" bg-gray-100 flex flex-col p-4">
|
||||
<!-- 标题 -->
|
||||
<div class="text-center text-2xl font-bold mb-4">授权书</div>
|
||||
|
||||
<!-- 授权书滚动区域 -->
|
||||
<div class="card flex-1 overflow-y-auto" ref="agreementBox" @scroll="handleScroll">
|
||||
<p class="my-2">海南天远大数据科技有限公司:</p>
|
||||
<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>
|
||||
依法成立的第三方服务商查询或核实、搜集、保存、处理、共享、使用(含合法业务应用)本人相关数据,且不再另行告知本人,但法律、法规、监管政策禁止的除外。
|
||||
</li>
|
||||
<!-- <li>本人授权本业务推广方( )可浏览本人大数据报告。</li> -->
|
||||
<li>
|
||||
本人授权有效期为自授权之日起
|
||||
1个月。本授权为不可撤销授权,但法律法规另有规定的除外。
|
||||
</li>
|
||||
</ol>
|
||||
<p class="mt-2 font-bold">用户声明与承诺:</p>
|
||||
<ul class="list-decimal pl-6">
|
||||
<li>
|
||||
本人在授权签署前,已通过实名认证及动态验证码验证(或其他身份验证手段),确认本授权行为为本人真实意思表示,平台已履行身份验证义务。
|
||||
</li>
|
||||
<li>
|
||||
本人在此声明已充分理解上述授权条款含义,知晓并自愿承担因授权数据使用可能带来的后果,包括但不限于影响个人信用评分、生活行为等。本人确认授权范围内的相关信息由本人提供并真实有效。
|
||||
</li>
|
||||
<li>
|
||||
若用户冒名签署或提供虚假信息,由用户自行承担全部法律责任,平台不承担任何后果。
|
||||
</li>
|
||||
</ul>
|
||||
<p class="mt-2 font-bold">特别提示:</p>
|
||||
<ul class="list-decimal pl-6">
|
||||
<li>
|
||||
本产品所有数据均来自第三方。可能部分数据未公开、数据更新延迟或信息受到限制,贵司不对数据的准确性、真实性、完整性做任何承诺。用户需根据实际情况,结合报告内容自行判断与决策。
|
||||
</li>
|
||||
<li>
|
||||
本产品仅供用户本人查询或被授权查询。除非用户取得合法授权,用户不得利用本产品查询他人信息。用户因未获得合法授权而擅自查询他人信息所产生的任何后果,由用户自行承担责任。
|
||||
</li>
|
||||
<li>
|
||||
本授权书涉及对本人敏感信息(包括但不限于婚姻状态、资产状况等)的查询与使用。本人已充分知晓相关信息的敏感性,并明确同意贵司及其合作方依据授权范围使用相关信息。
|
||||
</li>
|
||||
<li>
|
||||
平台声明:本授权书涉及的信息核实及查询结果由第三方服务商提供,平台不对数据的准确性、完整性、实时性承担责任;用户根据报告所作决策的风险由用户自行承担,平台对此不承担法律责任。
|
||||
</li>
|
||||
<li>
|
||||
本授权书中涉及的数据查询和报告生成由依法成立的第三方服务商提供。若因第三方行为导致数据错误或损失,用户应向第三方主张权利,平台不承担相关责任。
|
||||
</li>
|
||||
</ul>
|
||||
<p class="mt-2 font-bold">附加说明:</p>
|
||||
<ul class="list-decimal pl-6">
|
||||
<li>
|
||||
本人在授权的相关数据将依据法律法规及贵司内部数据管理规范妥善存储,存储期限为法律要求的最短必要时间。超过存储期限或在数据使用目的达成后,贵司将对相关数据进行销毁或匿名化处理。
|
||||
</li>
|
||||
<li>
|
||||
本人有权随时撤回本授权书中的授权,但撤回前的授权行为及其法律后果仍具有法律效力。若需撤回授权,本人可通过贵司官方渠道提交书面申请,贵司将在收到申请后依法停止对本人数据的使用。
|
||||
</li>
|
||||
<li>
|
||||
你通过“天远数据”,自愿支付相应费用,用于购买海南天远大数据科技有限公司的大数据报告产品。如若对产品内容存在异议,可通过邮箱admin@iieeii.com或APP“联系客服”按钮进行反馈,贵司将在收到异议之日起20日内进行核查和处理,并将结果答复。
|
||||
</li>
|
||||
<li>
|
||||
你向海南天远大数据科技有限公司的支付方式为:海南天远大数据科技有限公司及其经官方授权的相关企业的支付宝账户。
|
||||
</li>
|
||||
</ul>
|
||||
<p class="mt-2 font-bold">争议解决机制:</p>
|
||||
<ul>
|
||||
<li>
|
||||
若因本授权书引发争议,双方应友好协商解决;协商不成的,双方同意将争议提交至授权书签署地(海南省)有管辖权的人民法院解决。
|
||||
</li>
|
||||
</ul>
|
||||
<p class="mt-2 font-bold">签署方式的法律效力声明:</p>
|
||||
<ul>
|
||||
<li>
|
||||
本授权书通过用户在线勾选、电子签名或其他网络签署方式完成,与手写签名具有同等法律效力。平台已通过技术手段保存签署过程的完整记录,作为用户真实意思表示的证据。
|
||||
</li>
|
||||
</ul>
|
||||
<p class="mt-2">本授权书于 {{ signTime }}生效。</p>
|
||||
<p class="mt-4 font-bold">
|
||||
签署人:<span class="underline">{{
|
||||
signature ? props.name : "____________"
|
||||
}}</span>
|
||||
<br />
|
||||
手机号码:<span class="underline">
|
||||
{{ signature ? props.mobile : "____________" }}
|
||||
</span>
|
||||
<br />
|
||||
签署时间:<span class="underline">{{ signTime }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mt-4 flex justify-between">
|
||||
<button class="flex-shrink-0 bg-red-500 text-white px-4 py-2 rounded-lg" @click="cancel">
|
||||
取消
|
||||
</button>
|
||||
<div class="mt-2 px-2 text-center text-sm text-gray-500">
|
||||
{{ scrollMessage }}
|
||||
</div>
|
||||
<button class="flex-shrink-0 bg-blue-500 text-white px-4 py-2 rounded-lg active:bg-blue-600" :class="!canAgree &&
|
||||
'bg-gray-300 cursor-not-allowed active:bg-gray-300'
|
||||
" :disabled="!canAgree" @click="agree">
|
||||
{{ signature ? "同意" : "签署" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
const emit = defineEmits(['agreed', 'cancel']); // 定义事件
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
idCard: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
mobile: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const signature = ref(false);
|
||||
const formatDate = (date) => {
|
||||
const options = { year: "numeric", month: "long", day: "numeric" };
|
||||
return new Intl.DateTimeFormat("zh-CN", options).format(date);
|
||||
};
|
||||
const signTime = ref(formatDate(new Date()));
|
||||
|
||||
const canAgree = ref(false); // 同意按钮状态
|
||||
const scrollMessage = ref("请滑动并阅读完整授权书以继续");
|
||||
|
||||
// 滚动事件处理
|
||||
let timeout = null;
|
||||
|
||||
const handleScroll = (event) => {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
const element = event.target;
|
||||
if (
|
||||
Math.abs(
|
||||
element.scrollHeight - element.scrollTop - element.clientHeight
|
||||
) <= 50
|
||||
) {
|
||||
canAgree.value = true;
|
||||
scrollMessage.value = "您已阅读完整授权书,可以继续";
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
// 用户同意
|
||||
const agree = () => {
|
||||
if (signature.value) {
|
||||
emit("agreed")
|
||||
return
|
||||
}
|
||||
signature.value = true
|
||||
};
|
||||
|
||||
// 用户取消
|
||||
const cancel = () => {
|
||||
emit("cancel")
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
947
src/components/BaseReport.vue
Normal file
@@ -0,0 +1,947 @@
|
||||
<script setup>
|
||||
import ShareReportButton from "./ShareReportButton.vue";
|
||||
import { splitDWBG8B4DForTabs } from '@/ui/CDWBG8B4D/utils/simpleSplitter.js';
|
||||
import { splitDWBG6A2CForTabs } from '@/ui/DWBG6A2C/utils/simpleSplitter.js';
|
||||
import { splitCJRZQ5E9FForTabs } from '@/ui/CJRZQ5E9F/utils/simpleSplitter.js';
|
||||
import { splitCQYGL3F8EForTabs } from '@/ui/CQYGL3F8E/utils/simpleSplitter.js';
|
||||
|
||||
const props = defineProps({
|
||||
isShare: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
orderId: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
orderNo: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
feature: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
reportData: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
reportParams: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
reportName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
reportDateTime: {
|
||||
type: [String, null],
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
isEmpty: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
isDone: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 使用toRefs将props转换为组件内的ref
|
||||
const {
|
||||
feature,
|
||||
reportData,
|
||||
reportParams,
|
||||
reportName,
|
||||
reportDateTime,
|
||||
isEmpty,
|
||||
isDone,
|
||||
} = toRefs(props);
|
||||
|
||||
const active = ref(null);
|
||||
|
||||
const reportScore = ref(0); // 默认分数
|
||||
|
||||
// 处理数据拆分(支持DWBG8B4D、DWBG6A2C、CJRZQ5E9F和CQYGL3F8E)
|
||||
const processedReportData = computed(() => {
|
||||
let data = reportData.value;
|
||||
|
||||
// 拆分DWBG8B4D数据
|
||||
data = splitDWBG8B4DForTabs(data);
|
||||
|
||||
// 拆分DWBG6A2C数据
|
||||
data = splitDWBG6A2CForTabs(data);
|
||||
|
||||
// 拆分CJRZQ5E9F数据
|
||||
data = splitCJRZQ5E9FForTabs(data);
|
||||
|
||||
// 拆分CQYGL3F8E数据
|
||||
data = splitCQYGL3F8EForTabs(data);
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
watch(reportData, () => {
|
||||
reportScore.value = calculateScore(reportData.value);
|
||||
});
|
||||
const featureMap = {
|
||||
IVYZ5733: {
|
||||
name: "婚姻状态",
|
||||
component: defineAsyncComponent(() => import("@/ui/CIVYZ5733.vue")),
|
||||
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
|
||||
},
|
||||
JRZQ0A03: {
|
||||
name: "借贷申请记录",
|
||||
component: defineAsyncComponent(() =>
|
||||
import("@/ui/CJRZQ0A03.vue")
|
||||
),
|
||||
},
|
||||
JRZQ8203: {
|
||||
name: "借贷行为记录",
|
||||
component: defineAsyncComponent(() =>
|
||||
import("@/ui/CJRZQ8203.vue")
|
||||
),
|
||||
},
|
||||
FLXG3D56: {
|
||||
name: "违约失信",
|
||||
component: defineAsyncComponent(() => import("@/ui/CFLXG3D56.vue")),
|
||||
},
|
||||
|
||||
FLXG0V4B: {
|
||||
name: "司法涉诉",
|
||||
component: defineAsyncComponent(() =>
|
||||
import("@/ui/CFLXG0V4B/index.vue")
|
||||
),
|
||||
},
|
||||
QYGL3F8E: {
|
||||
name: "人企关系加强版",
|
||||
component: defineAsyncComponent(() =>
|
||||
import("@/ui/CQYGL3F8E/index.vue")
|
||||
),
|
||||
remark: '人企关系加强版提供全面的企业关联分析,包括投资企业记录、高管任职记录和涉诉风险等多维度信息。'
|
||||
},
|
||||
// 人企关系加强版拆分模块
|
||||
CQYGL3F8E_Investment: {
|
||||
name: "投资企业记录",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Investment.vue")),
|
||||
},
|
||||
CQYGL3F8E_SeniorExecutive: {
|
||||
name: "高管任职记录",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/SeniorExecutive.vue")),
|
||||
},
|
||||
CQYGL3F8E_Lawsuit: {
|
||||
name: "涉诉风险",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Lawsuit.vue")),
|
||||
},
|
||||
CQYGL3F8E_InvestHistory: {
|
||||
name: "对外投资历史",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/InvestHistory.vue")),
|
||||
},
|
||||
CQYGL3F8E_FinancingHistory: {
|
||||
name: "融资历史",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/FinancingHistory.vue")),
|
||||
},
|
||||
CQYGL3F8E_Punishment: {
|
||||
name: "行政处罚",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Punishment.vue")),
|
||||
},
|
||||
CQYGL3F8E_Abnormal: {
|
||||
name: "经营异常",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/Abnormal.vue")),
|
||||
},
|
||||
CQYGL3F8E_TaxRisk: {
|
||||
name: "税务风险",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQYGL3F8E/components/TaxRisk/index.vue")),
|
||||
},
|
||||
QCXG7A2B: {
|
||||
name: "名下车辆",
|
||||
component: defineAsyncComponent(() => import("@/ui/CQCXG7A2B.vue")),
|
||||
},
|
||||
BehaviorRiskScan: {
|
||||
name: "风险行为扫描",
|
||||
component: defineAsyncComponent(() =>
|
||||
import("@/ui/CBehaviorRiskScan.vue")
|
||||
),
|
||||
},
|
||||
JRZQ4AA8: {
|
||||
name: "还款压力",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ4AA8.vue")),
|
||||
},
|
||||
IVYZ9A2B: {
|
||||
name: "学历信息查询",
|
||||
component: defineAsyncComponent(() => import("@/ui/CIVYZ9A2B.vue")),
|
||||
},
|
||||
DWBG8B4D: {
|
||||
name: "谛听多维报告",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/index.vue")),
|
||||
},
|
||||
// 谛听多维报告拆分模块
|
||||
DWBG8B4D_Overview: {
|
||||
name: "报告概览",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/ReportOverview.vue")),
|
||||
},
|
||||
DWBG8B4D_ElementVerification: {
|
||||
name: "要素核查",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/ElementVerification.vue")),
|
||||
},
|
||||
DWBG8B4D_Identity: {
|
||||
name: "运营商核验",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/Identity.vue")),
|
||||
},
|
||||
DWBG8B4D_RiskWarning: {
|
||||
name: "公安重点人员检验",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/RiskWarning.vue")),
|
||||
},
|
||||
DWBG8B4D_OverdueRisk: {
|
||||
name: "逾期风险产品",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/OverdueRiskSection.vue")),
|
||||
},
|
||||
DWBG8B4D_CourtInfo: {
|
||||
name: "法院曝光台信息",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/MultCourtInfoSection.vue")),
|
||||
},
|
||||
DWBG8B4D_LoanEvaluation: {
|
||||
name: "借贷评估",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/LoanEvaluationSection.vue")),
|
||||
},
|
||||
DWBG8B4D_LeasingRisk: {
|
||||
name: "租赁风险评估",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/LeasingRiskSection.vue")),
|
||||
},
|
||||
DWBG8B4D_RiskSupervision: {
|
||||
name: "关联风险监督",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/RiskSupervisionSection.vue")),
|
||||
},
|
||||
DWBG8B4D_RiskWarningTab: {
|
||||
name: "规则风险提示",
|
||||
component: defineAsyncComponent(() => import("@/ui/CDWBG8B4D/components/RiskWarningTab.vue")),
|
||||
},
|
||||
JRZQ4B6C: {
|
||||
name: "信贷表现",
|
||||
component: defineAsyncComponent(() => import("@/ui/JRZQ4B6C/index.vue")),
|
||||
remark: '信贷表现主要为企业在背景调查过程中探查用户近期信贷表现时提供参考,帮助企业对其内部员工、外部业务进行个人信用过滤。数据来源于多个征信机构,可能存在数据延迟或不完整的情况。'
|
||||
},
|
||||
JRZQ09J8: {
|
||||
name: "收入评估",
|
||||
component: defineAsyncComponent(() => import("@/ui/JRZQ09J8/index.vue")),
|
||||
remark: '基于全国社会保险信息系统的缴费基数数据进行收入水平评估。评级反映相对收入水平,实际收入可能因地区差异而有所不同,建议结合其他收入证明材料进行综合评估。'
|
||||
},
|
||||
// 司南报告
|
||||
DWBG6A2C: {
|
||||
name: "司南报告",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/index.vue")),
|
||||
remark: '司南报告提供全面的个人信用风险评估,包括身份核验、风险名单、借贷行为、履约情况等多维度分析。'
|
||||
},
|
||||
// 司南报告拆分模块
|
||||
// DWBG6A2C_BaseInfo: {
|
||||
// name: "基本信息",
|
||||
// component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/BaseInfoSection.vue")),
|
||||
// },
|
||||
DWBG6A2C_StandLiveInfo: {
|
||||
name: "身份信息核验",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/StandLiveInfoSection.vue")),
|
||||
},
|
||||
DWBG6A2C_RiskPoint: {
|
||||
name: "命中风险标注",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RiskPointSection.vue")),
|
||||
},
|
||||
DWBG6A2C_SecurityInfo: {
|
||||
name: "公安重点人员核验",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/SecurityInfoSection.vue")),
|
||||
},
|
||||
DWBG6A2C_AntiFraudInfo: {
|
||||
name: "涉赌涉诈人员核验",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/AntiFraudInfoSection.vue")),
|
||||
},
|
||||
DWBG6A2C_RiskList: {
|
||||
name: "风险名单",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RiskListSection.vue")),
|
||||
},
|
||||
DWBG6A2C_ApplicationStatistics: {
|
||||
name: "历史借贷行为",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/ApplicationStatisticsSection.vue")),
|
||||
},
|
||||
DWBG6A2C_LendingStatistics: {
|
||||
name: "近24个月放款情况",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/LendingStatisticsSection.vue")),
|
||||
},
|
||||
DWBG6A2C_PerformanceStatistics: {
|
||||
name: "履约情况",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/PerformanceStatisticsSection.vue")),
|
||||
},
|
||||
DWBG6A2C_OverdueRecord: {
|
||||
name: "历史逾期记录",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/OverdueRecordSection.vue")),
|
||||
},
|
||||
DWBG6A2C_CreditDetail: {
|
||||
name: "授信详情",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/CreditDetailSection.vue")),
|
||||
},
|
||||
DWBG6A2C_RentalBehavior: {
|
||||
name: "租赁行为",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RentalBehaviorSection.vue")),
|
||||
},
|
||||
DWBG6A2C_RiskSupervision: {
|
||||
name: "关联风险监督",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/RiskSupervisionSection.vue")),
|
||||
},
|
||||
DWBG6A2C_CourtRiskInfo: {
|
||||
name: "法院风险信息",
|
||||
component: defineAsyncComponent(() => import("@/ui/DWBG6A2C/components/CourtRiskInfoSection.vue")),
|
||||
},
|
||||
// 贷款风险报告
|
||||
JRZQ5E9F: {
|
||||
name: "贷款风险评估",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/index.vue")),
|
||||
remark: '贷款风险评估提供全面的个人贷款风险分析,包括风险概览、信用评分、贷款行为分析、机构分析等多维度评估。'
|
||||
},
|
||||
// 贷款风险报告拆分模块
|
||||
CJRZQ5E9F_RiskOverview: {
|
||||
name: "风险概览",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/RiskOverview.vue")),
|
||||
},
|
||||
CJRZQ5E9F_CreditScores: {
|
||||
name: "信用评分",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/CreditScores.vue")),
|
||||
},
|
||||
CJRZQ5E9F_LoanBehaviorAnalysis: {
|
||||
name: "贷款行为分析",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/LoanBehaviorAnalysis.vue")),
|
||||
},
|
||||
CJRZQ5E9F_InstitutionAnalysis: {
|
||||
name: "机构分析",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/InstitutionAnalysis.vue")),
|
||||
},
|
||||
CJRZQ5E9F_TimeTrendAnalysis: {
|
||||
name: "时间趋势分析",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/TimeTrendAnalysis.vue")),
|
||||
},
|
||||
CJRZQ5E9F_RiskIndicators: {
|
||||
name: "风险指标详情",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/RiskIndicators.vue")),
|
||||
},
|
||||
CJRZQ5E9F_RiskAdvice: {
|
||||
name: "专业建议",
|
||||
component: defineAsyncComponent(() => import("@/ui/CJRZQ5E9F/components/RiskAdvice.vue")),
|
||||
}
|
||||
};
|
||||
|
||||
const maskValue = computed(() => {
|
||||
return (type, value) => {
|
||||
if (!value) return value;
|
||||
if (type === "name") {
|
||||
// 姓名脱敏(保留首位)
|
||||
if (value.length === 1) {
|
||||
return "*"; // 只保留一个字,返回 "*"
|
||||
} else if (value.length === 2) {
|
||||
return value[0] + "*"; // 两个字,保留姓氏,第二个字用 "*" 替代
|
||||
} else {
|
||||
return (
|
||||
value[0] +
|
||||
"*".repeat(value.length - 2) +
|
||||
value[value.length - 1]
|
||||
); // 两个字以上,保留第一个和最后一个字,其余的用 "*" 替代
|
||||
}
|
||||
} else if (type === "id_card") {
|
||||
// 身份证号脱敏(保留前6位和最后4位)
|
||||
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
|
||||
} else if (type === "mobile") {
|
||||
if (value.length === 11) {
|
||||
return value.substring(0, 3) + "****" + value.substring(7);
|
||||
}
|
||||
return value; // 如果手机号不合法或长度不为 11 位,直接返回原手机号
|
||||
} else if (type === "bank_card") {
|
||||
// 银行卡号脱敏(保留前6位和后4位)
|
||||
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
|
||||
} else if (type === "ent_name") {
|
||||
// 企业名称脱敏(保留前3个字符和后3个字符,中间部分用 "*" 替代)
|
||||
if (value.length <= 6) {
|
||||
return value[0] + "*".repeat(value.length - 1); // 少于6个字符时,只保留第一个字符,其他用 * 替代
|
||||
} else {
|
||||
return (
|
||||
value.slice(0, 3) +
|
||||
"*".repeat(value.length - 6) +
|
||||
value.slice(-3)
|
||||
); // 多于6个字符时保留前3和后3
|
||||
}
|
||||
} else if (type === "ent_code") {
|
||||
// 企业代码脱敏(保留前4个字符和后4个字符,中间部分用 "*" 替代)
|
||||
if (value.length <= 8) {
|
||||
return value.slice(0, 4) + "*".repeat(value.length - 4); // 长度不超过8时,保留前4个字符,其他用 * 替代
|
||||
} else {
|
||||
return (
|
||||
value.slice(0, 4) +
|
||||
"*".repeat(value.length - 8) +
|
||||
value.slice(-4)
|
||||
); // 长度超过8时,保留前4个字符和后4个字符
|
||||
}
|
||||
} else if (type === "car_license") {
|
||||
// 车牌号脱敏(保留前2个字符,后2个字符,其他部分用 "*" 替代)
|
||||
if (value.length <= 4) {
|
||||
return value[0] + "*".repeat(value.length - 1); // 如果车牌号长度小于等于4,只保留首字符
|
||||
} else {
|
||||
// 如果车牌号较长,保留前2个字符,后2个字符,其余部分用 "*" 替代
|
||||
return (
|
||||
value.slice(0, 2) +
|
||||
"*".repeat(value.length - 4) +
|
||||
value.slice(-2)
|
||||
);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
});
|
||||
|
||||
// 计算综合评分的函数
|
||||
const calculateScore = (reportData) => {
|
||||
// 从0分开始(0分表示无风险)
|
||||
let score = 0;
|
||||
// 最高分为90分(90分表示最高风险)
|
||||
const maxScore = 90;
|
||||
|
||||
// 定义各接口的相对风险权重比例
|
||||
const relativeWeights = {
|
||||
// 关键风险指标(高优先级)
|
||||
FLXG0V3B: 250, // 不良记录
|
||||
FLXG3D56: 100, // 违约异常
|
||||
FLXG0V4B: 400, // 司法涉诉
|
||||
G35SC01: 20, // 司法涉诉(次要)
|
||||
Q23SC01: 50, // 企业涉诉
|
||||
FIN019: 100, // 银行卡黑名单
|
||||
|
||||
// 高风险指标(中优先级)
|
||||
JRZQ0A03: 40, // 借贷申请记录
|
||||
JRZQ8203: 40, // 借贷行为记录
|
||||
FLXG54F5: 70, // 手机号码风险
|
||||
|
||||
// 中风险指标(低优先级)
|
||||
YYSYF7DB: 50, // 手机二次卡
|
||||
YYSY4B37: 50, // 手机在网时长
|
||||
QYGLB4C0: 50, // 人企关系
|
||||
JRZQ4B6C: 60, // 信贷表现
|
||||
JRZQ09J8: 40, // 收入评估
|
||||
|
||||
// 验证指标(最低优先级)
|
||||
YYSY6F2E: 25, // 手机三要素
|
||||
IVYZ0B03: 25, // 手机号二要素
|
||||
KZEYS: 25, // 身份证二要素
|
||||
JRZQDCBE: 25, // 银行卡四要素核验
|
||||
};
|
||||
|
||||
// 找出当前报告中包含的接口
|
||||
const availableAPIs = reportData
|
||||
.map((item) => item.data.apiID)
|
||||
.filter((id) => relativeWeights[id]);
|
||||
|
||||
// 如果没有可评分的接口,返回默认分数
|
||||
if (availableAPIs.length === 0) return 30; // 默认30分(中等风险)
|
||||
|
||||
// 计算当前报告中所有接口的相对权重总和
|
||||
let totalWeight = 0;
|
||||
availableAPIs.forEach((apiID) => {
|
||||
totalWeight += relativeWeights[apiID];
|
||||
});
|
||||
|
||||
// 计算每个权重点对应的分数
|
||||
const pointValue = maxScore / totalWeight;
|
||||
|
||||
// 基于当前报告中的接口计算实际权重
|
||||
const actualWeights = {};
|
||||
availableAPIs.forEach((apiID) => {
|
||||
// 将相对权重转换为实际分数权重
|
||||
actualWeights[apiID] = relativeWeights[apiID] * pointValue;
|
||||
});
|
||||
|
||||
// 遍历报告数据进行评分 - 风险越高分数越高
|
||||
reportData.forEach((item) => {
|
||||
const apiID = item.data.apiID;
|
||||
const data = item.data.data;
|
||||
|
||||
// 如果没有定义权重,跳过
|
||||
if (!actualWeights[apiID]) return;
|
||||
|
||||
// 根据不同的API ID计算分数(有风险时加分)
|
||||
switch (apiID) {
|
||||
case "G09SC02": // 婚姻状态
|
||||
// 不计入风险
|
||||
break;
|
||||
|
||||
case "JRZQ0A03": // 借贷申请记录
|
||||
if (data) {
|
||||
// 检查是否有申请记录(有则表示风险)
|
||||
let hasRisk = false;
|
||||
for (const key in data) {
|
||||
if (
|
||||
data[key] !== 0 &&
|
||||
data[key] !== "0" &&
|
||||
key.indexOf("allnum") > -1 &&
|
||||
!isNaN(parseInt(data[key])) &&
|
||||
parseInt(data[key]) > 0
|
||||
) {
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "JRZQ8203": // 借贷行为记录
|
||||
if (data) {
|
||||
// 检查是否有借贷记录(有则表示风险)
|
||||
let hasRisk = false;
|
||||
for (const key in data) {
|
||||
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 (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "FLXG3D56": // 违约异常
|
||||
if (data) {
|
||||
// 检查除特定字段外的其他字段是否有异常值(有异常则表示风险)
|
||||
const excludeFields = [
|
||||
"swift_number",
|
||||
"code",
|
||||
"flag_specialList_c",
|
||||
];
|
||||
let hasRisk = false;
|
||||
|
||||
for (const key in data) {
|
||||
if (
|
||||
!excludeFields.includes(key) &&
|
||||
data[key] !== 0 &&
|
||||
data[key] !== "0"
|
||||
) {
|
||||
hasRisk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "FLXG0V3B": // 不良记录
|
||||
if (data && data.risk_level) {
|
||||
// 根据风险等级加分
|
||||
switch (data.risk_level) {
|
||||
case "A": // 无风险
|
||||
// 不加分
|
||||
break;
|
||||
case "F": // 低风险
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case "C": // 中风险
|
||||
case "D": // 中风险
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case "B": // 高风险
|
||||
case "E": // 高风险
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "G35SC01": // 司法涉诉
|
||||
case "FLXG0V4B": // 司法涉诉
|
||||
case "Q23SC01": // 企业涉诉
|
||||
if (data) {
|
||||
let hasRisk = false;
|
||||
|
||||
// 检查各种涉诉信息 - 处理嵌套数据结构
|
||||
// entout是一个单元素数组,数组中第一个元素是JSON对象,对象中有entout属性
|
||||
if (
|
||||
data.entout &&
|
||||
Array.isArray(data.entout) &&
|
||||
data.entout.length > 0 &&
|
||||
data.entout[0] &&
|
||||
data.entout[0].entout &&
|
||||
((Array.isArray(data.entout[0].entout) &&
|
||||
data.entout[0].entout.length > 0) ||
|
||||
(typeof data.entout[0].entout === "object" &&
|
||||
Object.keys(data.entout[0].entout).length > 0))
|
||||
) {
|
||||
hasRisk = true;
|
||||
}
|
||||
|
||||
// 处理sxbzxr(失信被执行人)嵌套结构
|
||||
if (
|
||||
data.sxbzxr &&
|
||||
Array.isArray(data.sxbzxr) &&
|
||||
data.sxbzxr.length > 0 &&
|
||||
data.sxbzxr[0] &&
|
||||
data.sxbzxr[0].sxbzxr &&
|
||||
((Array.isArray(data.sxbzxr[0].sxbzxr) &&
|
||||
data.sxbzxr[0].sxbzxr.length > 0) ||
|
||||
(typeof data.sxbzxr[0].sxbzxr === "object" &&
|
||||
Object.keys(data.sxbzxr[0].sxbzxr).length > 0))
|
||||
) {
|
||||
hasRisk = true;
|
||||
}
|
||||
|
||||
// 处理xgbzxr(限制高消费被执行人)嵌套结构
|
||||
if (
|
||||
data.xgbzxr &&
|
||||
Array.isArray(data.xgbzxr) &&
|
||||
data.xgbzxr.length > 0 &&
|
||||
data.xgbzxr[0] &&
|
||||
data.xgbzxr[0].xgbzxr &&
|
||||
((Array.isArray(data.xgbzxr[0].xgbzxr) &&
|
||||
data.xgbzxr[0].xgbzxr.length > 0) ||
|
||||
(typeof data.xgbzxr[0].xgbzxr === "object" &&
|
||||
Object.keys(data.xgbzxr[0].xgbzxr).length > 0))
|
||||
) {
|
||||
hasRisk = true;
|
||||
}
|
||||
|
||||
if (hasRisk) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "FLXG54F5": // 手机号码风险
|
||||
if (data && data.filterType) {
|
||||
// 根据filterType判断风险等级
|
||||
switch (data.filterType) {
|
||||
case "0": // 安全
|
||||
// 不加分
|
||||
break;
|
||||
case "3": // 低危
|
||||
score += actualWeights[apiID] * 0.3;
|
||||
break;
|
||||
case "2": // 中危
|
||||
score += actualWeights[apiID] * 0.7;
|
||||
break;
|
||||
case "1": // 高危
|
||||
score += actualWeights[apiID];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "YYSYF7DB": // 手机二次卡
|
||||
if (data && data.is_second_card === true) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case "YYSY4B37": // 手机在网时长
|
||||
if (data && data.online_months < 6) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case "YYSY6F2E": // 手机三要素
|
||||
case "IVYZ0B03": // 手机号二要素
|
||||
case "KZEYS": // 身份证二要素
|
||||
case "JRZQDCBE": // 银行卡四要素核验
|
||||
if (data && data.is_consistent === false) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case "FIN019": // 银行卡黑名单
|
||||
if (data && data.is_blacklisted === true) {
|
||||
score += actualWeights[apiID];
|
||||
}
|
||||
break;
|
||||
|
||||
case "JRZQ4B6C": // 信贷表现
|
||||
if (data) {
|
||||
let riskScore = 0;
|
||||
|
||||
// 根据结果编码评分
|
||||
switch (data.result_code) {
|
||||
case "1": // A(Overdue) - 逾期,高风险
|
||||
riskScore += 0.8;
|
||||
break;
|
||||
case "3": // B(Delay) - 延迟,中风险
|
||||
riskScore += 0.5;
|
||||
break;
|
||||
case "2": // B(Normal) - 正常,低风险
|
||||
riskScore += 0.1;
|
||||
break;
|
||||
case "4": // U - 未知,中等风险
|
||||
riskScore += 0.3;
|
||||
break;
|
||||
}
|
||||
|
||||
// 当前逾期机构数
|
||||
const currentlyOverdue = parseInt(data.currently_overdue) || 0;
|
||||
if (currentlyOverdue > 0) {
|
||||
riskScore += Math.min(currentlyOverdue * 0.1, 0.3);
|
||||
}
|
||||
|
||||
// 异常还款机构数
|
||||
const accExc = parseInt(data.acc_exc) || 0;
|
||||
if (accExc > 0) {
|
||||
riskScore += Math.min(accExc * 0.05, 0.2);
|
||||
}
|
||||
|
||||
// 应用风险评分
|
||||
score += actualWeights[apiID] * Math.min(riskScore, 1.0);
|
||||
}
|
||||
break;
|
||||
|
||||
case "JRZQ09J8": // 收入评估
|
||||
if (data && data.level) {
|
||||
let riskScore = 0;
|
||||
|
||||
// 根据收入等级评分(收入越低风险越高)
|
||||
switch (data.level) {
|
||||
case "-": // 无记录,高风险
|
||||
riskScore = 0.9;
|
||||
break;
|
||||
case "A": // A级,中高风险
|
||||
riskScore = 0.7;
|
||||
break;
|
||||
case "B": // B级,中等风险
|
||||
riskScore = 0.5;
|
||||
break;
|
||||
case "C": // C级,中低风险
|
||||
riskScore = 0.3;
|
||||
break;
|
||||
case "D": // D级,低风险
|
||||
riskScore = 0.2;
|
||||
break;
|
||||
case "E": // E级,很低风险
|
||||
riskScore = 0.1;
|
||||
break;
|
||||
case "F": // F级,极低风险
|
||||
case "G": // G级,极低风险
|
||||
case "H": // H级,无风险
|
||||
case "I": // I级,无风险
|
||||
case "J": // J级,零风险
|
||||
riskScore = 0.05;
|
||||
break;
|
||||
}
|
||||
|
||||
// 应用风险评分
|
||||
score += actualWeights[apiID] * riskScore;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// 未知接口类型不影响评分
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 确保分数在0-90范围内并四舍五入
|
||||
return Math.max(0, Math.min(maxScore, Math.round(score)));
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
|
||||
|
||||
<template v-if="isDone">
|
||||
<van-tabs v-model:active="active" scrollspy sticky :offset-top="46">
|
||||
<div class="flex flex-col gap-y-4 p-4">
|
||||
<LEmpty v-if="isEmpty" />
|
||||
<van-tab title="分析指数">
|
||||
<div id="analysis" class="title mb-4">分析指数</div>
|
||||
<div class="card mb-4">
|
||||
<div class="my-4">
|
||||
<GaugeChart :score="reportScore" />
|
||||
</div>
|
||||
</div>
|
||||
</van-tab>
|
||||
<van-tab title="基本信息">
|
||||
<div id="basic" class="title mb-4">基本信息</div>
|
||||
<div class="card">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<LTitle title="报告信息" type="blue-green"></LTitle>
|
||||
<div class="flex flex-col gap-2 my-2">
|
||||
<div class="flex justify-between border-b pb-2 pl-2">
|
||||
<span class="text-gray-700 font-bold">报告时间:</span>
|
||||
<span class="text-gray-600">{{
|
||||
reportDateTime ||
|
||||
"2025-01-01 12:00:00"
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="!isEmpty">
|
||||
<span class="text-gray-700 font-bold">报告项目:</span>
|
||||
<span class="text-gray-600">
|
||||
{{ reportName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="Object.keys(reportParams).length != 0">
|
||||
<LTitle title="报告对象" type="blue-green"></LTitle>
|
||||
<div class="flex flex-col gap-2 my-2">
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.name">
|
||||
<span class="text-gray-700 font-bold">姓名</span>
|
||||
<span class="text-gray-600">{{
|
||||
maskValue(
|
||||
"name",
|
||||
reportParams?.name
|
||||
)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2"
|
||||
v-if="reportParams?.id_card">
|
||||
<span class="text-gray-700 font-bold">身份证号</span>
|
||||
<span class="text-gray-600">
|
||||
{{
|
||||
maskValue(
|
||||
"id_card",
|
||||
reportParams?.id_card
|
||||
)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2"
|
||||
v-if="reportParams?.mobile">
|
||||
<span class="text-gray-700 font-bold">手机号</span>
|
||||
<span class="text-gray-600">{{
|
||||
maskValue(
|
||||
"mobile",
|
||||
reportParams?.mobile
|
||||
)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<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>
|
||||
<div>
|
||||
<div class="font-bold text-lg">
|
||||
身份证检查结果
|
||||
</div>
|
||||
<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="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
|
||||
✔
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-lg">
|
||||
手机号检测结果
|
||||
</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
被查询人姓名与运营商提供的一致
|
||||
</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
被查询人身份证与运营商提供的一致
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<ShareReportButton v-if="!isShare" :order-id="orderId" :order-no="orderNo"
|
||||
:is-example="!orderId" />
|
||||
</div>
|
||||
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
|
||||
</van-tab>
|
||||
<van-tab v-for="(item, index) in processedReportData" :key="index"
|
||||
:title="featureMap[item.data.apiID]?.name">
|
||||
<div :id="item.data.apiID" 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" />
|
||||
</van-tab>
|
||||
<ShareReportButton v-if="!isShare" class="mb-4" :order-id="orderId" :order-no="orderNo"
|
||||
:is-example="!orderId" />
|
||||
|
||||
<div class="card">
|
||||
<div>
|
||||
<div class="text-bold text-blue-500 mb-2">
|
||||
报告说明
|
||||
</div>
|
||||
<div>
|
||||
|
||||
本报告的数据由用户本人明确授权后,我们才向相关合法存有用户个人数据的机构调取本报告相关内容,本平台只做大数据的获取与分析,仅向用户个人展示参考。
|
||||
</div>
|
||||
<p>
|
||||
报告有效期<strong class="text-red-500">30天</strong>,过期自动删除。
|
||||
</p>
|
||||
<p>
|
||||
|
||||
若您的数据不全面,可能是数据具有延迟性或者合作信息机构未获取到您的数据。若数据有错误请联系客服
|
||||
</p>
|
||||
<p>
|
||||
|
||||
本产品所有数据均来自第三方。可能部分数据未公开、数据更新延迟或信息受到限制,贵司不对数据的准确性、真实性、完整性做任何承诺。用户需根据实际情况,结合报告内容自行判断与决策。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-tabs>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div class="disclaimer">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="flex items-center">
|
||||
<img class="w-4 h-4 mr-2" src="@/assets/images/public_security_record_icon.png" alt="公安备案" />
|
||||
<text>琼公网安备46010002000584号</text>
|
||||
</div>
|
||||
<div>
|
||||
<a class="text-blue-500" href="https://beian.miit.gov.cn">
|
||||
琼ICP备2024048057号-2
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>海南天远大数据科技有限公司版权所有</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
@apply mx-auto mt-2 w-64 border rounded-3xl py-2 text-center text-white font-bold;
|
||||
background: linear-gradient(135deg, var(--van-theme-primary), var(--van-theme-primary-dark));
|
||||
}
|
||||
|
||||
.a {
|
||||
color: #e03131;
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
/* margin-top: 24px; */
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
padding-bottom: 60px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
:deep(.card) {
|
||||
@apply p-3;
|
||||
}
|
||||
</style>
|
||||
256
src/components/BindPhoneDialog.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<script setup>
|
||||
import { ref, computed, nextTick } from "vue";
|
||||
import { useDialogStore } from "@/stores/dialogStore";
|
||||
|
||||
const emit = defineEmits(['bind-success'])
|
||||
const router = useRouter();
|
||||
const dialogStore = useDialogStore();
|
||||
const agentStore = useAgentStore();
|
||||
const userStore = useUserStore();
|
||||
const phoneNumber = ref("");
|
||||
const verificationCode = ref("");
|
||||
const isCountingDown = ref(false);
|
||||
const countdown = ref(60);
|
||||
const isAgreed = ref(false);
|
||||
let timer = null;
|
||||
|
||||
// 聚焦状态变量
|
||||
const phoneFocused = ref(false);
|
||||
const codeFocused = ref(false);
|
||||
|
||||
const isPhoneNumberValid = computed(() => {
|
||||
return /^1[3-9]\d{9}$/.test(phoneNumber.value);
|
||||
});
|
||||
|
||||
const canBind = computed(() => {
|
||||
return (
|
||||
isPhoneNumberValid.value &&
|
||||
verificationCode.value.length === 6 &&
|
||||
isAgreed.value
|
||||
);
|
||||
});
|
||||
|
||||
async function sendVerificationCode() {
|
||||
if (isCountingDown.value || !isPhoneNumberValid.value) return;
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "请输入有效的手机号" });
|
||||
return;
|
||||
}
|
||||
const { data, error } = await useApiFetch("auth/sendSms")
|
||||
.post({ mobile: phoneNumber.value, actionType: "bindMobile" })
|
||||
.json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
showToast({ message: "获取成功" });
|
||||
startCountdown();
|
||||
// 聚焦到验证码输入框
|
||||
nextTick(() => {
|
||||
const verificationCodeInput = document.getElementById('verificationCode');
|
||||
if (verificationCodeInput) {
|
||||
verificationCodeInput.focus();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
showToast(data.value.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startCountdown() {
|
||||
isCountingDown.value = true;
|
||||
countdown.value = 60;
|
||||
timer = setInterval(() => {
|
||||
if (countdown.value > 0) {
|
||||
countdown.value--;
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
isCountingDown.value = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
async function handleBind() {
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "请输入有效的手机号" });
|
||||
return;
|
||||
}
|
||||
if (verificationCode.value.length !== 6) {
|
||||
showToast({ message: "请输入有效的验证码" });
|
||||
return;
|
||||
}
|
||||
if (!isAgreed.value) {
|
||||
showToast({ message: "请先同意用户协议" });
|
||||
return;
|
||||
}
|
||||
|
||||
const { data, error } = await useApiFetch("/user/bindMobile")
|
||||
.post({ mobile: phoneNumber.value, code: verificationCode.value })
|
||||
.json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
showToast({ message: "绑定成功" });
|
||||
localStorage.setItem('token', data.value.data.accessToken)
|
||||
localStorage.setItem('refreshAfter', data.value.data.refreshAfter)
|
||||
localStorage.setItem('accessExpire', data.value.data.accessExpire)
|
||||
closeDialog();
|
||||
agentStore.fetchAgentStatus();
|
||||
userStore.fetchUserInfo();
|
||||
// 发出绑定成功的事件
|
||||
emit('bind-success')
|
||||
} else {
|
||||
showToast(data.value.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeDialog() {
|
||||
dialogStore.closeBindPhone();
|
||||
// 重置表单
|
||||
phoneNumber.value = "";
|
||||
verificationCode.value = "";
|
||||
isAgreed.value = false;
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
}
|
||||
|
||||
function toUserAgreement() {
|
||||
closeDialog();
|
||||
router.push(`/userAgreement`);
|
||||
}
|
||||
|
||||
function toPrivacyPolicy() {
|
||||
closeDialog();
|
||||
router.push(`/privacyPolicy`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="dialogStore.showBindPhone">
|
||||
<van-popup v-model:show="dialogStore.showBindPhone" round position="bottom" :style="{ height: '80%' }"
|
||||
@close="closeDialog">
|
||||
<div class="bind-phone-dialog">
|
||||
<div class="title-bar">
|
||||
<div class="font-bold">绑定手机号码</div>
|
||||
<div class="text-sm text-gray-500 mt-1">
|
||||
为使用完整功能请绑定手机号码
|
||||
</div>
|
||||
<div class="text-sm text-gray-500 mt-1">
|
||||
如该微信号之前已绑定过手机号,请输入已绑定的手机号
|
||||
</div>
|
||||
<van-icon name="cross" class="close-icon" @click="closeDialog" />
|
||||
</div>
|
||||
<div class="px-8">
|
||||
<div class="mb-8 pt-8 text-left">
|
||||
<div class="flex flex-col items-center">
|
||||
<img class="h-16 w-16 rounded-full shadow" src="/logo.jpg" alt="Logo" />
|
||||
<div class="text-3xl mt-4 text-slate-700 font-bold">
|
||||
天远数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-5">
|
||||
<!-- 手机号输入 -->
|
||||
<div :class="[
|
||||
'input-container bg-blue-300/20',
|
||||
phoneFocused ? 'focused' : '',
|
||||
]">
|
||||
<input v-model="phoneNumber" class="input-field" type="tel" placeholder="请输入手机号"
|
||||
maxlength="11" @focus="phoneFocused = true" @blur="phoneFocused = false" />
|
||||
</div>
|
||||
|
||||
<!-- 验证码输入 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div :class="[
|
||||
'input-container bg-blue-300/20',
|
||||
codeFocused ? 'focused' : '',
|
||||
]">
|
||||
<input v-model="verificationCode" id="verificationCode" class="input-field"
|
||||
placeholder="请输入验证码" maxlength="6" @focus="codeFocused = true"
|
||||
@blur="codeFocused = false" />
|
||||
</div>
|
||||
<button
|
||||
class="ml-2 px-4 py-2 text-sm font-bold flex-shrink-0 rounded-lg transition duration-300"
|
||||
:class="isCountingDown || !isPhoneNumberValid
|
||||
? 'cursor-not-allowed bg-gray-300 text-gray-500'
|
||||
: 'bg-blue-500 text-white hover:bg-blue-600'
|
||||
" @click="sendVerificationCode">
|
||||
{{
|
||||
isCountingDown
|
||||
? `${countdown}s重新获取`
|
||||
: "获取验证码"
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 协议同意框 -->
|
||||
<div class="flex items-start space-x-2">
|
||||
<input type="checkbox" v-model="isAgreed" class="mt-1" />
|
||||
<span class="text-xs text-gray-400 leading-tight">
|
||||
绑定手机号即代表您已阅读并同意
|
||||
<a class="cursor-pointer text-blue-400" @click="toUserAgreement">
|
||||
《用户协议》
|
||||
</a>
|
||||
和
|
||||
<a class="cursor-pointer text-blue-400" @click="toPrivacyPolicy">
|
||||
《隐私政策》
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="mt-10 w-full py-3 text-lg font-bold text-white bg-blue-500 rounded-full transition duration-300"
|
||||
:class="{ 'opacity-50 cursor-not-allowed': !canBind }" @click="handleBind">
|
||||
确认绑定
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.bind-phone-dialog {
|
||||
background: url("@/assets/images/login_bg.png") no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
font-size: 20px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
border: 2px solid rgba(125, 211, 252, 0);
|
||||
border-radius: 1rem;
|
||||
transition: duration-200;
|
||||
}
|
||||
|
||||
.input-container.focused {
|
||||
border: 2px solid #3b82f6;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
333
src/components/CarNumberInput.vue
Normal file
391
src/components/ClickCaptcha.vue
Normal file
@@ -0,0 +1,391 @@
|
||||
<template>
|
||||
<div v-if="visible" class="captcha-overlay">
|
||||
<div class="captcha-modal">
|
||||
<div class="captcha-header">
|
||||
<h3 class="captcha-title">安全验证</h3>
|
||||
<button class="close-btn" @click="handleClose">×</button>
|
||||
</div>
|
||||
<div class="captcha-content">
|
||||
<canvas ref="canvasRef" :width="canvasWidth" :height="canvasHeight" class="captcha-canvas"
|
||||
@click="handleCanvasClick"></canvas>
|
||||
<div class="captcha-instruction">
|
||||
<p>
|
||||
请依次点击 <span class="target-list">【{{ targetChars.join(',') }}】</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="captcha-status">
|
||||
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
|
||||
<p v-else-if="successMessage" class="success-message">{{ successMessage }}</p>
|
||||
<p v-else class="status-text">点击图片中的目标文字</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="captcha-footer">
|
||||
<button class="refresh-btn" @click="refreshCaptcha" :disabled="isRefreshing">
|
||||
{{ isRefreshing ? '刷新中...' : '刷新验证' }}
|
||||
</button>
|
||||
<button class="confirm-btn" :disabled="clickedList.length < 3 || !!successMessage" @click="handleConfirm">
|
||||
确认
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch, nextTick } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['success', 'close'])
|
||||
|
||||
const canvasRef = ref(null)
|
||||
const canvasWidth = 300
|
||||
const canvasHeight = 180
|
||||
const bgImgUrl = '/image/clickCaptcha.jpg' // 可替换为任意背景图
|
||||
|
||||
const allChars = ['大', '数', '据', '司', '法', '风', '险', '报', '告']
|
||||
const targetChars = ref(['大', '数', '据']) // 目标点击顺序固定
|
||||
const charPositions = ref([]) // [{char, x, y, w, h}]
|
||||
const clickedIndex = ref(0)
|
||||
const errorMessage = ref('')
|
||||
const successMessage = ref('')
|
||||
const isRefreshing = ref(false)
|
||||
const clickedList = ref([]) // [{char, idx, ...}]
|
||||
let currentChars = [] // 当前乱序后的字顺序
|
||||
|
||||
function randomChars(count, except = []) {
|
||||
const pool = allChars.filter(c => !except.includes(c))
|
||||
const arr = []
|
||||
while (arr.length < count) {
|
||||
const c = pool[Math.floor(Math.random() * pool.length)]
|
||||
if (!arr.includes(c)) arr.push(c)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
function randomColor() {
|
||||
return (
|
||||
'#' +
|
||||
Math.floor(Math.random() * 0xffffff)
|
||||
.toString(16)
|
||||
.padStart(6, '0')
|
||||
)
|
||||
}
|
||||
|
||||
function drawCaptcha() {
|
||||
const canvas = canvasRef.value
|
||||
if (!canvas) return
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.clearRect(0, 0, canvasWidth, canvasHeight)
|
||||
|
||||
// 绘制背景图
|
||||
const bg = new window.Image()
|
||||
bg.src = bgImgUrl
|
||||
bg.onload = () => {
|
||||
ctx.drawImage(bg, 0, 0, canvasWidth, canvasHeight)
|
||||
// 绘制乱序文字
|
||||
charPositions.value.forEach(pos => {
|
||||
ctx.save()
|
||||
ctx.translate(pos.x + pos.w / 2, pos.y + pos.h / 2)
|
||||
ctx.rotate(pos.angle)
|
||||
ctx.font = 'bold 28px sans-serif'
|
||||
ctx.fillStyle = pos.color
|
||||
ctx.shadowColor = '#333'
|
||||
ctx.shadowBlur = 4
|
||||
ctx.fillText(pos.char, -pos.w / 2, pos.h / 2 - 8)
|
||||
ctx.restore()
|
||||
})
|
||||
// 绘制点击顺序标签
|
||||
clickedList.value.forEach((item, i) => {
|
||||
const pos = charPositions.value[item.idx]
|
||||
if (!pos) return
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
ctx.arc(pos.x + pos.w / 2, pos.y + 6, 12, 0, 2 * Math.PI)
|
||||
ctx.fillStyle = '#2563eb'
|
||||
ctx.fill()
|
||||
ctx.font = 'bold 16px sans-serif'
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.textAlign = 'center'
|
||||
ctx.textBaseline = 'middle'
|
||||
ctx.fillText((i + 1).toString(), pos.x + pos.w / 2, pos.y + 6)
|
||||
ctx.restore()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function refreshCaptcha() {
|
||||
isRefreshing.value = true
|
||||
setTimeout(() => {
|
||||
generateCaptcha()
|
||||
isRefreshing.value = false
|
||||
}, 500)
|
||||
}
|
||||
|
||||
function generateCaptcha() {
|
||||
// 乱序排列7个字
|
||||
const chars = [...allChars]
|
||||
for (let i = chars.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1))
|
||||
;[chars[i], chars[j]] = [chars[j], chars[i]]
|
||||
}
|
||||
currentChars = chars
|
||||
targetChars.value = ['大', '数', '据']
|
||||
clickedIndex.value = 0
|
||||
errorMessage.value = ''
|
||||
successMessage.value = ''
|
||||
clickedList.value = []
|
||||
// 生成每个字的坐标、角度、颜色
|
||||
charPositions.value = []
|
||||
const used = []
|
||||
chars.forEach((char, idx) => {
|
||||
let x,
|
||||
y,
|
||||
w = 36,
|
||||
h = 36,
|
||||
tryCount = 0
|
||||
do {
|
||||
x = Math.random() * (canvasWidth - w - 10) + 5
|
||||
y = Math.random() * (canvasHeight - h - 10) + 5
|
||||
tryCount++
|
||||
} while (used.some(pos => Math.abs(pos.x - x) < w && Math.abs(pos.y - y) < h) && tryCount < 20)
|
||||
used.push({ x, y })
|
||||
const angle = (Math.random() - 0.5) * 0.7
|
||||
const color = randomColor()
|
||||
charPositions.value.push({ char, x, y, w, h, idx, angle, color })
|
||||
})
|
||||
nextTick(drawCaptcha)
|
||||
}
|
||||
|
||||
function handleCanvasClick(e) {
|
||||
if (successMessage.value) return
|
||||
// 适配缩放
|
||||
const rect = canvasRef.value.getBoundingClientRect()
|
||||
const scaleX = canvasWidth / rect.width
|
||||
const scaleY = canvasHeight / rect.height
|
||||
const x = (e.clientX - rect.left) * scaleX
|
||||
const y = (e.clientY - rect.top) * scaleY
|
||||
// 找到被点中的字
|
||||
const posIdx = charPositions.value.findIndex(
|
||||
pos => x >= pos.x && x <= pos.x + pos.w && y >= pos.y && y <= pos.y + pos.h
|
||||
)
|
||||
if (posIdx === -1) {
|
||||
errorMessage.value = '请点击目标文字'
|
||||
setTimeout(() => (errorMessage.value = ''), 1200)
|
||||
return
|
||||
}
|
||||
// 已经点过不能重复点
|
||||
if (clickedList.value.some(item => item.idx === posIdx)) return
|
||||
if (clickedList.value.length >= charPositions.value.length) return
|
||||
clickedList.value.push({ char: charPositions.value[posIdx].char, idx: posIdx })
|
||||
console.log(
|
||||
'clickedList:',
|
||||
clickedList.value.map(i => i.char)
|
||||
) // 调试
|
||||
drawCaptcha()
|
||||
}
|
||||
|
||||
function handleConfirm() {
|
||||
if (clickedList.value.length < 3) {
|
||||
errorMessage.value = '请依次点击3个字'
|
||||
setTimeout(() => (errorMessage.value = ''), 1200)
|
||||
return
|
||||
}
|
||||
const userSeq = clickedList.value
|
||||
.slice(0, 3)
|
||||
.map(item => item.char)
|
||||
.join('')
|
||||
if (userSeq === '大数据') {
|
||||
successMessage.value = '验证成功!'
|
||||
setTimeout(() => emit('success'), 600)
|
||||
} else {
|
||||
errorMessage.value = '校验错误,请重试'
|
||||
setTimeout(() => {
|
||||
errorMessage.value = ''
|
||||
clickedList.value = []
|
||||
// 失败时重新打乱
|
||||
generateCaptcha()
|
||||
}, 1200)
|
||||
}
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.visible) generateCaptcha()
|
||||
})
|
||||
watch(
|
||||
() => props.visible,
|
||||
v => {
|
||||
if (v) generateCaptcha()
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.captcha-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.captcha-modal {
|
||||
background: #fff;
|
||||
border-radius: 1rem;
|
||||
width: 100%;
|
||||
max-width: 340px;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.18);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.captcha-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.captcha-title {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
padding: 0.25rem;
|
||||
border-radius: 0.25rem;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.close-btn:hover {
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.captcha-content {
|
||||
padding: 1.2rem 1.2rem 0.5rem 1.2rem;
|
||||
}
|
||||
|
||||
.captcha-canvas {
|
||||
width: 100%;
|
||||
border-radius: 0.75rem;
|
||||
background: #e0e7ef;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.captcha-instruction {
|
||||
margin: 1rem 0 0.5rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.target-list {
|
||||
color: #3b82f6;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.captcha-status {
|
||||
text-align: center;
|
||||
min-height: 1.5rem;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: #dc2626;
|
||||
font-size: 0.95em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.success-message {
|
||||
color: #059669;
|
||||
font-size: 0.95em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
color: #6b7280;
|
||||
font-size: 0.95em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.captcha-footer {
|
||||
padding: 1rem 1.5rem;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.95em;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.refresh-btn:hover:not(:disabled) {
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.refresh-btn:disabled {
|
||||
background: #9ca3af;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
background: #059669;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.95em;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.confirm-btn:disabled {
|
||||
background: #9ca3af;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.captcha-modal {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.captcha-content {
|
||||
padding: 0.7rem;
|
||||
}
|
||||
|
||||
.captcha-canvas {
|
||||
min-height: 120px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
255
src/components/GaugeChart.vue
Normal file
@@ -0,0 +1,255 @@
|
||||
<template>
|
||||
<div>
|
||||
<div ref="chartRef" :style="{ width: '100%', height: '200px' }"></div>
|
||||
<div class="risk-description">
|
||||
{{ riskDescription }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as echarts from "echarts";
|
||||
import { ref, onMounted, onUnmounted, watch, computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
score: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 根据分数计算风险等级和颜色
|
||||
const riskLevel = computed(() => {
|
||||
const score = props.score;
|
||||
if (score >= 0 && score <= 25) {
|
||||
return {
|
||||
level: "无任何风险",
|
||||
color: "#52c41a",
|
||||
gradient: [
|
||||
{ offset: 0, color: "#52c41a" },
|
||||
{ offset: 1, color: "#7fdb42" }
|
||||
]
|
||||
};
|
||||
} else if (score > 25 && score <= 50) {
|
||||
return {
|
||||
level: "风险指数较低",
|
||||
color: "#faad14",
|
||||
gradient: [
|
||||
{ offset: 0, color: "#faad14" },
|
||||
{ offset: 1, color: "#ffc53d" }
|
||||
]
|
||||
};
|
||||
} else if (score > 50 && score <= 75) {
|
||||
return {
|
||||
level: "风险指数较高",
|
||||
color: "#fa8c16",
|
||||
gradient: [
|
||||
{ offset: 0, color: "#fa8c16" },
|
||||
{ offset: 1, color: "#ffa940" }
|
||||
]
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
level: "高风险警告",
|
||||
color: "#f5222d",
|
||||
gradient: [
|
||||
{ offset: 0, color: "#f5222d" },
|
||||
{ offset: 1, color: "#ff4d4f" }
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// 评分解释文本
|
||||
const riskDescription = computed(() => {
|
||||
const score = props.score;
|
||||
if (score >= 0 && score <= 25) {
|
||||
return "根据综合分析,当前报告未检测到明显风险因素,各项指标表现正常,总体状况良好。";
|
||||
} else if (score > 25 && score <= 50) {
|
||||
return "根据综合分析,当前报告存在少量风险信号,建议关注相关指标变化,保持警惕。";
|
||||
} else if (score > 50 && score <= 75) {
|
||||
return "根据综合分析,当前报告风险指数较高,多项指标显示异常,建议进一步核实相关情况。";
|
||||
} else {
|
||||
return "根据综合分析,当前报告显示高度风险状态,多项重要指标严重异常,请立即采取相应措施。";
|
||||
}
|
||||
});
|
||||
|
||||
const chartRef = ref(null);
|
||||
let chartInstance = null;
|
||||
|
||||
const initChart = () => {
|
||||
if (!chartRef.value) return;
|
||||
|
||||
// 初始化ECharts实例
|
||||
chartInstance = echarts.init(chartRef.value);
|
||||
updateChart();
|
||||
};
|
||||
|
||||
const updateChart = () => {
|
||||
if (!chartInstance) return;
|
||||
|
||||
// 获取当前风险等级信息
|
||||
const risk = riskLevel.value;
|
||||
|
||||
// 配置项
|
||||
const option = {
|
||||
series: [
|
||||
{
|
||||
type: "gauge",
|
||||
startAngle: 180,
|
||||
endAngle: 0,
|
||||
min: 0,
|
||||
max: 100,
|
||||
radius: "100%",
|
||||
center: ["50%", "80%"],
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, risk.gradient),
|
||||
shadowBlur: 10,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
||||
},
|
||||
progress: {
|
||||
show: true,
|
||||
width: 20,
|
||||
roundCap: true,
|
||||
clip: false
|
||||
},
|
||||
axisLine: {
|
||||
roundCap: true,
|
||||
lineStyle: {
|
||||
width: 20,
|
||||
color: [
|
||||
[1, new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(0, 0, 0, 0.1)"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(0, 0, 0, 0.05)"
|
||||
}
|
||||
])]
|
||||
]
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
distance: -26,
|
||||
length: 5,
|
||||
lineStyle: {
|
||||
color: "#999",
|
||||
width: 2
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
distance: -8,
|
||||
fontSize: 12,
|
||||
color: "#999",
|
||||
formatter: function (value) {
|
||||
if (value % 20 === 0) {
|
||||
return value;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
},
|
||||
anchor: {
|
||||
show: false
|
||||
},
|
||||
pointer: {
|
||||
icon: "triangle",
|
||||
iconStyle: {
|
||||
color: risk.color,
|
||||
borderColor: risk.color,
|
||||
borderWidth: 1
|
||||
},
|
||||
offsetCenter: ["7%", "-67%"],
|
||||
length: "10%",
|
||||
width: 15
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
fontSize: 30,
|
||||
fontWeight: "bold",
|
||||
color: risk.color,
|
||||
offsetCenter: [0, "-25%"],
|
||||
formatter: function (value) {
|
||||
return `{value|${value}分}\n{level|${risk.level}}`;
|
||||
},
|
||||
rich: {
|
||||
value: {
|
||||
fontSize: 30,
|
||||
fontWeight: 'bold',
|
||||
color: risk.color,
|
||||
padding: [0, 0, 5, 0]
|
||||
},
|
||||
level: {
|
||||
fontSize: 14,
|
||||
fontWeight: 'normal',
|
||||
color: risk.color,
|
||||
padding: [5, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: props.score
|
||||
}
|
||||
],
|
||||
title: {
|
||||
fontSize: 14,
|
||||
color: risk.color,
|
||||
offsetCenter: [0, "10%"],
|
||||
formatter: risk.level
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 使用配置项设置图表
|
||||
chartInstance.setOption(option);
|
||||
};
|
||||
|
||||
// 监听分数变化
|
||||
watch(
|
||||
() => props.score,
|
||||
() => {
|
||||
updateChart();
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
initChart();
|
||||
|
||||
// 处理窗口大小变化
|
||||
window.addEventListener("resize", () => {
|
||||
if (chartInstance) {
|
||||
chartInstance.resize();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 在组件销毁前清理
|
||||
onUnmounted(() => {
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose();
|
||||
chartInstance = null;
|
||||
}
|
||||
window.removeEventListener("resize", chartInstance?.resize);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.risk-description {
|
||||
margin-top: 10px;
|
||||
padding: 8px 12px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
511
src/components/InquireForm.vue
Normal file
@@ -0,0 +1,511 @@
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted, onUnmounted } from "vue";
|
||||
import { aesEncrypt } from "@/utils/crypto";
|
||||
import { useRoute } from "vue-router";
|
||||
import CarNumberInput from "@/components/CarNumberInput.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter()
|
||||
const showAuthorizationPopup = ref(false);
|
||||
const authorization = ref(true);
|
||||
const showPayment = ref(false);
|
||||
const queryId = ref(null);
|
||||
const name = ref("");
|
||||
const nameMan = ref("");
|
||||
const nameWoman = ref("");
|
||||
const idCard = ref("");
|
||||
const idCardMan = ref("");
|
||||
const idCardWoman = ref("");
|
||||
const mobile = ref("");
|
||||
const bankCard = ref("");
|
||||
const startDate = ref([])
|
||||
const dateVal = ref("")
|
||||
const showDatePicker = ref(false)
|
||||
// 当前日期
|
||||
const today = new Date();
|
||||
const maxDate = today; // 最大日期为当前日期
|
||||
// 最小日期为2000年1月1日
|
||||
const minDate = new Date('2000-01-01');
|
||||
const entName = ref("");
|
||||
const entCode = ref("");
|
||||
const verificationCode = ref("");
|
||||
const agreeToTerms = ref(false);
|
||||
const isCountingDown = ref(false);
|
||||
const countdown = ref(60);
|
||||
const feature = ref(route.params.feature);
|
||||
const featureData = ref({});
|
||||
const carLicense = ref("");
|
||||
const carType = ref("小型汽车");
|
||||
const carPickerVal = ref([{ value: "02", text: "小型汽车" }]);
|
||||
const showCarTypePicker = ref(false);
|
||||
const carTypeColumns = [
|
||||
{ value: "01", text: "大型汽车" },
|
||||
{ value: "02", text: "小型汽车" },
|
||||
{ value: "03", text: "使馆汽车" },
|
||||
{ value: "04", text: "领馆汽车" },
|
||||
{ value: "05", text: "境外汽车" },
|
||||
{ value: "06", text: "外籍汽车" },
|
||||
{ value: "07", text: "普通摩托车" },
|
||||
{ value: "08", text: "轻便摩托车" },
|
||||
{ value: "09", text: "使馆摩托车" },
|
||||
{ value: "10", text: "领馆摩托车" },
|
||||
{ value: "11", text: "境外摩托车" },
|
||||
{ value: "12", text: "外籍摩托车" },
|
||||
{ value: "13", text: "低速车" },
|
||||
{ value: "14", text: "拖拉机" },
|
||||
{ value: "15", text: "挂车" },
|
||||
{ value: "16", text: "教练汽车" },
|
||||
{ value: "17", text: "教练摩托车" },
|
||||
{ value: "20", text: "临时入境汽车" },
|
||||
{ value: "21", text: "临时入境摩托车" },
|
||||
{ value: "22", text: "临时行驶车" },
|
||||
{ value: "23", text: "警用汽车" },
|
||||
{ value: "24", text: "警用摩托车" },
|
||||
{ value: "51", text: "新能源大型车" },
|
||||
{ value: "52", text: "新能源小型车" },
|
||||
];
|
||||
const formatterDate = (type, option) => {
|
||||
if (type === 'year') {
|
||||
option.text += '年';
|
||||
}
|
||||
if (type === 'month') {
|
||||
option.text += '月';
|
||||
}
|
||||
if (type === 'day') {
|
||||
option.text += '日';
|
||||
}
|
||||
return option;
|
||||
};
|
||||
const onConfirmDate = ({ selectedValues, selectedOptions }) => {
|
||||
dateVal.value = selectedOptions.map(item => item.text).join('');
|
||||
showDatePicker.value = false
|
||||
}
|
||||
const carLicenseChange = (e) => {
|
||||
carLicense.value = e;
|
||||
};
|
||||
const onConfirmCarType = ({ selectedValues, selectedOptions }) => {
|
||||
showCarTypePicker.value = false;
|
||||
carPickerVal.value = selectedValues;
|
||||
carType.value = selectedOptions[0].text;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
isFinishPayment()
|
||||
getProduct();
|
||||
initAuthorization();
|
||||
});
|
||||
const discountPrice = ref(false) // 是否应用折扣
|
||||
|
||||
function isFinishPayment() {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
let orderNo = query.get("out_trade_no");
|
||||
if (orderNo) {
|
||||
router.push({ path: '/report', query: { orderNo } });
|
||||
}
|
||||
}
|
||||
async function getProduct() {
|
||||
const { data, error } = await useApiFetch(`/product/en/${feature.value}`)
|
||||
.get()
|
||||
.json();
|
||||
|
||||
if (data.value) {
|
||||
featureData.value = data.value.data;
|
||||
}
|
||||
}
|
||||
function initAuthorization() {
|
||||
if (NeedAuthorization.includes(feature.value)) {
|
||||
authorization.value = false;
|
||||
}
|
||||
}
|
||||
const isPhoneNumberValid = computed(() => {
|
||||
return /^1[3-9]\d{9}$/.test(mobile.value);
|
||||
});
|
||||
const isIdCardValid = computed(() => /^\d{17}[\dX]$/i.test(idCard.value));
|
||||
const isIdCardManValid = computed(() => /^\d{17}[\dX]$/i.test(idCardMan.value));
|
||||
const isIdCardWomanValid = computed(() =>
|
||||
/^\d{17}[\dX]$/i.test(idCardWoman.value)
|
||||
);
|
||||
const isCreditCodeValid = computed(() => /^.{18}$/.test(entCode.value));
|
||||
const isCarLicense = computed(() => carLicense.value.trim().length > 6);
|
||||
const isBankCardValid = computed(() => {
|
||||
const card = bankCard.value.replace(/\D/g, ""); // 移除所有非数字字符
|
||||
if (card.length < 13 || card.length > 19) {
|
||||
return false; // 校验长度
|
||||
}
|
||||
|
||||
let sum = 0;
|
||||
let shouldDouble = false;
|
||||
|
||||
// 从卡号的右边开始遍历
|
||||
for (let i = card.length - 1; i >= 0; i--) {
|
||||
let digit = parseInt(card.charAt(i));
|
||||
|
||||
if (shouldDouble) {
|
||||
digit *= 2;
|
||||
if (digit > 9) {
|
||||
digit -= 9;
|
||||
}
|
||||
}
|
||||
|
||||
sum += digit;
|
||||
shouldDouble = !shouldDouble; // 反转是否乘 2
|
||||
}
|
||||
|
||||
return sum % 10 === 0; // 如果最终和能被 10 整除,则银行卡号有效
|
||||
});
|
||||
|
||||
function handleSubmit() {
|
||||
if (!agreeToTerms.value) {
|
||||
showToast({ message: `请阅读并同意用户协议、隐私政策${!NeedAuthorization.includes(feature.value) ? '和授权书' : ''}` });
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!validateField("name", name.value, (v) => v, "请输入姓名") ||
|
||||
!validateField("nameMan", nameMan.value, (v) => v, "请输入男方姓名") ||
|
||||
!validateField(
|
||||
"nameWoman",
|
||||
nameWoman.value,
|
||||
(v) => v,
|
||||
"请输入女方姓名"
|
||||
) ||
|
||||
!validateField(
|
||||
"mobile",
|
||||
mobile.value,
|
||||
(v) => isPhoneNumberValid.value,
|
||||
"请输入有效的手机号"
|
||||
) ||
|
||||
!validateField(
|
||||
"idCard",
|
||||
idCard.value,
|
||||
(v) => isIdCardValid.value,
|
||||
"请输入有效的身份证号码"
|
||||
) ||
|
||||
!validateField(
|
||||
"idCardMan",
|
||||
idCardMan.value,
|
||||
(v) => isIdCardManValid.value,
|
||||
"请输入有效的男方身份证号码"
|
||||
) ||
|
||||
!validateField(
|
||||
"idCardWoman",
|
||||
idCardWoman.value,
|
||||
(v) => isIdCardWomanValid.value,
|
||||
"请输入有效的女方身份证号码"
|
||||
) ||
|
||||
!validateField(
|
||||
"bankCard",
|
||||
bankCard.value,
|
||||
(v) => isBankCardValid.value,
|
||||
"请输入有效的银行卡号码"
|
||||
) ||
|
||||
!validateField(
|
||||
"verificationCode",
|
||||
verificationCode.value,
|
||||
(v) => v,
|
||||
"请输入验证码"
|
||||
) ||
|
||||
!validateField(
|
||||
"carPickerVal",
|
||||
carPickerVal.value,
|
||||
(v) => v,
|
||||
"请选择车辆类型"
|
||||
) ||
|
||||
!validateField(
|
||||
"carLicense",
|
||||
carLicense.value,
|
||||
(v) => isCarLicense.value,
|
||||
"请输入正确的车牌号"
|
||||
) ||
|
||||
!validateField("entName", entName.value, (v) => v, "请输入企业名称") ||
|
||||
!validateField(
|
||||
"entCode",
|
||||
entCode.value,
|
||||
(v) => isCreditCodeValid.value,
|
||||
"请输入统一社会信用代码"
|
||||
) ||
|
||||
!validateField(
|
||||
"date",
|
||||
dateVal.value,
|
||||
(v) => v,
|
||||
"请选择日期"
|
||||
)
|
||||
|
||||
) {
|
||||
return;
|
||||
}
|
||||
submitRequest();
|
||||
}
|
||||
const validateField = (field, value, validationFn, errorMessage) => {
|
||||
if (isHasInput(field) && !validationFn(value)) {
|
||||
showToast({ message: errorMessage });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const defaultInput = ["name", "idCard", "mobile", "verificationCode"];
|
||||
const specialProduct = {
|
||||
toc_EnterpriseLawsuit: ["entName", "entCode", "mobile", "verificationCode"],
|
||||
toc_PhoneThreeElements: ["name", "idCard", "mobile"],
|
||||
toc_IDCardTwoElements: ["name", "idCard"],
|
||||
toc_PhoneTwoElements: ["name", "mobile"],
|
||||
toc_PersonVehicleVerification: ["name", "carType", "carLicense"],
|
||||
toc_VehiclesUnderName: ["name", "idCard"],
|
||||
toc_DualMarriage: ["nameMan", "idCardMan", "nameWoman", "idCardWoman"],
|
||||
toc_BankCardBlacklist: ["name", "idCard", "mobile", "bankCard"],
|
||||
toc_BankCardFourElements: ["name", "idCard", "mobile", "bankCard"],
|
||||
toc_NaturalLifeStatus: ["name", "idCard"],
|
||||
toc_NetworkDuration: ["mobile"],
|
||||
toc_PhoneSecondaryCard: ["mobile", "date"],
|
||||
toc_PhoneNumberRisk: ["mobile"],
|
||||
};
|
||||
const NeedAuthorization = [
|
||||
"toc_Marriage",
|
||||
"marriage"
|
||||
];
|
||||
const isHasInput = (input) => {
|
||||
if (specialProduct[feature.value]) {
|
||||
return specialProduct[feature.value].includes(input);
|
||||
} else {
|
||||
return defaultInput.includes(input);
|
||||
}
|
||||
};
|
||||
async function submitRequest() {
|
||||
const req = {};
|
||||
if (isHasInput("name")) {
|
||||
req.name = name.value;
|
||||
}
|
||||
if (isHasInput("idCard")) {
|
||||
req.id_card = idCard.value;
|
||||
}
|
||||
if (isHasInput("nameMan")) {
|
||||
req.name_man = nameMan.value;
|
||||
}
|
||||
if (isHasInput("idCardMan")) {
|
||||
req.id_card_man = idCardMan.value;
|
||||
}
|
||||
if (isHasInput("nameWoman")) {
|
||||
req.name_woman = nameWoman.value;
|
||||
}
|
||||
if (isHasInput("idCardWoman")) {
|
||||
req.id_card_woman = idCardWoman.value;
|
||||
}
|
||||
if (isHasInput("bankCard")) {
|
||||
req.bank_card = bankCard.value.replace(/\D/g, "");
|
||||
}
|
||||
if (isHasInput("mobile")) {
|
||||
req.mobile = mobile.value;
|
||||
}
|
||||
if (isHasInput("verificationCode")) {
|
||||
req.code = verificationCode.value;
|
||||
}
|
||||
if (isHasInput("carType")) {
|
||||
req.car_type = carPickerVal.value[0].value;
|
||||
}
|
||||
if (isHasInput("carLicense")) {
|
||||
req.car_license = carLicense.value.trim();
|
||||
}
|
||||
if (isHasInput("date")) {
|
||||
req.start_date = startDate.value.map(item => item).join('')
|
||||
}
|
||||
if (isHasInput("entName")) {
|
||||
req.ent_name = entName.value;
|
||||
}
|
||||
if (isHasInput("entCode")) {
|
||||
req.ent_code = entCode.value;
|
||||
}
|
||||
const reqStr = JSON.stringify(req);
|
||||
const encodeData = aesEncrypt(reqStr, "3a7f1e9d4c2b8a05e6f0d3c7b2a9845d");
|
||||
const { data, error } = await useApiFetch(`/query/service/${feature.value}`)
|
||||
.post({ data: encodeData })
|
||||
.json();
|
||||
if (data.value.code === 200) {
|
||||
queryId.value = data.value.data.id;
|
||||
if (authorization.value) {
|
||||
showPayment.value = true;
|
||||
} else {
|
||||
showAuthorizationPopup.value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function sendVerificationCode() {
|
||||
if (isCountingDown.value || !isPhoneNumberValid.value) return;
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "请输入有效的手机号" });
|
||||
return;
|
||||
}
|
||||
|
||||
const { data, error } = await useApiFetch("/auth/sendSms")
|
||||
.post({ mobile: mobile.value, actionType: "query" })
|
||||
.json();
|
||||
|
||||
if (!error.value && data.value.code === 200) {
|
||||
showToast({ message: "验证码发送成功", type: "success" });
|
||||
startCountdown();
|
||||
} else {
|
||||
showToast({ message: "验证码发送失败,请重试" });
|
||||
}
|
||||
}
|
||||
let timer = null;
|
||||
|
||||
function startCountdown() {
|
||||
isCountingDown.value = true;
|
||||
countdown.value = 60;
|
||||
timer = setInterval(() => {
|
||||
if (countdown.value > 0) {
|
||||
countdown.value--;
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
isCountingDown.value = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
function toUserAgreement() {
|
||||
router.push(`/userAgreement`)
|
||||
}
|
||||
|
||||
function toPrivacyPolicy() {
|
||||
router.push(`/privacyPolicy`)
|
||||
}
|
||||
|
||||
function toAuthorization() {
|
||||
router.push(`/authorization`)
|
||||
}
|
||||
const toExample = () => {
|
||||
router.push(`/example?feature=${feature.value}`)
|
||||
};
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="inquire-bg min-h-screen p-6">
|
||||
<div class="card">
|
||||
<div class="mb-4 text-lg font-semibold text-gray-800">基本信息</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('name')">
|
||||
<label for="name" class="form-label">姓名</label>
|
||||
<input v-model="name" id="name" type="text" placeholder="请输入姓名" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('idCard')">
|
||||
<label for="idCard" class="form-label">身份证号</label>
|
||||
<input v-model="idCard" id="idCard" type="text" placeholder="请输入身份证号" class="form-input" />
|
||||
</div>
|
||||
<!-- 双人婚姻 -->
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('nameMan')">
|
||||
<label for="nameMan" class="form-label">男方姓名</label>
|
||||
<input v-model="nameMan" id="nameMan" type="text" placeholder="请输入男方姓名" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('idCardMan')">
|
||||
<label for="idCardMan" class="form-label">男方身份证号</label>
|
||||
<input v-model="idCardMan" id="idCardMan" type="text" placeholder="请输入男方身份证号" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('nameWoman')">
|
||||
<label for="nameWoman" class="form-label">女方姓名</label>
|
||||
<input v-model="nameWoman" id="nameWoman" type="text" placeholder="请输入女方姓名" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('idCardWoman')">
|
||||
<label for="idCardWoman" class="form-label">女方身份证号</label>
|
||||
<input v-model="idCardWoman" id="idCardWoman" type="text" placeholder="请输入女方身份证号" class="form-input" />
|
||||
</div>
|
||||
<!-- 双人婚姻 -->
|
||||
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('entName')">
|
||||
<label for="entName" class="form-label">企业名称</label>
|
||||
<input v-model="entName" id="entName" type="text" placeholder="请输入企业名称" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('entCode')">
|
||||
<label for="entCode" class="form-label">统一社会信用代码</label>
|
||||
<input v-model="entCode" id="entCode" type="text" placeholder="请输入统一社会信用代码" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('carType')">
|
||||
<label for="carType" class="form-label">汽车类型</label>
|
||||
<van-field id="carType" v-model="carType" is-link readonly placeholder="点击选择汽车类型"
|
||||
@click="showCarTypePicker = true" class="form-input" />
|
||||
<van-popup v-model:show="showCarTypePicker" destroy-on-close round position="bottom">
|
||||
<van-picker :model-value="carPickerVal" :columns="carTypeColumns"
|
||||
@cancel="showCarTypePicker = false" @confirm="onConfirmCarType" />
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('carLicense')">
|
||||
<!-- <label for="entCode" class="form-label">车牌号</label> -->
|
||||
<CarNumberInput class="form-input" @number-input-result="carLicenseChange" :default-str="carLicense">
|
||||
</CarNumberInput>
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('bankCard')">
|
||||
<label for="bankCard" class="form-label">银行卡号</label>
|
||||
<input v-model="bankCard" id="bankCard" type="tel" placeholder="请输入银行卡号" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('mobile')">
|
||||
<label for="mobile" class="form-label">手机号</label>
|
||||
<input v-model="mobile" id="mobile" type="tel" placeholder="请输入手机号" class="form-input" />
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('date')">
|
||||
<label for="date" class="form-label">业务日期</label>
|
||||
<van-field id="date" v-model="dateVal" is-link readonly placeholder="点击选择日期"
|
||||
@click="showDatePicker = true" class="form-input" />
|
||||
<van-popup v-model:show="showDatePicker" destroy-on-close round position="bottom">
|
||||
<van-date-picker v-model="startDate" :formatter="formatterDate" :min-date="minDate"
|
||||
:max-date="maxDate" title="选择日期" @confirm="onConfirmDate" @cancel="showDatePicker = false" />
|
||||
</van-popup>
|
||||
</div>
|
||||
<div class="mb-4 flex items-center" v-if="isHasInput('verificationCode')">
|
||||
<label for="verificationCode" class="form-label">验证码</label>
|
||||
<div class="flex-1 flex items-center">
|
||||
<input v-model="verificationCode" id="verificationCode" type="text" placeholder="请输入验证码"
|
||||
class="form-input flex-1" />
|
||||
<button class="ml-2 px-4 py-2 text-sm text-blue-500 disabled:text-gray-400"
|
||||
:disabled="isCountingDown || !isPhoneNumberValid" @click="sendVerificationCode">
|
||||
{{
|
||||
isCountingDown
|
||||
? `${countdown}s重新获取`
|
||||
: "获取验证码"
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4 flex items-center">
|
||||
<input type="checkbox" v-model="agreeToTerms" />
|
||||
<span class="ml-2 text-xs text-gray-400">
|
||||
我已阅读并同意
|
||||
<span @click="toUserAgreement" class="text-blue-500 ">用户协议、</span>
|
||||
<span @click="toPrivacyPolicy" class="text-blue-500 ">隐私政策</span>
|
||||
<template v-if="!NeedAuthorization.includes(feature)">
|
||||
<span @click="toAuthorization" class="text-blue-500 ">、授权书</span>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<button class="w-24 rounded-l-xl bg-blue-400 py-2 text-white" @click="toExample">
|
||||
示例报告
|
||||
</button>
|
||||
<button class="flex-1 rounded-r-xl bg-blue-500 py-2 text-white" @click="handleSubmit">
|
||||
立即查询
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.form-label {
|
||||
@apply w-20 text-sm font-medium text-gray-700 flex-shrink-0;
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: var(--van-text-color-3);
|
||||
}
|
||||
|
||||
.form-input {
|
||||
@apply w-full border-b border-gray-200 px-2 py-2 focus:outline-none;
|
||||
}
|
||||
</style>
|
||||
79
src/components/LButtonGroup.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script setup>
|
||||
// 接收 type 和 options props 以及 v-model
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'purple-pink', // 默认颜色渐变
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true, // 动态传入选项
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '', // v-model 绑定的值
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
// 选中内容绑定 v-model
|
||||
const selected = ref(props.modelValue)
|
||||
|
||||
// 监听 v-model 的变化
|
||||
watch(() => props.modelValue, (newValue) => {
|
||||
selected.value = newValue
|
||||
})
|
||||
|
||||
// 根据type动态生成分割线的类名
|
||||
const lineClass = computed(() => {
|
||||
// 统一使用主题色渐变
|
||||
return 'bg-gradient-to-r from-red-600 via-red-500 to-red-700'
|
||||
})
|
||||
|
||||
// 计算滑动线的位置和宽度
|
||||
const slideLineStyle = computed(() => {
|
||||
const index = props.options.findIndex(option => option.value === selected.value)
|
||||
const buttonWidth = 100 / props.options.length
|
||||
return {
|
||||
width: `${buttonWidth}%`,
|
||||
transform: `translateX(${index * 100}%)`,
|
||||
}
|
||||
})
|
||||
|
||||
// 选择选项函数
|
||||
function selectOption(option) {
|
||||
selected.value = option.value
|
||||
// 触发 v-model 的更新
|
||||
emit('update:modelValue', option.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative flex">
|
||||
<div
|
||||
v-for="(option, index) in options"
|
||||
:key="index"
|
||||
class="flex-1 shrink-0 cursor-pointer py-2 text-center text-size-sm font-bold transition-transform duration-200 ease-in-out"
|
||||
:class="{ 'text-gray-900': selected === option.value, 'text-gray-500': selected !== option.value }"
|
||||
@click="selectOption(option)"
|
||||
>
|
||||
{{ option.label }}
|
||||
</div>
|
||||
<div
|
||||
class="absolute bottom-0 h-[3px] rounded transition-all duration-300"
|
||||
:style="slideLineStyle"
|
||||
:class="lineClass"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义样式 */
|
||||
button {
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:focus {
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
41
src/components/LEmpty.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="card flex flex-col items-center justify-center text-center">
|
||||
<!-- 图片插画 -->
|
||||
<img src="@/assets/images/empty.svg" alt="空状态" class="w-64 h-64" />
|
||||
|
||||
<!-- 提示文字 -->
|
||||
<h2 class="text-xl font-semibold text-gray-700 mb-2">
|
||||
没有查询到相关结果
|
||||
</h2>
|
||||
<p class="text-gray-500 text-sm mb-2 leading-relaxed">
|
||||
订单已申请退款,预计
|
||||
<span class="font-medium" style="color: var(--van-theme-primary);">24小时内到账</span>。
|
||||
</p>
|
||||
<p class="text-gray-400 text-xs">
|
||||
如果已到账,您可以忽略本提示。
|
||||
</p>
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<button @click="goBack"
|
||||
class="mt-4 px-6 py-2 text-white rounded-lg transition duration-300 ease-in-out"
|
||||
style="background-color: var(--van-theme-primary);"
|
||||
onmouseover="this.style.backgroundColor='var(--van-theme-primary-dark)'"
|
||||
onmouseout="this.style.backgroundColor='var(--van-theme-primary)'">
|
||||
返回上一页
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const route = useRoute();
|
||||
|
||||
|
||||
// 返回上一页逻辑
|
||||
function goBack() {
|
||||
route.goBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 你可以添加一些额外的样式(如果需要) */
|
||||
</style>
|
||||
55
src/components/LExpandCollapse.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<script setup>
|
||||
import { computed, ref, useSlots } from 'vue'
|
||||
|
||||
// 接收最大长度的 prop,默认值 100
|
||||
const props = defineProps({
|
||||
maxLength: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
})
|
||||
|
||||
// 记录当前是否展开
|
||||
const isExpanded = ref(false)
|
||||
|
||||
// 获取 slot 内容
|
||||
const slots = useSlots()
|
||||
|
||||
// 计算截断后的内容
|
||||
const truncatedContent = computed(() => {
|
||||
const slotContent = getSlotContent()
|
||||
return slotContent.length > props.maxLength
|
||||
? `${slotContent.slice(0, props.maxLength)}...`
|
||||
: slotContent
|
||||
})
|
||||
|
||||
// 获取 slot 内容,确保返回的内容为字符串
|
||||
function getSlotContent() {
|
||||
const slotVNode = slots.default ? slots.default()[0] : null
|
||||
return slotVNode ? slotVNode.children.toString().trim() : '' // 获取并转化为字符串
|
||||
}
|
||||
|
||||
// 切换展开/收起状态
|
||||
function toggleExpand() {
|
||||
isExpanded.value = !isExpanded.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- 展开/收起按钮 -->
|
||||
|
||||
<!-- 展开/收起的内容 -->
|
||||
<text v-if="isExpanded">
|
||||
<slot /> <!-- 使用 slot 来展示传递的内容 -->
|
||||
</text>
|
||||
<text v-else>
|
||||
<text>{{ truncatedContent }}</text>
|
||||
</text>
|
||||
<text :title="isExpanded ? '点击收起' : '点击展开'" class="cursor-pointer" style="color: var(--van-theme-primary);" @click="toggleExpand">
|
||||
{{ isExpanded ? '收起' : '展开' }}
|
||||
</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
85
src/components/LPendding.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="card flex flex-col items-center justify-center text-center">
|
||||
<!-- 图片插画 -->
|
||||
<img
|
||||
src="@/assets/images/pendding.svg"
|
||||
alt="查询中"
|
||||
class="w-64 h-64"
|
||||
/>
|
||||
|
||||
<!-- 提示文字 -->
|
||||
<h2 class="text-xl font-semibold text-gray-700 mb-2 floating-text">
|
||||
报告正在查询中
|
||||
</h2>
|
||||
<p class="text-gray-500 text-sm mb-2 leading-relaxed">
|
||||
请稍候,我们正在为您查询报告。查询过程可能需要一些时间。
|
||||
</p>
|
||||
<p class="text-gray-400 text-xs mb-4">
|
||||
您可以稍后刷新页面查看结果,或之后访问历史报告列表查看。
|
||||
</p>
|
||||
<p class="text-gray-400 text-xs mb-4">
|
||||
如过久未查询成功,请联系客服为您处理
|
||||
</p>
|
||||
<!-- 按钮组 -->
|
||||
<div class="flex gap-4">
|
||||
<!-- 刷新按钮 -->
|
||||
<button
|
||||
@click="refreshPage"
|
||||
class="px-6 py-2 text-white rounded-lg transition duration-300 ease-in-out"
|
||||
style="background-color: var(--van-theme-primary);"
|
||||
onmouseover="this.style.backgroundColor='var(--van-theme-primary-dark)'"
|
||||
onmouseout="this.style.backgroundColor='var(--van-theme-primary)'"
|
||||
>
|
||||
刷新页面
|
||||
</button>
|
||||
<!-- 历史报告按钮 -->
|
||||
<button
|
||||
@click="viewHistory"
|
||||
class="px-6 py-2 text-white rounded-lg transition duration-300 ease-in-out"
|
||||
style="background-color: var(--van-text-color-2);"
|
||||
onmouseover="this.style.backgroundColor='var(--van-text-color)'"
|
||||
onmouseout="this.style.backgroundColor='var(--van-text-color-2)'"
|
||||
>
|
||||
查看历史报告
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const router = useRouter();
|
||||
|
||||
// 刷新页面逻辑
|
||||
function refreshPage() {
|
||||
location.reload(); // 浏览器刷新页面
|
||||
}
|
||||
|
||||
// 查看历史报告逻辑
|
||||
function viewHistory() {
|
||||
router.replace({ path: "/historyQuery" }); // 假设历史报告页面的路由名为 'historyReports'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@keyframes floatUpDown {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
/* 向上浮动 */
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
/* 返回原位 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 给提示文字和其他需要浮动的元素添加动画 */
|
||||
.floating-text {
|
||||
animation: floatUpDown 3s ease-in-out infinite;
|
||||
/* 动画持续3秒,缓入缓出,循环播放 */
|
||||
}
|
||||
</style>
|
||||
90
src/components/LRemark.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="l-remark-card my-[20px]">
|
||||
<!-- 顶部连接点 -->
|
||||
<div class="connection-line">
|
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAACTCAYAAADmz7tVAAAAAXNSR0IArs4c6QAAB59JREFUeF7tXFtsFFUY/s7sbreFUiyFglxaEJUgVaAYNBAjl/hgYrgU44PhRd+Ud3xQE4xP8izx0RfiGwX1xcQYMApegFakSghgWygIFVqope3e5phvzo47O53ZmcM2zT6cSTZsujPnfPP9l/P/w3xHQOM42S/rFxTQhCQ6bAtdkNgIidUSaOYwAhiFwDUI9Fo2upFH30gCY9tXiam404i4J/42KPcXJLosYOucRrTmckChANgFQEo1ihCAlQASCSCVAibGMWwDpxMC3RvaxdE4c0UC6rkhX4aNzyDxlGUhycldAFETECA/to08BK7AwjudK8T3la4LBXTmhmxosHEomcTBfD4+iLDJCCyZBPJ5HJ60cGjLCjEZdG4goL5+uSQrcCSdRlcmE8WD3u/pNJDJoLtO4kDHKnHbf/U0QASTEzglLKyx7fDJHH8pXs3vPFxT2hFmtSxA2ricktjmB1UGiGaqL+CoZaErDAz9N5cH7o0DQyPAv1PARFYBmlMHzKsHli8AWhqBVNKJvMCDoGwb3VMJ7Pear+z83kH5SV0dDgaZKWEBow+B6/eAm6PAVE4xxAG8DBEwGapPAcuagbYWoHkuUAhgm+bLZnF4Y7t4z0X9PyBGU8rCKYbzNLsK4NYI0HcTyOTD79p/HcGlk0DHMmDpguDAYHrI2djmRl8J0KD8UwBr/SHNu6dpegZKPqPnxoqxzpXKlEHjS+BSZ7t4pphcASY9W+JzAEnvZDTT0D3gXBVg3PEI6nmCagk0X94SeIvJU3A5aBL4ImFhr9+RxyaBX64B2bwuJ8Hn1yWBF1YDTQ3lv9PBCzaOj0m8KS5cla12Ehch0Oqlk/b/YwgYuBvfZ6Jgc8yVC4F1y8vHdIJCYtjK41lxYUDuqG/Edw/Hy4cjKycvAflC1DR6vycTwPa1ANnyHnMbgalx7BS91+WnqRQOZD0ZmYhvjQK//gUkrfAJyWjeLjkqqU8U16+wq3j+5ieApc3lDl6XBnI5HBG9g/K0lcCWgsdP6Mw/XwVuPwiOLALhHa5cBHS2Ay3zFJM3R4Dfh4C/R51QDkyKdO4l84EXnyx37kTSqRzOiN4BeRsCi73+Q0Df9gETmVLSc++Y5zHRvboeWN0KZHJArgBkCyqDE0j/MHCuHxjn9T6qeP2cNPBKRzmgoh/dET0Dksaq815HO584H3yHqQTw+mblnE5WtpXZCIZJcyoLTOWVyX+6Gpyhed2eTYH+mQ0F9OX56V7Au1uzFHhjs0p2PPgvzUWGyBaXFILiUvHjFWU+d2nxjrg7DJCOyWiat18C2haWhnYB8TeHoRwwmVW5iz74w2WALuA1eUWT6Tg1J/lgj4o8965pMrLhZ4hmI2Nf9QB0AW/GruzUGmFPBj7eBxSkCm8e/M7amoCyRZORITJF9o6dLQcUGfY6ibEioLwC5ZgsEw4oMjHqLB3VAoq1dOgsrtUCirW40g/ilh/VAIpdfrje3xOjQGNohzp1BR/iGqdVoBFUnBL2/CDw4e6QKAsB9HUvsKHtEUpYgooq8v8ZA7atVU38tLAPAMSouz+hOhDtIp+Aotog+sH6NpUU4wByGoKQPihWG0RQlRpFZuX17dUDit0oug4e1krPBCDtVtoFFfSwoRpAVT1s8JYJ3scxEkg+t0LPZHxWNCOPY/zVEJNnroA9m1ZhH507jlOzPygUcMwSODFjD6z8wKSUMnC1Dwj7VAOwZmFYnAW3AZFP0AygsP4p7O/GZFGMGYYMQz4GTB6KcgnDkGHI20qb1b7s6Yeph4rhYRbXqDxhGDIMmfLDNIrug3OzdJilIyojGoYMQ+YJGmC6DtN1BMWBqamj8qNhyDBkug7TdZiuwxcFJjGaxGgSo0mMJjGaxBiVCQ1DhqHKDJj/Jo/yEMOQYci8SGC6jqgoMAyFMVQzbwvXzPvUNfXGeU29k19TqoWa03XUlPKlam1QiALvkbVBWuopG6B6hUeoRpHbcEig+6w6V0s9paUv61ITufs1hKk4HY2iDXSfUxrF2PoyXQXeR/vURH5AfhUnhUpUTB0vAiKbsRR4uhrFQ3vVRK52ld+nKYGp5swr4FQUu7LSWBpFHRUnda7v71L0e33IUQJT6+oqgXNKeMvzqCj26lwjVZw68nZOcvA1Z8+Oksm47QaF226U8bWd4odSZr/wNlLnqqME5qTv7lR37FcCO4CKAm5HVV4E+c3Fcs3+jMrbeXe7NgKPP1ZSmjtRRj9yWSqCoW+NPFS6fS2ttI68nSbgxiI71pWk6fwb0wABOZ8iODLIrTnuPAjQ7M+UvJ2hS+H21qeB1ia1xYELyNXdkxmyxq1cLlwPFktynBmRt3Mghu7ctJKKLm5SjLggCI7MDI8Bl26pPWW0dyTQcWq3vCUoMrWoCWhvAeY3KKbuTwKDdxU7BBr04CDaqTXk7f56myCcrX2KPxCAs8FNhUcYkWGvkxijWqQ4v0cmRp2lI86Elc6JtXToLK7VAoq1uHKSuOVHNYBilx/uJHEKNLfk0AWmvf8QJ4hTws7qDk0EFVXkz+oeVgQU1Qa5mXrWdvnihDW1D5rrrDW1U5wLqqb20vOGdc3sNujPNTWzH6MX2GzsWPkfBLU1i3+dVUIAAAAASUVORK5CYII=" alt="左链条" class="connection-chain left" />
|
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAACTCAYAAADmz7tVAAAAAXNSR0IArs4c6QAAB59JREFUeF7tXFtsFFUY/s7sbreFUiyFglxaEJUgVaAYNBAjl/hgYrgU44PhRd+Ud3xQE4xP8izx0RfiGwX1xcQYMApegFakSghgWygIFVqope3e5phvzo47O53ZmcM2zT6cSTZsujPnfPP9l/P/w3xHQOM42S/rFxTQhCQ6bAtdkNgIidUSaOYwAhiFwDUI9Fo2upFH30gCY9tXiam404i4J/42KPcXJLosYOucRrTmckChANgFQEo1ihCAlQASCSCVAibGMWwDpxMC3RvaxdE4c0UC6rkhX4aNzyDxlGUhycldAFETECA/to08BK7AwjudK8T3la4LBXTmhmxosHEomcTBfD4+iLDJCCyZBPJ5HJ60cGjLCjEZdG4goL5+uSQrcCSdRlcmE8WD3u/pNJDJoLtO4kDHKnHbf/U0QASTEzglLKyx7fDJHH8pXs3vPFxT2hFmtSxA2ricktjmB1UGiGaqL+CoZaErDAz9N5cH7o0DQyPAv1PARFYBmlMHzKsHli8AWhqBVNKJvMCDoGwb3VMJ7Pear+z83kH5SV0dDgaZKWEBow+B6/eAm6PAVE4xxAG8DBEwGapPAcuagbYWoHkuUAhgm+bLZnF4Y7t4z0X9PyBGU8rCKYbzNLsK4NYI0HcTyOTD79p/HcGlk0DHMmDpguDAYHrI2djmRl8J0KD8UwBr/SHNu6dpegZKPqPnxoqxzpXKlEHjS+BSZ7t4pphcASY9W+JzAEnvZDTT0D3gXBVg3PEI6nmCagk0X94SeIvJU3A5aBL4ImFhr9+RxyaBX64B2bwuJ8Hn1yWBF1YDTQ3lv9PBCzaOj0m8KS5cla12Ehch0Oqlk/b/YwgYuBvfZ6Jgc8yVC4F1y8vHdIJCYtjK41lxYUDuqG/Edw/Hy4cjKycvAflC1DR6vycTwPa1ANnyHnMbgalx7BS91+WnqRQOZD0ZmYhvjQK//gUkrfAJyWjeLjkqqU8U16+wq3j+5ieApc3lDl6XBnI5HBG9g/K0lcCWgsdP6Mw/XwVuPwiOLALhHa5cBHS2Ay3zFJM3R4Dfh4C/R51QDkyKdO4l84EXnyx37kTSqRzOiN4BeRsCi73+Q0Df9gETmVLSc++Y5zHRvboeWN0KZHJArgBkCyqDE0j/MHCuHxjn9T6qeP2cNPBKRzmgoh/dET0Dksaq815HO584H3yHqQTw+mblnE5WtpXZCIZJcyoLTOWVyX+6Gpyhed2eTYH+mQ0F9OX56V7Au1uzFHhjs0p2PPgvzUWGyBaXFILiUvHjFWU+d2nxjrg7DJCOyWiat18C2haWhnYB8TeHoRwwmVW5iz74w2WALuA1eUWT6Tg1J/lgj4o8965pMrLhZ4hmI2Nf9QB0AW/GruzUGmFPBj7eBxSkCm8e/M7amoCyRZORITJF9o6dLQcUGfY6ibEioLwC5ZgsEw4oMjHqLB3VAoq1dOgsrtUCirW40g/ilh/VAIpdfrje3xOjQGNohzp1BR/iGqdVoBFUnBL2/CDw4e6QKAsB9HUvsKHtEUpYgooq8v8ZA7atVU38tLAPAMSouz+hOhDtIp+Aotog+sH6NpUU4wByGoKQPihWG0RQlRpFZuX17dUDit0oug4e1krPBCDtVtoFFfSwoRpAVT1s8JYJ3scxEkg+t0LPZHxWNCOPY/zVEJNnroA9m1ZhH507jlOzPygUcMwSODFjD6z8wKSUMnC1Dwj7VAOwZmFYnAW3AZFP0AygsP4p7O/GZFGMGYYMQz4GTB6KcgnDkGHI20qb1b7s6Yeph4rhYRbXqDxhGDIMmfLDNIrug3OzdJilIyojGoYMQ+YJGmC6DtN1BMWBqamj8qNhyDBkug7TdZiuwxcFJjGaxGgSo0mMJjGaxBiVCQ1DhqHKDJj/Jo/yEMOQYci8SGC6jqgoMAyFMVQzbwvXzPvUNfXGeU29k19TqoWa03XUlPKlam1QiALvkbVBWuopG6B6hUeoRpHbcEig+6w6V0s9paUv61ITufs1hKk4HY2iDXSfUxrF2PoyXQXeR/vURH5AfhUnhUpUTB0vAiKbsRR4uhrFQ3vVRK52ld+nKYGp5swr4FQUu7LSWBpFHRUnda7v71L0e33IUQJT6+oqgXNKeMvzqCj26lwjVZw68nZOcvA1Z8+Oksm47QaF226U8bWd4odSZr/wNlLnqqME5qTv7lR37FcCO4CKAm5HVV4E+c3Fcs3+jMrbeXe7NgKPP1ZSmjtRRj9yWSqCoW+NPFS6fS2ttI68nSbgxiI71pWk6fwb0wABOZ8iODLIrTnuPAjQ7M+UvJ2hS+H21qeB1ia1xYELyNXdkxmyxq1cLlwPFktynBmRt3Mghu7ctJKKLm5SjLggCI7MDI8Bl26pPWW0dyTQcWq3vCUoMrWoCWhvAeY3KKbuTwKDdxU7BBr04CDaqTXk7f56myCcrX2KPxCAs8FNhUcYkWGvkxijWqQ4v0cmRp2lI86Elc6JtXToLK7VAoq1uHKSuOVHNYBilx/uJHEKNLfk0AWmvf8QJ4hTws7qDk0EFVXkz+oeVgQU1Qa5mXrWdvnihDW1D5rrrDW1U5wLqqb20vOGdc3sNujPNTWzH6MX2GzsWPkfBLU1i3+dVUIAAAAASUVORK5CYII=" alt="右链条" class="connection-chain right" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<van-icon name="info-o" class="tips-icon" />
|
||||
<span class="tips-title">温馨提示</span>
|
||||
</div>
|
||||
<div>
|
||||
<van-text-ellipsis rows="2" :content="content" expand-text="展开" collapse-text="收起" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineProps } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const isExpanded = ref(false);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.l-remark-card {
|
||||
position: relative;
|
||||
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
border-radius: 0.75rem;
|
||||
background-color: #ffffff;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.tips-card {
|
||||
background: var(--van-theme-primary-light);
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.tips-icon {
|
||||
color: var(--van-theme-primary);
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 连接链条样式 */
|
||||
.connection-line {
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 60px;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.connection-chain {
|
||||
height: 60px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.connection-chain.left {
|
||||
width: 80px;
|
||||
margin-left: -10px;
|
||||
}
|
||||
|
||||
.connection-chain.right {
|
||||
width: 80px;
|
||||
margin-right: -10px;
|
||||
}
|
||||
</style>
|
||||
80
src/components/LTable.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<script setup>
|
||||
import { computed, onMounted } from "vue";
|
||||
|
||||
// 接收表格数据和类型的 props
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: "purple-pink", // 默认渐变颜色
|
||||
},
|
||||
});
|
||||
// 根据 type 设置不同的渐变颜色(偶数行)
|
||||
const evenClass = computed(() => {
|
||||
// 统一使用主题色浅色背景
|
||||
return "bg-red-50/40";
|
||||
});
|
||||
|
||||
// 动态计算表头的背景颜色和文本颜色
|
||||
const headerClass = computed(() => {
|
||||
// 统一使用主题色浅色背景
|
||||
return "bg-red-100";
|
||||
});
|
||||
// 斑马纹样式,偶数行带颜色,奇数行没有颜色,且从第二行开始
|
||||
function zebraClass(index) {
|
||||
return index % 2 === 1 ? evenClass.value : "";
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="l-table overflow-x-auto">
|
||||
<table
|
||||
class="min-w-full border-collapse table-auto text-center text-size-xs"
|
||||
>
|
||||
<thead :class="headerClass">
|
||||
<tr>
|
||||
<!-- 插槽渲染表头 -->
|
||||
<slot name="header" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(row, index) in props.data"
|
||||
:key="index"
|
||||
:class="zebraClass(index)"
|
||||
class="border-t"
|
||||
>
|
||||
<slot :row="row" />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 基础表格样式 */
|
||||
th {
|
||||
font-weight: bold;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
/* 表格行样式 */
|
||||
td {
|
||||
padding: 12px;
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
}
|
||||
.l-table {
|
||||
@apply rounded-xl;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
37
src/components/LTitle.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<script setup>
|
||||
// 接收 props
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
})
|
||||
|
||||
const titleClass = computed(() => {
|
||||
// 统一使用主题色渐变
|
||||
return 'bg-gradient-to-r from-red-600 via-red-500 to-red-700'
|
||||
})
|
||||
|
||||
// 分割线颜色与背景对应
|
||||
const lineClass = computed(() => {
|
||||
// 统一使用主题色渐变
|
||||
return 'bg-gradient-to-r from-red-600 via-red-500 to-red-700'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative">
|
||||
<!-- 标题部分 -->
|
||||
<div :class="titleClass" class="inline-block rounded-lg px-2 py-1 text-white font-bold shadow-md">
|
||||
{{ title }}
|
||||
</div>
|
||||
|
||||
<!-- 左上角修饰 -->
|
||||
<div
|
||||
class="absolute left-0 top-0 h-4 w-4 transform rounded-full bg-white shadow-md -translate-x-2 -translate-y-2" />
|
||||
|
||||
<!-- 分割线 -->
|
||||
<div class="relative mt-1.5">
|
||||
<div :class="lineClass" class="h-[2px] w-full rounded" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
173
src/components/Payment.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<van-popup
|
||||
v-model:show="show"
|
||||
position="bottom"
|
||||
class="flex flex-col justify-between p-6"
|
||||
:style="{ height: '50%' }"
|
||||
>
|
||||
<div class="text-center">
|
||||
<h3 class="text-lg font-bold">支付</h3>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="font-bold text-xl">{{ data.product_name }}</div>
|
||||
<div class="text-3xl text-red-500 font-bold">
|
||||
<!-- 显示原价和折扣价格 -->
|
||||
<div
|
||||
v-if="discountPrice"
|
||||
class="line-through text-gray-500 mt-4"
|
||||
:class="{ 'text-2xl': discountPrice }"
|
||||
>
|
||||
¥ {{ data.sell_price }}
|
||||
</div>
|
||||
<div>
|
||||
¥
|
||||
{{
|
||||
discountPrice
|
||||
? (data.sell_price * 0.2).toFixed(2)
|
||||
: data.sell_price
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 仅在折扣时显示活动说明 -->
|
||||
<div v-if="discountPrice" class="text-sm text-red-500 mt-1">
|
||||
活动价:2折优惠
|
||||
</div>
|
||||
</div>
|
||||
<!-- 支付方式选择 -->
|
||||
<div class="">
|
||||
<van-cell-group inset>
|
||||
<van-cell
|
||||
v-if="isWeChat"
|
||||
title="微信支付"
|
||||
clickable
|
||||
@click="selectedPaymentMethod = 'wechat'"
|
||||
>
|
||||
<template #icon>
|
||||
<van-icon
|
||||
size="24"
|
||||
name="wechat-pay"
|
||||
color="#1AAD19"
|
||||
class="mr-2"
|
||||
/>
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<van-radio
|
||||
v-model="selectedPaymentMethod"
|
||||
name="wechat"
|
||||
/>
|
||||
</template>
|
||||
</van-cell>
|
||||
|
||||
<!-- 支付宝支付 -->
|
||||
<van-cell
|
||||
v-else
|
||||
title="支付宝支付"
|
||||
clickable
|
||||
@click="selectedPaymentMethod = 'alipay'"
|
||||
>
|
||||
<template #icon>
|
||||
<van-icon
|
||||
size="24"
|
||||
name="alipay"
|
||||
color="#00A1E9"
|
||||
class="mr-2"
|
||||
/>
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<van-radio
|
||||
v-model="selectedPaymentMethod"
|
||||
name="alipay"
|
||||
/>
|
||||
</template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</div>
|
||||
<!-- 确认按钮 -->
|
||||
<div class="">
|
||||
<van-button class="w-full" round type="primary" @click="getPayment"
|
||||
>确认支付</van-button
|
||||
>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineProps } from "vue";
|
||||
const { isWeChat } = useEnv();
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const show = defineModel();
|
||||
const selectedPaymentMethod = ref(isWeChat.value ? "wechat" : "alipay");
|
||||
onMounted(() => {
|
||||
if (isWeChat.value) {
|
||||
selectedPaymentMethod.value = "wechat";
|
||||
} else {
|
||||
selectedPaymentMethod.value = "alipay";
|
||||
}
|
||||
});
|
||||
const orderNo = ref("");
|
||||
const router = useRouter();
|
||||
const discountPrice = ref(false); // 是否应用折扣
|
||||
onMounted(() => {
|
||||
if (isWeChat.value) {
|
||||
selectedPaymentMethod.value = "wechat";
|
||||
} else {
|
||||
selectedPaymentMethod.value = "alipay";
|
||||
}
|
||||
});
|
||||
|
||||
async function getPayment() {
|
||||
const { data, error } = await useApiFetch("/pay/payment")
|
||||
.post({
|
||||
id: props.id,
|
||||
pay_method: selectedPaymentMethod.value,
|
||||
pay_type: props.type,
|
||||
})
|
||||
.json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (selectedPaymentMethod.value === "alipay") {
|
||||
orderNo.value = data.value.data.order_no;
|
||||
// 存储订单ID以便支付宝返回时获取
|
||||
const prepayUrl = data.value.data.prepay_id;
|
||||
const paymentForm = document.createElement("form");
|
||||
paymentForm.method = "POST";
|
||||
paymentForm.action = prepayUrl;
|
||||
paymentForm.style.display = "none";
|
||||
document.body.appendChild(paymentForm);
|
||||
paymentForm.submit();
|
||||
} else {
|
||||
const payload = data.value.data.prepay_data;
|
||||
WeixinJSBridge.invoke(
|
||||
"getBrandWCPayRequest",
|
||||
payload,
|
||||
function (res) {
|
||||
if (res.err_msg == "get_brand_wcpay_request:ok") {
|
||||
// 支付成功,直接跳转到结果页面
|
||||
router.push({
|
||||
path: "/payment/result",
|
||||
query: { orderNo: data.value.data.order_no },
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
show.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
161
src/components/PriceInputPopup.vue
Normal file
@@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<van-popup v-model:show="show" destroy-on-close round position="bottom">
|
||||
<div class="min-h-[500px] bg-gray-50 text-gray-600">
|
||||
<div class="h-10 bg-white flex items-center justify-center font-semibold text-lg">设置客户查询价
|
||||
</div>
|
||||
<div class="card m-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-lg">
|
||||
客户查询价 (元)</div>
|
||||
</div>
|
||||
|
||||
<div class="border-b border-gray-200">
|
||||
<van-field v-model="price" type="number" label="¥" label-width="28"
|
||||
:placeholder="`${productConfig.price_range_min} - ${productConfig.price_range_max}`"
|
||||
@blur="onBlurPrice" class="!text-3xl" />
|
||||
</div>
|
||||
<div class="flex items-center justify-between mt-2">
|
||||
<div>推广收益为<span class="text-orange-500"> {{ promotionRevenue }} </span>元</div>
|
||||
<div>我的成本为<span class="text-orange-500"> {{ costPrice }} </span>元</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card m-4">
|
||||
<div class="text-lg mb-2">收益与成本说明</div>
|
||||
|
||||
<div>推广收益 = 客户查询价 - 我的成本</div>
|
||||
<div>我的成本 = 提价成本 + 底价成本</div>
|
||||
<div class="mt-1">提价成本:超过平台标准定价部分,平台会收取部分成本价</div>
|
||||
<div class="">设定范围:<span class="text-orange-500">{{
|
||||
productConfig.price_range_min }}</span>元 - <span class="text-orange-500">{{
|
||||
productConfig.price_range_max }}</span>元</div>
|
||||
</div>
|
||||
<div class="px-4 pb-4">
|
||||
<van-button class="w-full" round type="primary" size="large" @click="onConfirm">确认</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
defaultPrice: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
productConfig: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
const { defaultPrice, productConfig } = toRefs(props)
|
||||
const emit = defineEmits(["change"])
|
||||
const show = defineModel("show")
|
||||
const price = ref(null)
|
||||
|
||||
|
||||
watch(show, () => {
|
||||
price.value = defaultPrice.value
|
||||
})
|
||||
|
||||
|
||||
const costPrice = computed(() => {
|
||||
if (!productConfig.value) return 0.00
|
||||
// 平台定价成本
|
||||
let platformPricing = 0
|
||||
platformPricing += productConfig.value.cost_price
|
||||
if (price.value > productConfig.value.p_pricing_standard) {
|
||||
platformPricing += (price.value - productConfig.value.p_pricing_standard) * productConfig.value.p_overpricing_ratio
|
||||
}
|
||||
|
||||
if (productConfig.value.a_pricing_standard > platformPricing && productConfig.value.a_pricing_end > platformPricing && productConfig.value.a_overpricing_ratio > 0) {
|
||||
if (price.value > productConfig.value.a_pricing_standard) {
|
||||
if (price.value > productConfig.value.a_pricing_end) {
|
||||
platformPricing += (productConfig.value.a_pricing_end - productConfig.value.a_pricing_standard) * productConfig.value.a_overpricing_ratio
|
||||
} else {
|
||||
platformPricing += (price.value - productConfig.value.a_pricing_standard) * productConfig.value.a_overpricing_ratio
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return safeTruncate(platformPricing)
|
||||
})
|
||||
|
||||
const promotionRevenue = computed(() => {
|
||||
return safeTruncate(price.value - costPrice.value)
|
||||
});
|
||||
|
||||
// 价格校验与修正逻辑
|
||||
const validatePrice = (currentPrice) => {
|
||||
const min = productConfig.value.price_range_min;
|
||||
const max = productConfig.value.price_range_max;
|
||||
let newPrice = Number(currentPrice);
|
||||
let message = '';
|
||||
|
||||
// 处理无效输入
|
||||
if (isNaN(newPrice)) {
|
||||
newPrice = defaultPrice.value;
|
||||
return { newPrice, message: '输入无效,请输入价格' };
|
||||
}
|
||||
|
||||
// 处理小数位数(兼容科学计数法)
|
||||
try {
|
||||
const priceString = newPrice.toString()
|
||||
const [_, decimalPart = ""] = priceString.split('.');
|
||||
console.log(priceString, decimalPart)
|
||||
// 当小数位数超过2位时处理
|
||||
if (decimalPart.length > 2) {
|
||||
newPrice = parseFloat(safeTruncate(newPrice));
|
||||
message = '价格已自动格式化为两位小数';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('价格格式化异常:', e);
|
||||
}
|
||||
|
||||
// 范围校验(基于可能格式化后的值)
|
||||
if (newPrice < min) {
|
||||
message = `价格不能低于 ${min} 元`;
|
||||
newPrice = min;
|
||||
} else if (newPrice > max) {
|
||||
message = `价格不能高于 ${max} 元`;
|
||||
newPrice = max;
|
||||
}
|
||||
console.log(newPrice, message)
|
||||
return { newPrice, message };
|
||||
}
|
||||
function safeTruncate(num, decimals = 2) {
|
||||
if (isNaN(num) || !isFinite(num)) return "0.00";
|
||||
|
||||
const factor = 10 ** decimals;
|
||||
const scaled = Math.trunc(num * factor);
|
||||
const truncated = scaled / factor;
|
||||
|
||||
return truncated.toFixed(decimals);
|
||||
}
|
||||
const isManualConfirm = ref(false)
|
||||
const onConfirm = () => {
|
||||
if (isManualConfirm.value) return
|
||||
const { newPrice, message } = validatePrice(price.value)
|
||||
if (message) {
|
||||
price.value = newPrice
|
||||
showToast({ message });
|
||||
} else {
|
||||
emit("change", price.value)
|
||||
show.value = false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
const onBlurPrice = () => {
|
||||
const { newPrice, message } = validatePrice(price.value)
|
||||
if (message) {
|
||||
isManualConfirm.value = true
|
||||
price.value = newPrice
|
||||
showToast({ message });
|
||||
}
|
||||
setTimeout(() => {
|
||||
isManualConfirm.value = false
|
||||
}, 0)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
338
src/components/QRcode.vue
Normal file
@@ -0,0 +1,338 @@
|
||||
<template>
|
||||
<van-popup v-model:show="show" round position="bottom">
|
||||
<div class="max-h-[calc(100vh-100px)] m-4">
|
||||
<div class="p-4">
|
||||
<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
|
||||
v-if="mode === 'promote'"
|
||||
class="swipe-tip text-center text-gray-700 text-sm mb-2"
|
||||
>
|
||||
<span class="swipe-icon">←</span> 左右滑动切换海报
|
||||
<span class="swipe-icon">→</span>
|
||||
</div>
|
||||
<van-divider>分享到好友</van-divider>
|
||||
|
||||
<div class="flex items-center justify-around">
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-col items-center justify-center"
|
||||
@click="copyUrl"
|
||||
>
|
||||
<img
|
||||
src="@/assets/images/icon_share_url.svg"
|
||||
class="w-10 h-10 rounded-full"
|
||||
/>
|
||||
<div class="text-center mt-1 text-gray-600 text-xs">
|
||||
复制链接
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, nextTick, computed, onMounted, toRefs } from "vue";
|
||||
import QRCode from "qrcode";
|
||||
import { showToast } from "vant";
|
||||
|
||||
const props = defineProps({
|
||||
linkIdentifier: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: "promote", // 例如 "promote" | "invitation"
|
||||
},
|
||||
});
|
||||
const { linkIdentifier, mode } = toRefs(props);
|
||||
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"
|
||||
? `${baseUrl}/agent/promotionInquire/` // 使用动态的域名
|
||||
: `${baseUrl}/agent/invitationAgentApply/`;
|
||||
});
|
||||
|
||||
// 海报图片数组
|
||||
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 () => {
|
||||
posterImages.value = await loadPosterImages();
|
||||
// 根据加载的图片数量初始化postersGenerated数组
|
||||
postersGenerated.value = Array(posterImages.value.length).fill(false);
|
||||
});
|
||||
|
||||
// 生成海报并合成二维码
|
||||
const generatePoster = async (index) => {
|
||||
// 如果已经生成过海报,就直接返回
|
||||
if (postersGenerated.value[index]) return;
|
||||
|
||||
// 确保 DOM 已经渲染完成
|
||||
await nextTick();
|
||||
|
||||
const canvas = posterCanvasRefs.value[index];
|
||||
if (!canvas) return; // 如果 canvas 元素为空则直接返回
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// 1. 加载海报图片
|
||||
const posterImg = new Image();
|
||||
posterImg.src = posterImages.value[index];
|
||||
|
||||
posterImg.onload = () => {
|
||||
// 设置 canvas 尺寸与海报图一致
|
||||
canvas.width = posterImg.width;
|
||||
canvas.height = posterImg.height;
|
||||
|
||||
// 2. 绘制海报图片
|
||||
ctx.drawImage(posterImg, 0, 0);
|
||||
|
||||
// 3. 生成二维码
|
||||
QRCode.toDataURL(
|
||||
generalUrl(),
|
||||
{ width: 150, margin: 0 },
|
||||
(err, qrCodeUrl) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 加载二维码图片
|
||||
const qrCodeImg = new Image();
|
||||
qrCodeImg.src = qrCodeUrl;
|
||||
qrCodeImg.onload = () => {
|
||||
// 获取当前海报的二维码位置配置
|
||||
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
|
||||
);
|
||||
|
||||
// 标记海报已生成
|
||||
postersGenerated.value[index] = true;
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
// 监听 show 变化,show 为 true 时生成海报
|
||||
watch(show, (newVal) => {
|
||||
if (newVal && !postersGenerated.value[currentIndex.value]) {
|
||||
generatePoster(currentIndex.value); // 当弹窗显示且当前海报未生成时生成海报
|
||||
}
|
||||
});
|
||||
|
||||
// 分享到微信
|
||||
const toPromote = () => {
|
||||
// 这里可以实现微信分享的功能,比如调用微信JS-SDK等
|
||||
console.log("分享到微信好友");
|
||||
};
|
||||
|
||||
// 保存海报图片
|
||||
const savePoster = () => {
|
||||
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);
|
||||
};
|
||||
|
||||
const copyUrl = () => {
|
||||
copyToClipboard(generalUrl());
|
||||
};
|
||||
|
||||
// 复制链接
|
||||
const copyToClipboard = (text) => {
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
// 支持 Clipboard API
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
showToast({ message: "链接已复制!" });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("复制失败:", err);
|
||||
});
|
||||
} else {
|
||||
// 对于不支持 Clipboard API 的浏览器,使用 fallback 方法
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
try {
|
||||
document.execCommand("copy");
|
||||
showToast({ message: "链接已复制!" });
|
||||
} catch (err) {
|
||||
console.error("复制失败:", err);
|
||||
} finally {
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.poster-swiper {
|
||||
height: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.poster-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.swipe-tip {
|
||||
animation: fadeInOut 2s infinite;
|
||||
}
|
||||
|
||||
.swipe-icon {
|
||||
display: inline-block;
|
||||
animation: slideLeftRight 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes fadeInOut {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideLeftRight {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(5px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
14
src/components/QrcodePop.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<van-popup v-model:show="show" closeable round :style="{ padding: '18px' }">
|
||||
<img src="@/assets/images/qrcode_qnc.jpg" alt="qrcode" />
|
||||
<div class="text-center font-bold text-2xl">
|
||||
更多服务请关注天远数据公众号
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const show = defineModel("show");
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
362
src/components/RealNameAuthDialog.vue
Normal file
@@ -0,0 +1,362 @@
|
||||
<script setup>
|
||||
import { ref, computed } from "vue";
|
||||
import { useDialogStore } from "@/stores/dialogStore";
|
||||
const router = useRouter();
|
||||
const dialogStore = useDialogStore();
|
||||
const agentStore = useAgentStore();
|
||||
const userStore = useUserStore();
|
||||
import { showToast } from "vant";
|
||||
// 表单数据
|
||||
const realName = ref("");
|
||||
const idCard = ref("");
|
||||
const phoneNumber = ref("");
|
||||
const verificationCode = ref("");
|
||||
const isAgreed = ref(false);
|
||||
|
||||
// 倒计时相关
|
||||
const isCountingDown = ref(false);
|
||||
const countdown = ref(60);
|
||||
let timer = null;
|
||||
|
||||
// 聚焦状态变量
|
||||
const nameFocused = ref(false);
|
||||
const idCardFocused = ref(false);
|
||||
const phoneFocused = ref(false);
|
||||
const codeFocused = ref(false);
|
||||
|
||||
// 表单验证
|
||||
const isPhoneNumberValid = computed(() => {
|
||||
return /^1[3-9]\d{9}$/.test(phoneNumber.value);
|
||||
});
|
||||
|
||||
const isIdCardValid = computed(() => {
|
||||
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(idCard.value);
|
||||
});
|
||||
|
||||
const isRealNameValid = computed(() => {
|
||||
return /^[\u4e00-\u9fa5]{2,}$/.test(realName.value);
|
||||
});
|
||||
|
||||
const canSubmit = computed(() => {
|
||||
return (
|
||||
isPhoneNumberValid.value &&
|
||||
isIdCardValid.value &&
|
||||
isRealNameValid.value &&
|
||||
verificationCode.value.length === 6 &&
|
||||
isAgreed.value
|
||||
);
|
||||
});
|
||||
|
||||
// 发送验证码
|
||||
async function sendVerificationCode() {
|
||||
if (isCountingDown.value || !isPhoneNumberValid.value) return;
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "请输入有效的手机号" });
|
||||
return;
|
||||
}
|
||||
const { data, error } = await useApiFetch("auth/sendSms")
|
||||
.post({ mobile: phoneNumber.value, actionType: "realName" })
|
||||
.json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
showToast({ message: "获取成功" });
|
||||
startCountdown();
|
||||
} else {
|
||||
showToast(data.value.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startCountdown() {
|
||||
isCountingDown.value = true;
|
||||
countdown.value = 60;
|
||||
timer = setInterval(() => {
|
||||
if (countdown.value > 0) {
|
||||
countdown.value--;
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
isCountingDown.value = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// 提交实名认证
|
||||
async function handleSubmit() {
|
||||
if (!isRealNameValid.value) {
|
||||
showToast({ message: "请输入有效的姓名" });
|
||||
return;
|
||||
}
|
||||
if (!isIdCardValid.value) {
|
||||
showToast({ message: "请输入有效的身份证号" });
|
||||
return;
|
||||
}
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "请输入有效的手机号" });
|
||||
return;
|
||||
}
|
||||
if (verificationCode.value.length !== 6) {
|
||||
showToast({ message: "请输入有效的验证码" });
|
||||
return;
|
||||
}
|
||||
if (!isAgreed.value) {
|
||||
showToast({ message: "请先同意用户协议" });
|
||||
return;
|
||||
}
|
||||
|
||||
const { data, error } = await useApiFetch("/agent/real_name")
|
||||
.post({
|
||||
name: realName.value,
|
||||
id_card: idCard.value,
|
||||
mobile: phoneNumber.value,
|
||||
code: verificationCode.value,
|
||||
})
|
||||
.json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
showToast({ message: "认证成功" });
|
||||
// 更新实名状态
|
||||
agentStore.isRealName = true;
|
||||
// 刷新代理状态信息
|
||||
await agentStore.fetchAgentStatus();
|
||||
// 刷新用户信息
|
||||
await userStore.fetchUserInfo();
|
||||
closeDialog();
|
||||
} else {
|
||||
showToast(data.value.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeDialog() {
|
||||
dialogStore.closeRealNameAuth();
|
||||
// 重置表单
|
||||
realName.value = "";
|
||||
idCard.value = "";
|
||||
phoneNumber.value = "";
|
||||
verificationCode.value = "";
|
||||
isAgreed.value = false;
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
}
|
||||
|
||||
function toUserAgreement() {
|
||||
closeDialog();
|
||||
router.push(`/userAgreement`);
|
||||
}
|
||||
|
||||
function toPrivacyPolicy() {
|
||||
closeDialog();
|
||||
router.push(`/privacyPolicy`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="dialogStore.showRealNameAuth" class="real-name-auth-dialog-box">
|
||||
<van-popup
|
||||
v-model:show="dialogStore.showRealNameAuth"
|
||||
round
|
||||
position="bottom"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<div class="real-name-auth-dialog" style="background: linear-gradient(135deg, var(--van-theme-primary-light), rgba(255,255,255,0.9));">
|
||||
<div class="title-bar">
|
||||
<div class="font-bold" style="color: var(--van-text-color);">实名认证</div>
|
||||
<van-icon
|
||||
name="cross"
|
||||
class="close-icon"
|
||||
style="color: var(--van-text-color-2);"
|
||||
@click="closeDialog"
|
||||
/>
|
||||
</div>
|
||||
<div class="px-8 py-2">
|
||||
<div class="auth-notice p-4 rounded-lg mb-6" style="background-color: var(--van-theme-primary-light); border: 1px solid rgba(162, 37, 37, 0.2);">
|
||||
<div class="text-sm space-y-2" style="color: var(--van-text-color);">
|
||||
<p class="font-medium" style="color: var(--van-theme-primary);">
|
||||
实名认证说明:
|
||||
</p>
|
||||
<p>1. 实名认证是提现的必要条件</p>
|
||||
<p>2. 提现金额将转入您实名认证的银行卡账户</p>
|
||||
<p>
|
||||
3.
|
||||
请确保填写的信息真实有效,否则将影响提现功能的使用
|
||||
</p>
|
||||
<p>4. 认证信息提交后将无法修改,请仔细核对</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-5">
|
||||
<!-- 姓名输入 -->
|
||||
<div
|
||||
:class="[
|
||||
'input-container',
|
||||
nameFocused ? 'focused' : '',
|
||||
]"
|
||||
style="background-color: var(--van-theme-primary-light); border: 2px solid rgba(162, 37, 37, 0);"
|
||||
>
|
||||
<input
|
||||
v-model="realName"
|
||||
class="input-field"
|
||||
type="text"
|
||||
placeholder="请输入真实姓名"
|
||||
style="color: var(--van-text-color);"
|
||||
@focus="nameFocused = true"
|
||||
@blur="nameFocused = false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 身份证号输入 -->
|
||||
<div
|
||||
:class="[
|
||||
'input-container',
|
||||
idCardFocused ? 'focused' : '',
|
||||
]"
|
||||
style="background-color: var(--van-theme-primary-light); border: 2px solid rgba(162, 37, 37, 0);"
|
||||
>
|
||||
<input
|
||||
v-model="idCard"
|
||||
class="input-field"
|
||||
type="text"
|
||||
placeholder="请输入身份证号"
|
||||
maxlength="18"
|
||||
style="color: var(--van-text-color);"
|
||||
@focus="idCardFocused = true"
|
||||
@blur="idCardFocused = false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 手机号输入 -->
|
||||
<div
|
||||
:class="[
|
||||
'input-container',
|
||||
phoneFocused ? 'focused' : '',
|
||||
]"
|
||||
style="background-color: var(--van-theme-primary-light); border: 2px solid rgba(162, 37, 37, 0);"
|
||||
>
|
||||
<input
|
||||
v-model="phoneNumber"
|
||||
class="input-field"
|
||||
type="tel"
|
||||
placeholder="请输入手机号"
|
||||
maxlength="11"
|
||||
style="color: var(--van-text-color);"
|
||||
@focus="phoneFocused = true"
|
||||
@blur="phoneFocused = false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 验证码输入 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div
|
||||
:class="[
|
||||
'input-container',
|
||||
codeFocused ? 'focused' : '',
|
||||
]"
|
||||
style="background-color: var(--van-theme-primary-light); border: 2px solid rgba(162, 37, 37, 0);"
|
||||
>
|
||||
<input
|
||||
v-model="verificationCode"
|
||||
class="input-field"
|
||||
placeholder="请输入验证码"
|
||||
maxlength="6"
|
||||
style="color: var(--van-text-color);"
|
||||
@focus="codeFocused = true"
|
||||
@blur="codeFocused = false"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="ml-2 px-4 py-2 text-sm font-bold flex-shrink-0 rounded-lg transition duration-300"
|
||||
:class="
|
||||
isCountingDown || !isPhoneNumberValid
|
||||
? 'cursor-not-allowed bg-gray-300 text-gray-500'
|
||||
: 'text-white hover:opacity-90'
|
||||
"
|
||||
:style="isCountingDown || !isPhoneNumberValid
|
||||
? ''
|
||||
: 'background-color: var(--van-theme-primary);'"
|
||||
@click="sendVerificationCode"
|
||||
>
|
||||
{{
|
||||
isCountingDown
|
||||
? `${countdown}s重新获取`
|
||||
: "获取验证码"
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 协议同意框 -->
|
||||
<div class="flex items-start space-x-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="isAgreed"
|
||||
class="mt-1"
|
||||
/>
|
||||
<span class="text-xs leading-tight" style="color: var(--van-text-color-2);">
|
||||
我已阅读并同意
|
||||
<a
|
||||
class="cursor-pointer hover:underline"
|
||||
style="color: var(--van-theme-primary);"
|
||||
@click="toUserAgreement"
|
||||
>《用户协议》</a
|
||||
>
|
||||
和
|
||||
<a
|
||||
class="cursor-pointer hover:underline"
|
||||
style="color: var(--van-theme-primary);"
|
||||
@click="toPrivacyPolicy"
|
||||
>《隐私政策》</a
|
||||
>
|
||||
,并确认以上信息真实有效,将用于提现等资金操作
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="mb-12 mt-10 w-full py-3 text-lg font-bold text-white rounded-full transition duration-300"
|
||||
:class="{ 'opacity-50 cursor-not-allowed': !canSubmit }"
|
||||
:style="canSubmit ? 'background-color: var(--van-theme-primary);' : 'background-color: var(--van-text-color-3);'"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
确认认证
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.title-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--van-border-color);
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
border-radius: 1rem;
|
||||
transition: duration-200;
|
||||
}
|
||||
|
||||
.input-container.focused {
|
||||
border: 2px solid var(--van-theme-primary) !important;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
</style>
|
||||
140
src/components/ShareReportButton.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { showToast, showDialog } from "vant";
|
||||
|
||||
const props = defineProps({
|
||||
orderId: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
orderNo: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
isExample: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const isLoading = ref(false);
|
||||
|
||||
const copyToClipboard = async (text) => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
showToast({
|
||||
type: "success",
|
||||
message: "链接已复制到剪贴板",
|
||||
position: "bottom",
|
||||
});
|
||||
};
|
||||
|
||||
const handleShare = async () => {
|
||||
if (isLoading.value) return;
|
||||
|
||||
// 如果是示例模式,直接分享当前URL
|
||||
if (props.isExample) {
|
||||
try {
|
||||
const currentUrl = window.location.href;
|
||||
await copyToClipboard(currentUrl);
|
||||
showToast({
|
||||
type: "success",
|
||||
message: "示例链接已复制到剪贴板",
|
||||
position: "bottom",
|
||||
});
|
||||
} catch (err) {
|
||||
showToast({
|
||||
type: "fail",
|
||||
message: "复制链接失败",
|
||||
position: "bottom",
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 优先使用 orderId,如果没有则使用 orderNo
|
||||
const orderIdentifier = props.orderId || props.orderNo;
|
||||
if (!orderIdentifier) {
|
||||
showToast({
|
||||
type: "fail",
|
||||
message: "缺少订单标识",
|
||||
position: "bottom",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
// 根据实际使用的标识构建请求参数
|
||||
const requestData = props.orderId
|
||||
? { order_id: parseInt(props.orderId) }
|
||||
: { order_no: props.orderNo };
|
||||
|
||||
const { data, error } = await useApiFetch("/query/generate_share_link")
|
||||
.post(requestData)
|
||||
.json();
|
||||
|
||||
if (error.value) {
|
||||
throw new Error(error.value);
|
||||
}
|
||||
|
||||
if (data.value?.code === 200 && data.value.data?.share_link) {
|
||||
const baseUrl = window.location.origin;
|
||||
const linkId = encodeURIComponent(data.value.data.share_link);
|
||||
const fullShareUrl = `${baseUrl}/report/share/${linkId}`;
|
||||
|
||||
try {
|
||||
// 显示确认对话框
|
||||
await showDialog({
|
||||
title: "分享链接已生成",
|
||||
message: "链接将在7天后过期,是否复制到剪贴板?",
|
||||
confirmButtonText: "复制链接",
|
||||
cancelButtonText: "取消",
|
||||
showCancelButton: true,
|
||||
});
|
||||
|
||||
// 用户点击确认后复制链接
|
||||
await copyToClipboard(fullShareUrl);
|
||||
} catch (dialogErr) {
|
||||
// 用户点击取消按钮时,dialogErr 会是 'cancel'
|
||||
// 这里不需要显示错误提示,直接返回即可
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
throw new Error(data.value?.message || "生成分享链接失败");
|
||||
}
|
||||
} catch (err) {
|
||||
showToast({
|
||||
type: "fail",
|
||||
message: err.message || "生成分享链接失败",
|
||||
position: "bottom",
|
||||
});
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-4 flex flex-col items-center gap-2">
|
||||
<van-button
|
||||
type="primary"
|
||||
size="small"
|
||||
class="!bg-blue-500 !border-blue-500"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
@click="handleShare"
|
||||
>
|
||||
<template #icon>
|
||||
<van-icon name="share-o" />
|
||||
</template>
|
||||
{{ isLoading ? "生成中..." : (isExample ? "分享示例" : "分享报告") }}
|
||||
</van-button>
|
||||
<div class="text-xs text-gray-500">{{ isExample ? "分享当前示例链接" : "分享链接将在7天后过期" }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-button) {
|
||||
min-width: 120px;
|
||||
}
|
||||
</style>
|
||||
18
src/components/VipBanner.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="mb-4" @click="toAgentVip">
|
||||
<img
|
||||
src="@/assets/images/vip_banner.png"
|
||||
class="rounded-xl shadow-lg"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const router = useRouter();
|
||||
const toAgentVip = () => {
|
||||
router.push({ name: "agentVipApply" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||