Compare commits
2 Commits
0bf9d95075
...
f37e0dd927
Author | SHA1 | Date | |
---|---|---|---|
f37e0dd927 | |||
d7d10f55bc |
11
index.html
@ -4,9 +4,14 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>全能查-专业防风险</title>
|
||||
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<title>全能查 - 婚恋评估、司法涉诉查询、婚姻状态、判决书查询工具</title>
|
||||
<meta name="description"
|
||||
content="全能查提供婚恋评估报告、司法涉诉查询、婚姻状态查询、判决书查询、失信人、个人涉诉、企业涉诉、车辆核验等多项服务,帮助您查询婚姻信息、名下车辆、涉诉风险等,提供全面的法律与金融风险防范工具。" />
|
||||
<meta name="keywords"
|
||||
content="婚恋评估, 司法涉诉查询, 判决书查询, 婚姻状态查询, 失信人, 个人涉诉查询, 企业涉诉查询, 名下车辆核验, 车辆核验, 婚姻报告, 法律风险, 信用风险, 银行卡黑名单, 手机身份证核验, 学历核验, AI律师" />
|
||||
<meta name="author" content="全能查" />
|
||||
<meta name="baidu-site-verification" content="4d551d55896a88badef8dcdb14cf874c" />
|
||||
<style>
|
||||
#app-loading {
|
||||
position: fixed;
|
||||
|
35
src/App.vue
@ -1,10 +1,43 @@
|
||||
<script setup>
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
import WechatOverlay from './components/WechatOverlay.vue';
|
||||
onMounted(() => {
|
||||
RefreshToken()
|
||||
})
|
||||
const RefreshToken = async () => {
|
||||
const token = localStorage.getItem("token")
|
||||
const refreshAfter = localStorage.getItem("refreshAfter")
|
||||
const currentTime = new Date().getTime();
|
||||
|
||||
// 1. 如果没有 token,直接返回
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 如果有 refreshAfter,检查当前时间是否超过 refreshAfter(refreshAfter 是秒级,需要转换为毫秒级)
|
||||
if (refreshAfter) {
|
||||
const refreshAfterInMilliseconds = parseInt(refreshAfter) * 1000; // 转换为毫秒级
|
||||
if (currentTime < refreshAfterInMilliseconds) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 如果没有 refreshAfter 或者时间超过 refreshAfter,执行刷新 token 的请求
|
||||
const { data, error } = await useApiFetch("/user/getToken")
|
||||
.post()
|
||||
.json();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value !== 200) {
|
||||
localStorage.setItem("token", data.value.data.accessToken);
|
||||
localStorage.setItem("refreshAfter", data.value.data.refreshAfter);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<WechatOverlay />
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
|
@ -5,8 +5,12 @@
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
html {
|
||||
margin: auto !important;
|
||||
@apply max-w-lg;
|
||||
}
|
||||
body {
|
||||
background-color: #f8f8f8;
|
||||
min-height: 100vh;
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
|
BIN
src/assets/images/ai_picture.webp
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
src/assets/images/banner.png
Normal file
After Width: | Height: | Size: 131 KiB |
BIN
src/assets/images/baogao-icon.png
Normal file
After Width: | Height: | Size: 20 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/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 |
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: 11 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_5.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
src/assets/images/index_icon_6.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
src/assets/images/index_icon_7.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src/assets/images/liu.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
src/assets/images/llqdk.jpg
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
src/assets/images/login_bg.png
Normal file
After Width: | Height: | Size: 507 KiB |
BIN
src/assets/images/logo copy.png
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
src/assets/images/logo.png
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
src/assets/images/logo_title.png
Normal file
After Width: | Height: | Size: 16 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/public_security_record_icon.png
Normal file
After Width: | Height: | Size: 11 KiB |
@ -24,3 +24,6 @@ a,
|
||||
.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;
|
||||
}
|
||||
|
1
src/assets/uni-webview.js
Normal file
2
src/auto-imports.d.ts
vendored
@ -7,6 +7,8 @@
|
||||
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']
|
||||
|
@ -64,7 +64,7 @@
|
||||
本人有权随时撤回本授权书中的授权,但撤回前的授权行为及其法律后果仍具有法律效力。若需撤回授权,本人可通过贵司官方渠道提交书面申请,贵司将在收到申请后依法停止对本人数据的使用。
|
||||
</li>
|
||||
<li>
|
||||
你通过“全能查”APP或推广方推广查询模式,自愿支付相应费用,用于购买海南省学宇思网络科技有限公司的大数据报告产品。如若对产品内容存在异议,可通过邮箱admin@iieeii.com或APP“联系客服”按钮进行反馈,贵司将在收到异议之日起20日内进行核查和处理,并将结果答复。
|
||||
你通过“全能查”,自愿支付相应费用,用于购买海南省学宇思网络科技有限公司的大数据报告产品。如若对产品内容存在异议,可通过邮箱admin@iieeii.com或APP“联系客服”按钮进行反馈,贵司将在收到异议之日起20日内进行核查和处理,并将结果答复。
|
||||
</li>
|
||||
<li>
|
||||
你向海南省学宇思网络科技有限公司的支付方式为:海南省学宇思网络科技有限公司及其经官方授权的相关企业的支付宝账户。
|
||||
@ -86,7 +86,7 @@
|
||||
<p class="mt-4 font-bold">
|
||||
签署人:<span class="underline">{{
|
||||
signature ? props.name : "____________"
|
||||
}}</span>
|
||||
}}</span>
|
||||
<br />
|
||||
手机号码:<span class="underline">
|
||||
{{ signature ? props.mobile : "____________" }}
|
||||
|
333
src/components/CarNumberInput.vue
Normal file
@ -24,12 +24,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 导入 Vue 3 的响应式和路由方法
|
||||
const route = useRoute();
|
||||
|
||||
|
||||
// 返回上一页逻辑
|
||||
function goBack() {
|
||||
unionuni.navigateBack({ delta: 1 })
|
||||
route.goBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
71
src/components/LPendding.vue
Normal file
@ -0,0 +1,71 @@
|
||||
<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 bg-blue-500 rounded-lg hover:bg-blue-600 transition duration-300 ease-in-out">
|
||||
刷新页面
|
||||
</button>
|
||||
<!-- 历史报告按钮 -->
|
||||
<button @click="viewHistory"
|
||||
class="px-6 py-2 text-white bg-gray-500 rounded-lg hover:bg-gray-600 transition duration-300 ease-in-out">
|
||||
查看历史报告
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const router = useRouter();
|
||||
|
||||
// 刷新页面逻辑
|
||||
function refreshPage() {
|
||||
location.reload(); // 浏览器刷新页面
|
||||
}
|
||||
|
||||
// 查看历史报告逻辑
|
||||
function viewHistory() {
|
||||
router.push({ 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>
|
@ -45,7 +45,8 @@ const lineClass = computed(() => {
|
||||
</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="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">
|
||||
@ -54,5 +55,4 @@ const lineClass = computed(() => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
@ -5,14 +5,27 @@
|
||||
<h3 class="text-lg font-bold">支付</h3>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<p class="text-base">{{ data.product_name }}</p>
|
||||
<p class="text-3xl text-red-500 font-bold">¥ {{ data.sell_price }}</p>
|
||||
<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="platform === 'h5'" title="支付宝支付" clickable @click="selectedPaymentMethod = 'alipay'">
|
||||
<van-cell title="支付宝支付" clickable @click="selectedPaymentMethod = 'alipay'">
|
||||
<template #icon>
|
||||
<van-icon size="24" name="alipay" color="#00A1E9" class="mr-2" />
|
||||
</template>
|
||||
@ -20,20 +33,11 @@
|
||||
<van-radio v-model="selectedPaymentMethod" name="alipay" />
|
||||
</template>
|
||||
</van-cell>
|
||||
<!-- 微信支付 -->
|
||||
<van-cell v-if="platform !== 'h5'" title="微信支付" clickable @click="selectedPaymentMethod = 'wechat'">
|
||||
<template #icon>
|
||||
<van-icon size="24" name="wechatpay" color="#1AAD19" class="mr-2" />
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<van-radio v-model="selectedPaymentMethod" name="wechat" />
|
||||
</template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</div>
|
||||
<!-- 确认按钮 -->
|
||||
<div class="">
|
||||
<van-button class="w-full" round type="primary" @click="payment">确认支付</van-button>
|
||||
<van-button class="w-full" round type="primary" @click="getPayment">确认支付</van-button>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
@ -53,13 +57,25 @@ const props = defineProps({
|
||||
const show = defineModel()
|
||||
const orderId = ref("")
|
||||
const selectedPaymentMethod = ref('alipay')
|
||||
const { platform } = useUni()
|
||||
function onConfirmPayment(data) {
|
||||
window.parent.postMessage({ type: "payment", data: data }, "*");
|
||||
show.value = false
|
||||
}
|
||||
const discountPrice = ref(false) // 是否应用折扣
|
||||
onMounted(() => {
|
||||
// let m = localStorage.getItem("m")
|
||||
// let hour = "12"
|
||||
// if (m === "shifenliangzai") {
|
||||
// hour = "00"
|
||||
// }
|
||||
// const currentDate = new Date()
|
||||
// const startDate = new Date(`2025-01-01T${hour}:00:00+08:00`) // 2025年1月1日中午12点
|
||||
// const endDate = new Date('2025-01-02T12:00:00+08:00') // 2025年1月2日中午12点
|
||||
// console.log(startDate, endDate)
|
||||
// if (currentDate >= startDate && currentDate <= endDate) {
|
||||
// discountPrice.value = true // 在折扣时间范围内,启用折扣
|
||||
// } else {
|
||||
// discountPrice.value = false // 否则不启用折扣
|
||||
// }
|
||||
})
|
||||
|
||||
async function payment() {
|
||||
async function getPayment() {
|
||||
const { data, error } = await useApiFetch('/pay/payment')
|
||||
.post({
|
||||
id: props.id,
|
||||
@ -69,9 +85,16 @@ async function payment() {
|
||||
|
||||
if (data.value && !error.value) {
|
||||
orderId.value = data.value.data.order_id
|
||||
onConfirmPayment(data.value.data.prepay_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();
|
||||
}
|
||||
show.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
72
src/components/WechatOverlay.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div v-if="isWeChat" class="wechat-overlay">
|
||||
<div class="wechat-content">
|
||||
<p class="wechat-message">
|
||||
点击右上角的<van-icon class="ml-2" name="weapp-nav" /><br />然后点击在浏览器中打开
|
||||
</p>
|
||||
<img src="@/assets/images/llqdk.jpg" alt="In WeChat" class="wechat-image" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
// 定义一个响应式变量,表示是否在微信环境
|
||||
const isWeChat = ref(false);
|
||||
|
||||
// 检查是否为微信环境
|
||||
const checkIfWeChat = () => {
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
isWeChat.value = /micromessenger/.test(userAgent);
|
||||
};
|
||||
|
||||
// 在组件挂载后检查环境
|
||||
onMounted(() => {
|
||||
checkIfWeChat();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 遮罩层样式 */
|
||||
.wechat-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 遮罩中的内容 */
|
||||
.wechat-content {
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 图片样式 */
|
||||
.wechat-image {
|
||||
/* position: absolute;
|
||||
bottom: 0;
|
||||
left: 0; */
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 提示信息的样式 */
|
||||
.wechat-message {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
/* 图标样式 */
|
||||
.icon-more-vert {
|
||||
font-size: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
</style>
|
@ -1,8 +1,7 @@
|
||||
// src/plugins/fetch.js
|
||||
import { createFetch } from '@vueuse/core'
|
||||
import router from '@/router' // 假设你使用 Vue Router
|
||||
const { getCurrentPlatform, platform } = useUni() // 获取平台信息(如 "app", "h5" 等)
|
||||
getCurrentPlatform()
|
||||
|
||||
// 创建全局的 fetch 实例
|
||||
const useApiFetch = createFetch({
|
||||
baseUrl: '/api/v1', // 你的 API 基础路径
|
||||
@ -18,12 +17,13 @@ const useApiFetch = createFetch({
|
||||
// 获取平台信息
|
||||
|
||||
const brand = "qnc"; // 固定的品牌信息
|
||||
|
||||
// 在请求前添加通用的 Header,例如 Authorization
|
||||
const token = localStorage.getItem('token')
|
||||
if (token) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
'X-Platform': platform.value, // 添加平台信息
|
||||
'X-Platform': 'h5', // 添加平台信息
|
||||
'X-Brand': brand, // 添加品牌信息
|
||||
Authorization: `${token}`,
|
||||
}
|
||||
@ -38,10 +38,7 @@ const useApiFetch = createFetch({
|
||||
localStorage.removeItem('token')
|
||||
|
||||
// 跳转到登录页
|
||||
router.push('/login')
|
||||
uni.redirectTo({
|
||||
url: '/pages/login',
|
||||
})
|
||||
router.replace('/login')
|
||||
}
|
||||
|
||||
if (data.code !== 200) {
|
||||
@ -52,19 +49,19 @@ const useApiFetch = createFetch({
|
||||
return { data, response }
|
||||
},
|
||||
async onFetchError({ error, response }) {
|
||||
console.log("error", error)
|
||||
closeToast();
|
||||
if (response.status === 401) {
|
||||
// 清除本地存储的 token
|
||||
localStorage.removeItem('token')
|
||||
|
||||
// 跳转到登录页
|
||||
router.push('/login')
|
||||
uni.redirectTo({
|
||||
url: '/pages/login',
|
||||
})
|
||||
router.replace('/login')
|
||||
} else {
|
||||
if (typeof error === 'string') {
|
||||
showToast({ message: error });
|
||||
}
|
||||
}
|
||||
// 全局错误处理
|
||||
showToast({ message: error });
|
||||
return { error }
|
||||
},
|
||||
},
|
||||
|
@ -1,49 +0,0 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
export function useUni() {
|
||||
const platform = ref('') // 存储当前的平台
|
||||
|
||||
// 判断是否在微信浏览器中
|
||||
const checkWeixinBrowser = () => {
|
||||
return /MicroMessenger/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
// 获取当前平台并判断环境
|
||||
const getCurrentPlatform = async () => {
|
||||
try {
|
||||
uni.getEnv(env => {
|
||||
if (env.h5) {
|
||||
// 如果是 H5 环境,检查是否在微信浏览器中
|
||||
if (checkWeixinBrowser()) {
|
||||
platform.value = 'h5-weixin'
|
||||
} else {
|
||||
platform.value = 'h5' // 当前是 Web 平台
|
||||
}
|
||||
} else if (env['mp-weixin']) {
|
||||
platform.value = 'mp-weixin' // 当前是 微信小程序平台
|
||||
} else if (env.app) {
|
||||
platform.value = 'app' // 当前是 App 平台
|
||||
} else if (env['mp-qq']) {
|
||||
platform.value = 'mp-qq' // 当前是 QQ 小程序平台
|
||||
} else if (env['mp-alipay']) {
|
||||
platform.value = 'mp-alipay' // 当前是 支付宝小程序平台
|
||||
} else {
|
||||
platform.value = 'unknown' // 未知平台
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('获取平台信息失败:', error)
|
||||
platform.value = 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
// 在组件挂载时执行环境判断
|
||||
onMounted(() => {
|
||||
getCurrentPlatform()
|
||||
})
|
||||
|
||||
return {
|
||||
platform,
|
||||
getCurrentPlatform,
|
||||
}
|
||||
}
|
@ -1,22 +1,16 @@
|
||||
import { ref, onMounted } from "vue";
|
||||
import "@/assets/uni-webview"
|
||||
|
||||
export function useWebView() {
|
||||
const platform = ref("");
|
||||
const token = ref("");
|
||||
|
||||
// 检测环境并通知父窗口加载完毕
|
||||
const handleBridgeReady = (platformName) => {
|
||||
console.log("handleBridgeReady", platformName)
|
||||
if (platformName.h5) {
|
||||
window.parent.postMessage({ loaded: true }, "*");
|
||||
const handleBridgeReady = () => {
|
||||
if (platform.value) {
|
||||
h5PostMessage("loaded", true);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaymentMessage = () => {
|
||||
if (platformName.h5) {
|
||||
window.parent.postMessage({ loaded: true }, "*");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取 Token(从 URL 中解析)
|
||||
const getTokenFromUrl = () => {
|
||||
@ -29,14 +23,92 @@ export function useWebView() {
|
||||
return tokenFromUrl;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
console.log(" /MicroMessenger/i.test(navigator.userAgent)", /MicroMessenger/i.test(navigator.userAgent))
|
||||
// 检测平台环境
|
||||
uni.getEnv((env) => {
|
||||
platform.value = env;
|
||||
handleBridgeReady(platform.value);
|
||||
});
|
||||
// 封装 postMessage 方法
|
||||
const postMessage = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
h5PostMessage("postMessage", data);
|
||||
} else if (uni && uni.webView.postMessage) {
|
||||
uni.webView.postMessage(data);
|
||||
} else {
|
||||
console.error("uni.webView.postMessage is not available.");
|
||||
}
|
||||
};
|
||||
|
||||
const redirectTo = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
h5PostMessage("redirectTo", data)
|
||||
} else if (uni && uni.webView.redirectTo) {
|
||||
// 非 H5 环境,调用 uni.webView.redirectTo
|
||||
uni.webView.redirectTo(data);
|
||||
} else {
|
||||
console.error("uni.webView.redirectTo is not available.");
|
||||
}
|
||||
};
|
||||
|
||||
// 封装 navigateBack 方法
|
||||
const navigateBack = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
window.top.history.back();
|
||||
// h5PostMessage("navigateBack", data)
|
||||
} else if (uni && uni.webView.navigateBack) {
|
||||
// 非 H5 环境,调用 uni.webView.navigateBack
|
||||
uni.webView.navigateBack(data);
|
||||
} else {
|
||||
console.error("uni.webView.navigateBack is not available.");
|
||||
}
|
||||
};
|
||||
|
||||
// 封装 navigateTo 方法
|
||||
const navigateTo = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
// h5PostMessage("navigateTo", data)
|
||||
window.top.location.href = "/app" + data.url
|
||||
} else if (uni && uni.webView.navigateTo) {
|
||||
uni.webView.navigateTo(data);
|
||||
} else {
|
||||
console.error("uni.webView.navigateTo is not available.");
|
||||
}
|
||||
};
|
||||
const payment = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
h5PostMessage("payment", data)
|
||||
} else if (uni && uni.webView.navigateTo) {
|
||||
// 非 H5 环境,调用 uni.webView.navigateTo
|
||||
uni.webView.navigateTo(data);
|
||||
} else {
|
||||
console.error("uni.webView.navigateTo is not available.");
|
||||
}
|
||||
}
|
||||
const getEnv = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let env = localStorage.getItem(platform)
|
||||
if (env) {
|
||||
platform.value = env
|
||||
resolve(env);
|
||||
} else {
|
||||
uni.webView.getEnv((env) => {
|
||||
// 遍历 env 对象,找到值为 true 的键
|
||||
const platformKey = Object.keys(env).find(key => env[key] === true);
|
||||
platform.value = platformKey;
|
||||
if (platformKey) {
|
||||
resolve(platformKey); // 返回键名(如 'h5', 'mp-weixin' 等)
|
||||
} else {
|
||||
reject('未知平台');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const envValue = await getEnv();
|
||||
console.log("当前环境", envValue)
|
||||
// 将返回的键名(如 'h5', 'mp-weixin')存储到 platform
|
||||
handleBridgeReady();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
// 获取 Token
|
||||
getTokenFromUrl();
|
||||
});
|
||||
@ -44,6 +116,15 @@ export function useWebView() {
|
||||
return {
|
||||
platform,
|
||||
token,
|
||||
handlePaymentMessage
|
||||
getEnv,
|
||||
redirectTo,
|
||||
postMessage,
|
||||
navigateTo,
|
||||
navigateBack,
|
||||
payment
|
||||
};
|
||||
}
|
||||
const h5PostMessage = (action, data) => {
|
||||
window.parent.postMessage({ action, data, messageId: generateUniqueId(action) }, "*");
|
||||
}
|
||||
const generateUniqueId = (action) => `msg_${action}_${new Date().getTime()}`;
|
||||
|
93
src/layouts/GlobalLayout.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<router-view />
|
||||
<van-popup v-model:show="showPopup" round @click-overlay="onClickOverlay">
|
||||
<div class="popup-content text-center p-8">
|
||||
<div v-html="currentNotify?.content"></div>
|
||||
<div class="flex justify-center">
|
||||
<van-button type="primary" @click="showPopup = false" class="w-24">关闭</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
// 响应式变量
|
||||
const showPopup = ref(false)
|
||||
const notify = ref([])
|
||||
const currentNotify = ref(null)
|
||||
|
||||
// 获取当前页面路径
|
||||
const route = useRoute()
|
||||
|
||||
// 获取通知数据
|
||||
onMounted(() => {
|
||||
getGlobalNotify()
|
||||
})
|
||||
|
||||
// 获取通知数据
|
||||
const getGlobalNotify = async () => {
|
||||
const { data, error } = await useApiFetch("/notification/list")
|
||||
.get()
|
||||
.json()
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value !== 200) {
|
||||
notify.value = data.value.data.notifications
|
||||
checkNotification() // 在获取数据后检查通知
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断当前时间是否在通知的时间范围内
|
||||
const isWithinTimeRange = (startTime, endTime) => {
|
||||
const now = new Date()
|
||||
|
||||
// 获取当前时间的小时和分钟
|
||||
const currentMinutes = now.getHours() * 60 + now.getMinutes()
|
||||
|
||||
// 将 startTime 和 endTime 转换为分钟数
|
||||
const startParts = startTime.split(':').map(Number)
|
||||
const endParts = endTime.split(':').map(Number)
|
||||
const startMinutes = startParts[0] * 60 + startParts[1]
|
||||
const endMinutes = endParts[0] * 60 + endParts[1]
|
||||
|
||||
// 如果 endTime 小于 startTime,表示跨越了午夜
|
||||
if (endMinutes < startMinutes) {
|
||||
// 判断当前时间是否在 [startTime, 23:59:59] 或 [00:00:00, endTime] 之间
|
||||
return currentMinutes >= startMinutes || currentMinutes < endMinutes
|
||||
}
|
||||
|
||||
// 普通情况,直接判断时间是否在范围内
|
||||
return currentMinutes >= startMinutes && currentMinutes <= endMinutes
|
||||
}
|
||||
// 检查通知并更新showPopup
|
||||
const checkNotification = () => {
|
||||
// 遍历通知数组,找到第一个符合条件的通知
|
||||
for (let notification of notify.value) {
|
||||
// 判断时间是否符合当前时间
|
||||
const isTimeValid = isWithinTimeRange(notification.startTime, notification.endTime)
|
||||
// 判断页面是否符合
|
||||
|
||||
if (isTimeValid && notification.notificationPage === route.path) {
|
||||
currentNotify.value = notification
|
||||
showPopup.value = true
|
||||
break // 只显示第一个符合的通知
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 监听路由变化
|
||||
watch(() => route.path, () => {
|
||||
checkNotification() // 每次路由变化时重新判断通知
|
||||
})
|
||||
|
||||
// 关闭弹窗
|
||||
const onClickOverlay = () => {
|
||||
showPopup.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
139
src/layouts/HomeLayout.vue
Normal file
@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<div class="home-layout min-h-screen flex flex-col">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<img class="logo" src="@/assets/images/logo.png" alt="Logo" />
|
||||
<div class="title">全能查</div>
|
||||
</div>
|
||||
|
||||
<!-- Content Area -->
|
||||
<div class="content flex flex-col flex-1">
|
||||
<router-view />
|
||||
</div>
|
||||
|
||||
<!-- Vant Tabbar -->
|
||||
|
||||
<van-tabbar v-model="tabbar" @change="tabChange">
|
||||
<van-tabbar-item v-for="(item, index) in menu" :key="index" :name="item.name" :icon="item.icon">{{
|
||||
item.title }} </van-tabbar-item>
|
||||
</van-tabbar>
|
||||
|
||||
<!-- Complaint Button -->
|
||||
<div @click="toComplaint" class="complaint-button">
|
||||
<!-- <i class="icon-warning"></i> -->
|
||||
<span>投诉</span>
|
||||
</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>琼公网安备46010002000443号</text>
|
||||
</div>
|
||||
<div>
|
||||
<a class="text-blue-500" href="https://beian.miit.gov.cn">
|
||||
琼ICP备2024038584号-2
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
海南省学宇思网络科技有限公司版权所有
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router'; // 引入 Vue Router
|
||||
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const tabbar = ref('index');
|
||||
const menu = reactive([
|
||||
{ title: '首页', icon: 'home-o', name: 'index' },
|
||||
{ title: 'AI律师', icon: 'chat-o', name: 'ai' },
|
||||
{ title: '我的', icon: 'user-o', name: 'me' },
|
||||
]);
|
||||
|
||||
// 根据当前路由设置 Tabbar 的高亮项
|
||||
onMounted(() => {
|
||||
const currentPage = route.name; // 获取当前路由的名称
|
||||
tabbar.value = currentPage;
|
||||
});
|
||||
|
||||
const onClickOverlay = () => { }
|
||||
// 跳转到相应页面
|
||||
const tabChange = (name) => {
|
||||
router.push({ name }); // 使用 Vue Router 进行跳转
|
||||
};
|
||||
|
||||
// 跳转到投诉页面
|
||||
const toComplaint = () => {
|
||||
router.push({ name: 'complaint' }); // 使用 Vue Router 进行跳转
|
||||
};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.home-layout {
|
||||
background: linear-gradient(to bottom, #cfe0fa, #f4f8ff);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
margin-right: 0.75rem;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content {
|
||||
/* min-height: calc(100vh - 3rem); */
|
||||
}
|
||||
|
||||
.complaint-button {
|
||||
position: fixed;
|
||||
bottom: 6rem;
|
||||
right: 1rem;
|
||||
background: linear-gradient(to bottom, #e24949, #e4827b);
|
||||
border-radius: 1.5rem;
|
||||
padding: 0.25rem 1rem;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.complaint-button i {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
/* margin-top: 24px; */
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
padding-bottom: 60px;
|
||||
background: #ffffff;
|
||||
}
|
||||
</style>
|
35
src/layouts/PageLayout.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<van-nav-bar fixed :border="false" placeholder :title="pageTitle" left-text="返回" left-arrow
|
||||
@click-left="onClickLeft" />
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const pageTitle = ref('') // 用来保存页面标题
|
||||
const onClickLeft = () => {
|
||||
if (route.name === 'report') {
|
||||
router.replace('/historyQuery')
|
||||
} else if (route.name === 'history') {
|
||||
router.replace('/')
|
||||
} else {
|
||||
router.back()
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
})
|
||||
// 监听路由变化并更新标题
|
||||
watch(
|
||||
() => route.meta.title,
|
||||
(newTitle) => {
|
||||
pageTitle.value = newTitle || '默认标题'
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -5,9 +5,7 @@ import { createPinia } from 'pinia'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import 'vant/lib/index.css';
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
|
||||
|
@ -1,74 +1,136 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import NProgress from 'nprogress';
|
||||
|
||||
import GlobalLayout from '@/layouts/GlobalLayout.vue';
|
||||
import HomeLayout from '@/layouts/HomeLayout.vue';
|
||||
import PageLayout from '@/layouts/PageLayout.vue';
|
||||
import index from '@/views/index.vue';
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: () => import('@/views/Home.vue'),
|
||||
component: GlobalLayout, // 使用 Layout 作为父组件
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: HomeLayout, // 使用 Layout 作为父组件
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'index',
|
||||
component: index,
|
||||
},
|
||||
{
|
||||
path: 'ai',
|
||||
name: 'ai',
|
||||
component: () => import('@/views/Ai.vue'),
|
||||
},
|
||||
{
|
||||
path: 'me',
|
||||
name: 'me',
|
||||
component: () => import('@/views/Me.vue'),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: PageLayout,
|
||||
children: [
|
||||
{
|
||||
path: '/historyQuery',
|
||||
name: 'history',
|
||||
component: () => import('@/views/HistoryQuery.vue'),
|
||||
meta: { title: '历史报告' },
|
||||
},
|
||||
{
|
||||
path: '/service',
|
||||
name: 'service',
|
||||
component: () => import('@/views/Service.vue'),
|
||||
meta: { title: '客服' },
|
||||
},
|
||||
{
|
||||
path: '/complaint',
|
||||
name: 'complaint',
|
||||
component: () => import('@/views/Complaint.vue'),
|
||||
meta: { title: '投诉' },
|
||||
},
|
||||
{
|
||||
path: '/report',
|
||||
name: 'report',
|
||||
component: () => import('@/views/Report.vue'),
|
||||
meta: { title: '报告结果' },
|
||||
},
|
||||
{
|
||||
path: '/example',
|
||||
name: 'example',
|
||||
component: () => import('@/views/Example.vue'),
|
||||
meta: { title: '示例报告' },
|
||||
},
|
||||
{
|
||||
path: '/authorization',
|
||||
name: 'authorization',
|
||||
component: () => import('@/views/Authorization.vue'),
|
||||
meta: { title: '授权书' },
|
||||
},
|
||||
{
|
||||
path: '/privacyPolicy',
|
||||
name: 'privacyPolicy',
|
||||
component: () => import('@/views/PrivacyPolicy.vue'),
|
||||
meta: { title: '隐私政策' },
|
||||
},
|
||||
{
|
||||
path: '/userAgreement',
|
||||
name: 'userAgreement',
|
||||
component: () => import('@/views/UserAgreement.vue'),
|
||||
meta: { title: '用户协议' },
|
||||
},
|
||||
{
|
||||
path: '/listMarriage',
|
||||
name: 'listMarriage',
|
||||
component: () => import('@/views/list_marriage.vue'),
|
||||
meta: { title: '婚姻查询' },
|
||||
},
|
||||
{
|
||||
path: '/listRisk',
|
||||
name: 'listRisk',
|
||||
component: () => import('@/views/list_risk.vue'),
|
||||
meta: { title: '风险查询' },
|
||||
},
|
||||
{
|
||||
path: '/listLawsuit',
|
||||
name: 'listLawsuit',
|
||||
component: () => import('@/views/list_lawsuit.vue'),
|
||||
meta: { title: '诉讼查询' },
|
||||
},
|
||||
{
|
||||
path: '/listVerify',
|
||||
name: 'listVerify',
|
||||
component: () => import('@/views/list_verify.vue'),
|
||||
meta: { title: '核验查询' },
|
||||
},
|
||||
{
|
||||
path: '/inquire/:feature',
|
||||
name: 'inquire',
|
||||
component: () => import('@/views/Inquire.vue'),
|
||||
meta: { title: '查询报告' },
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/service',
|
||||
name: 'service',
|
||||
component: () => import('@/views/Service.vue'),
|
||||
},
|
||||
{
|
||||
path: '/complaint',
|
||||
name: 'complaint',
|
||||
component: () => import('@/views/Complaint.vue'),
|
||||
},
|
||||
{
|
||||
path: '/report',
|
||||
name: 'report',
|
||||
component: () => import('@/views/Report.vue'),
|
||||
},
|
||||
{
|
||||
path: '/example',
|
||||
name: 'example',
|
||||
component: () => import('@/views/Example.vue'),
|
||||
},
|
||||
{
|
||||
path: '/authorization',
|
||||
name: 'authorization',
|
||||
component: () => import('@/views/Authorization.vue'),
|
||||
},
|
||||
{
|
||||
path: '/privacyPolicy',
|
||||
name: 'privacyPolicy',
|
||||
component: () => import('@/views/PrivacyPolicy.vue'),
|
||||
},
|
||||
{
|
||||
path: '/userAgreement',
|
||||
name: 'userAgreement',
|
||||
component: () => import('@/views/UserAgreement.vue'),
|
||||
},
|
||||
{
|
||||
path: '/listMarriage',
|
||||
name: 'listMarriage',
|
||||
component: () => import('@/views/list_marriage.vue'),
|
||||
},
|
||||
{
|
||||
path: '/listRisk',
|
||||
name: 'listRisk',
|
||||
component: () => import('@/views/list_risk.vue'),
|
||||
},
|
||||
{
|
||||
path: '/listLawsuit',
|
||||
name: 'listLawsuit',
|
||||
component: () => import('@/views/list_lawsuit.vue'),
|
||||
},
|
||||
{
|
||||
path: '/listVerify',
|
||||
name: 'listVerify',
|
||||
component: () => import('@/views/list_verify.vue'),
|
||||
},
|
||||
{
|
||||
path: '/inquire/:feature',
|
||||
name: 'inquire',
|
||||
component: () => import('@/views/Inquire.vue'),
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('@/views/Login.vue'),
|
||||
},
|
||||
// {
|
||||
// path: '/home',
|
||||
// name: 'home',
|
||||
// component: () => import('@/views/Home.vue'),
|
||||
// },
|
||||
|
||||
|
||||
{
|
||||
path: "/:pathMatch(.*)*",
|
||||
name: "NotFound",
|
||||
|
@ -16,22 +16,23 @@ const riskLevel = ref("");
|
||||
const riskLevelText = ref("");
|
||||
const riskLevelClass = ref("");
|
||||
const riskInfoList = ref([
|
||||
{ level: "低风险", description: "涉稳、寻衅滋事", class: "span-lime-600" },
|
||||
{
|
||||
level: "无风险",
|
||||
description: "无任何不良风险记录",
|
||||
class: "text-green-600",
|
||||
},
|
||||
{ level: "低风险", description: "涉稳、寻衅滋事", class: "text-yellow-500" },
|
||||
{
|
||||
level: "中风险",
|
||||
description: "吸毒、涉毒、犯罪前科",
|
||||
class: "text-orange-400",
|
||||
class: "text-orange-500",
|
||||
},
|
||||
{
|
||||
level: "高风险",
|
||||
description: "涉案人员、在逃、犯罪嫌疑人",
|
||||
class: "text-red-500",
|
||||
},
|
||||
{
|
||||
level: "无风险",
|
||||
description: "无任何不良风险记录",
|
||||
class: "text-green-600",
|
||||
},
|
||||
|
||||
]);
|
||||
|
||||
// 根据风险等级动态设置图表配置
|
||||
@ -45,9 +46,17 @@ function getChartOption(level) {
|
||||
E: 90, // 高风险
|
||||
default: 0, // 未知风险
|
||||
};
|
||||
|
||||
const labelNameMap = {
|
||||
A: "无风险", // 无风险
|
||||
F: "低风险", // 低风险
|
||||
C: "中风险", // 中风险
|
||||
D: "中风险", // 中风险
|
||||
B: "高风险", // 高风险
|
||||
E: "高风险", // 高风险
|
||||
default: "未知风险", // 未知风险
|
||||
};
|
||||
const value = valueMap[level] || valueMap.default;
|
||||
|
||||
const labelName = labelNameMap[level] || valueMap.default;
|
||||
return {
|
||||
tooltip: {
|
||||
formatter: "{a} <br/>{b} : {c}",
|
||||
@ -66,7 +75,7 @@ function getChartOption(level) {
|
||||
fontWeight: "bold",
|
||||
color: "#333",
|
||||
},
|
||||
data: [{ value, name: "风险等级" }],
|
||||
data: [{ value, name: labelName }],
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 15,
|
||||
@ -74,40 +83,33 @@ function getChartOption(level) {
|
||||
shadowColor: "rgba(0, 0, 0, 0.3)", // 阴影颜色
|
||||
color: [
|
||||
[
|
||||
0.2,
|
||||
0.25,
|
||||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: "#10B981" },
|
||||
{ offset: 1, color: "#34D399" },
|
||||
]),
|
||||
], // 无风险渐变
|
||||
[
|
||||
0.4,
|
||||
0.5,
|
||||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: "#A3E635" },
|
||||
{ offset: 1, color: "#D9F99D" },
|
||||
{ offset: 0, color: "#FFC300" },
|
||||
{ offset: 1, color: "#EAB308" },
|
||||
]),
|
||||
], // 低风险渐变
|
||||
[
|
||||
0.6,
|
||||
0.75,
|
||||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: "#F97316" },
|
||||
{ offset: 1, color: "#FDBA74" },
|
||||
{ offset: 1, color: "#E68416" },
|
||||
]),
|
||||
], // 中风险渐变
|
||||
[
|
||||
0.8,
|
||||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: "#EF4444" },
|
||||
{ offset: 1, color: "#FCA5A5" },
|
||||
]),
|
||||
], // 高风险渐变
|
||||
[
|
||||
1,
|
||||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: "#9CA3AF" },
|
||||
{ offset: 1, color: "#E5E7EB" },
|
||||
{ offset: 0, color: "#EF4444" },
|
||||
{ offset: 1, color: "#FF6347" },
|
||||
]),
|
||||
], // 未知风险渐变
|
||||
], // 高风险渐变
|
||||
],
|
||||
},
|
||||
},
|
||||
@ -125,7 +127,7 @@ function getChartOption(level) {
|
||||
},
|
||||
title: {
|
||||
offsetCenter: [0, "75%"], // 标题位置
|
||||
fontSize: 14,
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
detail: {
|
||||
|
38
src/ui/CCAR061.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<!-- 名下车辆信息展示 -->
|
||||
<div class="bg-yellow-100 text-yellow-700 p-4 rounded-lg">
|
||||
<h3 class="text-xl font-semibold">名下车辆</h3>
|
||||
<p class="text-sm">此人名下拥有车辆:{{ data?.carNum }} 辆</p>
|
||||
</div>
|
||||
|
||||
<!-- 校验对象展示 -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
// 接收父组件传入的 props
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
params: Object,
|
||||
});
|
||||
|
||||
// 脱敏函数:姓名脱敏(保留首位)
|
||||
const maskName = (name) => {
|
||||
if (!name) return '';
|
||||
return name.length > 1 ? name[0] + "*".repeat(name.length - 1) : "*";
|
||||
};
|
||||
|
||||
// 脱敏函数:身份证号脱敏(保留前6位和最后4位)
|
||||
const maskIdCard = (idCard) => {
|
||||
if (!idCard) return '';
|
||||
return idCard.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义样式 */
|
||||
</style>
|
81
src/ui/CDualMarriage.vue
Normal file
@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center card">
|
||||
<div class="max-w-md w-full p-4">
|
||||
<!-- 核验结果 -->
|
||||
<h3 class="text-xl font-semibold text-gray-700 mb-4">婚姻核验结果</h3>
|
||||
<div
|
||||
:class="['mb-6 p-2 rounded-3xl text-lg font-medium text-center text-white shadow-lg', getStatusClass(data.status)]">
|
||||
{{ getStatusText(data.status) }}
|
||||
</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
<p>{{ statusDescription(data.status) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
// 状态背景色和图标
|
||||
const getStatusClass = (status) => {
|
||||
const statusClassMapping = {
|
||||
"0": "bg-yellow-500",
|
||||
"1": "bg-green-600",
|
||||
"2": "bg-red-500",
|
||||
"3": "bg-blue-400",
|
||||
};
|
||||
return statusClassMapping[status] || "bg-gray-500";
|
||||
};
|
||||
|
||||
|
||||
// 核验状态描述
|
||||
const getStatusText = (status) => {
|
||||
const statusMapping = {
|
||||
"0": "无婚姻关系",
|
||||
"1": "已婚",
|
||||
"2": "已离婚",
|
||||
"3": "离婚冷静期",
|
||||
};
|
||||
return statusMapping[status] || "未知状态";
|
||||
};
|
||||
|
||||
const statusDescription = (status) => {
|
||||
const descriptionMapping = {
|
||||
"1": "双方是夫妻关系,目前处于已婚状态。",
|
||||
"2": "双方存在过婚姻关系,目前已离婚。",
|
||||
"3": "双方目前处于离婚冷静期。",
|
||||
"0": "双方不存在婚姻关系。",
|
||||
};
|
||||
return descriptionMapping[status] || "无详细描述。";
|
||||
};
|
||||
|
||||
// 对请求参数进行脱敏处理
|
||||
const maskValue = (value, type) => {
|
||||
if (type === "name") {
|
||||
// 姓名脱敏(保留首位)
|
||||
return value.length > 1 ? value[0] + "*".repeat(value.length - 1) : "*";
|
||||
} else if (type === "id_card") {
|
||||
// 身份证号脱敏(保留前6位和最后4位)
|
||||
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const maskedParams = {
|
||||
nameMan: maskValue(props.params.nameMan, "name"),
|
||||
idCardMan: maskValue(props.params.idCardMan, "id_card"),
|
||||
nameWoman: maskValue(props.params.nameWoman, "name"),
|
||||
idCardWoman: maskValue(props.params.idCardWoman, "id_card"),
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
49
src/ui/CFIN019.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div class="p-4 card space-y-4">
|
||||
<!-- 黑名单信息 -->
|
||||
<div class="">
|
||||
<!-- <LTitle title="银行卡黑名单" type="blue-green" class="mb-4"></LTitle> -->
|
||||
|
||||
<div class="space-y-4">
|
||||
<div v-for="(value, key) in data" :key="key" class="flex justify-between items-center">
|
||||
<div class="font-medium">{{ labelMap[key] }}</div>
|
||||
<div
|
||||
:class="['text-white rounded-lg font-bold py-1 px-2', { 'bg-red-500': value === '1', 'bg-green-500': value === '0' }]">
|
||||
{{ value === '0' ? '未存在' : '被列入该黑名单' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from 'vue'
|
||||
|
||||
// 接收 props
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
})
|
||||
// 映射黑名单标签
|
||||
const labelMap = {
|
||||
onlineBlack: "线上卡号黑名单",
|
||||
offlineBlack: "线下卡号黑名单",
|
||||
badCardHolder: "不良持卡人名单",
|
||||
fraudTrans: "交易欺诈名单",
|
||||
otherBlack: "其他卡号黑名单",
|
||||
caseRelated: "涉案卡片"
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 添加需要的样式 */
|
||||
</style>
|
65
src/ui/CG02BJ02.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<!-- 手机在网时长状态展示 -->
|
||||
<div class=" bg-blue-100 text-blue-700 p-4 rounded-lg ">
|
||||
<h3 class="text-xl font-semibold">手机在网时长</h3>
|
||||
<p class="text-lg font-medium">{{ getTimeDuration(data?.code) }}</p>
|
||||
<p class="text-sm mt-2">运营商:{{ getPhoneType(data?.phoneType) }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 手机号码展示 -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
// 接收父组件传入的 props
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
params: Object,
|
||||
});
|
||||
|
||||
// 脱敏函数:手机号码脱敏(保留前三位和后四位)
|
||||
const maskMobile = (mobile) => {
|
||||
if (!mobile) return '';
|
||||
return mobile.replace(/^(\d{3})(?:\d+)(\d{4})$/, "$1****$2");
|
||||
};
|
||||
|
||||
// 根据 code 获取手机在网时长描述
|
||||
const getTimeDuration = (code) => {
|
||||
switch (code) {
|
||||
case 1006:
|
||||
return "0 - 3 个月";
|
||||
case 1007:
|
||||
return "3 - 6 个月";
|
||||
case 1008:
|
||||
return "6 - 12 个月";
|
||||
case 1009:
|
||||
return "12 - 24 个月";
|
||||
case 1010:
|
||||
return "24 个月以上";
|
||||
default:
|
||||
return "未知时长";
|
||||
}
|
||||
};
|
||||
|
||||
// 根据 phoneType 获取运营商名称
|
||||
const getPhoneType = (phoneType) => {
|
||||
switch (phoneType) {
|
||||
case "CMCC":
|
||||
return "中国移动";
|
||||
case "CUCC":
|
||||
return "中国联通";
|
||||
case "CTCC":
|
||||
return "中国电信";
|
||||
default:
|
||||
return "未知运营商";
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义样式 */
|
||||
</style>
|
50
src/ui/CG03HZ01.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<!-- 手机号码展示 -->
|
||||
<!-- 风险等级展示 -->
|
||||
<div v-if="data?.filterType === '0'" class="bg-green-100 text-green-700 p-4 rounded-lg">
|
||||
<h3 class="text-xl font-semibold">安全号码</h3>
|
||||
<p class="text-sm">该手机号码为安全号码,没有发现任何风险。</p>
|
||||
</div>
|
||||
|
||||
<div v-if="data?.filterType === '1'" class="bg-red-100 text-red-700 p-4 rounded-lg">
|
||||
<h3 class="text-xl font-semibold">高危</h3>
|
||||
<p class="text-sm">该手机号码存在较高风险,请谨慎处理。</p>
|
||||
</div>
|
||||
|
||||
<div v-if="data?.filterType === '2'" class="bg-yellow-100 text-yellow-700 p-4 rounded-lg">
|
||||
<h3 class="text-xl font-semibold">中危</h3>
|
||||
<p class="text-sm">该手机号码存在一定风险,请留意相关信息。</p>
|
||||
</div>
|
||||
|
||||
<div v-if="data?.filterType === '3'" class="bg-blue-100 text-blue-700 p-4 rounded-lg">
|
||||
<h3 class="text-xl font-semibold">低危</h3>
|
||||
<p class="text-sm">该手机号码风险较低,但仍需关注。</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
// 接收父组件传入的 props
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
});
|
||||
// 脱敏函数:手机号码脱敏(保留前三位和后四位)
|
||||
const maskMobile = (mobile) => {
|
||||
if (!mobile) return '';
|
||||
return mobile.replace(/^(\d{3})(?:\d+)(\d{4})$/, "$1****$2");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义样式 */
|
||||
</style>
|
60
src/ui/CG19BJ02.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<!-- 手机号码展示 -->
|
||||
<div class="pb-4">
|
||||
<ul>
|
||||
<li class="flex justify-between py-2 border-b">
|
||||
<span class="font-medium">手机号码</span>
|
||||
<span>{{ maskMobile(params?.mobile) }}</span>
|
||||
</li>
|
||||
<li class="flex justify-between py-2 border-b">
|
||||
<span class="font-medium">业务日期</span>
|
||||
<span>{{ formatDate(params?.startDate) }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 二次卡状态展示 -->
|
||||
<div v-if="data?.code === 1026" class="bg-green-100 text-gray-700 p-4 rounded-lg mb-6">
|
||||
<h3 class="text-xl font-semibold">非二次卡</h3>
|
||||
<p class="text-sm">该手机号码不是二次卡,请注意核对。</p>
|
||||
</div>
|
||||
|
||||
<div v-if="data?.code === 1025" class="bg-red-500 text-white p-4 rounded-lg mb-6">
|
||||
<h3 class="text-xl font-semibold">二次卡</h3>
|
||||
<p class="text-sm">该手机号码是二次卡,请注意核对。</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
// 接收父组件传入的 props
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
params: Object,
|
||||
});
|
||||
props.data.code = 1025
|
||||
// 脱敏函数:手机号码脱敏(保留前三位和后四位)
|
||||
const maskMobile = (mobile) => {
|
||||
if (!mobile) return '';
|
||||
return mobile.replace(/^(\d{3})(?:\d+)(\d{4})$/, "$1****$2");
|
||||
};
|
||||
// 格式化日期函数:将日期格式化为 YYYY-MM-DD
|
||||
const formatDate = (dateString) => {
|
||||
if (!dateString) return '';
|
||||
// 确保输入是一个8位数字字符串,格式为 YYYYMMDD
|
||||
const year = dateString.slice(0, 4);
|
||||
const month = dateString.slice(4, 6);
|
||||
const day = dateString.slice(6, 8);
|
||||
|
||||
// 返回格式化后的日期
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义样式 */
|
||||
</style>
|
101
src/ui/CG20GZ01.vue
Normal file
@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<!-- 状态展示 -->
|
||||
<div :class="stateClass" class="text-center rounded-lg py-2">
|
||||
<h2 class="text-xl font-semibold mb-2">银行卡四要素校验</h2>
|
||||
<p class="text-sm">{{ stateMessage }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, computed } from 'vue'
|
||||
|
||||
// 接收 props 参数
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
})
|
||||
// 校验状态对应的消息和样式
|
||||
const stateMessage = computed(() => {
|
||||
const state = props.data.data.state
|
||||
switch (state) {
|
||||
case '1':
|
||||
return '验证一致';
|
||||
case '2':
|
||||
return '验证不一致';
|
||||
case '3':
|
||||
return '异常情况';
|
||||
default:
|
||||
return '未知状态';
|
||||
}
|
||||
})
|
||||
|
||||
const stateClass = computed(() => {
|
||||
const state = props.data.data.state
|
||||
switch (state) {
|
||||
case '1':
|
||||
return 'bg-green-100 text-green-600';
|
||||
case '2':
|
||||
return 'bg-red-100 text-red-600';
|
||||
case '3':
|
||||
return 'bg-yellow-100 text-yellow-600';
|
||||
default:
|
||||
return 'bg-gray-100 text-gray-600';
|
||||
}
|
||||
})
|
||||
// 脱敏函数,根据类型判断如何脱敏
|
||||
const maskValue = (value, type) => {
|
||||
if (!value) return ''; // 处理空值
|
||||
|
||||
if (type === "name") {
|
||||
// 姓名脱敏(保留首位)
|
||||
return value.length > 1 ? value[0] + "*".repeat(value.length - 1) : "*";
|
||||
} else if (type === "id_card") {
|
||||
// 身份证号脱敏(保留前6位和最后4位)
|
||||
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
|
||||
} else if (type === "mobile") {
|
||||
// 手机号脱敏(保留前三位和后四位)
|
||||
return value.replace(/^(\d{3})(?:\d+)(\d{4})$/, "$1****$2");
|
||||
} else if (type === "bank_card") {
|
||||
// 银行卡号脱敏(保留前四位和后四位)
|
||||
return value.replace(/^(\d{4})(?:\d+)(\d{4})$/, "$1 **** **** $2");
|
||||
}
|
||||
return value; // 如果没有匹配的类型,返回原值
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 使按钮和状态信息的显示更为美观 */
|
||||
.bg-green-100 {
|
||||
background-color: #d1fad6;
|
||||
}
|
||||
|
||||
.bg-red-100 {
|
||||
background-color: #fcd0d0;
|
||||
}
|
||||
|
||||
.bg-yellow-100 {
|
||||
background-color: #fdf2b8;
|
||||
}
|
||||
|
||||
.text-green-600 {
|
||||
color: #16a34a;
|
||||
}
|
||||
|
||||
.text-red-600 {
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.text-yellow-600 {
|
||||
color: #e4b200;
|
||||
}
|
||||
</style>
|
86
src/ui/CIDCardTwoElements.vue
Normal file
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center card">
|
||||
<div class="max-w-md w-full p-4">
|
||||
|
||||
<!-- 核验结果 -->
|
||||
<h3 class="text-xl font-semibold text-gray-700 mb-2">二要素验证结果</h3>
|
||||
<div v-if="data.result === 0" class="flex items-center space-x-4 mb-6">
|
||||
<div class="h-12 w-12 rounded-full flex flex-shrink-0 items-center justify-center bg-green-500">
|
||||
<span class="text-white text-lg font-bold">✔</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-lg font-medium text-gray-800">一致</p>
|
||||
<p class="text-sm text-gray-500">姓名和身份证号匹配成功。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex items-center space-x-4 mb-6">
|
||||
<div class="h-12 w-12 rounded-full flex items-center justify-center bg-red-500">
|
||||
<span class="text-white text-lg font-bold">✘</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-lg font-medium text-gray-800">不一致</p>
|
||||
<p class="text-sm text-gray-500">姓名和身份证号不匹配。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 核验详情 -->
|
||||
<!-- <h3 class="text-lg font-semibold text-gray-700 mb-2">附加信息</h3> -->
|
||||
<div class="text-sm text-gray-600 space-y-2 ">
|
||||
<p>
|
||||
<span class="font-medium text-gray-800">地址:</span>
|
||||
{{ data.address }}
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-medium text-gray-800">生日:</span>
|
||||
{{ formatBirthday(data.birthday) }}
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-medium text-gray-800">性别:</span>
|
||||
{{ data.sex }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 对生日进行格式化显示
|
||||
const formatBirthday = (birthday) => {
|
||||
if (!birthday) return "未知";
|
||||
const year = birthday.slice(0, 4);
|
||||
const month = birthday.slice(4, 6);
|
||||
const day = birthday.slice(6, 8);
|
||||
return `${year}年${month}月${day}日`;
|
||||
};
|
||||
|
||||
// 对请求参数进行脱敏处理
|
||||
const maskValue = (value, type) => {
|
||||
if (type === "name") {
|
||||
// 姓名脱敏(保留首位)
|
||||
return value.length > 1 ? value[0] + "*".repeat(value.length - 1) : "*";
|
||||
} else if (type === "id_card") {
|
||||
// 身份证号脱敏(保留前6位和最后4位)
|
||||
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const maskedParams = {
|
||||
name: maskValue(props.params.name, "name"),
|
||||
id_card: maskValue(props.params.id_card, "id_card"),
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@ -12,10 +12,10 @@ const { data } = props;
|
||||
// 状态映射,包括显示的文字和样式
|
||||
const statusMap = {
|
||||
0: {
|
||||
text: "未登记",
|
||||
text: "未婚或尚未登记结婚",
|
||||
bgClass: "bg-yellow-100",
|
||||
textClass: "text-yellow-700",
|
||||
description: "尚未登记婚姻信息",
|
||||
description: "未进行民政登记婚姻",
|
||||
},
|
||||
1: {
|
||||
text: "已婚",
|
||||
@ -42,34 +42,24 @@ const currentStatus =
|
||||
data.status !== undefined
|
||||
? statusMap[data.status] || statusMap["0"]
|
||||
: {
|
||||
text: "无相关记录",
|
||||
bgClass: "bg-gray-200",
|
||||
textClass: "text-gray-500",
|
||||
description: "暂无婚姻相关记录",
|
||||
};
|
||||
text: "无相关记录",
|
||||
bgClass: "bg-gray-200",
|
||||
textClass: "text-gray-500",
|
||||
description: "暂无婚姻相关记录",
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card">
|
||||
<div class="status-info mb-4 flex flex-col items-center">
|
||||
<div class="status-info flex flex-col items-center ">
|
||||
<div
|
||||
:class="`status-label rounded-full px-6 py-3 text-center font-bold shadow-md ${currentStatus.bgClass} ${currentStatus.textClass}`"
|
||||
>
|
||||
:class="`status-label rounded-full px-6 py-3 text-center font-bold shadow-md ${currentStatus.bgClass} ${currentStatus.textClass}`">
|
||||
{{ currentStatus.text }}
|
||||
</div>
|
||||
<p class="status-description mt-3 text-sm text-gray-600">
|
||||
{{ currentStatus.description }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- <div class="additional-info mt-6 text-center">
|
||||
<p class="text-xs text-gray-500">
|
||||
<strong>数据更新时间:</strong> {{ lastUpdated }}
|
||||
</p>
|
||||
<p class="text-xs text-gray-500">
|
||||
本数据仅供参考,如有疑问请联系相关部门。
|
||||
</p>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
222
src/ui/CP_C_B332.vue
Normal file
@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<div class="flex flex-col items-center card">
|
||||
<div class="max-w-4xl w-full space-y-6">
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<div>
|
||||
<LTitle title="基本信息" type="blue-green" class="mb-4"></LTitle>
|
||||
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">号牌种类:</span>
|
||||
<span>{{ plateTypeMapping[data.plateType] }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">核定载客数:</span>
|
||||
<span>{{ data.passengers }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">车牌号:</span>
|
||||
<span>{{ data.plate }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">车架号:</span>
|
||||
<span>{{ data.vin }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">使用性质:</span>
|
||||
<span>{{ data.properties }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">车辆类型:</span>
|
||||
<span>{{ data.vehicleType }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">品牌名称:</span>
|
||||
<span>{{ data.brandName }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">车身颜色:</span>
|
||||
<span>{{ filterDataNull(bodyColorMapping[data.bodyColor]) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 一致性核验 -->
|
||||
<div>
|
||||
<LTitle title="一致性核验" type="blue-green" class="mb-4"></LTitle>
|
||||
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">车牌种类一致性:</span>
|
||||
<span>{{ data.carType }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">车牌号一致性:</span>
|
||||
<span>{{ data.carNumber }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">姓名一致性:</span>
|
||||
<span>{{ data.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 发动机信息 -->
|
||||
<div>
|
||||
<LTitle title="发动机信息" type="blue-green" class="mb-4"></LTitle>
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">发动机型号:</span>
|
||||
<span>{{ data.engineModel }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">发动机号:</span>
|
||||
<span>{{ data.engineNumber }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">排量:</span>
|
||||
<span>{{ data.cc }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">燃料种类:</span>
|
||||
<span>{{ data.fuelType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 车辆状态 -->
|
||||
<div>
|
||||
<LTitle title="车辆状态" type="blue-green" class="mb-4"></LTitle>
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">机动车状态:</span>
|
||||
<span>{{ data.vehicleStatus }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">强制报废期止:</span>
|
||||
<span>{{ filterDataNull(data.retirementDate) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">检验有效期止:</span>
|
||||
<span>{{ filterDataNull(data.validityDayEnd) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">初次登记日期:</span>
|
||||
<span>{{ filterDataNull(data.firstIssueDate) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">年检日期:</span>
|
||||
<span>{{ filterDataNull(data.jianCheTime) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 尺寸及重量 -->
|
||||
<div>
|
||||
<LTitle title="车辆尺寸及重量" type="blue-green" class="mb-4"></LTitle>
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">总质量:</span>
|
||||
<span>{{ filterDataNull(data.crossWeight) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">整备质量:</span>
|
||||
<span>{{ filterDataNull(data.curbWeight) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">轴数:</span>
|
||||
<span>{{ filterDataNull(data.shaft) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">轴距:</span>
|
||||
<span>{{ filterDataNull(data.wheelBase) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">前轮距:</span>
|
||||
<span>{{ filterDataNull(data.frontTread) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-medium text-gray-800">后轮距:</span>
|
||||
<span>{{ filterDataNull(data.rearTread) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 号牌种类映射
|
||||
const plateTypeMapping = {
|
||||
"02": "小型汽车",
|
||||
"01": "大型汽车",
|
||||
"03": "使馆汽车",
|
||||
"04": "领馆汽车",
|
||||
"05": "境外汽车",
|
||||
"06": "外籍汽车",
|
||||
"07": "普通摩托车",
|
||||
"08": "轻便摩托车",
|
||||
"09": "使馆摩托车",
|
||||
"10": "领馆摩托车",
|
||||
"11": "境外摩托车",
|
||||
"12": "外籍摩托车",
|
||||
"13": "低速车",
|
||||
"14": "拖拉机",
|
||||
"15": "挂车",
|
||||
"16": "教练汽车",
|
||||
"17": "教练摩托车",
|
||||
"20": "临时入境汽车",
|
||||
"21": "临时入境摩托车",
|
||||
"22": "临时行驶车",
|
||||
"23": "警用汽车",
|
||||
"24": "警用摩托",
|
||||
"51": "新能源大型汽车",
|
||||
"52": "新能源小型汽车"
|
||||
};
|
||||
|
||||
// 车身颜色映射
|
||||
const bodyColorMapping = {
|
||||
"A": "白",
|
||||
"B": "灰",
|
||||
"C": "黄",
|
||||
"D": "粉",
|
||||
"E": "红",
|
||||
"F": "紫",
|
||||
"G": "绿",
|
||||
"H": "蓝",
|
||||
"I": "棕",
|
||||
"J": "黑",
|
||||
"K": "香槟",
|
||||
"L": "银",
|
||||
"M": "橙",
|
||||
"N": "金",
|
||||
"Z": "其他"
|
||||
};
|
||||
|
||||
// 对请求参数中的姓名进行脱敏
|
||||
const maskValue = (value, type) => {
|
||||
if (type === "name") {
|
||||
return value.length > 1 ? value[0] + "*".repeat(value.length - 1) : "*";
|
||||
} else if (type === "car_license") {
|
||||
return value.slice(0, 2) + "*".repeat(value.length - 2) + value.slice(-2);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
const filterDataNull = (data) => {
|
||||
return data ? data : '-'
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
89
src/ui/CPhoneThreeElements.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center card">
|
||||
<div class="max-w-md w-full p-2">
|
||||
<!-- 核验结果 -->
|
||||
<h3 class="text-xl font-semibold text-gray-700 mb-4">核验结果</h3>
|
||||
<div v-if="result" class="flex items-center space-x-4">
|
||||
<div
|
||||
:class="['h-12 w-12 rounded-full flex flex-shrink-0 items-center justify-center', result.statusClass]">
|
||||
<span class="text-white text-lg font-bold">{{ result.icon }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-lg font-medium text-gray-800">{{ result.message }}</p>
|
||||
<p class="text-sm text-gray-500">{{ result.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-center mb-6">
|
||||
<p class="text-gray-500">无效的核验代码</p>
|
||||
</div>
|
||||
|
||||
<!-- 三要素请求参数 -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
// 核验结果映射
|
||||
const codeMapping = {
|
||||
1000: {
|
||||
statusClass: "bg-green-500",
|
||||
icon: "✔",
|
||||
message: "一致",
|
||||
description: "姓名、证件号与手机号码信息完全匹配。",
|
||||
},
|
||||
1003: {
|
||||
statusClass: "bg-yellow-500",
|
||||
icon: "⚠",
|
||||
message: "不一致",
|
||||
description: "姓名、证件号与手机号码信息不一致。",
|
||||
},
|
||||
1004: {
|
||||
statusClass: "bg-red-500",
|
||||
icon: "✘",
|
||||
message: "姓名不正确",
|
||||
description: "请检查姓名输入是否正确。",
|
||||
},
|
||||
1005: {
|
||||
statusClass: "bg-red-500",
|
||||
icon: "✘",
|
||||
message: "证件号码不正确",
|
||||
description: "请检查证件号码输入是否正确。",
|
||||
},
|
||||
};
|
||||
|
||||
const result = codeMapping[props.data.code];
|
||||
|
||||
// 对请求参数进行脱敏处理
|
||||
const maskValue = (value, type) => {
|
||||
if (type === "name") {
|
||||
// 姓名脱敏(保留首位)
|
||||
return value.length > 1 ? value[0] + "*".repeat(value.length - 1) : "*";
|
||||
} else if (type === "id_card") {
|
||||
// 身份证号脱敏(保留前6位和最后4位)
|
||||
return value.replace(/^(.{6})(?:\d+)(.{4})$/, "$1****$2");
|
||||
} else if (type === "mobile") {
|
||||
// 手机号脱敏(保留前三位和后四位)
|
||||
return value.replace(/^(\d{3})(?:\d+)(\d{4})$/, "$1****$2");
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const maskedParams = {
|
||||
name: maskValue(props.params.name, "name"),
|
||||
id_card: maskValue(props.params.id_card, "id_card"),
|
||||
mobile: maskValue(props.params.mobile, "mobile"),
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
80
src/ui/CPhoneTwoElements.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center card">
|
||||
<div class="max-w-md w-full p-4">
|
||||
<!-- 请求参数 -->
|
||||
<!-- 核验结果 -->
|
||||
<h3 class="text-xl font-semibold text-gray-700 mb-4">手机二要素验证结果</h3>
|
||||
<div v-if="data.code === '1000'" class="flex items-center space-x-4 mb-6">
|
||||
<div class="h-12 w-12 rounded-full flex flex-shrink-0 items-center justify-center bg-green-500">
|
||||
<span class="text-white text-lg font-bold">✔</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-lg font-medium text-gray-800">一致</p>
|
||||
<p class="text-sm text-gray-500">姓名和手机号匹配成功。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex items-center space-x-4 mb-6">
|
||||
<div class="h-12 w-12 rounded-full flex items-center flex-shrink-0 justify-center bg-red-500">
|
||||
<span class="text-white text-lg font-bold">✘</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-lg font-medium text-gray-800">不一致</p>
|
||||
<p class="text-sm text-gray-500">手机二要素验证失败,请检查输入信息。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 核验详情 -->
|
||||
<h3 class="text-lg font-semibold text-gray-700 mb-2">附加信息</h3>
|
||||
<div class="text-sm text-gray-600 space-y-2">
|
||||
<p>
|
||||
<span class="font-medium text-gray-800">运营商类型:</span>
|
||||
{{ getPhoneType(data.data.phoneType) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 手机号类型映射
|
||||
const getPhoneType = (type) => {
|
||||
const phoneTypeMapping = {
|
||||
CMCC: "中国移动",
|
||||
CUCC: "中国联通",
|
||||
CTCC: "中国电信",
|
||||
};
|
||||
return phoneTypeMapping[type] || "未知类型";
|
||||
};
|
||||
|
||||
// 对请求参数进行脱敏处理
|
||||
const maskValue = (value, type) => {
|
||||
if (type === "name") {
|
||||
// 姓名脱敏(保留首位)
|
||||
return value.length > 1 ? value[0] + "*".repeat(value.length - 1) : "*";
|
||||
} else if (type === "mobile") {
|
||||
// 手机号脱敏(保留前三位和后四位)
|
||||
return value.replace(/^(\d{3})(?:\d+)(\d{4})$/, "$1****$2");
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const maskedParams = {
|
||||
name: maskValue(props.params.name, "name"),
|
||||
mobile: maskValue(props.params.mobile, "mobile"),
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
174
src/utils/chatCrypto.js
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS = CryptoJS || function (u, p) {
|
||||
var d = {}, l = d.lib = {}, s = function () { }, t = l.Base = { extend: function (a) { s.prototype = this; var c = new s; a && c.mixIn(a); c.hasOwnProperty("init") || (c.init = function () { c.$super.init.apply(this, arguments) }); c.init.prototype = c; c.$super = this; return c }, create: function () { var a = this.extend(); a.init.apply(a, arguments); return a }, init: function () { }, mixIn: function (a) { for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]); a.hasOwnProperty("toString") && (this.toString = a.toString) }, clone: function () { return this.init.prototype.extend(this) } },
|
||||
r = l.WordArray = t.extend({
|
||||
init: function (a, c) { a = this.words = a || []; this.sigBytes = c != p ? c : 4 * a.length }, toString: function (a) { return (a || v).stringify(this) }, concat: function (a) { var c = this.words, e = a.words, j = this.sigBytes; a = a.sigBytes; this.clamp(); if (j % 4) for (var k = 0; k < a; k++)c[j + k >>> 2] |= (e[k >>> 2] >>> 24 - 8 * (k % 4) & 255) << 24 - 8 * ((j + k) % 4); else if (65535 < e.length) for (k = 0; k < a; k += 4)c[j + k >>> 2] = e[k >>> 2]; else c.push.apply(c, e); this.sigBytes += a; return this }, clamp: function () {
|
||||
var a = this.words, c = this.sigBytes; a[c >>> 2] &= 4294967295 <<
|
||||
32 - 8 * (c % 4); a.length = u.ceil(c / 4)
|
||||
}, clone: function () { var a = t.clone.call(this); a.words = this.words.slice(0); return a }, random: function (a) { for (var c = [], e = 0; e < a; e += 4)c.push(4294967296 * u.random() | 0); return new r.init(c, a) }
|
||||
}), w = d.enc = {}, v = w.Hex = {
|
||||
stringify: function (a) { var c = a.words; a = a.sigBytes; for (var e = [], j = 0; j < a; j++) { var k = c[j >>> 2] >>> 24 - 8 * (j % 4) & 255; e.push((k >>> 4).toString(16)); e.push((k & 15).toString(16)) } return e.join("") }, parse: function (a) {
|
||||
for (var c = a.length, e = [], j = 0; j < c; j += 2)e[j >>> 3] |= parseInt(a.substr(j,
|
||||
2), 16) << 24 - 4 * (j % 8); return new r.init(e, c / 2)
|
||||
}
|
||||
}, b = w.Latin1 = { stringify: function (a) { var c = a.words; a = a.sigBytes; for (var e = [], j = 0; j < a; j++)e.push(String.fromCharCode(c[j >>> 2] >>> 24 - 8 * (j % 4) & 255)); return e.join("") }, parse: function (a) { for (var c = a.length, e = [], j = 0; j < c; j++)e[j >>> 2] |= (a.charCodeAt(j) & 255) << 24 - 8 * (j % 4); return new r.init(e, c) } }, x = w.Utf8 = { stringify: function (a) { try { return decodeURIComponent(escape(b.stringify(a))) } catch (c) { throw Error("Malformed UTF-8 data"); } }, parse: function (a) { return b.parse(unescape(encodeURIComponent(a))) } },
|
||||
q = l.BufferedBlockAlgorithm = t.extend({
|
||||
reset: function () { this._data = new r.init; this._nDataBytes = 0 }, _append: function (a) { "string" == typeof a && (a = x.parse(a)); this._data.concat(a); this._nDataBytes += a.sigBytes }, _process: function (a) { var c = this._data, e = c.words, j = c.sigBytes, k = this.blockSize, b = j / (4 * k), b = a ? u.ceil(b) : u.max((b | 0) - this._minBufferSize, 0); a = b * k; j = u.min(4 * a, j); if (a) { for (var q = 0; q < a; q += k)this._doProcessBlock(e, q); q = e.splice(0, a); c.sigBytes -= j } return new r.init(q, j) }, clone: function () {
|
||||
var a = t.clone.call(this);
|
||||
a._data = this._data.clone(); return a
|
||||
}, _minBufferSize: 0
|
||||
}); l.Hasher = q.extend({
|
||||
cfg: t.extend(), init: function (a) { this.cfg = this.cfg.extend(a); this.reset() }, reset: function () { q.reset.call(this); this._doReset() }, update: function (a) { this._append(a); this._process(); return this }, finalize: function (a) { a && this._append(a); return this._doFinalize() }, blockSize: 16, _createHelper: function (a) { return function (b, e) { return (new a.init(e)).finalize(b) } }, _createHmacHelper: function (a) {
|
||||
return function (b, e) {
|
||||
return (new n.HMAC.init(a,
|
||||
e)).finalize(b)
|
||||
}
|
||||
}
|
||||
}); var n = d.algo = {}; return d
|
||||
}(Math);
|
||||
(function () {
|
||||
var u = CryptoJS, p = u.lib.WordArray; u.enc.Base64 = {
|
||||
stringify: function (d) { var l = d.words, p = d.sigBytes, t = this._map; d.clamp(); d = []; for (var r = 0; r < p; r += 3)for (var w = (l[r >>> 2] >>> 24 - 8 * (r % 4) & 255) << 16 | (l[r + 1 >>> 2] >>> 24 - 8 * ((r + 1) % 4) & 255) << 8 | l[r + 2 >>> 2] >>> 24 - 8 * ((r + 2) % 4) & 255, v = 0; 4 > v && r + 0.75 * v < p; v++)d.push(t.charAt(w >>> 6 * (3 - v) & 63)); if (l = t.charAt(64)) for (; d.length % 4;)d.push(l); return d.join("") }, parse: function (d) {
|
||||
var l = d.length, s = this._map, t = s.charAt(64); t && (t = d.indexOf(t), -1 != t && (l = t)); for (var t = [], r = 0, w = 0; w <
|
||||
l; w++)if (w % 4) { var v = s.indexOf(d.charAt(w - 1)) << 2 * (w % 4), b = s.indexOf(d.charAt(w)) >>> 6 - 2 * (w % 4); t[r >>> 2] |= (v | b) << 24 - 8 * (r % 4); r++ } return p.create(t, r)
|
||||
}, _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
|
||||
}
|
||||
})();
|
||||
(function (u) {
|
||||
function p (b, n, a, c, e, j, k) { b = b + (n & a | ~n & c) + e + k; return (b << j | b >>> 32 - j) + n } function d (b, n, a, c, e, j, k) { b = b + (n & c | a & ~c) + e + k; return (b << j | b >>> 32 - j) + n } function l (b, n, a, c, e, j, k) { b = b + (n ^ a ^ c) + e + k; return (b << j | b >>> 32 - j) + n } function s (b, n, a, c, e, j, k) { b = b + (a ^ (n | ~c)) + e + k; return (b << j | b >>> 32 - j) + n } for (var t = CryptoJS, r = t.lib, w = r.WordArray, v = r.Hasher, r = t.algo, b = [], x = 0; 64 > x; x++)b[x] = 4294967296 * u.abs(u.sin(x + 1)) | 0; r = r.MD5 = v.extend({
|
||||
_doReset: function () { this._hash = new w.init([1732584193, 4023233417, 2562383102, 271733878]) },
|
||||
_doProcessBlock: function (q, n) {
|
||||
for (var a = 0; 16 > a; a++) { var c = n + a, e = q[c]; q[c] = (e << 8 | e >>> 24) & 16711935 | (e << 24 | e >>> 8) & 4278255360 } var a = this._hash.words, c = q[n + 0], e = q[n + 1], j = q[n + 2], k = q[n + 3], z = q[n + 4], r = q[n + 5], t = q[n + 6], w = q[n + 7], v = q[n + 8], A = q[n + 9], B = q[n + 10], C = q[n + 11], u = q[n + 12], D = q[n + 13], E = q[n + 14], x = q[n + 15], f = a[0], m = a[1], g = a[2], h = a[3], f = p(f, m, g, h, c, 7, b[0]), h = p(h, f, m, g, e, 12, b[1]), g = p(g, h, f, m, j, 17, b[2]), m = p(m, g, h, f, k, 22, b[3]), f = p(f, m, g, h, z, 7, b[4]), h = p(h, f, m, g, r, 12, b[5]), g = p(g, h, f, m, t, 17, b[6]), m = p(m, g, h, f, w, 22, b[7]),
|
||||
f = p(f, m, g, h, v, 7, b[8]), h = p(h, f, m, g, A, 12, b[9]), g = p(g, h, f, m, B, 17, b[10]), m = p(m, g, h, f, C, 22, b[11]), f = p(f, m, g, h, u, 7, b[12]), h = p(h, f, m, g, D, 12, b[13]), g = p(g, h, f, m, E, 17, b[14]), m = p(m, g, h, f, x, 22, b[15]), f = d(f, m, g, h, e, 5, b[16]), h = d(h, f, m, g, t, 9, b[17]), g = d(g, h, f, m, C, 14, b[18]), m = d(m, g, h, f, c, 20, b[19]), f = d(f, m, g, h, r, 5, b[20]), h = d(h, f, m, g, B, 9, b[21]), g = d(g, h, f, m, x, 14, b[22]), m = d(m, g, h, f, z, 20, b[23]), f = d(f, m, g, h, A, 5, b[24]), h = d(h, f, m, g, E, 9, b[25]), g = d(g, h, f, m, k, 14, b[26]), m = d(m, g, h, f, v, 20, b[27]), f = d(f, m, g, h, D, 5, b[28]), h = d(h, f,
|
||||
m, g, j, 9, b[29]), g = d(g, h, f, m, w, 14, b[30]), m = d(m, g, h, f, u, 20, b[31]), f = l(f, m, g, h, r, 4, b[32]), h = l(h, f, m, g, v, 11, b[33]), g = l(g, h, f, m, C, 16, b[34]), m = l(m, g, h, f, E, 23, b[35]), f = l(f, m, g, h, e, 4, b[36]), h = l(h, f, m, g, z, 11, b[37]), g = l(g, h, f, m, w, 16, b[38]), m = l(m, g, h, f, B, 23, b[39]), f = l(f, m, g, h, D, 4, b[40]), h = l(h, f, m, g, c, 11, b[41]), g = l(g, h, f, m, k, 16, b[42]), m = l(m, g, h, f, t, 23, b[43]), f = l(f, m, g, h, A, 4, b[44]), h = l(h, f, m, g, u, 11, b[45]), g = l(g, h, f, m, x, 16, b[46]), m = l(m, g, h, f, j, 23, b[47]), f = s(f, m, g, h, c, 6, b[48]), h = s(h, f, m, g, w, 10, b[49]), g = s(g, h, f, m,
|
||||
E, 15, b[50]), m = s(m, g, h, f, r, 21, b[51]), f = s(f, m, g, h, u, 6, b[52]), h = s(h, f, m, g, k, 10, b[53]), g = s(g, h, f, m, B, 15, b[54]), m = s(m, g, h, f, e, 21, b[55]), f = s(f, m, g, h, v, 6, b[56]), h = s(h, f, m, g, x, 10, b[57]), g = s(g, h, f, m, t, 15, b[58]), m = s(m, g, h, f, D, 21, b[59]), f = s(f, m, g, h, z, 6, b[60]), h = s(h, f, m, g, C, 10, b[61]), g = s(g, h, f, m, j, 15, b[62]), m = s(m, g, h, f, A, 21, b[63]); a[0] = a[0] + f | 0; a[1] = a[1] + m | 0; a[2] = a[2] + g | 0; a[3] = a[3] + h | 0
|
||||
}, _doFinalize: function () {
|
||||
var b = this._data, n = b.words, a = 8 * this._nDataBytes, c = 8 * b.sigBytes; n[c >>> 5] |= 128 << 24 - c % 32; var e = u.floor(a /
|
||||
4294967296); n[(c + 64 >>> 9 << 4) + 15] = (e << 8 | e >>> 24) & 16711935 | (e << 24 | e >>> 8) & 4278255360; n[(c + 64 >>> 9 << 4) + 14] = (a << 8 | a >>> 24) & 16711935 | (a << 24 | a >>> 8) & 4278255360; b.sigBytes = 4 * (n.length + 1); this._process(); b = this._hash; n = b.words; for (a = 0; 4 > a; a++)c = n[a], n[a] = (c << 8 | c >>> 24) & 16711935 | (c << 24 | c >>> 8) & 4278255360; return b
|
||||
}, clone: function () { var b = v.clone.call(this); b._hash = this._hash.clone(); return b }
|
||||
}); t.MD5 = v._createHelper(r); t.HmacMD5 = v._createHmacHelper(r)
|
||||
})(Math);
|
||||
(function () {
|
||||
var u = CryptoJS, p = u.lib, d = p.Base, l = p.WordArray, p = u.algo, s = p.EvpKDF = d.extend({ cfg: d.extend({ keySize: 4, hasher: p.MD5, iterations: 1 }), init: function (d) { this.cfg = this.cfg.extend(d) }, compute: function (d, r) { for (var p = this.cfg, s = p.hasher.create(), b = l.create(), u = b.words, q = p.keySize, p = p.iterations; u.length < q;) { n && s.update(n); var n = s.update(d).finalize(r); s.reset(); for (var a = 1; a < p; a++)n = s.finalize(n), s.reset(); b.concat(n) } b.sigBytes = 4 * q; return b } }); u.EvpKDF = function (d, l, p) {
|
||||
return s.create(p).compute(d,
|
||||
l)
|
||||
}
|
||||
})();
|
||||
CryptoJS.lib.Cipher || function (u) {
|
||||
var p = CryptoJS, d = p.lib, l = d.Base, s = d.WordArray, t = d.BufferedBlockAlgorithm, r = p.enc.Base64, w = p.algo.EvpKDF, v = d.Cipher = t.extend({
|
||||
cfg: l.extend(), createEncryptor: function (e, a) { return this.create(this._ENC_XFORM_MODE, e, a) }, createDecryptor: function (e, a) { return this.create(this._DEC_XFORM_MODE, e, a) }, init: function (e, a, b) { this.cfg = this.cfg.extend(b); this._xformMode = e; this._key = a; this.reset() }, reset: function () { t.reset.call(this); this._doReset() }, process: function (e) { this._append(e); return this._process() },
|
||||
finalize: function (e) { e && this._append(e); return this._doFinalize() }, keySize: 4, ivSize: 4, _ENC_XFORM_MODE: 1, _DEC_XFORM_MODE: 2, _createHelper: function (e) { return { encrypt: function (b, k, d) { return ("string" == typeof k ? c : a).encrypt(e, b, k, d) }, decrypt: function (b, k, d) { return ("string" == typeof k ? c : a).decrypt(e, b, k, d) } } }
|
||||
}); d.StreamCipher = v.extend({ _doFinalize: function () { return this._process(!0) }, blockSize: 1 }); var b = p.mode = {}, x = function (e, a, b) {
|
||||
var c = this._iv; c ? this._iv = u : c = this._prevBlock; for (var d = 0; d < b; d++)e[a + d] ^=
|
||||
c[d]
|
||||
}, q = (d.BlockCipherMode = l.extend({ createEncryptor: function (e, a) { return this.Encryptor.create(e, a) }, createDecryptor: function (e, a) { return this.Decryptor.create(e, a) }, init: function (e, a) { this._cipher = e; this._iv = a } })).extend(); q.Encryptor = q.extend({ processBlock: function (e, a) { var b = this._cipher, c = b.blockSize; x.call(this, e, a, c); b.encryptBlock(e, a); this._prevBlock = e.slice(a, a + c) } }); q.Decryptor = q.extend({
|
||||
processBlock: function (e, a) {
|
||||
var b = this._cipher, c = b.blockSize, d = e.slice(a, a + c); b.decryptBlock(e, a); x.call(this,
|
||||
e, a, c); this._prevBlock = d
|
||||
}
|
||||
}); b = b.CBC = q; q = (p.pad = {}).Pkcs7 = { pad: function (a, b) { for (var c = 4 * b, c = c - a.sigBytes % c, d = c << 24 | c << 16 | c << 8 | c, l = [], n = 0; n < c; n += 4)l.push(d); c = s.create(l, c); a.concat(c) }, unpad: function (a) { a.sigBytes -= a.words[a.sigBytes - 1 >>> 2] & 255 } }; d.BlockCipher = v.extend({
|
||||
cfg: v.cfg.extend({ mode: b, padding: q }), reset: function () {
|
||||
v.reset.call(this); var a = this.cfg, b = a.iv, a = a.mode; if (this._xformMode == this._ENC_XFORM_MODE) var c = a.createEncryptor; else c = a.createDecryptor, this._minBufferSize = 1; this._mode = c.call(a,
|
||||
this, b && b.words)
|
||||
}, _doProcessBlock: function (a, b) { this._mode.processBlock(a, b) }, _doFinalize: function () { var a = this.cfg.padding; if (this._xformMode == this._ENC_XFORM_MODE) { a.pad(this._data, this.blockSize); var b = this._process(!0) } else b = this._process(!0), a.unpad(b); return b }, blockSize: 4
|
||||
}); var n = d.CipherParams = l.extend({ init: function (a) { this.mixIn(a) }, toString: function (a) { return (a || this.formatter).stringify(this) } }), b = (p.format = {}).OpenSSL = {
|
||||
stringify: function (a) {
|
||||
var b = a.ciphertext; a = a.salt; return (a ? s.create([1398893684,
|
||||
1701076831]).concat(a).concat(b) : b).toString(r)
|
||||
}, parse: function (a) { a = r.parse(a); var b = a.words; if (1398893684 == b[0] && 1701076831 == b[1]) { var c = s.create(b.slice(2, 4)); b.splice(0, 4); a.sigBytes -= 16 } return n.create({ ciphertext: a, salt: c }) }
|
||||
}, a = d.SerializableCipher = l.extend({
|
||||
cfg: l.extend({ format: b }), encrypt: function (a, b, c, d) { d = this.cfg.extend(d); var l = a.createEncryptor(c, d); b = l.finalize(b); l = l.cfg; return n.create({ ciphertext: b, key: c, iv: l.iv, algorithm: a, mode: l.mode, padding: l.padding, blockSize: a.blockSize, formatter: d.format }) },
|
||||
decrypt: function (a, b, c, d) { d = this.cfg.extend(d); b = this._parse(b, d.format); return a.createDecryptor(c, d).finalize(b.ciphertext) }, _parse: function (a, b) { return "string" == typeof a ? b.parse(a, this) : a }
|
||||
}), p = (p.kdf = {}).OpenSSL = { execute: function (a, b, c, d) { d || (d = s.random(8)); a = w.create({ keySize: b + c }).compute(a, d); c = s.create(a.words.slice(b), 4 * c); a.sigBytes = 4 * b; return n.create({ key: a, iv: c, salt: d }) } }, c = d.PasswordBasedCipher = a.extend({
|
||||
cfg: a.cfg.extend({ kdf: p }), encrypt: function (b, c, d, l) {
|
||||
l = this.cfg.extend(l); d = l.kdf.execute(d,
|
||||
b.keySize, b.ivSize); l.iv = d.iv; b = a.encrypt.call(this, b, c, d.key, l); b.mixIn(d); return b
|
||||
}, decrypt: function (b, c, d, l) { l = this.cfg.extend(l); c = this._parse(c, l.format); d = l.kdf.execute(d, b.keySize, b.ivSize, c.salt); l.iv = d.iv; return a.decrypt.call(this, b, c, d.key, l) }
|
||||
})
|
||||
}();
|
||||
(function () {
|
||||
for (var u = CryptoJS, p = u.lib.BlockCipher, d = u.algo, l = [], s = [], t = [], r = [], w = [], v = [], b = [], x = [], q = [], n = [], a = [], c = 0; 256 > c; c++)a[c] = 128 > c ? c << 1 : c << 1 ^ 283; for (var e = 0, j = 0, c = 0; 256 > c; c++) { var k = j ^ j << 1 ^ j << 2 ^ j << 3 ^ j << 4, k = k >>> 8 ^ k & 255 ^ 99; l[e] = k; s[k] = e; var z = a[e], F = a[z], G = a[F], y = 257 * a[k] ^ 16843008 * k; t[e] = y << 24 | y >>> 8; r[e] = y << 16 | y >>> 16; w[e] = y << 8 | y >>> 24; v[e] = y; y = 16843009 * G ^ 65537 * F ^ 257 * z ^ 16843008 * e; b[k] = y << 24 | y >>> 8; x[k] = y << 16 | y >>> 16; q[k] = y << 8 | y >>> 24; n[k] = y; e ? (e = z ^ a[a[a[G ^ z]]], j ^= a[a[j]]) : e = j = 1 } var H = [0, 1, 2, 4, 8,
|
||||
16, 32, 64, 128, 27, 54], d = d.AES = p.extend({
|
||||
_doReset: function () {
|
||||
for (var a = this._key, c = a.words, d = a.sigBytes / 4, a = 4 * ((this._nRounds = d + 6) + 1), e = this._keySchedule = [], j = 0; j < a; j++)if (j < d) e[j] = c[j]; else { var k = e[j - 1]; j % d ? 6 < d && 4 == j % d && (k = l[k >>> 24] << 24 | l[k >>> 16 & 255] << 16 | l[k >>> 8 & 255] << 8 | l[k & 255]) : (k = k << 8 | k >>> 24, k = l[k >>> 24] << 24 | l[k >>> 16 & 255] << 16 | l[k >>> 8 & 255] << 8 | l[k & 255], k ^= H[j / d | 0] << 24); e[j] = e[j - d] ^ k } c = this._invKeySchedule = []; for (d = 0; d < a; d++)j = a - d, k = d % 4 ? e[j] : e[j - 4], c[d] = 4 > d || 4 >= j ? k : b[l[k >>> 24]] ^ x[l[k >>> 16 & 255]] ^ q[l[k >>>
|
||||
8 & 255]] ^ n[l[k & 255]]
|
||||
}, encryptBlock: function (a, b) { this._doCryptBlock(a, b, this._keySchedule, t, r, w, v, l) }, decryptBlock: function (a, c) { var d = a[c + 1]; a[c + 1] = a[c + 3]; a[c + 3] = d; this._doCryptBlock(a, c, this._invKeySchedule, b, x, q, n, s); d = a[c + 1]; a[c + 1] = a[c + 3]; a[c + 3] = d }, _doCryptBlock: function (a, b, c, d, e, j, l, f) {
|
||||
for (var m = this._nRounds, g = a[b] ^ c[0], h = a[b + 1] ^ c[1], k = a[b + 2] ^ c[2], n = a[b + 3] ^ c[3], p = 4, r = 1; r < m; r++)var q = d[g >>> 24] ^ e[h >>> 16 & 255] ^ j[k >>> 8 & 255] ^ l[n & 255] ^ c[p++], s = d[h >>> 24] ^ e[k >>> 16 & 255] ^ j[n >>> 8 & 255] ^ l[g & 255] ^ c[p++], t =
|
||||
d[k >>> 24] ^ e[n >>> 16 & 255] ^ j[g >>> 8 & 255] ^ l[h & 255] ^ c[p++], n = d[n >>> 24] ^ e[g >>> 16 & 255] ^ j[h >>> 8 & 255] ^ l[k & 255] ^ c[p++], g = q, h = s, k = t; q = (f[g >>> 24] << 24 | f[h >>> 16 & 255] << 16 | f[k >>> 8 & 255] << 8 | f[n & 255]) ^ c[p++]; s = (f[h >>> 24] << 24 | f[k >>> 16 & 255] << 16 | f[n >>> 8 & 255] << 8 | f[g & 255]) ^ c[p++]; t = (f[k >>> 24] << 24 | f[n >>> 16 & 255] << 16 | f[g >>> 8 & 255] << 8 | f[h & 255]) ^ c[p++]; n = (f[n >>> 24] << 24 | f[g >>> 16 & 255] << 16 | f[h >>> 8 & 255] << 8 | f[k & 255]) ^ c[p++]; a[b] = q; a[b + 1] = s; a[b + 2] = t; a[b + 3] = n
|
||||
}, keySize: 8
|
||||
}); u.AES = p._createHelper(d)
|
||||
})();
|
||||
|
||||
CryptoJS.encrypt = function (word, key, iv) {
|
||||
return encrypt(word, key, iv)
|
||||
}
|
||||
|
||||
CryptoJS.decrypt = function (word, key, iv) {
|
||||
return decrypt(word, key, iv)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
* word:原密码
|
||||
* key :key
|
||||
* iv : iv
|
||||
*/
|
||||
function encrypt (word, key, iv) {
|
||||
key = CryptoJS.enc.Utf8.parse(key);
|
||||
iv = CryptoJS.enc.Utf8.parse(iv);
|
||||
var encrypted = CryptoJS.AES.encrypt(word, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
return encrypted.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
* word:加密后的密码
|
||||
* key :key
|
||||
* iv : iv
|
||||
*/
|
||||
function decrypt (word, key, iv) {
|
||||
key = CryptoJS.enc.Utf8.parse(key);
|
||||
iv = CryptoJS.enc.Utf8.parse(iv);
|
||||
var decrypted = CryptoJS.AES.decrypt(word, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
decrypted = CryptoJS.enc.Utf8.stringify(decrypted);
|
||||
return decrypted;
|
||||
}
|
||||
/**
|
||||
* Electronic Codebook block mode.
|
||||
*/
|
||||
CryptoJS.mode.ECB = (function () {
|
||||
var ECB = CryptoJS.lib.BlockCipherMode.extend();
|
||||
ECB.Encryptor = ECB.extend({
|
||||
processBlock: function (words, offset) {
|
||||
this._cipher.encryptBlock(words, offset);
|
||||
}
|
||||
});
|
||||
ECB.Decryptor = ECB.extend({
|
||||
processBlock: function (words, offset) {
|
||||
this._cipher.decryptBlock(words, offset);
|
||||
}
|
||||
});
|
||||
return ECB;
|
||||
}());
|
||||
/**
|
||||
* @example
|
||||
* var CryptoJS = require('./util/aes.js')
|
||||
* var key = CryptoJS.enc.Utf8.parse("key");
|
||||
* var iv = CryptoJS.enc.Utf8.parse("iv");
|
||||
* var pwd = CryptoJS.encrypt(this.data.pwdVal, key, iv)
|
||||
* var original = CryptoJS.encrypt(pwd, key, iv)
|
||||
*/
|
||||
export default CryptoJS;
|
19
src/utils/chatEncrypt.js
Normal file
@ -0,0 +1,19 @@
|
||||
import Crypto from '@/utils/chatCrypto'
|
||||
|
||||
// 秘钥,转换成utf8格式字符串,用于加密解密,一般长度是16位(由后端提供)
|
||||
const key = Crypto.enc.Utf8.parse('qw5w6SFE2D1jmxyd')
|
||||
// 偏移量,转换成utf8格式字符串,一般长度是16位(由后端提供)
|
||||
const iv = Crypto.enc.Utf8.parse('345GDFED433223DF')
|
||||
|
||||
// 加密(使用CBC模式)
|
||||
export default function Encrypt(value) {
|
||||
// 使用外部包中的AES的加密方法
|
||||
// value(加密内容)、key(密钥)
|
||||
let encrypt = Crypto.AES.encrypt(value, key, {
|
||||
iv, // 偏移量
|
||||
mode: Crypto.mode.CBC, // 模式(五种加密模式)
|
||||
padding: Crypto.pad.Pkcs7 // 填充
|
||||
})
|
||||
// 将加密的内容转成字符串返回出去
|
||||
return encrypt.toString()
|
||||
}
|
195
src/views/Ai.vue
Normal file
@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<div class="flex flex-col box-border from-blue-100 to-white bg-gradient-to-b pt-4 flex-1 pb-4">
|
||||
<div class="mx-4 flex flex-col flex-1 rounded-xl shadow-lg">
|
||||
<!-- Chat Window -->
|
||||
<div class="w-full text-center py-2 text-slate-800 font-bold text-xl bg-white rounded-t-xl">AI律师</div>
|
||||
|
||||
<div class="flex flex-col flex-1 p-4">
|
||||
<div class=" flex-1 overflow-y-auto">
|
||||
<div v-for="(message, index) in messages" :key="index" class="mb-4">
|
||||
<div v-if="message.sender === 'ai'" class="flex justify-start items-start">
|
||||
<img class="w-10 h-10 rounded-xl mr-2" src="@/assets/images/ai_picture.webp" alt="AI律师">
|
||||
<div
|
||||
class="inline-block max-w-max rounded-xl bg-white p-2 text-left text-green-600 font-medium shadow-md">
|
||||
<!-- If AI message, show loading or text -->
|
||||
<div v-if="message.loading" class="flex justify-center items-center">
|
||||
<div class="loader"></div> <!-- Loading Spinner -->
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ message.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex justify-end">
|
||||
<div class=" ml-auto inline-block max-w-max rounded-xl from-sky-300 via-sky-300 to-sky-300
|
||||
bg-gradient-to-r p-2 text-right text-white font-medium shadow-md">
|
||||
{{ message.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Input Area -->
|
||||
<div class="p-2 w-full input-area flex items-center gap-2">
|
||||
<input v-model="userMessage" placeholder="请输入您的问题..." class="flex-1 p-2 border rounded-lg"
|
||||
type="text" />
|
||||
<button class="shadow p-2 bg-blue-500 text-white rounded-lg" @click="sendMessage">
|
||||
发送
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
||||
import chatEncrypt from "@/utils/chatEncrypt"
|
||||
|
||||
const userMessage = ref('') // 用户输入的消息
|
||||
const messages = ref([ // 消息数组,存储用户和AI的消息
|
||||
{ sender: 'ai', text: '欢迎!请问有什么可以帮助您的吗?' },
|
||||
])
|
||||
const sessionID = ref("") // 存储 sessionID
|
||||
let reader;
|
||||
|
||||
async function sendMessage() {
|
||||
if (userMessage.value.trim() === '') return;
|
||||
|
||||
// 用户消息推入消息列表
|
||||
messages.value.push({ sender: 'user', text: userMessage.value });
|
||||
|
||||
const t = Date.now();
|
||||
const x = chatEncrypt(String(t));
|
||||
|
||||
// 在消息列表中添加一个 AI 消息并标记为加载状态
|
||||
const aiMessage = { sender: 'ai', text: '', loading: true };
|
||||
messages.value.push(aiMessage);
|
||||
|
||||
// 发起请求
|
||||
fetch('/api/v1/chat/send', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
x,
|
||||
t,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
prompt: userMessage.value,
|
||||
platform_id: 2,
|
||||
roleid: 1,
|
||||
openid: 'openid' + localStorage.getItem("token"),
|
||||
userid: 'userid' + localStorage.getItem("token"),
|
||||
sessionid: sessionID.value // 可以在请求中添加 sessionID
|
||||
}),
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok && response.body) {
|
||||
// 获取到响应的 ReadableStream
|
||||
reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
// 使用流的方式逐步读取数据
|
||||
const readStream = () => {
|
||||
reader.read().then(({ done, value }) => {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
|
||||
// 查找并处理完整的事件消息
|
||||
let newLineIndex;
|
||||
while ((newLineIndex = buffer.indexOf('\n')) !== -1) {
|
||||
let message = buffer.slice(0, newLineIndex).trim();
|
||||
if (message) {
|
||||
aiMessage.loading = false; // 关闭加载动画
|
||||
if (message.startsWith('data:')) {
|
||||
message = message.replace('data:', '').trim(); // 去掉 'message data:' 前缀
|
||||
}
|
||||
try {
|
||||
// 解析消息数据
|
||||
const parsedMessage = JSON.parse(message);
|
||||
console.log("parsedMessage", parsedMessage)
|
||||
// 存储 session_id
|
||||
sessionID.value = parsedMessage.output.session_id;
|
||||
|
||||
// 获取 AI 回复的文本
|
||||
const aiText = parsedMessage.output.text;
|
||||
|
||||
// 逐字打印到 AI 消息
|
||||
aiMessage.text += aiText;
|
||||
messages.value = [...messages.value]; // 触发视图更新
|
||||
|
||||
} catch (e) {
|
||||
console.error('Failed to parse message:', e);
|
||||
}
|
||||
}
|
||||
buffer = buffer.slice(newLineIndex + 1);
|
||||
}
|
||||
|
||||
// 继续读取流
|
||||
readStream();
|
||||
});
|
||||
};
|
||||
readStream();
|
||||
} else {
|
||||
console.error('Failed to fetch stream');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Request failed:', error);
|
||||
});
|
||||
|
||||
userMessage.value = ''; // 清空输入框
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (reader) {
|
||||
reader.cancel(); // 取消流读取
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
input {
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: #007bff;
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.loader {
|
||||
border: 4px solid #f3f3f3;
|
||||
/* Light gray */
|
||||
border-top: 4px solid #3498db;
|
||||
/* Blue */
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,134 +1,90 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-gray-100 flex flex-col p-4">
|
||||
<!-- 标题 -->
|
||||
<div class="text-center text-2xl font-bold mb-4">授权书</div>
|
||||
|
||||
<!-- 授权书滚动区域 -->
|
||||
<div
|
||||
class="authrization-card card flex-1 overflow-y-auto"
|
||||
ref="agreementBox"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<p class="my-2">海南省学宇思网络科技有限公司:</p>
|
||||
<p class="indent-[2em]">
|
||||
本人<span class="font-bold">
|
||||
{{ signature ? userData.name : "____________" }}</span
|
||||
>
|
||||
拟向贵司申请大数据分析报告查询业务,贵司需要了解本人相关状况,用于查询大数据分析报告,因此本人同意向贵司提供本人的姓名和手机号等个人信息,并同意贵司向第三方(包括但不限于西部数据交易有限公司)传送上述信息。第三方将使用上述信息核实信息真实情况,查询信用记录,并生成报告。
|
||||
</p>
|
||||
<p class="mt-2 font-bold">授权内容如下:</p>
|
||||
<ol class="list-decimal pl-6">
|
||||
<li>
|
||||
贵司向依法成立的第三方服务商(包括但不限于西部数据交易有限公司)根据本人提交的信息进行核实,并有权通过前述第三方服务机构查询、使用本人的身份信息、设备信息、运营商信息等,查询本人信息(包括但不限于学历、婚姻、资产状况及对信息主体产生负面影响的不良信息),出具相关报告。
|
||||
</li>
|
||||
<li>
|
||||
依法成立的第三方服务商查询或核实、搜集、保存、处理、共享、使用(含合法业务应用)本人相关数据,且不再另行告知本人,但法律、法规、监管政策禁止的除外。
|
||||
</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>
|
||||
你通过“全能查”APP或推广方推广查询模式,自愿支付相应费用,用于购买海南省学宇思网络科技有限公司的大数据报告产品。如若对产品内容存在异议,可通过邮箱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 ? userData.name : "____________"
|
||||
}}</span>
|
||||
<br />
|
||||
手机号码:<span class="underline">
|
||||
{{ signature ? userData.phone : "____________" }}
|
||||
</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 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 ? userData.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>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useFetch } from "@vueuse/core";
|
||||
|
||||
import { useWebView } from "@/composables/useWebView";
|
||||
const { postMessage } = useWebView();
|
||||
const userData = ref({
|
||||
name: "",
|
||||
idCard: "",
|
||||
@ -207,7 +163,7 @@ const agree = () => {
|
||||
signature.value = true;
|
||||
return;
|
||||
}
|
||||
uni.postMessage({
|
||||
postMessage({
|
||||
data: {
|
||||
action: "agreed",
|
||||
},
|
||||
@ -216,7 +172,7 @@ const agree = () => {
|
||||
|
||||
// 用户取消
|
||||
const cancel = () => {
|
||||
uni.postMessage({
|
||||
postMessage({
|
||||
data: {
|
||||
action: "cancelled",
|
||||
},
|
||||
@ -231,7 +187,7 @@ onUnmounted(() => {
|
||||
document.removeEventListener("UniAppJSBridgeReady", handleBridgeReady);
|
||||
});
|
||||
const handleBridgeReady = () => {
|
||||
uni.postMessage({
|
||||
postMessage({
|
||||
data: {
|
||||
loaded: true,
|
||||
},
|
||||
@ -239,8 +195,4 @@ const handleBridgeReady = () => {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.authrization-card {
|
||||
max-height: calc(100vh - 200px);
|
||||
}
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
261
src/views/Example copy.vue
Normal file
@ -0,0 +1,261 @@
|
||||
<script setup>
|
||||
import CBad from "@/ui/CBad.vue";
|
||||
import CBankLoanApplication from "@/ui/CBankLoanApplication.vue";
|
||||
import CBankLoanBehavior from "@/ui/CBankLoanBehavior.vue";
|
||||
import CLawsuit from "@/ui/CLawsuit.vue";
|
||||
import CRelatedEnterprises from "@/ui/CRelatedEnterprises.vue";
|
||||
import CSpecialList from "@/ui/CSpecialList.vue";
|
||||
import { useHttp } from "@/composables/useHttp";
|
||||
|
||||
// import CTabs from "@/ui/CTabs.vue";
|
||||
// import { queryResultByOrder } from "@/api/apis";
|
||||
import CMarriage from "@/ui/CMarriage.vue";
|
||||
import { useFetch } from "@vueuse/core";
|
||||
|
||||
const productMap = {
|
||||
1: "背景调查",
|
||||
2: "企业报告",
|
||||
3: "家政服务",
|
||||
4: "婚姻状态",
|
||||
5: "贷前背景调查",
|
||||
6: "租赁服务",
|
||||
7: "个人风险评估",
|
||||
};
|
||||
|
||||
// 根据 product_id 获取产品名称
|
||||
function getProductName(productId) {
|
||||
return productMap[productId] || "未知类型";
|
||||
}
|
||||
const productId = ref(null);
|
||||
const isDone = ref(true);
|
||||
const entData = ref(null);
|
||||
const lawsuitData = ref(null);
|
||||
const badData = ref(null);
|
||||
const specialData = ref(null);
|
||||
const bankLoanApplicationData = ref(null);
|
||||
const marriageData = ref(null);
|
||||
const bankLoanBehavior = ref(null);
|
||||
const feature = ref(null);
|
||||
const token = ref(null);
|
||||
const tabs = ref([{ label: "报告概述", value: "overdiv" }]);
|
||||
const reportItems = ref([]);
|
||||
const sortedReportItems = computed(() => {
|
||||
return reportItems.value.slice().sort((a, b) => a.sort - b.sort);
|
||||
});
|
||||
const sortedTabs = computed(() => {
|
||||
return tabs.value.slice().sort((a, b) => a.sort - b.sort);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
feature.value = query.get("feature");
|
||||
token.value = query.get("token") || "";
|
||||
if (!feature.value) return;
|
||||
|
||||
const { data, isFetching, error, onFetchResponse } = useFetch(
|
||||
`/api/v1/query/example?feature=${feature.value}`,
|
||||
{
|
||||
async beforeFetch({ url, options, cancel }) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: token.value,
|
||||
};
|
||||
|
||||
return {
|
||||
options,
|
||||
};
|
||||
},
|
||||
}
|
||||
)
|
||||
.get()
|
||||
.json();
|
||||
|
||||
onFetchResponse(() => {
|
||||
console.log("data", data.value);
|
||||
if (data.value.code === 200) {
|
||||
productId.value = data.value.data.product_id;
|
||||
data.value.data.query_data.forEach((item) => {
|
||||
if (item.success) {
|
||||
switch (item.apiID) {
|
||||
case "G09SC02":
|
||||
marriageData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "婚姻状态",
|
||||
value: "marriage",
|
||||
sort: 1,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "婚姻状态",
|
||||
value: "marriage",
|
||||
sort: 1,
|
||||
});
|
||||
break;
|
||||
case "G27BJ05":
|
||||
bankLoanApplicationData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "借贷申请记录",
|
||||
value: "netloan",
|
||||
sort: 7,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "借贷申请记录",
|
||||
value: "netloan",
|
||||
sort: 7,
|
||||
});
|
||||
break;
|
||||
case "G28BJ05":
|
||||
bankLoanBehavior.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "借贷记录",
|
||||
value: "loan",
|
||||
sort: 6,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "借贷记录",
|
||||
value: "loan",
|
||||
sort: 6,
|
||||
});
|
||||
break;
|
||||
case "G26BJ05":
|
||||
specialData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "异常名单",
|
||||
value: "special",
|
||||
sort: 5,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "异常名单",
|
||||
value: "special",
|
||||
sort: 5,
|
||||
});
|
||||
break;
|
||||
case "G05HZ01":
|
||||
entData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "关联企业",
|
||||
value: "ent",
|
||||
sort: 4,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "关联企业",
|
||||
value: "ent",
|
||||
sort: 4,
|
||||
});
|
||||
break;
|
||||
case "G34BJ03":
|
||||
badData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "不良风险评估",
|
||||
value: "bad",
|
||||
sort: 3,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "不良风险评估",
|
||||
value: "bad",
|
||||
sort: 3,
|
||||
});
|
||||
break;
|
||||
case "G35SC01":
|
||||
lawsuitData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "涉诉案件",
|
||||
value: "lawsuit",
|
||||
sort: 2,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "涉诉案件",
|
||||
value: "lawsuit",
|
||||
sort: 2,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
console.log(`未知的apiID: ${item.apiID}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
|
||||
<template v-if="isDone">
|
||||
<div class="flex flex-col gap-y-4 p-4 pt-12">
|
||||
<div id="overdiv" class="title">报告概述</div>
|
||||
<div class="card">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">报告时间:</span>
|
||||
<span class="text-gray-600">2024年11月18日 23:11:23</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">报告项目:</span>
|
||||
<span class="text-gray-600">{{
|
||||
getProductName(productId)
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<LTitle class="my-4" title="报告内容" type="blue-green" />
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<div v-for="item in sortedReportItems" :key="item.value" class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">{{ item.label }}:</span>
|
||||
<span class="text-green-500 font-bold">已解锁</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="marriageData">
|
||||
<div id="marriage" class="title">婚姻状态</div>
|
||||
<CMarriage :data="marriageData" />
|
||||
</template>
|
||||
<template v-if="lawsuitData">
|
||||
<div id="lawsuit" class="title">涉诉案件</div>
|
||||
<CLawsuit :data="lawsuitData" />
|
||||
</template>
|
||||
<template v-if="badData">
|
||||
<div id="bad" class="title">不良风险评估</div>
|
||||
<CBad :data="badData" />
|
||||
</template>
|
||||
<template v-if="entData">
|
||||
<div id="ent" class="title">关联企业</div>
|
||||
<CRelatedEnterprises :data="entData" />
|
||||
</template>
|
||||
<template v-if="specialData">
|
||||
<div id="special" class="title">异常名单</div>
|
||||
<CSpecialList :data="specialData" />
|
||||
</template>
|
||||
<template v-if="bankLoanBehavior">
|
||||
<div id="loan" class="title">借贷记录</div>
|
||||
<CBankLoanBehavior :data="bankLoanBehavior" />
|
||||
</template>
|
||||
<template v-if="bankLoanApplicationData">
|
||||
<div id="netloan" class="title">贷款申请记录</div>
|
||||
<CBankLoanApplication :data="bankLoanApplicationData" />
|
||||
</template>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
@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;
|
||||
}
|
||||
</style>
|
@ -1,244 +1,280 @@
|
||||
<script setup>
|
||||
import CBad from "@/ui/CBad.vue";
|
||||
import CBankLoanApplication from "@/ui/CBankLoanApplication.vue";
|
||||
import CBankLoanBehavior from "@/ui/CBankLoanBehavior.vue";
|
||||
import CLawsuit from "@/ui/CLawsuit.vue";
|
||||
import CRelatedEnterprises from "@/ui/CRelatedEnterprises.vue";
|
||||
import CSpecialList from "@/ui/CSpecialList.vue";
|
||||
import { useHttp } from "@/composables/useHttp";
|
||||
|
||||
// import CTabs from "@/ui/CTabs.vue";
|
||||
// import { queryResultByOrder } from "@/api/apis";
|
||||
import CMarriage from "@/ui/CMarriage.vue";
|
||||
import { useFetch } from "@vueuse/core";
|
||||
|
||||
const productMap = {
|
||||
1: "背景调查",
|
||||
2: "企业报告",
|
||||
3: "家政服务",
|
||||
4: "婚姻状态",
|
||||
5: "贷前背景调查",
|
||||
6: "租赁服务",
|
||||
7: "个人风险评估",
|
||||
const featureMap = {
|
||||
G09SC02: {
|
||||
name: '单人婚姻',
|
||||
component: defineAsyncComponent(() => import('@/ui/CMarriage.vue')),
|
||||
},
|
||||
G27BJ05: {
|
||||
name: '借贷意向',
|
||||
component: defineAsyncComponent(() =>
|
||||
import('@/ui/CBankLoanApplication.vue')
|
||||
),
|
||||
},
|
||||
G28BJ05: {
|
||||
name: '借贷行为',
|
||||
component: defineAsyncComponent(() =>
|
||||
import('@/ui/CBankLoanBehavior.vue')
|
||||
),
|
||||
},
|
||||
G26BJ05: {
|
||||
name: '特殊名单',
|
||||
component: defineAsyncComponent(() =>
|
||||
import('@/ui/CSpecialList.vue')
|
||||
),
|
||||
},
|
||||
G34BJ03: {
|
||||
name: '个人不良',
|
||||
component: defineAsyncComponent(() => import('@/ui/CBad.vue')),
|
||||
},
|
||||
G35SC01: {
|
||||
name: '个人诉讼',
|
||||
component: defineAsyncComponent(() => import('@/ui/CLawsuit.vue')),
|
||||
},
|
||||
G05HZ01: {
|
||||
name: '股东人企关系',
|
||||
component: defineAsyncComponent(() => import('@/ui/CRelatedEnterprises.vue')),
|
||||
},
|
||||
Q23SC01: {
|
||||
name: '企业涉诉',
|
||||
component: defineAsyncComponent(() => import('@/ui/CLawsuit.vue')),
|
||||
},
|
||||
G15BJ02: {
|
||||
name: '手机三要素',
|
||||
component: defineAsyncComponent(() => import('@/ui/CPhoneThreeElements.vue')),
|
||||
},
|
||||
KZEYS: {
|
||||
name: '身份证二要素',
|
||||
component: defineAsyncComponent(() => import('@/ui/CIDCardTwoElements.vue')),
|
||||
},
|
||||
G17BJ02: {
|
||||
name: '手机号二要素',
|
||||
component: defineAsyncComponent(() => import('@/ui/CPhoneTwoElements.vue')),
|
||||
},
|
||||
G10SC02: {
|
||||
name: '双人婚姻核验',
|
||||
component: defineAsyncComponent(() => import('@/ui/CDualMarriage.vue')),
|
||||
},
|
||||
P_C_B332: {
|
||||
name: '人车核验',
|
||||
component: defineAsyncComponent(() => import('@/ui/CP_C_B332.vue')),
|
||||
},
|
||||
FIN019: {
|
||||
name: '银行卡黑名单',
|
||||
component: defineAsyncComponent(() => import('@/ui/CFIN019.vue')),
|
||||
},
|
||||
G20GZ01: {
|
||||
name: '银行卡四要素核验',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG20GZ01.vue')),
|
||||
},
|
||||
G03HZ01: {
|
||||
name: '手机号码风险',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG03HZ01.vue')),
|
||||
},
|
||||
G19BJ02: {
|
||||
name: '手机二次卡',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG19BJ02.vue')),
|
||||
},
|
||||
G02BJ02: {
|
||||
name: '手机在网时长',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG02BJ02.vue')),
|
||||
},
|
||||
CAR061: {
|
||||
name: '名下车辆',
|
||||
component: defineAsyncComponent(() => import('@/ui/CCAR061.vue')),
|
||||
}
|
||||
};
|
||||
|
||||
// 根据 product_id 获取产品名称
|
||||
function getProductName(productId) {
|
||||
return productMap[productId] || "未知类型";
|
||||
}
|
||||
|
||||
import LEmpty from "@/components/LEmpty.vue";
|
||||
|
||||
|
||||
const productId = ref(null);
|
||||
const isDone = ref(true);
|
||||
const entData = ref(null);
|
||||
const lawsuitData = ref(null);
|
||||
const badData = ref(null);
|
||||
const specialData = ref(null);
|
||||
const bankLoanApplicationData = ref(null);
|
||||
const marriageData = ref(null);
|
||||
const bankLoanBehavior = ref(null);
|
||||
const feature = ref(null);
|
||||
const token = ref(null);
|
||||
const tabs = ref([{ label: "报告概述", value: "overdiv" }]);
|
||||
const reportItems = ref([]);
|
||||
const sortedReportItems = computed(() => {
|
||||
return reportItems.value.slice().sort((a, b) => a.sort - b.sort);
|
||||
});
|
||||
const sortedTabs = computed(() => {
|
||||
return tabs.value.slice().sort((a, b) => a.sort - b.sort);
|
||||
});
|
||||
|
||||
const reportData = ref([])
|
||||
const reportParams = ref({})
|
||||
const reportName = ref("")
|
||||
const reportDateTime = ref(null)
|
||||
const feature = ref("")
|
||||
const isEmpty = ref(false)
|
||||
onMounted(() => {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
feature.value = query.get("feature");
|
||||
token.value = query.get("token") || "";
|
||||
console.log("feature", feature.value)
|
||||
|
||||
if (!feature.value) return;
|
||||
getReport()
|
||||
});
|
||||
|
||||
const { data, isFetching, error, onFetchResponse } = useFetch(
|
||||
`/api/v1/query/example?feature=${feature.value}`,
|
||||
{
|
||||
async beforeFetch({ url, options, cancel }) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: token.value,
|
||||
};
|
||||
|
||||
return {
|
||||
options,
|
||||
};
|
||||
},
|
||||
}
|
||||
)
|
||||
const getReport = async () => {
|
||||
let queryUrl = `/query/example?feature=${feature.value}`
|
||||
const { data, error } = await useApiFetch(queryUrl)
|
||||
.get()
|
||||
.json();
|
||||
.json()
|
||||
|
||||
onFetchResponse(() => {
|
||||
console.log("data", data.value);
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
if (data.value.data.product_name === '婚姻评估') {
|
||||
reportData.value = data.value.data.query_data.reverse()
|
||||
} else {
|
||||
reportData.value = data.value.data.query_data
|
||||
}
|
||||
productId.value = data.value.data.product_id;
|
||||
data.value.data.query_data.forEach((item) => {
|
||||
if (item.success) {
|
||||
switch (item.apiID) {
|
||||
case "G09SC02":
|
||||
marriageData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "婚姻状态",
|
||||
value: "marriage",
|
||||
sort: 1,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "婚姻状态",
|
||||
value: "marriage",
|
||||
sort: 1,
|
||||
});
|
||||
break;
|
||||
case "G27BJ05":
|
||||
bankLoanApplicationData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "借贷申请记录",
|
||||
value: "netloan",
|
||||
sort: 7,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "借贷申请记录",
|
||||
value: "netloan",
|
||||
sort: 7,
|
||||
});
|
||||
break;
|
||||
case "G28BJ05":
|
||||
bankLoanBehavior.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "借贷记录",
|
||||
value: "loan",
|
||||
sort: 6,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "借贷记录",
|
||||
value: "loan",
|
||||
sort: 6,
|
||||
});
|
||||
break;
|
||||
case "G26BJ05":
|
||||
specialData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "异常名单",
|
||||
value: "special",
|
||||
sort: 5,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "异常名单",
|
||||
value: "special",
|
||||
sort: 5,
|
||||
});
|
||||
break;
|
||||
case "G05HZ01":
|
||||
entData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "关联企业",
|
||||
value: "ent",
|
||||
sort: 4,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "关联企业",
|
||||
value: "ent",
|
||||
sort: 4,
|
||||
});
|
||||
break;
|
||||
case "G34BJ03":
|
||||
badData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "不良风险评估",
|
||||
value: "bad",
|
||||
sort: 3,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "不良风险评估",
|
||||
value: "bad",
|
||||
sort: 3,
|
||||
});
|
||||
break;
|
||||
case "G35SC01":
|
||||
lawsuitData.value = item.data;
|
||||
tabs.value.push({
|
||||
label: "涉诉案件",
|
||||
value: "lawsuit",
|
||||
sort: 2,
|
||||
});
|
||||
reportItems.value.push({
|
||||
label: "涉诉案件",
|
||||
value: "lawsuit",
|
||||
sort: 2,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
console.log(`未知的apiID: ${item.apiID}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
reportParams.value = data.value.data.query_params
|
||||
reportName.value = data.value.data.product_name
|
||||
reportDateTime.value = data.value.data.create_time
|
||||
} else if (data.value.code === 200003) {
|
||||
isEmpty.value = true
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
|
||||
<van-notice-bar color="#e03131" background="#ecf9ff" left-icon="info-o" text="由于全能查APP暂未上线,建议将此网站加入收藏夹或书签!!!" />
|
||||
<!-- <CTabs :tabs="sortedTabs" type="blue-green" /> -->
|
||||
<template v-if="isDone">
|
||||
<div class="flex flex-col gap-y-4 p-4 pt-12">
|
||||
<div class="flex flex-col gap-y-4 p-4">
|
||||
<div id="overdiv" class="title">报告概述</div>
|
||||
<div class="card">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">报告时间:</span>
|
||||
<span class="text-gray-600">2024年11月18日 23:11:23</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">报告项目:</span>
|
||||
<span class="text-gray-600">{{
|
||||
getProductName(productId)
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<LTitle class="my-4" title="报告内容" type="blue-green" />
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<div v-for="item in sortedReportItems" :key="item.value" class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">{{ item.label }}:</span>
|
||||
<span class="text-green-500 font-bold">已解锁</span>
|
||||
<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">2025-1-1 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?.nameMan">
|
||||
<span class="text-gray-700 font-bold">男方姓名</span>
|
||||
<span class="text-gray-600">{{ maskValue("name", reportParams?.nameMan) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.idCardMan">
|
||||
<span class="text-gray-700 font-bold">男方身份证号</span>
|
||||
<span class="text-gray-600">{{ maskValue("id_card", reportParams?.idCardMan)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.nameWoman">
|
||||
<span class="text-gray-700 font-bold">女方姓名</span>
|
||||
<span class="text-gray-600">{{ maskValue("name", reportParams?.nameWoman) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.idCardWoman">
|
||||
<span class="text-gray-700 font-bold">女方身份证号</span>
|
||||
<span class="text-gray-600">{{ maskValue("id_card", reportParams?.idCardWoman)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.bank_card">
|
||||
<span class="text-gray-700 font-bold">银行卡号</span>
|
||||
<span class="text-gray-600">{{ maskValue("bank_card", reportParams?.bank_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 justify-between border-b pb-2 pl-2"
|
||||
v-if="reportParams?.verification_code">
|
||||
<span class="text-gray-700 font-bold">验证码</span>
|
||||
<span class="text-gray-600">{{ maskValue("code", reportParams?.verification_code)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.car_license">
|
||||
<span class="text-gray-700 font-bold">车牌号</span>
|
||||
<span class="text-gray-600">{{ maskValue("car_license", reportParams?.car_license)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.ent_name">
|
||||
<span class="text-gray-700 font-bold">企业名称</span>
|
||||
<span class="text-gray-600">{{ maskValue("ent_name", reportParams?.ent_name)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.ent_code">
|
||||
<span class="text-gray-700 font-bold">企业代码</span>
|
||||
<span class="text-gray-600">{{ maskValue("ent_code", reportParams?.ent_code)
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="marriageData">
|
||||
<div id="marriage" class="title">婚姻状态</div>
|
||||
<CMarriage :data="marriageData" />
|
||||
</template>
|
||||
<template v-if="lawsuitData">
|
||||
<div id="lawsuit" class="title">涉诉案件</div>
|
||||
<CLawsuit :data="lawsuitData" />
|
||||
</template>
|
||||
<template v-if="badData">
|
||||
<div id="bad" class="title">不良风险评估</div>
|
||||
<CBad :data="badData" />
|
||||
</template>
|
||||
<template v-if="entData">
|
||||
<div id="ent" class="title">关联企业</div>
|
||||
<CRelatedEnterprises :data="entData" />
|
||||
</template>
|
||||
<template v-if="specialData">
|
||||
<div id="special" class="title">异常名单</div>
|
||||
<CSpecialList :data="specialData" />
|
||||
</template>
|
||||
<template v-if="bankLoanBehavior">
|
||||
<div id="loan" class="title">借贷记录</div>
|
||||
<CBankLoanBehavior :data="bankLoanBehavior" />
|
||||
</template>
|
||||
<template v-if="bankLoanApplicationData">
|
||||
<div id="netloan" class="title">贷款申请记录</div>
|
||||
<CBankLoanApplication :data="bankLoanApplicationData" />
|
||||
<LEmpty v-if="isEmpty" />
|
||||
<template v-for="(item, index) in reportData" :key="index">
|
||||
<div id="lawsuit" class="title">{{ featureMap[item.apiID].name }}</div>
|
||||
<component :is="featureMap[item.apiID].component" :data="item.data" :params="reportParams">
|
||||
</component>
|
||||
</template>
|
||||
<div class="card">
|
||||
<div>
|
||||
<div class="text-bold text-blue-500 mb-2">报告说明</div>
|
||||
<div>
|
||||
本报告的数据由用户本人明确授权后,我们才向相关合法存有用户个人数据的机构调取本报告相关内容,本平台只做大数据的获取与分析,仅向用户个人展示参考。
|
||||
本报告的数据由用户本人明确授权后,我们才向相关合法存有用户个人数据的机构调取本报告相关内容,本平台只做大数据的获取与分析,仅向用户个人展示参考。
|
||||
</div>
|
||||
<p>
|
||||
报告有效期<strong class="text-red-500">30天</strong>,过期自动删除。
|
||||
@ -247,15 +283,46 @@ onMounted(() => {
|
||||
|
||||
若您的数据不全面,可能是数据具有延迟性或者合作信息机构未获取到您的数据。若数据有错误请联系客服
|
||||
</p>
|
||||
<p>
|
||||
本产品所有数据均来自第三方。可能部分数据未公开、数据更新延迟或信息受到限制,贵司不对数据的准确性、真实性、完整性做任何承诺。用户需根据实际情况,结合报告内容自行判断与决策。
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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>琼公网安备46010002000443号</text>
|
||||
</div>
|
||||
<div>
|
||||
<a class="text-blue-500" href="https://beian.miit.gov.cn">
|
||||
琼ICP备2024038584号-2
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
海南省学宇思网络科技有限公司版权所有
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
@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;
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
/* margin-top: 24px; */
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
padding-bottom: 60px;
|
||||
background: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
130
src/views/HistoryQuery.vue
Normal file
@ -0,0 +1,130 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
const router = useRouter()
|
||||
const page = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const total = ref(0)
|
||||
const reportList = ref([])
|
||||
const num = ref(0)
|
||||
const max = ref(60)
|
||||
const loading = ref(false)
|
||||
const finished = ref(false)
|
||||
// 初始加载数据
|
||||
async function fetchData() {
|
||||
// { page: page.value, page_size: pageSize.value }
|
||||
loading.value = true
|
||||
const { data, error } = await useApiFetch(`query/list?page=${page.value}&page_size=${pageSize.value}`)
|
||||
.get()
|
||||
.json()
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
total.value = data.value.data.total
|
||||
if (data.value.data.list && data.value.data.list.length > 0) {
|
||||
reportList.value.push(...data.value.data.list)
|
||||
page.value += 1
|
||||
}
|
||||
if (reportList.value.length >= total.value) {
|
||||
finished.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
|
||||
}
|
||||
|
||||
// 初始加载
|
||||
onMounted(() => {
|
||||
fetchData()
|
||||
})
|
||||
|
||||
// 下拉触底加载更多
|
||||
const onLoad = () => {
|
||||
if (!finished.value) {
|
||||
console.log("finished", finished.value)
|
||||
if (num.value >= max.value) {
|
||||
finished.value = true
|
||||
} else {
|
||||
fetchData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toDetail(item) {
|
||||
router.push({ path: '/report', query: { orderId: item.order_id } });
|
||||
}
|
||||
|
||||
// 状态文字映射
|
||||
function stateText(state) {
|
||||
switch (state) {
|
||||
case 'pending':
|
||||
return '查询中'
|
||||
case 'success':
|
||||
return '查询成功'
|
||||
case 'failed':
|
||||
return '查询失败'
|
||||
default:
|
||||
return '未知状态'
|
||||
}
|
||||
}
|
||||
|
||||
// 状态颜色映射
|
||||
function statusClass(state) {
|
||||
switch (state) {
|
||||
case 'pending':
|
||||
return 'status-pending'
|
||||
case 'success':
|
||||
return 'status-success'
|
||||
case 'failed':
|
||||
return 'status-failed'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Vant 通知栏 -->
|
||||
<van-notice-bar color="#1989fa" background="#ecf9ff" left-icon="info-o"
|
||||
text="为保证用户的隐私以及数据安全,您的报告生成30天之后将自动清除,请及时保存您的报告。" />
|
||||
|
||||
<div class="flex flex-col gap-4 p-4">
|
||||
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad"><van-cell
|
||||
v-for="item in reportList" :key="item.id" @click="toDetail(item)" class="card mb-4">
|
||||
<div class=" text-gray-600 flex flex-col gap-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>状态:</div>
|
||||
<div class="rounded-xl px-2 py-1" :class="[statusClass(item.query_state)]">
|
||||
{{ stateText(item.query_state) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>报告类型</div>
|
||||
<div>{{ item.product_name }}</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>查询时间:</div>
|
||||
<div>{{ item.create_time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-cell>
|
||||
</van-list>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.status-pending {
|
||||
background-color: #fff3cd;
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
.status-success {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.status-failed {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
</style>
|
@ -1,42 +1,30 @@
|
||||
<template>
|
||||
<div class="font-sans text-gray-800">
|
||||
<!-- 头部导航 -->
|
||||
<header
|
||||
class="flex justify-between items-center bg-blue-100 p-4 border-b border-blue-200"
|
||||
>
|
||||
<header class="flex justify-between items-center bg-blue-100 p-4 border-b border-blue-200">
|
||||
<div class="text-2xl font-bold text-blue-700">全能查 APP</div>
|
||||
<button
|
||||
class="lg:hidden text-blue-700 text-2xl focus:outline-none transition-transform transform hover:scale-110"
|
||||
@click="toggleMenu"
|
||||
>
|
||||
@click="toggleMenu">
|
||||
<span v-if="!isMenuOpen">☰</span>
|
||||
<span v-else>✕</span>
|
||||
</button>
|
||||
<nav
|
||||
:class="`lg:flex lg:items-center lg:gap-6 ${
|
||||
isMenuOpen
|
||||
? 'flex flex-col items-end absolute top-16 right-0 bg-blue-100 w-full shadow-md py-4 px-6'
|
||||
: 'hidden'
|
||||
}`"
|
||||
>
|
||||
<a
|
||||
href="#support"
|
||||
class="text-blue-700 hover:text-blue-500 transition-colors"
|
||||
@click="toggleMenu"
|
||||
>联系我们</a
|
||||
>
|
||||
<nav :class="`lg:flex lg:items-center lg:gap-6 ${isMenuOpen
|
||||
? 'flex flex-col items-end absolute top-16 right-0 bg-blue-100 w-full shadow-md py-4 px-6'
|
||||
: 'hidden'
|
||||
}`">
|
||||
<a href="#support" class="text-blue-700 hover:text-blue-500 transition-colors"
|
||||
@click="toggleMenu">联系我们</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<!-- 横幅 -->
|
||||
<section
|
||||
class="text-center py-16 bg-gradient-to-r from-blue-100 to-blue-200 text-blue-800"
|
||||
>
|
||||
<section class="text-center py-16 bg-gradient-to-r from-blue-100 to-blue-200 text-blue-800">
|
||||
<h1 class="text-4xl lg:text-5xl font-bold mb-4 animate-fade-in">
|
||||
防范风险,从全能查开始
|
||||
</h1>
|
||||
<p class="text-lg lg:text-xl mb-6 animate-fade-in delay-200">
|
||||
全能查 APP,为您的安全保驾护航
|
||||
全能查,为您的安全保驾护航
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@ -44,21 +32,12 @@
|
||||
<section id="features" class="py-16 bg-blue-50 text-center">
|
||||
<h2 class="text-3xl font-bold text-blue-700 mb-6">APP 预览</h2>
|
||||
<div class="flex flex-wrap justify-center gap-6">
|
||||
<img
|
||||
class="shadow-lg rounded-lg transition-transform transform hover:scale-105 h-96 object-contain"
|
||||
src="/image/app_1.jpg"
|
||||
alt="APP preview"
|
||||
/>
|
||||
<img
|
||||
class="shadow-lg rounded-lg transition-transform transform hover:scale-105 h-96 object-contain"
|
||||
src="/image/app_2.jpg"
|
||||
alt="APP preview"
|
||||
/>
|
||||
<img
|
||||
class="shadow-lg rounded-lg transition-transform transform hover:scale-105 h-96 object-contain"
|
||||
src="/image/app_3.jpg"
|
||||
alt="APP preview"
|
||||
/>
|
||||
<img class="shadow-lg rounded-lg transition-transform transform hover:scale-105 h-96 object-contain"
|
||||
src="/image/app_1.jpg" alt="APP preview" />
|
||||
<img class="shadow-lg rounded-lg transition-transform transform hover:scale-105 h-96 object-contain"
|
||||
src="/image/app_2.jpg" alt="APP preview" />
|
||||
<img class="shadow-lg rounded-lg transition-transform transform hover:scale-105 h-96 object-contain"
|
||||
src="/image/app_3.jpg" alt="APP preview" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -68,9 +47,7 @@
|
||||
<p class="text-lg text-blue-800 mb-2">
|
||||
如需帮助,请通过以下邮箱联系我们:
|
||||
</p>
|
||||
<p
|
||||
class="text-blue-700 underline hover:text-blue-500 transition-colors"
|
||||
>
|
||||
<p class="text-blue-700 underline hover:text-blue-500 transition-colors">
|
||||
<a href="mailto:admin@iieeii.com">admin@iieeii.com</a>
|
||||
</p>
|
||||
</section>
|
||||
@ -78,11 +55,8 @@
|
||||
<!-- 页脚 -->
|
||||
<footer class="bg-blue-200 text-gray-700 text-center py-4">
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
<img
|
||||
src="https://qcloudimg.tencent-cloud.cn/raw/eed02831a0e201b8d794c8282c40cf2e.png"
|
||||
alt="网安 icon"
|
||||
class="w-6 h-6"
|
||||
/>
|
||||
<img src="https://qcloudimg.tencent-cloud.cn/raw/eed02831a0e201b8d794c8282c40cf2e.png" alt="网安 icon"
|
||||
class="w-6 h-6" />
|
||||
<p class="text-sm">
|
||||
琼公网安备 46010002000443 号 | 琼ICP备 2024038584 号-2
|
||||
</p>
|
||||
@ -107,17 +81,21 @@ function toggleMenu() {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fade-in 1s ease-out;
|
||||
}
|
||||
|
||||
.animate-fade-in.delay-200 {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.animate-fade-in.delay-400 {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
@ -1,21 +1,34 @@
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted, onUnmounted } from "vue";
|
||||
import { aesEncrypt } from '@/utils/crypto'
|
||||
import { aesEncrypt } from "@/utils/crypto";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useWebView } from "@/composables/useWebView";
|
||||
|
||||
import Authorization from "@/components/Authorization.vue";
|
||||
import Payment from "@/components/Payment.vue";
|
||||
import CarNumberInput from "@/components/CarNumberInput.vue";
|
||||
|
||||
const route = useRoute();
|
||||
useWebView()
|
||||
|
||||
const showAuthorizationPopup = ref(false)
|
||||
const authorization = ref(false)
|
||||
const showPayment = ref(false)
|
||||
const queryId = ref(null)
|
||||
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("");
|
||||
@ -24,11 +37,102 @@ 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 }) => {
|
||||
console.log("selectedValues", selectedValues)
|
||||
console.log("startDate", startDate.value)
|
||||
dateVal.value = selectedOptions.map(item => item.text).join('');
|
||||
showDatePicker.value = false
|
||||
}
|
||||
const carLicenseChange = (e) => {
|
||||
console.log("carLicenseChange", e);
|
||||
carLicense.value = e;
|
||||
};
|
||||
const onConfirmCarType = ({ selectedValues, selectedOptions }) => {
|
||||
console.log(
|
||||
"selectedValues, selectedOptions",
|
||||
selectedValues,
|
||||
selectedOptions
|
||||
);
|
||||
showCarTypePicker.value = false;
|
||||
carPickerVal.value = selectedValues;
|
||||
carType.value = selectedOptions[0].text;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getProduct()
|
||||
initAuthorization()
|
||||
// discountPriceInit()
|
||||
isFinishPayment()
|
||||
getProduct();
|
||||
initAuthorization();
|
||||
});
|
||||
const discountPrice = ref(false) // 是否应用折扣
|
||||
// const discountPriceInit = () => {
|
||||
// let m = localStorage.getItem("m")
|
||||
// let hour = "12"
|
||||
// if (m === "shifenliangzai") {
|
||||
// hour = "00"
|
||||
// }
|
||||
// const currentDate = new Date()
|
||||
// const startDate = new Date(`2025-01-01T${hour}:00:00+08:00`) // 2025年1月1日中午12点
|
||||
// const endDate = new Date('2025-01-02T12:00:00+08:00') // 2025年1月2日中午12点
|
||||
// console.log(startDate, endDate)
|
||||
// if (currentDate >= startDate && currentDate <= endDate) {
|
||||
// discountPrice.value = true // 在折扣时间范围内,启用折扣
|
||||
// } else {
|
||||
// discountPrice.value = 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()
|
||||
@ -39,33 +143,127 @@ async function getProduct() {
|
||||
}
|
||||
}
|
||||
function initAuthorization() {
|
||||
if (noAuthorization.includes(feature.value)) {
|
||||
authorization.value = true
|
||||
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: "请阅读并同意用户协议和隐私政策" });
|
||||
showToast({ message: `请阅读并同意用户协议、隐私政策${!NeedAuthorization.includes(feature.value) ? '和授权书' : ''}` });
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!validateField('name', name.value, v => v, '请输入姓名') ||
|
||||
!validateField('mobile', mobile.value, v => isPhoneNumberValid.value, '请输入有效的手机号') ||
|
||||
!validateField('idCard', idCard.value, v => isIdCardValid.value, '请输入有效的身份证号码') ||
|
||||
!validateField('verificationCode', verificationCode.value, v => v, '请输入验证码') ||
|
||||
!validateField('entName', entName.value, v => v, '请输入企业名称') ||
|
||||
!validateField('entCode', entCode.value, v => isCreditCodeValid.value, '请输入统一社会信用代码')
|
||||
!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()
|
||||
submitRequest();
|
||||
}
|
||||
const validateField = (field, value, validationFn, errorMessage) => {
|
||||
if (isHasInput(field) && !validationFn(value)) {
|
||||
@ -73,59 +271,95 @@ const validateField = (field, value, validationFn, errorMessage) => {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const defaultInput = ["name", "mobile", "idCard", "verificationCode"]
|
||||
const defaultInput = ["name", "idCard", "mobile", "verificationCode"];
|
||||
const specialProduct = {
|
||||
"toc_EnterpriseLawsuit": ["entName", "entCode", "mobile", "verificationCode"]
|
||||
}
|
||||
const noAuthorization = ["toc_EnterpriseLawsuit"]
|
||||
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"
|
||||
];
|
||||
const isHasInput = (input) => {
|
||||
if (specialProduct[feature.value]) {
|
||||
return specialProduct[feature.value].includes(input)
|
||||
return specialProduct[feature.value].includes(input);
|
||||
} else {
|
||||
return defaultInput.includes(input)
|
||||
return defaultInput.includes(input);
|
||||
}
|
||||
}
|
||||
};
|
||||
async function submitRequest() {
|
||||
const req = {}
|
||||
if (isHasInput('name')) {
|
||||
req.name = name.value
|
||||
const req = {};
|
||||
if (isHasInput("name")) {
|
||||
req.name = name.value;
|
||||
}
|
||||
if (isHasInput('id_card')) {
|
||||
req.id_card = idCard.value
|
||||
if (isHasInput("idCard")) {
|
||||
req.id_card = idCard.value;
|
||||
}
|
||||
if (isHasInput('mobile')) {
|
||||
req.mobile = mobile.value
|
||||
if (isHasInput("nameMan")) {
|
||||
req.name_man = nameMan.value;
|
||||
}
|
||||
if (isHasInput('verificationCode')) {
|
||||
req.code = verificationCode.value
|
||||
if (isHasInput("idCardMan")) {
|
||||
req.id_card_man = idCardMan.value;
|
||||
}
|
||||
if (isHasInput('entName')) {
|
||||
req.ent_name = entName.value
|
||||
if (isHasInput("nameWoman")) {
|
||||
req.name_woman = nameWoman.value;
|
||||
}
|
||||
if (isHasInput('entCode')) {
|
||||
req.ent_code = entCode.value
|
||||
if (isHasInput("idCardWoman")) {
|
||||
req.id_card_woman = idCardWoman.value;
|
||||
}
|
||||
const reqStr = JSON.stringify(req)
|
||||
const encodeData = aesEncrypt(reqStr, 'ff83609b2b24fc73196aac3d3dfb874f')
|
||||
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, "ff83609b2b24fc73196aac3d3dfb874f");
|
||||
const { data, error } = await useApiFetch(`/query/service/${feature.value}`)
|
||||
.post({ data: encodeData })
|
||||
.json();
|
||||
if (data.value.code === 200) {
|
||||
queryId.value = data.value.data.id
|
||||
queryId.value = data.value.data.id;
|
||||
if (authorization.value) {
|
||||
showPayment.value = true
|
||||
showPayment.value = true;
|
||||
} else {
|
||||
showAuthorizationPopup.value = true
|
||||
showAuthorizationPopup.value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function sendVerificationCode() {
|
||||
if (isCountingDown.value || !isPhoneNumberValid.value)
|
||||
return
|
||||
if (isCountingDown.value || !isPhoneNumberValid.value) return;
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "请输入有效的手机号" });
|
||||
return;
|
||||
@ -157,30 +391,29 @@ function startCountdown() {
|
||||
}, 1000);
|
||||
}
|
||||
function toUserAgreement() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/userAgreement'
|
||||
})
|
||||
router.push(`/userAgreement`)
|
||||
}
|
||||
|
||||
function toPrivacyPolicy() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/privacyPolicy'
|
||||
})
|
||||
router.push(`/privacyPolicy`)
|
||||
}
|
||||
|
||||
function toAuthorization() {
|
||||
router.push(`/authorization`)
|
||||
}
|
||||
// 用户同意
|
||||
const agreed = () => {
|
||||
showAuthorizationPopup.value = false
|
||||
authorization.value = true
|
||||
showPayment.value = true
|
||||
showAuthorizationPopup.value = false;
|
||||
authorization.value = true;
|
||||
showPayment.value = true;
|
||||
};
|
||||
|
||||
// 用户取消
|
||||
const cancel = () => {
|
||||
showAuthorizationPopup.value = false
|
||||
showAuthorizationPopup.value = false;
|
||||
};
|
||||
const toExample = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/example'
|
||||
})
|
||||
router.push(`/example?feature=${feature.value}`)
|
||||
};
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
@ -194,7 +427,6 @@ onUnmounted(() => {
|
||||
<div class="mb-6 text-center text-3xl font-bold text-blue-700">
|
||||
{{ featureData.product_name }}
|
||||
</div>
|
||||
|
||||
<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')">
|
||||
@ -205,6 +437,25 @@ onUnmounted(() => {
|
||||
<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" />
|
||||
@ -213,10 +464,38 @@ onUnmounted(() => {
|
||||
<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">
|
||||
@ -224,7 +503,11 @@ onUnmounted(() => {
|
||||
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重新获取` : '获取验证码' }}
|
||||
{{
|
||||
isCountingDown
|
||||
? `${countdown}s重新获取`
|
||||
: "获取验证码"
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -233,8 +516,11 @@ onUnmounted(() => {
|
||||
<input type="checkbox" v-model="agreeToTerms" />
|
||||
<span class="ml-2 text-xs text-gray-400">
|
||||
我已阅读并同意
|
||||
<span @click="toUserAgreement" class="text-blue-500 underline">用户协议</span>和
|
||||
<span @click="toPrivacyPolicy" class="text-blue-500 underline">隐私政策</span>
|
||||
<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">
|
||||
@ -247,36 +533,44 @@ onUnmounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-4">
|
||||
<div class="mb-6 text-xl text-gray-800 font-bold">
|
||||
<div class="mb-4 text-xl text-gray-800 font-bold">
|
||||
{{ featureData.product_name }}
|
||||
</div>
|
||||
<div class="mb-4 flex items-start justify-between">
|
||||
<div class="text-lg text-gray-500">价格:</div>
|
||||
<div>
|
||||
<div v-if="discountPrice" class="line-through text-gray-500" :class="{ 'text-lg': discountPrice }">
|
||||
¥ {{ featureData.sell_price }}
|
||||
</div>
|
||||
<div class="text-2xl text-red-600 font-semibold">
|
||||
¥{{ discountPrice ? (featureData.sell_price * 0.2).toFixed(2) : featureData.sell_price }}
|
||||
</div>
|
||||
|
||||
<div class="mb-4 text-gray-600 leading-relaxed">
|
||||
{{ featureData.description }}
|
||||
</div>
|
||||
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<div class="text-lg text-gray-500">
|
||||
价格:
|
||||
</div>
|
||||
<div class="text-lg text-blue-600 font-semibold">
|
||||
¥{{ featureData.sell_price }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="discountPrice" class="text-sm text-right text-red-500 mb-4">
|
||||
限时活动价:2折优惠
|
||||
</div>
|
||||
<div class="mb-4 text-gray-600 leading-relaxed" v-html="featureData.description">
|
||||
|
||||
<div class="mb-4 text-lg text-gray-800 font-semibold">
|
||||
报告主要内容
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div v-for="(feature, index) in featureData.features" :key="feature.id"
|
||||
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium" :class="[
|
||||
(Math.floor(index / 2) + (index % 2)) % 2 === 0
|
||||
? 'bg-gradient-to-r from-blue-200 via-blue-200 to-blue-100'
|
||||
: 'bg-gradient-to-r from-sky-200 via-sky-200 to-sky-100',
|
||||
]">
|
||||
{{ feature.name }}
|
||||
|
||||
|
||||
<template v-if="featureData.features && featureData.features.length > 1">
|
||||
<div class="mb-4 text-lg text-gray-800 font-semibold">
|
||||
报告包含内容
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div v-for="(feature, index) in featureData.features" :key="feature.id"
|
||||
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium" :class="[
|
||||
(Math.floor(index / 2) + (index % 2)) % 2 === 0
|
||||
? 'bg-gradient-to-r from-blue-200 via-blue-200 to-blue-100'
|
||||
: 'bg-gradient-to-r from-sky-200 via-sky-200 to-sky-100',
|
||||
]">
|
||||
{{ feature.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部弹出 -->
|
||||
@ -292,12 +586,16 @@ onUnmounted(() => {
|
||||
@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;
|
||||
}
|
||||
|
||||
.inquire-bg {
|
||||
background: url("@/assets/images/inquire_banner_2.png") no-repeat;
|
||||
background: url("@/assets/images/bg_2.png") no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
209
src/views/Login.vue
Normal file
@ -0,0 +1,209 @@
|
||||
<script setup>
|
||||
import { ref, computed, onUnmounted } from 'vue'
|
||||
const router = useRouter()
|
||||
const phoneNumber = ref('')
|
||||
const verificationCode = ref('')
|
||||
const password = ref('')
|
||||
const isPasswordLogin = ref(false)
|
||||
const isAgreed = ref(false)
|
||||
const isCountingDown = ref(false)
|
||||
const countdown = ref(60)
|
||||
let timer = null
|
||||
|
||||
// 聚焦状态变量
|
||||
const phoneFocused = ref(false)
|
||||
const codeFocused = ref(false)
|
||||
const passwordFocused = ref(false)
|
||||
|
||||
const isPhoneNumberValid = computed(() => {
|
||||
return /^1[3-9]\d{9}$/.test(phoneNumber.value)
|
||||
})
|
||||
|
||||
const canLogin = computed(() => {
|
||||
if (!isPhoneNumberValid.value) return false
|
||||
if (isPasswordLogin.value) {
|
||||
return password.value.length >= 6
|
||||
} else {
|
||||
return verificationCode.value.length === 6
|
||||
}
|
||||
})
|
||||
|
||||
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: 'login' })
|
||||
.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 handleLogin() {
|
||||
if (!isPhoneNumberValid.value) {
|
||||
showToast({ message: "请输入有效的手机号" });
|
||||
return
|
||||
}
|
||||
if (isPasswordLogin.value) {
|
||||
if (password.value.length < 6) {
|
||||
showToast({ message: "密码长度不能小于6位" });
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (verificationCode.value.length !== 6) {
|
||||
showToast({ message: "请输入有效的验证码" });
|
||||
}
|
||||
}
|
||||
if (!isAgreed.value) {
|
||||
showToast({ message: "请先同意用户协议" });
|
||||
return
|
||||
}
|
||||
|
||||
const { data, error } = await useApiFetch('/user/mobileCodeLogin')
|
||||
.post({ mobile: phoneNumber.value, code: verificationCode.value })
|
||||
.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)
|
||||
// if (phoneNumber.value === "18276151590") {
|
||||
// localStorage.setItem('m', "shifenliangzai")
|
||||
// }
|
||||
window.location.href = '/'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toUserAgreement() {
|
||||
router.push(`/userAgreement`)
|
||||
}
|
||||
|
||||
function toPrivacyPolicy() {
|
||||
router.push(`/privacyPolicy`)
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
})
|
||||
const onClickLeft = () => {
|
||||
router.replace('/')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="login-layout ">
|
||||
<van-nav-bar fixed placeholder title="用户登录" left-text="" left-arrow @click-left="onClickLeft" />
|
||||
<div class="login 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="@/assets/images/logo.png" alt="Logo" />
|
||||
<img class="mt-4 h-10" src="@/assets/images/logo_title.png" alt="Title" />
|
||||
</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 v-if="!isPasswordLogin">
|
||||
<div class="flex items-center justify-between">
|
||||
<div :class="['input-container bg-blue-300/20', codeFocused ? 'focused' : '']">
|
||||
<input v-model="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>
|
||||
|
||||
<!-- 密码输入 -->
|
||||
<div v-if="isPasswordLogin" :class="['input-container', passwordFocused ? 'focused' : '']">
|
||||
<input v-model="password" class="input-field" type="password" placeholder="请输入密码"
|
||||
@focus="passwordFocused = true" @blur="passwordFocused = false" />
|
||||
</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-20 w-full py-3 text-lg font-bold text-white bg-blue-500 rounded-full transition duration-300"
|
||||
@click="handleLogin">
|
||||
登录
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.login-layout {
|
||||
background: url("@/assets/images/login_bg.png") no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
border: 2px solid rgba(125, 211, 252, 0.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>
|
129
src/views/Me.vue
Normal file
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="box-border min-h-screen from-blue-100 to-white bg-gradient-to-b">
|
||||
<div class="flex flex-col p-4">
|
||||
<!-- Profile Section -->
|
||||
<div class="profile-section mb-4 flex items-center gap-4 rounded-md bg-white p-4 shadow-md"
|
||||
@click="!isLoggedIn ? redirectToLogin() : null">
|
||||
<img :src="userAvatar" alt="User Avatar" class="rounded-full" width="100" height="100" />
|
||||
<div>
|
||||
<h2 class="text-lg font-bold">
|
||||
{{ isLoggedIn ? maskName(userName) : '点击登录' }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Divider (Optional) -->
|
||||
<hr />
|
||||
|
||||
<!-- Features Section -->
|
||||
<div class="features-section flex flex-col gap-2">
|
||||
<div v-for="(feature, index) in features" :key="index"
|
||||
class="feature-item rounded-md bg-white p-3 shadow-sm cursor-pointer" @click="feature.action">
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- <van-icon :name="feature.icon" /> -->
|
||||
<span>{{ feature.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
const router = useRouter()
|
||||
const userName = ref('点击登录')
|
||||
const userAvatar = ref('https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180')
|
||||
const isLoggedIn = ref(false)
|
||||
const features = ref([
|
||||
{ title: '我的报告', icon: 'list', action: () => toHistory() },
|
||||
{ title: '联系客服', icon: 'service-o', action: () => toService() },
|
||||
{ title: '用户协议', icon: 'file', action: () => toUserAgreement() },
|
||||
{ title: '退出登录', icon: 'logout', action: () => handleLogout() },
|
||||
])
|
||||
|
||||
const maskName = computed(() => {
|
||||
return (name) => {
|
||||
return name.substring(0, 3) + "****" + name.substring(7);
|
||||
}
|
||||
})
|
||||
function toHistory() {
|
||||
router.push(`/historyQuery`)
|
||||
}
|
||||
|
||||
function toUserAgreement() {
|
||||
router.push(`/userAgreement`)
|
||||
}
|
||||
|
||||
function redirectToLogin() {
|
||||
router.push(`/login`)
|
||||
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
localStorage.removeItem('token') // 使用浏览器的 localStorage 来存储 token
|
||||
isLoggedIn.value = false
|
||||
userName.value = '点击登录'
|
||||
userAvatar.value = 'https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180'
|
||||
}
|
||||
|
||||
function toService() {
|
||||
window.location.href = '/service' // 跳转到客服页面
|
||||
}
|
||||
|
||||
async function fetchUserInfo() {
|
||||
const { data, error } = await useApiFetch('/user/detail')
|
||||
.get()
|
||||
.json()
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
const userinfo = data.value.data.userInfo
|
||||
userName.value = userinfo.nickName || ''
|
||||
userAvatar.value = userinfo.userAvatar || 'https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180'
|
||||
isLoggedIn.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const safeAreaTop = ref(0)
|
||||
onMounted(() => {
|
||||
const token = localStorage.getItem('token') // 使用 localStorage 获取 token
|
||||
if (token) {
|
||||
isLoggedIn.value = true
|
||||
fetchUserInfo()
|
||||
} else {
|
||||
isLoggedIn.value = false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.profile-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.features-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
background-color: white;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.feature-item:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
</style>
|
@ -1,6 +1,5 @@
|
||||
<script setup>
|
||||
import { useWebView } from "@/composables/useWebView";
|
||||
useWebView()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -95,30 +94,7 @@ useWebView()
|
||||
当您在使用全能查服务过程中,为向您提供您需求的全能查软件服务、交互展示、搜索结果、识别账号异常状态,维护全能查服务的正常运行,改进及优化您对全能查服务的体验并保障您的账号安全,包括您使用全能查服务以及使用方式的信息,并将这些信息进行关联:
|
||||
</div>
|
||||
<div class="leading-relaxed">
|
||||
<div>1、使用信息:</div>
|
||||
<div>
|
||||
在提供服务过程中,为了保证您能正常使用产品功能,我们可能会向系统申请您的设备权限,可能包括但不限于IMEI、IMSI、设备MAC地址、软件列表、设备序列号、android
|
||||
ID等。申请前我们会通过弹窗或页面说明的方式征询您的同意,你可以选择“允许”或“禁止”权限申请。因少量设备厂商在应用安装时就默认您给予了部分基础权限,不支持弹窗确认功能,具体我们建议您关注您的设备功能说明及权限列表,如您不同意给我们这些权限的,您可以及时通过设备中设置的路径取消对我们的授权;支持弹窗功能的设备权限申请成功后,您可以随时进入设备“设置-权限管理”中关闭相应权限,权限关闭后相关产品功能可能无法正常使用。在不同设备中,权限显示方式及关闭方式可能有所不同,具体请您参考设备及系统开发方说明或指引。
|
||||
</div>
|
||||
<div>
|
||||
提供服务过程中主要涉及的访问权限如下:
|
||||
基于设备相机及相册权限的附加功能:出于您的使用需求,当您需要在使用在线客服的相机、相册时,我们需要取得您的设备相机或相册权限,并收集您提供的图文和/或视频信息。如您拒绝提供仅会使您无法在相关功能中添加图片和/或视频,但并不影响您正常使用其他功能。
|
||||
</div>
|
||||
<div>
|
||||
基于设备麦克风权限的附加功能:若您需要在使用客服电话服务时,我们需要取得您的设备麦克风权限,并收集您的语音信息。如您拒绝提供仅会使您无法使用相关语音功能,但并不影响您正常使用其他功能。
|
||||
</div>
|
||||
<div>
|
||||
您理解并同意,前述涉及设备权限(相机(摄像头)、相册、麦克风、通讯录、)的授权需要您在您的设备中打开相关访问权限,以实现这些权限所涉及信息的收集与使用。您亦可以在您的设备中查看或调整前述权限状态。您了解并知悉,一旦您开启权限则表示您授权我们可以收集和使用相关个人信息来为您提供相关服务;一旦您关闭该权限则表示您取消了授权,我们将不再基于该权限继续收集和使用相关个人信息,也无法为您提供对应的服务与功能。但是,您的关闭行为并不会影响此前基于您的授权行为所进行的信息收集与使用。
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-relaxed">
|
||||
<div>2、设备信息:</div>
|
||||
<div>
|
||||
我们会根据您在软件安装及使用中授予的具体权限,接收并记录您所使用的设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、GPS/北斗位置信息以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息)。
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-relaxed">
|
||||
<div>3、日志信息:</div>
|
||||
<div>1、日志信息:</div>
|
||||
<div>
|
||||
当您使用我们的网站或客户端提供的产品或服务时,我们会自动收集您对我们服务的详细使用情况,作为有关网络日志保存。例如您的搜索查询内容、IP地址、使用的语言、访问日期和时间、您访问的网页记录、日志信息。
|
||||
</div>
|
||||
@ -127,180 +103,14 @@ useWebView()
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-relaxed">
|
||||
<div>4、您向我们提供的信息:</div>
|
||||
<div>2、您向我们提供的信息:</div>
|
||||
<div>
|
||||
在服务使用过程中,您可以对全能查产品及服务的体验问题反馈,帮助我们更好地了解您使用我们产品或服务的体验和需求,改善我们产品或服务,为此我们会记录您的联系信息、反馈的问题或建议,以便我们进一步联系您反馈您我们的处理意见。
|
||||
为向您提供更好的服务,例如在不同的服务端或设备上提供体验一致的服务和您需求的客服接待,了解产品适配性,识别账号异常状态。
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-relaxed">
|
||||
<div>5、第三方软件开发包(SDK):</div>
|
||||
<div>
|
||||
我们产品中可能会包含第三方SDK或其他类似的应用程序,如您在我们平台上使用这类由第三方提供的服务时,您同意将由其直接收集和处理您的信息(如以嵌入代码、插件等形式),例如:当您使用支付宝账号授权我们的产品时,支付宝SDK需要收集您的账号信息。前述服务商收集和处理信息等行为遵守其自身的隐私条款,而不适用于本政策。但我们也会努力审查该第三方的业务准入资质并努力要求该服务商的合法合规性与安全性。为了最大程度保障您的信息安全,我们强烈建议您在使用任何第三方SDK类服务前先行查看其隐私条款。为保障您的合法权益,如您发现这等SDK或其他类似的应用程序存在风险时,建议您立即终止相关操作并及时与我们取得联系;
|
||||
</div>
|
||||
<div>以下是我们目前接入的第三方SDK类服务商的信息:</div>
|
||||
<div class="mb-4">
|
||||
<div class="mb-2 text-center text-xl font-bold leading-relaxed">
|
||||
权限清单
|
||||
</div>
|
||||
<div class="w-full table border-collapse border border-gray-300">
|
||||
<div class="table-row bg-gray-100">
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
权限名称
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
权限功能说明
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
使用场景或目的
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
使用平台
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
读取/写入外置存储
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
读取和写入设备储存空间内的数据
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
用于保障全能查的稳定运行,以便用户在使用功能时可读取、写入/下载/保存/修改图片、文件、崩溃日志等信息
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
Android、iOS
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
位置
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
通过GPS或网络位置信息获取设备所在的地理位置信息
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
用于安全保障、提供精准服务和内容
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
Android、iOS
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
摄像头
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
使用摄像头拍摄图片
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
用于完成照片的拍摄和发布
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
Android、iOS
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
读取/写入相册
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
读取和写入设备相册中的内容
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
用于设置头像图片,以及完成照片的发布
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
Android、iOS
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="mb-2 text-center text-xl font-bold leading-relaxed">
|
||||
Android操作系统第三方SDK列表
|
||||
</div>
|
||||
<div class="w-full table border-collapse border border-gray-300">
|
||||
<div class="table-row bg-gray-100">
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
第三方SDK名称
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
应用场景
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
收集个人信息的类型
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
第三方SDK提供方
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
隐私政策链接
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
支付宝SDK
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
提供支付宝支付、提现能力
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
网络状态信息、设备信息、本机号码
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
支付宝
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 text-blue-500">
|
||||
<a href="https://render.alipay.com/p/c/k2cx0tg8" target="_blank">查看隐私政策</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="mb-2 text-center text-xl font-bold leading-relaxed">
|
||||
IOS操作系统第三方SDK列表
|
||||
</div>
|
||||
<div class="w-full table border-collapse border border-gray-300">
|
||||
<div class="table-row bg-gray-100">
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
第三方SDK名称
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
应用场景
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
收集个人信息的类型
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
第三方SDK提供方
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 font-bold">
|
||||
隐私政策链接
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
支付宝SDK
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
提供支付宝支付、提现能力
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
网络状态信息、设备信息、本机号码
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2">
|
||||
支付宝
|
||||
</div>
|
||||
<div class="table-cell border border-gray-300 p-2 text-blue-500">
|
||||
<a href="https://render.alipay.com/p/c/k2cx0tg8" target="_blank">查看隐私政策</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-relaxed">
|
||||
<div>6、为您提供安全保障收集信息:</div>
|
||||
<div>3、为您提供安全保障收集信息:</div>
|
||||
<div>
|
||||
为预防、发现、调查欺诈、侵权、危害安全、非法或违反与我们或与我们关联公司的协议、政策或规则的行为,我们可能收集或整合您的用户个人信息、服务使用信息、设备信息、日志信息以及我们关联公司、合作伙伴取得您授权或依据法律共享的信息。
|
||||
您理解并同意,我们向您提供的功能和服务场景是不断迭代升级的,如我们未在上述场景中明示您需要收集的个人信息,我们将会通过页面提示、交互设计等方式另行向您明示信息收集的内容、范围和目的并征得您同意。
|
||||
@ -309,6 +119,18 @@ useWebView()
|
||||
如我们停止运营全能查产品或服务,我们将及时停止继续收集您个人信息的活动,将停止运营的通知以公告或短信的形式通知您,并依照所适用的法律对所持有的您的个人信息进行删除或匿名化处理。
|
||||
</div>
|
||||
</div>
|
||||
<div class="leading-relaxed">
|
||||
<div>4、手机号码收集及其用途:</div>
|
||||
<div>
|
||||
在您使用全能查服务的过程中,我们可能会要求您提供手机号码。我们收集您的手机号码,主要是为了向您发送重要的通知、服务更新、账户安全信息、促销活动、服务相关的短信等。为了确保您能及时获得关于您账号安全、产品更新和优化、系统维护等信息,我们可能会向您发送有关服务变更、功能更新、版本升级等通知,确保您能够持续享受我们的产品和服务。
|
||||
</div>
|
||||
<div>
|
||||
此外,您的手机号码还可能用于为您提供个性化的短信推广内容,帮助您了解我们新推出的服务、产品或活动优惠。我们承诺,不会在未经您明确同意的情况下,将您的手机号码用于任何与服务相关以外的用途,且不会将您的信息出售或租赁给第三方。为了保障您的权益,您可以随时通过设置页面或联系客户服务停止接收短信通知或推广信息。如果您选择取消订阅短信通知或推广,您仍将继续收到与账户安全、系统通知等相关的重要信息。
|
||||
</div>
|
||||
<div>
|
||||
我们会采取严格的措施保护您的手机号码不被滥用,包括采用加密存储、定期审查访问权限等技术和管理手段,以确保您的个人信息安全。同时,我们也会根据适用的法律法规,在您停止使用我们的服务或终止您的账户时,删除或匿名化处理您的手机号码及其他相关信息。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<!-- 第二部分 -->
|
||||
|
@ -2,7 +2,7 @@
|
||||
const featureMap = {
|
||||
G09SC02: {
|
||||
name: '单人婚姻',
|
||||
component: defineAsyncComponent(() => import('@/ui/CBad.vue')),
|
||||
component: defineAsyncComponent(() => import('@/ui/CMarriage.vue')),
|
||||
},
|
||||
G27BJ05: {
|
||||
name: '借贷意向',
|
||||
@ -32,34 +32,83 @@ const featureMap = {
|
||||
},
|
||||
G05HZ01: {
|
||||
name: '股东人企关系',
|
||||
component: defineAsyncComponent(() =>
|
||||
import('@/ui/CRelatedEnterprises.vue')
|
||||
),
|
||||
component: defineAsyncComponent(() => import('@/ui/CRelatedEnterprises.vue')),
|
||||
},
|
||||
Q23SC01: {
|
||||
name: '企业涉诉',
|
||||
component: defineAsyncComponent(() => import('@/ui/CLawsuit.vue')),
|
||||
},
|
||||
G15BJ02: {
|
||||
name: '手机三要素',
|
||||
component: defineAsyncComponent(() => import('@/ui/CPhoneThreeElements.vue')),
|
||||
},
|
||||
KZEYS: {
|
||||
name: '身份证二要素',
|
||||
component: defineAsyncComponent(() => import('@/ui/CIDCardTwoElements.vue')),
|
||||
},
|
||||
G17BJ02: {
|
||||
name: '手机号二要素',
|
||||
component: defineAsyncComponent(() => import('@/ui/CPhoneTwoElements.vue')),
|
||||
},
|
||||
G10SC02: {
|
||||
name: '双人婚姻核验',
|
||||
component: defineAsyncComponent(() => import('@/ui/CDualMarriage.vue')),
|
||||
},
|
||||
P_C_B332: {
|
||||
name: '人车核验',
|
||||
component: defineAsyncComponent(() => import('@/ui/CP_C_B332.vue')),
|
||||
},
|
||||
FIN019: {
|
||||
name: '银行卡黑名单',
|
||||
component: defineAsyncComponent(() => import('@/ui/CFIN019.vue')),
|
||||
},
|
||||
G20GZ01: {
|
||||
name: '银行卡四要素核验',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG20GZ01.vue')),
|
||||
},
|
||||
G03HZ01: {
|
||||
name: '手机号码风险',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG03HZ01.vue')),
|
||||
},
|
||||
G19BJ02: {
|
||||
name: '手机二次卡',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG19BJ02.vue')),
|
||||
},
|
||||
G02BJ02: {
|
||||
name: '手机在网时长',
|
||||
component: defineAsyncComponent(() => import('@/ui/CG02BJ02.vue')),
|
||||
},
|
||||
CAR061: {
|
||||
name: '名下车辆',
|
||||
component: defineAsyncComponent(() => import('@/ui/CCAR061.vue')),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
import LEmpty from "@/components/LEmpty.vue";
|
||||
import { useWebView } from "@/composables/useWebView";
|
||||
useWebView()
|
||||
import LPendding from "@/components/LPendding.vue";
|
||||
import LTitle from "@/components/LTitle.vue";
|
||||
const route = useRoute();
|
||||
|
||||
const productId = ref(null);
|
||||
const isDone = ref(true);
|
||||
|
||||
const reportData = ref([])
|
||||
const reportParams = ref({})
|
||||
const reportName = ref("")
|
||||
const reportDateTime = ref(null)
|
||||
const orderId = ref(null);
|
||||
const orderNo = ref("")
|
||||
const isEmpty = ref(false)
|
||||
const isPending = ref(false)
|
||||
onMounted(() => {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
orderNo.value = query.get("out_trade_no");
|
||||
orderId.value = query.get("order_id");
|
||||
orderNo.value = query.get("order_no");
|
||||
|
||||
if (!orderNo.value && !orderId.value) {
|
||||
orderId.value = route.query.orderId;
|
||||
orderNo.value = route.query.orderNo;
|
||||
}
|
||||
if (!orderId.value && !orderNo.value) return;
|
||||
|
||||
getReport()
|
||||
@ -80,48 +129,176 @@ const getReport = async () => {
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
if (data.value.data.product_name === '婚姻评估') {
|
||||
reportData.value = data.value.data.query_data.reverse()
|
||||
} else {
|
||||
reportData.value = data.value.data.query_data
|
||||
}
|
||||
productId.value = data.value.data.product_id;
|
||||
reportData.value = data.value.data.query_data
|
||||
reportParams.value = data.value.data.query_params
|
||||
reportName.value = data.value.data.product_name
|
||||
reportDateTime.value = data.value.data.create_time
|
||||
} else if (data.value.code === 200003) {
|
||||
isEmpty.value = true
|
||||
} else if (data.value.code === 200002) {
|
||||
isPending.value = true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// 对请求参数进行脱敏处理
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
|
||||
<van-notice-bar color="#e03131" background="#ecf9ff" left-icon="info-o" text="由于全能查APP暂未上线,建议将此网站加入收藏夹或书签!!!" />
|
||||
<!-- <CTabs :tabs="sortedTabs" type="blue-green" /> -->
|
||||
<template v-if="isDone">
|
||||
<div class="flex flex-col gap-y-4 p-4 pt-12">
|
||||
<div id="overdiv" class="title">报告概述</div>
|
||||
<div class="card">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">报告时间:</span>
|
||||
<span class="text-gray-600">2024年11月18日 23:11:23</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">报告项目:</span>
|
||||
<span class="text-gray-600">
|
||||
{{ reportName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2" v-if="reportData.length > 1">
|
||||
<LTitle class="my-4" title="报告内容" type="blue-green" />
|
||||
<div class="flex flex-col gap-y-4 p-4">
|
||||
<template v-if="!isEmpty && !isPending">
|
||||
<div id="overdiv" class="title">报告概述</div>
|
||||
<div class="card">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<div v-for="item in sortedReportItems" :key="item.value" class="flex justify-between">
|
||||
<span class="text-gray-700 font-bold">{{ item.label }}:</span>
|
||||
<span class="text-green-500 font-bold">已解锁</span>
|
||||
<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 }}</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?.nameMan">
|
||||
<span class="text-gray-700 font-bold">男方姓名</span>
|
||||
<span class="text-gray-600">{{ maskValue("name", reportParams?.nameMan)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.idCardMan">
|
||||
<span class="text-gray-700 font-bold">男方身份证号</span>
|
||||
<span class="text-gray-600">{{ maskValue("id_card", reportParams?.idCardMan)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.nameWoman">
|
||||
<span class="text-gray-700 font-bold">女方姓名</span>
|
||||
<span class="text-gray-600">{{ maskValue("name", reportParams?.nameWoman)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2"
|
||||
v-if="reportParams?.idCardWoman">
|
||||
<span class="text-gray-700 font-bold">女方身份证号</span>
|
||||
<span class="text-gray-600">{{ maskValue("id_card", reportParams?.idCardWoman)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.bank_card">
|
||||
<span class="text-gray-700 font-bold">银行卡号</span>
|
||||
<span class="text-gray-600">{{ maskValue("bank_card", reportParams?.bank_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 justify-between border-b pb-2 pl-2"
|
||||
v-if="reportParams?.verification_code">
|
||||
<span class="text-gray-700 font-bold">验证码</span>
|
||||
<span class="text-gray-600">{{ maskValue("code",
|
||||
reportParams?.verification_code)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2"
|
||||
v-if="reportParams?.car_license">
|
||||
<span class="text-gray-700 font-bold">车牌号</span>
|
||||
<span class="text-gray-600">{{ maskValue("car_license",
|
||||
reportParams?.car_license)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.ent_name">
|
||||
<span class="text-gray-700 font-bold">企业名称</span>
|
||||
<span class="text-gray-600">{{ maskValue("ent_name", reportParams?.ent_name)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.ent_code">
|
||||
<span class="text-gray-700 font-bold">企业代码</span>
|
||||
<span class="text-gray-600">{{ maskValue("ent_code", reportParams?.ent_code)
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<LEmpty v-if="isEmpty" />
|
||||
<LPendding v-if="isPending" />
|
||||
<template v-for="(item, index) in reportData" :key="index">
|
||||
<div id="lawsuit" class="title">{{ featureMap[item.apiID].name }}</div>
|
||||
<component :is="featureMap[item.apiID].component" :data="item.data"></component>
|
||||
<component :is="featureMap[item.apiID].component" :data="item.data" :params="reportParams">
|
||||
</component>
|
||||
</template>
|
||||
<div class="card">
|
||||
<div>
|
||||
@ -145,10 +322,41 @@ const getReport = async () => {
|
||||
</div>
|
||||
</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>琼公网安备46010002000443号</text>
|
||||
</div>
|
||||
<div>
|
||||
<a class="text-blue-500" href="https://beian.miit.gov.cn">
|
||||
琼ICP备2024038584号-2
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
海南省学宇思网络科技有限公司版权所有
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
@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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
|
@ -7,6 +7,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
onMounted(() => {
|
||||
// 插入客服脚本
|
||||
(function (d, t) {
|
||||
@ -47,9 +48,11 @@ onMounted(() => {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
iframe {
|
||||
background: #000000;
|
||||
}
|
||||
|
||||
iframe::content .file-uploads.file-uploads-html5.text-black-900 {
|
||||
display: none !important;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
<script setup>
|
||||
import { useWebView } from "@/composables/useWebView";
|
||||
useWebView()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -241,7 +240,7 @@ useWebView()
|
||||
<div class="leading-relaxed">
|
||||
如您对本协议及本服务有任何问题,请通过邮箱
|
||||
<text class="text-blue-500"> admin@iieeii.com </text> 或
|
||||
APP“联系客服”联系海南省学宇思网络科技有限公司进行咨询。
|
||||
通过“联系客服”联系海南省学宇思网络科技有限公司进行咨询。
|
||||
海南省学宇思网络科技有限公司会尽最大努力解决您的问题。
|
||||
</div>
|
||||
</div>
|
||||
|
118
src/views/index.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<script setup>
|
||||
const router = useRouter();
|
||||
|
||||
function toInquire(name) {
|
||||
if (name === 'Marriage') {
|
||||
router.push(`/inquire/toc_Marriage`);
|
||||
}
|
||||
else {
|
||||
router.push(`/list${name}`,);
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载时生成 30 条通知数据
|
||||
onMounted(() => {
|
||||
})
|
||||
function toHistory() {
|
||||
router.push(`/historyQuery`);
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative p-4">
|
||||
<img class="h-full w-full overflow-hidden rounded-xl" src="@/assets/images/banner.png" />
|
||||
</div>
|
||||
<div class="relative p-4 pb-4 pt-2">
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div
|
||||
class="relative flex flex-col cursor-pointer rounded-bl-[35px] rounded-br-lg rounded-tl-[35px] rounded-tr-lg bg-white px-4 py-6 shadow-lg"
|
||||
@click="toInquire('Risk')">
|
||||
<div class="min-h-18 gap-2 bg-white px-1">
|
||||
<div class="mb-2 flex justify-around">
|
||||
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_3.png" />
|
||||
<div class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
|
||||
风险评估
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-max text-left text-xs text-gray-600">
|
||||
检测个人不良记录、人企关系等
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="relative flex flex-col cursor-pointer rounded-bl-lg rounded-br-[35px] rounded-tl-lg rounded-tr-[35px] bg-white px-4 py-6 shadow-lg"
|
||||
@click="toInquire('Marriage')">
|
||||
<div class="min-h-18 gap-2 bg-white px-1">
|
||||
<div class="mb-2 flex justify-around">
|
||||
<div class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
|
||||
婚姻报告
|
||||
</div>
|
||||
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_1.png" />
|
||||
</div>
|
||||
<div class="max-w-max text-left text-xs text-gray-600">
|
||||
核查个人不良,婚姻状态是否未婚、已婚、离婚、离婚冷静期
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="relative flex flex-col cursor-pointer rounded-bl-[35px] rounded-br-lg rounded-tl-[35px] rounded-tr-lg bg-white px-4 py-6 shadow-lg"
|
||||
@click="toInquire('Lawsuit')">
|
||||
<div class="min-h-18 gap-2 bg-white px-1">
|
||||
<div class="mb-2 flex justify-around">
|
||||
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_2.png" />
|
||||
<div class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
|
||||
司法涉诉
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-max text-left text-xs text-gray-600">
|
||||
查询个人与企业的民事案件、刑事案件、行政案件、非诉保全审查、执行案件、强制清算与破产等司法涉诉记录
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="relative flex flex-col cursor-pointer rounded-bl-lg rounded-br-[35px] rounded-tl-lg rounded-tr-[35px] bg-white px-4 py-6 shadow-lg"
|
||||
@click="toInquire('Verify')">
|
||||
<div class="min-h-18 gap-2 bg-white px-1">
|
||||
<div class="mb-2 flex justify-around">
|
||||
<div class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
|
||||
核验工具
|
||||
</div>
|
||||
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_4.png" />
|
||||
</div>
|
||||
<div class="max-w-max text-left text-xs text-gray-600">
|
||||
核验身份证、手机、银行卡、自然人生存状态、学历、人车关系等的查询工具
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 font-bold">
|
||||
更多服务
|
||||
</div>
|
||||
<div class="mt-4 box-border h-14 w-full flex items-center rounded-xl bg-white px-4 text-gray-700 shadow-xl"
|
||||
@click="toHistory">
|
||||
<img class="mr-4 h-10 w-10" src="@/assets/images/bg_icon.png" mode="widthFix" />
|
||||
<div class="">
|
||||
<div class="font-bold">
|
||||
我的历史查询记录
|
||||
</div>
|
||||
<div class="text-xs">
|
||||
查询记录有效期为30天
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shadow-3xl mt-8 w-full">
|
||||
<img class="shadow-3xl w-full overflow-hidden rounded-xl" src="@/assets/images/liu.png" mode="widthFix" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.clip-left {
|
||||
clip-path: polygon(0 0, 0 100%, 90% 100%, 0 100%);
|
||||
}
|
||||
|
||||
.clip-right {
|
||||
clip-path: polygon(0 0, 0 0, 90% 100%, 0 0);
|
||||
}
|
||||
</style>
|
@ -22,20 +22,24 @@
|
||||
本平台提供全方位司法涉诉查询服务,助您全面防范。功能包括:
|
||||
</p>
|
||||
<ul class="list-disc list-inside mt-4 space-y-2 text-gray-600">
|
||||
<li>个人涉诉:查看XXXXXXXXXXXXXXXXXXX</li>
|
||||
<li>企业涉诉:查看XXXXXXXXXXXXXXXXXXX</li>
|
||||
<li>
|
||||
<strong>个人涉诉:</strong> 查看个人是否涉及诉讼案件,了解其法律纠纷情况,帮助您判断该个人的法律风险。
|
||||
</li>
|
||||
<li>
|
||||
<strong>企业涉诉:</strong> 查看企业是否涉及诉讼案件,了解企业的法律风险及潜在的经营问题,帮助您评估与该企业合作的安全性。
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useWebView } from "@/composables/useWebView";
|
||||
useWebView()
|
||||
|
||||
import grssIcon from '@/assets/images/grss_icon.svg';
|
||||
import qyssIcon from '@/assets/images/qyss_icon.svg';
|
||||
const router = useRouter()
|
||||
const menuItems = [
|
||||
{ title: "个人涉诉", icon: grssIcon, product: "toc_PersonalLawsuit" },
|
||||
{ title: "企业涉诉", icon: qyssIcon, product: "toc_EnterpriseLawsuit" },
|
||||
@ -43,7 +47,7 @@ const menuItems = [
|
||||
|
||||
const toInquire = (product) => {
|
||||
if (!product) return
|
||||
uni.navigateTo({ url: '/pages/inquire?p=' + product })
|
||||
router.push('/inquire/' + product)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -43,7 +43,6 @@ const menuItems = [
|
||||
{ title: "出险信息", icon: "/static/icon-accident.png", textColor: "text-red-500" },
|
||||
{ title: "维修记录", icon: "/static/icon-maintain.png", textColor: "text-blue-500" },
|
||||
];
|
||||
// console.log("uni", uni.navigateTo({ url: "/pages/index" }))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -24,8 +24,12 @@
|
||||
本平台提供全方位风险评估查询服务,助您全面防范。功能包括:
|
||||
</p>
|
||||
<ul class="list-disc list-inside mt-4 space-y-2 text-gray-600">
|
||||
<li>个人不良:查看XXXXXXXXXXXXXXXXXXX</li>
|
||||
<li>股东人企关系:查看XXXXXXXXXXXXXXXXXXX</li>
|
||||
<li>
|
||||
<strong>个人不良记录查询:</strong> 通过查询个人的不良记录,评估其风险等级(低、中、高风险)。帮助您识别潜在的信用和法律风险,确保合作方的合法合规。
|
||||
</li>
|
||||
<li>
|
||||
<strong>股东人企关系查询:</strong> 通过个人关联的企业,了解其可能涉及的风险,帮助您判断该个人的风险水平,特别是与高风险企业有联系的个人。
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -33,18 +37,16 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useWebView } from "@/composables/useWebView";
|
||||
useWebView()
|
||||
|
||||
import grblIcon from '@/assets/images/grbl_icon.svg';
|
||||
import gdrqgxIcon from '@/assets/images/gdrqgx_icon.svg';
|
||||
const router = useRouter()
|
||||
const menuItems = [
|
||||
{ title: "个人不良", icon: grblIcon, product: "toc_PersonalBadRecord" },
|
||||
{ title: "股东人企关系", icon: gdrqgxIcon, product: "toc_ShareholderBusinessRelation" },
|
||||
];
|
||||
|
||||
const toInquire = (product) => {
|
||||
uni.navigateTo({ url: '/pages/inquire?p=' + product })
|
||||
router.push('/inquire/' + product)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -8,7 +8,8 @@
|
||||
<!-- 功能菜单 -->
|
||||
<div class="card">
|
||||
<div class="grid grid-cols-3 gap-6">
|
||||
<div v-for="(item, index) in menuItems" :key="index" class="flex flex-col items-center">
|
||||
<div v-for="(item, index) in menuItems" :key="index" class="flex flex-col items-center"
|
||||
@click="toInquire(item.product)">
|
||||
<div class="bg-slate-100 rounded-full p-4">
|
||||
<img :src="item.icon" :alt="item.title" class="w-10 h-10">
|
||||
</div>
|
||||
@ -23,9 +24,22 @@
|
||||
本平台提供全方位核验工具服务,助您全面防范。功能包括:
|
||||
</p>
|
||||
<ul class="list-disc list-inside mt-4 space-y-2 text-gray-600">
|
||||
<li>手机三要素核验:查看XXXXXXXXXXXXXXXXXXX</li>
|
||||
<li>银行卡黑名单:查看XXXXXXXXXXXXXXXXXXX</li>
|
||||
<li><strong>手机三要素:</strong> 查询个人与手机号码是否匹配,确保手机号码的真实性。</li>
|
||||
<li><strong>银行卡黑名单:</strong> 查询银行卡是否被列入黑名单,帮助您识别潜在的金融风险。</li>
|
||||
<li><strong>身份证二要素:</strong> 验证姓名与身份证号码的匹配情况,确保身份真实性。</li>
|
||||
<li><strong>手机二要素:</strong> 查询手机号码和身份证的匹配情况,用于验证身份的真实性。</li>
|
||||
<li><strong>在网时长:</strong> 查询手机号码的在网时长,帮助评估号码的稳定性与历史。</li>
|
||||
<li><strong>手机二次卡:</strong> 检查手机是否有二次卡,防止诈骗等风险。</li>
|
||||
<li><strong>手机号码风险:</strong> 评估手机号码的潜在风险,包括是否与违法行为关联。</li>
|
||||
<li><strong>银行卡四要素:</strong> 通过四要素核验银行卡与个人是否匹配,进一步验证银行账户的真实性。</li>
|
||||
<li><strong>人车核验:</strong> 查询个人与车辆的关联情况,帮助识别车辆的所有权和风险。</li>
|
||||
<li><strong>名下车辆:</strong> 查询个人名下的所有车辆信息,了解其车辆资产。</li>
|
||||
<li><strong>双人婚姻:</strong> 查询双人婚姻状况,帮助评估婚姻的法律状态和风险。</li>
|
||||
<!-- <li><strong>自然人生存状态:</strong> 查询个人的生存状态,帮助验证其是否真实存在。</li> -->
|
||||
<!-- <li><strong>银行卡三要素:</strong> 查询银行卡的三要素,验证账户信息的安全性。</li> -->
|
||||
<!-- <li><strong>学历核验:</strong> 验证学历信息的真实性,确保所提供的学历符合实际。</li> -->
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -46,43 +60,28 @@ import xlhyIcon from '@/assets/images/xlhy_icon.svg'; // 学历核验
|
||||
import rchyIcon from '@/assets/images/rchy_icon.svg'; // 人车核验
|
||||
import mxclIcon from '@/assets/images/mxcl_icon.svg'; // 名下车辆
|
||||
import srhyIcon from '@/assets/images/srhy_icon.svg'; // 双人婚姻
|
||||
|
||||
const router = useRouter()
|
||||
const menuItems = [
|
||||
{ title: "手机三要素", icon: sjsysIcon },
|
||||
{ title: "银行卡黑名单", icon: yhkhmdIcon },
|
||||
{ title: "身份证二要素", icon: sfzeysIcon },
|
||||
{ title: "手机二要素", icon: sjeysIcon },
|
||||
{ title: "在网时长", icon: sjzwscIcon },
|
||||
{ title: "手机二次卡", icon: sjeckIcon },
|
||||
{ title: "手机号码风险", icon: sjhmfxIcon },
|
||||
{ title: "银行卡四要素", icon: yhk4ysIcon },
|
||||
{ title: "银行卡三要素", icon: yhksysIcon },
|
||||
{ title: "自然人生存状态", icon: zrrscztIcon },
|
||||
{ title: "学历核验", icon: xlhyIcon },
|
||||
{ title: "人车核验", icon: rchyIcon },
|
||||
{ title: "名下车辆", icon: mxclIcon },
|
||||
{ title: "双人婚姻", icon: srhyIcon },
|
||||
{ title: "手机三要素", icon: sjsysIcon, product: "toc_PhoneThreeElements" },
|
||||
{ title: "银行卡黑名单", icon: yhkhmdIcon, product: "toc_BankCardBlacklist" },
|
||||
{ title: "身份证二要素", icon: sfzeysIcon, product: "toc_IDCardTwoElements" },
|
||||
{ title: "手机二要素", icon: sjeysIcon, product: "toc_PhoneTwoElements" },
|
||||
{ title: "在网时长", icon: sjzwscIcon, product: "toc_NetworkDuration" },
|
||||
{ title: "手机二次卡", icon: sjeckIcon, product: "toc_PhoneSecondaryCard" },
|
||||
{ title: "手机号码风险", icon: sjhmfxIcon, product: "toc_PhoneNumberRisk" },
|
||||
{ title: "银行卡四要素", icon: yhk4ysIcon, product: "toc_BankCardFourElements" },
|
||||
// { title: "自然人生存状态", icon: zrrscztIcon, product: "toc_NaturalLifeStatus" },
|
||||
// { title: "银行卡三要素", icon: yhksysIcon, product: "toc_BankCardThreeElements" },
|
||||
// { title: "学历核验", icon: xlhyIcon, product: "toc_EducationVerification" },
|
||||
{ title: "人车核验", icon: rchyIcon, product: "toc_PersonVehicleVerification" },
|
||||
{ title: "名下车辆", icon: mxclIcon, product: "toc_VehiclesUnderName" },
|
||||
{ title: "双人婚姻", icon: srhyIcon, product: "toc_DualMarriage" },
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
uni.getEnv((platform) => {
|
||||
console.log("当前运行环境", platform)
|
||||
handleBridgeReady(platform)
|
||||
});
|
||||
})
|
||||
const handleBridgeReady = (platform) => {
|
||||
if (platform.h5) {
|
||||
window.parent.postMessage({ loaded: true }, '*');
|
||||
}
|
||||
// else {
|
||||
// uni.postMessage({
|
||||
// data: {
|
||||
// loaded: true,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
};
|
||||
// console.log("uni", uni.navigateTo({ url: "/pages/index" }))
|
||||
const toInquire = (product) => {
|
||||
router.push('/inquire/' + product)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@ -14,14 +14,20 @@ export default defineConfig({
|
||||
port: 5678, // 自定义端口号,可选
|
||||
strictPort: true, // 如果端口被占用则抛出错误而不是使用下一个可用端口
|
||||
proxy: {
|
||||
// '/api/v1': {
|
||||
// target: 'https://app.quannengcha.com', // 本地接口地址
|
||||
// changeOrigin: true,
|
||||
// },
|
||||
'/api/v1': {
|
||||
target: 'http://127.0.0.1:8888', // 本地接口地址
|
||||
target: 'https://www.quannengcha.com', // 本地接口地址
|
||||
changeOrigin: true,
|
||||
},
|
||||
'/api/v1/chat': {
|
||||
target: 'https://www.quannengcha.com', // 本地接口地址
|
||||
changeOrigin: true,
|
||||
// rewrite: (path) => path.replace(/^\/api\/v1\/chat/, '/chat')
|
||||
},
|
||||
// '/api/v1': {
|
||||
// target: 'https://6m4685017o.goho.co', // 本地接口地址
|
||||
// changeOrigin: true,
|
||||
// },
|
||||
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|