This commit is contained in:
2025-12-25 14:49:46 +08:00
parent 526370bb41
commit fd22ad2884
65 changed files with 13647 additions and 3166 deletions

268
SEO_OPTIMIZATION_GUIDE.md Normal file
View File

@@ -0,0 +1,268 @@
# 天远查 - SEO优化指南
## 概述
天远查是一个专业的司法涉诉查询平台提供婚恋评估、判决书查询、婚姻状态查询等服务。本文档详细说明了网站的SEO优化策略和实施方法。
## SEO优化特性
### 1. 基础SEO配置
#### HTML头部优化
- ✅ 完整的meta标签配置
- ✅ Open Graph标签支持
- ✅ Twitter Card标签支持
- ✅ 结构化数据标记
- ✅ 规范链接设置
- ✅ 移动端优化
#### 技术优化
- ✅ 响应式设计
- ✅ 页面加载速度优化
- ✅ 代码分割和懒加载
- ✅ Gzip压缩
- ✅ 图片优化
### 2. 内容优化
#### 关键词策略
主要关键词:
- 天远查
- 司法涉诉查询
- 婚恋评估
- 判决书查询
- 婚姻状态查询
- 被执行人查询
- 失信人查询
- 限高查询
- 个人涉诉查询
- 企业涉诉查询
- 车辆核验
- 身份核验
- 手机核验
- 银行卡核验
- 学历核验
- 风险报告
- 法律风险
- 信用风险
- 在线查询平台
#### 页面标题结构
```
首页:天远查 - 专业司法涉诉查询平台 | 婚恋评估、判决书查询、婚姻状态查询
功能页:{功能名称} - 天远查
详情页:{具体内容} - 天远查
```
### 3. 技术实现
#### 文件结构
```
├── index.html # 主HTML文件已优化
├── public/
│ ├── robots.txt # 搜索引擎爬虫配置
│ ├── sitemap.xml # 网站地图
│ └── site.webmanifest # PWA配置
├── src/
│ ├── utils/
│ │ └── seo.js # SEO工具函数
│ ├── composables/
│ │ └── useSEO.js # SEO Composable
│ ├── router/
│ │ └── index.js # 路由配置(已优化)
│ └── views/
│ └── index.vue # 主页组件(已优化)
└── vite.config.js # 构建配置(已优化)
```
#### 核心功能
##### SEO工具函数 (`src/utils/seo.js`)
- `setPageTitle()` - 设置页面标题
- `setPageDescription()` - 设置页面描述
- `setPageKeywords()` - 设置页面关键词
- `setOpenGraph()` - 设置Open Graph标签
- `setTwitterCard()` - 设置Twitter Card标签
- `setStructuredData()` - 设置结构化数据
- `setCanonicalUrl()` - 设置规范链接
- `generateBreadcrumbStructuredData()` - 生成面包屑结构化数据
- `generateFAQStructuredData()` - 生成FAQ结构化数据
- `generateOrganizationStructuredData()` - 生成组织结构化数据
- `generateWebsiteStructuredData()` - 生成网站结构化数据
- `initPageSEO()` - 初始化页面SEO
##### SEO Composable (`src/composables/useSEO.js`)
- `setPageSEO()` - 设置页面SEO信息
- `setRouteSEO()` - 根据路由设置SEO
- `setStructuredData()` - 设置结构化数据
- `setPerformanceMonitoring()` - 设置性能监控
- `setErrorMonitoring()` - 设置错误监控
### 4. 使用方法
#### 在组件中使用SEO
```javascript
<script setup>
import { useSEO } from '@/composables/useSEO'
// 自动根据路由设置SEO
const { setPageSEO } = useSEO()
// 自定义SEO设置
setPageSEO({
title: '自定义标题',
description: '自定义描述',
keywords: '自定义关键词',
ogData: {
title: 'Open Graph标题',
description: 'Open Graph描述',
image: 'https://example.com/image.jpg'
}
})
</script>
```
#### 在路由中使用SEO
```javascript
{
path: '/example',
name: 'example',
component: () => import('@/views/Example.vue'),
meta: {
title: '示例页面 - 天远查',
description: '这是一个示例页面的描述',
keywords: '示例,页面,关键词'
}
}
```
### 5. 性能优化
#### 构建优化
- 代码分割vendor、vant、echarts分别打包
- 压缩优化移除console和debugger
- 资源优化:小文件内联,大文件分离
#### 运行时优化
- 路由懒加载
- 图片懒加载
- 组件按需加载
### 6. 监控和分析
#### 性能监控
- DNS解析时间
- TCP连接时间
- TTFB首字节时间
- DOM内容加载时间
- 页面完全加载时间
- 首次绘制时间
- 首次内容绘制时间
#### 错误监控
- JavaScript错误捕获
- Promise拒绝捕获
- 网络错误监控
### 7. 搜索引擎优化
#### 百度优化
- 百度站长验证
- 百度爬虫友好配置
- 百度结构化数据
#### Google优化
- Google爬虫友好配置
- Google结构化数据
- Google Analytics集成
### 8. 移动端优化
#### PWA支持
- Service Worker
- 离线缓存
- 推送通知
- 添加到主屏幕
#### 移动端适配
- 响应式设计
- 触摸友好
- 快速加载
### 9. 安全优化
#### 内容安全策略
- CSP头部设置
- XSS防护
- CSRF防护
#### 隐私保护
- 隐私政策
- 用户协议
- 数据加密
### 10. 维护和更新
#### 定期检查
- 页面加载速度
- SEO排名变化
- 用户行为分析
- 错误日志分析
#### 持续优化
- 内容更新
- 技术升级
- 用户体验改进
## 部署建议
### 1. 服务器配置
```nginx
# Nginx配置示例
server {
listen 80;
server_name www.tianyuancha.cn;
# Gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 缓存设置
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
location / {
try_files $uri $uri/ /index.html;
}
}
```
### 2. CDN配置
- 静态资源CDN加速
- 图片CDN优化
- 全球节点分布
### 3. SSL证书
- HTTPS强制跳转
- HSTS头部设置
- 证书自动续期
## 总结
通过以上全面的SEO优化天远查网站已经具备了
1. **技术基础**完整的SEO技术实现
2. **内容优化**:合理的关键词布局和内容结构
3. **性能优化**:快速的页面加载速度
4. **用户体验**:良好的移动端适配和交互体验
5. **监控分析**:完善的性能监控和错误追踪
6. **安全保护**:全面的安全防护和隐私保护
这些优化将显著提升网站在搜索引擎中的排名,提高用户访问量和转化率。

View File

@@ -1,27 +1,137 @@
<!DOCTYPE html>
<html lang="">
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon-16x16.png"
/>
<link rel="manifest" href="/site.webmanifest" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=yes"
/>
<title>天远查 - 婚恋评估、司法涉诉查询、婚姻状态、判决书查询工具</title>
<title>
天远查 - 专业司法涉诉查询平台 | 婚恋评估、判决书查询、婚姻状态查询
</title>
<!-- 基础SEO Meta标签 -->
<meta
name="description"
content="天远查依托大数据技术,精准查询司法涉诉风险!个人司法风险,支持婚姻状况/婚姻状态/判决书/被执行人/老赖/失信人/限高查询,并提供身份/银行卡/手机号码一键核验!多维防控财产/信用/身份风险"
content="天远查是专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询、被执行人查询、失信人查询等服务。依托大数据技术,精准查询司法风险,多维防控财产信用身份风险"
/>
<meta
name="keywords"
content="婚恋评估, 司法涉诉查询, 判决书查询, 婚姻状态查询, 老赖, 被执行人, 限高, 失信人, 个人涉诉查询, 企业涉诉查询, 名下车辆核验, 车辆核验, 婚姻状况, 风险报告, 法律风险, 信用风险, 银行卡黑名单, 手机身份证核验, 学历核验, 在线查询"
content="天远查,司法涉诉查询,婚恋评估,判决书查询,婚姻状态查询,被执行人查询,失信人查询,限高查询,个人涉诉查询,企业涉诉查询,车辆核验,身份核验,手机核验,银行卡核验,学历核验,风险报告,法律风险,信用风险,在线查询平台"
/>
<meta name="author" content="天远查" />
<meta name="robots" content="index, follow" />
<meta name="googlebot" content="index, follow" />
<meta name="baiduspider" content="index, follow" />
<!-- 百度站长验证 -->
<meta
name="baidu-site-verification"
content="4d551d55896a88badef8dcdb14cf874c"
/>
<!-- Open Graph 标签 -->
<meta
property="og:title"
content="天远查 - 专业司法涉诉查询平台 | 婚恋评估、判决书查询、婚姻状态查询"
/>
<meta
property="og:description"
content="天远查是专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询、被执行人查询、失信人查询等服务。"
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.tianyuancha.cn" />
<meta
property="og:image"
content="https://www.tianyuancha.cn/og-image.jpg"
/>
<meta property="og:site_name" content="天远查" />
<meta property="og:locale" content="zh_CN" />
<!-- Twitter Card 标签 -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="天远查 - 专业司法涉诉查询平台" />
<meta
name="twitter:description"
content="提供婚恋评估、判决书查询、婚姻状态查询等专业服务"
/>
<meta
name="twitter:image"
content="https://www.tianyuancha.cn/twitter-image.jpg"
/>
<!-- 移动端优化 -->
<meta name="format-detection" content="telephone=no" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="天远查" />
<!-- 安全相关 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="referrer" content="strict-origin-when-cross-origin" />
<!-- 结构化数据 -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "天远查",
"url": "https://www.tianyuancha.cn",
"description": "专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询等服务",
"potentialAction": {
"@type": "SearchAction",
"target": "https://www.tianyuancha.cn/search?q={search_term_string}",
"query-input": "required name=search_term_string"
}
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "天远查",
"url": "https://www.tianyuancha.cn",
"logo": "https://www.tianyuancha.cn/logo.png",
"contactPoint": {
"@type": "ContactPoint",
"contactType": "customer service",
"availableLanguage": "Chinese"
},
"sameAs": [
"https://www.tianyuanapi.com/",
"https://www.tybigdata.com/"
]
}
</script>
<!-- 预加载关键资源 -->
<link rel="preload" href="/src/main.js" as="script" />
<link rel="preload" href="/src/assets/main.css" as="style" />
<link rel="dns-prefetch" href="//d.alicdn.com" />
<link rel="dns-prefetch" href="//www.tianyuancha.cn" />
<!-- 阿里云日志统计 -->
<script>
(function (w, d, s, q, i) {
w[q] = w[q] || [];
@@ -50,6 +160,8 @@
arguments: ["aplus-idtype", "uuid"], //取值参考见附表1
});
</script>
<!-- 加载动画样式 -->
<style>
#app-loading {
position: fixed;

181
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"@vueuse/core": "^11.3.0",
"@vueuse/head": "^2.0.0",
"axios": "^1.7.7",
"crypto-js": "^4.2.0",
"echarts": "^5.5.1",
@@ -16,22 +17,23 @@
"nprogress": "^0.2.0",
"pinia": "^2.2.6",
"vant": "^4.9.9",
"vue": "^3.5.12",
"vue": "^3.5.13",
"vue-echarts": "^7.0.3",
"vue-router": "^4.4.5"
},
"devDependencies": {
"@vant/auto-import-resolver": "^1.2.1",
"@vitejs/plugin-vue": "^5.1.4",
"@vitejs/plugin-vue-jsx": "^4.0.1",
"@vitejs/plugin-vue": "^5.2.0",
"@vitejs/plugin-vue-jsx": "^4.1.0",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"sass-embedded": "^1.81.0",
"tailwindcss": "^3.4.15",
"terser": "^5.43.1",
"unplugin-auto-import": "^0.18.5",
"unplugin-vue-components": "^0.27.5",
"vite": "^5.4.10",
"vite-plugin-vue-devtools": "^7.5.4"
"vite": "^5.4.11",
"vite-plugin-vue-devtools": "^7.6.4"
}
},
"node_modules/@alloc/quick-lru": {
@@ -967,6 +969,16 @@
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.11",
"resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz",
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
@@ -1375,6 +1387,71 @@
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
"license": "MIT"
},
"node_modules/@unhead/dom": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/@unhead/dom/-/dom-1.11.20.tgz",
"integrity": "sha512-jgfGYdOH+xHJF/j8gudjsYu3oIjFyXhCWcgKaw3vQnT616gSqyqnGQGOItL+BQtQZACKNISwIfx5PuOtztMKLA==",
"dependencies": {
"@unhead/schema": "1.11.20",
"@unhead/shared": "1.11.20"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@unhead/schema": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/@unhead/schema/-/schema-1.11.20.tgz",
"integrity": "sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA==",
"dependencies": {
"hookable": "^5.5.3",
"zhead": "^2.2.4"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@unhead/shared": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/@unhead/shared/-/shared-1.11.20.tgz",
"integrity": "sha512-1MOrBkGgkUXS+sOKz/DBh4U20DNoITlJwpmvSInxEUNhghSNb56S0RnaHRq0iHkhrO/cDgz2zvfdlRpoPLGI3w==",
"dependencies": {
"@unhead/schema": "1.11.20",
"packrup": "^0.1.2"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@unhead/ssr": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/@unhead/ssr/-/ssr-1.11.20.tgz",
"integrity": "sha512-j6ehzmdWGAvv0TEZyLE3WBnG1ULnsbKQcLqBDh3fvKS6b3xutcVZB7mjvrVE7ckSZt6WwOtG0ED3NJDS7IjzBA==",
"dependencies": {
"@unhead/schema": "1.11.20",
"@unhead/shared": "1.11.20"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@unhead/vue": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/@unhead/vue/-/vue-1.11.20.tgz",
"integrity": "sha512-sqQaLbwqY9TvLEGeq8Fd7+F2TIuV3nZ5ihVISHjWpAM3y7DwNWRU7NmT9+yYT+2/jw1Vjwdkv5/HvDnvCLrgmg==",
"dependencies": {
"@unhead/schema": "1.11.20",
"@unhead/shared": "1.11.20",
"hookable": "^5.5.3",
"unhead": "1.11.20"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
},
"peerDependencies": {
"vue": ">=2.7 || >=3"
}
},
"node_modules/@vant/auto-import-resolver": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/@vant/auto-import-resolver/-/auto-import-resolver-1.2.1.tgz",
@@ -1665,6 +1742,20 @@
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/head": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/@vueuse/head/-/head-2.0.0.tgz",
"integrity": "sha512-ykdOxTGs95xjD4WXE4na/umxZea2Itl0GWBILas+O4oqS7eXIods38INvk3XkJKjqMdWPcpCyLX/DioLQxU1KA==",
"dependencies": {
"@unhead/dom": "^1.7.0",
"@unhead/schema": "^1.7.0",
"@unhead/ssr": "^1.7.0",
"@unhead/vue": "^1.7.0"
},
"peerDependencies": {
"vue": ">=2.7 || >=3"
}
},
"node_modules/@vueuse/metadata": {
"version": "11.3.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-11.3.0.tgz",
@@ -1901,6 +1992,12 @@
"dev": true,
"license": "MIT/X11"
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"node_modules/bundle-name": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz",
@@ -2616,7 +2713,6 @@
"version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"dev": true,
"license": "MIT"
},
"node_modules/html-tags": {
@@ -3219,6 +3315,14 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/packrup": {
"version": "0.1.2",
"resolved": "https://registry.npmmirror.com/packrup/-/packrup-0.1.2.tgz",
"integrity": "sha512-ZcKU7zrr5GlonoS9cxxrb5HVswGnyj6jQvwFBa6p5VFw7G71VAHcUKL5wyZSU/ECtPM/9gacWxy2KFQKt1gMNA==",
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/parse-ms": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-4.0.0.tgz",
@@ -4153,6 +4257,15 @@
"node": ">=18"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -4162,6 +4275,16 @@
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/speakingurl": {
"version": "14.0.1",
"resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
@@ -4441,6 +4564,30 @@
"node": ">=14.0.0"
}
},
"node_modules/terser": {
"version": "5.43.1",
"resolved": "https://registry.npmmirror.com/terser/-/terser-5.43.1.tgz",
"integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.14.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz",
@@ -4507,6 +4654,20 @@
"dev": true,
"license": "MIT"
},
"node_modules/unhead": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/unhead/-/unhead-1.11.20.tgz",
"integrity": "sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==",
"dependencies": {
"@unhead/dom": "1.11.20",
"@unhead/schema": "1.11.20",
"@unhead/shared": "1.11.20",
"hookable": "^5.5.3"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/unicorn-magic": {
"version": "0.3.0",
"resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
@@ -5131,6 +5292,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zhead": {
"version": "2.2.4",
"resolved": "https://registry.npmmirror.com/zhead/-/zhead-2.2.4.tgz",
"integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==",
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/zrender": {
"version": "5.6.1",
"resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",

View File

@@ -10,6 +10,7 @@
},
"dependencies": {
"@vueuse/core": "^11.3.0",
"@vueuse/head": "^2.0.0",
"axios": "^1.7.7",
"crypto-js": "^4.2.0",
"echarts": "^5.5.1",
@@ -29,6 +30,7 @@
"postcss": "^8.4.49",
"sass-embedded": "^1.81.0",
"tailwindcss": "^3.4.15",
"terser": "^5.43.1",
"unplugin-auto-import": "^0.18.5",
"unplugin-vue-components": "^0.27.5",
"vite": "^5.4.11",

132
pnpm-lock.yaml generated
View File

@@ -47,10 +47,10 @@ importers:
version: 1.2.1
'@vitejs/plugin-vue':
specifier: ^5.2.0
version: 5.2.0(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13)
version: 5.2.0(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13)
'@vitejs/plugin-vue-jsx':
specifier: ^4.1.0
version: 4.1.0(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13)
version: 4.1.0(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13)
autoprefixer:
specifier: ^10.4.20
version: 10.4.20(postcss@8.4.49)
@@ -63,6 +63,9 @@ importers:
tailwindcss:
specifier: ^3.4.15
version: 3.4.15
terser:
specifier: ^5.43.1
version: 5.43.1
unplugin-auto-import:
specifier: ^0.18.5
version: 0.18.5(@vueuse/core@11.3.0(vue@3.5.13))(rollup@4.27.3)
@@ -71,10 +74,10 @@ importers:
version: 0.27.5(@babel/parser@7.26.2)(rollup@4.27.3)(vue@3.5.13)
vite:
specifier: ^5.4.11
version: 5.4.11(sass-embedded@1.81.0)
version: 5.4.11(sass-embedded@1.81.0)(terser@5.43.1)
vite-plugin-vue-devtools:
specifier: ^7.6.4
version: 7.6.4(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13)
version: 7.6.4(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13)
packages:
@@ -370,6 +373,9 @@ packages:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
'@jridgewell/gen-mapping@0.3.5':
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
engines: {node: '>=6.0.0'}
@@ -382,12 +388,21 @@ packages:
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
engines: {node: '>=6.0.0'}
'@jridgewell/source-map@0.3.11':
resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
'@jridgewell/sourcemap-codec@1.5.0':
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
'@jridgewell/sourcemap-codec@1.5.5':
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
'@jridgewell/trace-mapping@0.3.30':
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -619,6 +634,11 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
hasBin: true
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -683,6 +703,9 @@ packages:
buffer-builder@0.2.0:
resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
bundle-name@4.1.0:
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
engines: {node: '>=18'}
@@ -691,8 +714,8 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
caniuse-lite@1.0.30001713:
resolution: {integrity: sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==}
caniuse-lite@1.0.30001739:
resolution: {integrity: sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==}
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
@@ -712,6 +735,9 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
commander@4.1.1:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
@@ -1393,6 +1419,13 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
speakingurl@14.0.1:
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
engines: {node: '>=0.10.0'}
@@ -1453,6 +1486,11 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
terser@5.43.1:
resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==}
engines: {node: '>=10'}
hasBin: true
thenify-all@1.6.0:
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
engines: {node: '>=0.8'}
@@ -1942,6 +1980,11 @@ snapshots:
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
'@jridgewell/trace-mapping': 0.3.30
'@jridgewell/gen-mapping@0.3.5':
dependencies:
'@jridgewell/set-array': 1.2.1
@@ -1952,12 +1995,24 @@ snapshots:
'@jridgewell/set-array@1.2.1': {}
'@jridgewell/source-map@0.3.11':
dependencies:
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.30
'@jridgewell/sourcemap-codec@1.5.0': {}
'@jridgewell/sourcemap-codec@1.5.5': {}
'@jridgewell/trace-mapping@0.3.25':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
'@jridgewell/sourcemap-codec': 1.5.5
'@jridgewell/trace-mapping@0.3.30':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@nodelib/fs.scandir@2.1.5':
dependencies:
@@ -2050,19 +2105,19 @@ snapshots:
dependencies:
vue: 3.5.13
'@vitejs/plugin-vue-jsx@4.1.0(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13)':
'@vitejs/plugin-vue-jsx@4.1.0(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13)':
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0)
'@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0)
vite: 5.4.11(sass-embedded@1.81.0)
vite: 5.4.11(sass-embedded@1.81.0)(terser@5.43.1)
vue: 3.5.13
transitivePeerDependencies:
- supports-color
'@vitejs/plugin-vue@5.2.0(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13)':
'@vitejs/plugin-vue@5.2.0(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13)':
dependencies:
vite: 5.4.11(sass-embedded@1.81.0)
vite: 5.4.11(sass-embedded@1.81.0)(terser@5.43.1)
vue: 3.5.13
'@vue/babel-helper-vue-transform-on@1.2.5': {}
@@ -2127,14 +2182,14 @@ snapshots:
'@vue/devtools-api@6.6.4': {}
'@vue/devtools-core@7.6.4(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13)':
'@vue/devtools-core@7.6.4(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13)':
dependencies:
'@vue/devtools-kit': 7.6.4
'@vue/devtools-shared': 7.6.4
mitt: 3.0.1
nanoid: 3.3.7
pathe: 1.1.2
vite-hot-client: 0.2.3(vite@5.4.11(sass-embedded@1.81.0))
vite-hot-client: 0.2.3(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))
vue: 3.5.13
transitivePeerDependencies:
- vite
@@ -2198,6 +2253,8 @@ snapshots:
acorn@8.14.0: {}
acorn@8.15.0: {}
ansi-regex@5.0.1: {}
ansi-regex@6.1.0: {}
@@ -2222,7 +2279,7 @@ snapshots:
autoprefixer@10.4.20(postcss@8.4.49):
dependencies:
browserslist: 4.24.2
caniuse-lite: 1.0.30001713
caniuse-lite: 1.0.30001739
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.1.1
@@ -2253,20 +2310,22 @@ snapshots:
browserslist@4.24.2:
dependencies:
caniuse-lite: 1.0.30001713
caniuse-lite: 1.0.30001739
electron-to-chromium: 1.5.63
node-releases: 2.0.18
update-browserslist-db: 1.1.1(browserslist@4.24.2)
buffer-builder@0.2.0: {}
buffer-from@1.1.2: {}
bundle-name@4.1.0:
dependencies:
run-applescript: 7.0.0
camelcase-css@2.0.1: {}
caniuse-lite@1.0.30001713: {}
caniuse-lite@1.0.30001739: {}
chokidar@3.6.0:
dependencies:
@@ -2292,6 +2351,8 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
commander@2.20.3: {}
commander@4.1.1: {}
confbox@0.1.8: {}
@@ -2879,6 +2940,13 @@ snapshots:
source-map-js@1.2.1: {}
source-map-support@0.5.21:
dependencies:
buffer-from: 1.1.2
source-map: 0.6.1
source-map@0.6.1: {}
speakingurl@14.0.1: {}
string-width@4.2.3:
@@ -2962,6 +3030,13 @@ snapshots:
transitivePeerDependencies:
- ts-node
terser@5.43.1:
dependencies:
'@jridgewell/source-map': 0.3.11
acorn: 8.15.0
commander: 2.20.3
source-map-support: 0.5.21
thenify-all@1.6.0:
dependencies:
thenify: 3.3.1
@@ -3060,11 +3135,11 @@ snapshots:
varint@6.0.0: {}
vite-hot-client@0.2.3(vite@5.4.11(sass-embedded@1.81.0)):
vite-hot-client@0.2.3(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1)):
dependencies:
vite: 5.4.11(sass-embedded@1.81.0)
vite: 5.4.11(sass-embedded@1.81.0)(terser@5.43.1)
vite-plugin-inspect@0.8.8(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0)):
vite-plugin-inspect@0.8.8(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1)):
dependencies:
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.1.3(rollup@4.27.3)
@@ -3075,28 +3150,28 @@ snapshots:
perfect-debounce: 1.0.0
picocolors: 1.1.1
sirv: 3.0.0
vite: 5.4.11(sass-embedded@1.81.0)
vite: 5.4.11(sass-embedded@1.81.0)(terser@5.43.1)
transitivePeerDependencies:
- rollup
- supports-color
vite-plugin-vue-devtools@7.6.4(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13):
vite-plugin-vue-devtools@7.6.4(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13):
dependencies:
'@vue/devtools-core': 7.6.4(vite@5.4.11(sass-embedded@1.81.0))(vue@3.5.13)
'@vue/devtools-core': 7.6.4(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))(vue@3.5.13)
'@vue/devtools-kit': 7.6.4
'@vue/devtools-shared': 7.6.4
execa: 8.0.1
sirv: 3.0.0
vite: 5.4.11(sass-embedded@1.81.0)
vite-plugin-inspect: 0.8.8(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0))
vite-plugin-vue-inspector: 5.2.0(vite@5.4.11(sass-embedded@1.81.0))
vite: 5.4.11(sass-embedded@1.81.0)(terser@5.43.1)
vite-plugin-inspect: 0.8.8(rollup@4.27.3)(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))
vite-plugin-vue-inspector: 5.2.0(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1))
transitivePeerDependencies:
- '@nuxt/kit'
- rollup
- supports-color
- vue
vite-plugin-vue-inspector@5.2.0(vite@5.4.11(sass-embedded@1.81.0)):
vite-plugin-vue-inspector@5.2.0(vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1)):
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.0)
@@ -3107,11 +3182,11 @@ snapshots:
'@vue/compiler-dom': 3.5.13
kolorist: 1.8.0
magic-string: 0.30.13
vite: 5.4.11(sass-embedded@1.81.0)
vite: 5.4.11(sass-embedded@1.81.0)(terser@5.43.1)
transitivePeerDependencies:
- supports-color
vite@5.4.11(sass-embedded@1.81.0):
vite@5.4.11(sass-embedded@1.81.0)(terser@5.43.1):
dependencies:
esbuild: 0.21.5
postcss: 8.4.49
@@ -3119,6 +3194,7 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
sass-embedded: 1.81.0
terser: 5.43.1
vue-demi@0.13.11(vue@3.5.13):
dependencies:

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

13
public/robots.txt Normal file
View File

@@ -0,0 +1,13 @@
User-agent: *
Allow: /
# 允许搜索引擎抓取所有页面
Disallow: /api/
Disallow: /admin/
Disallow: /private/
# 站点地图
Sitemap: https://www.tianyuancha.cn/sitemap.xml
# 爬取延迟(秒)
Crawl-delay: 1

45
public/site.webmanifest Normal file
View File

@@ -0,0 +1,45 @@
{
"name": "天远查 - 专业司法涉诉查询平台",
"short_name": "天远查",
"description": "提供婚恋评估、判决书查询、婚姻状态查询等专业服务",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3498db",
"orientation": "portrait-primary",
"scope": "/",
"lang": "zh-CN",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
],
"categories": [
"business",
"productivity",
"utilities"
],
"screenshots": [
{
"src": "/screenshot-desktop.png",
"sizes": "1280x720",
"type": "image/png",
"form_factor": "wide"
},
{
"src": "/screenshot-mobile.png",
"sizes": "390x844",
"type": "image/png",
"form_factor": "narrow"
}
]
}

112
public/sitemap.xml Normal file
View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<!-- 首页 -->
<url>
<loc>https://www.tianyuancha.cn/</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<!-- 主要功能页面 -->
<url>
<loc>https://www.tianyuancha.cn/listMarriage</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://www.tianyuancha.cn/listRisk</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://www.tianyuancha.cn/listCar</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://www.tianyuancha.cn/listLawsuit</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://www.tianyuancha.cn/listVerify</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<!-- 历史查询 -->
<url>
<loc>https://www.tianyuancha.cn/historyQuery</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
</url>
<!-- 示例报告 -->
<url>
<loc>https://www.tianyuancha.cn/example</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.6</priority>
</url>
<!-- 服务页面 -->
<url>
<loc>https://www.tianyuancha.cn/service</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<!-- 投诉页面 -->
<url>
<loc>https://www.tianyuancha.cn/complaint</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<!-- 法律文件页面 -->
<url>
<loc>https://www.tianyuancha.cn/privacyPolicy</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.4</priority>
</url>
<url>
<loc>https://www.tianyuancha.cn/userAgreement</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.4</priority>
</url>
<url>
<loc>https://www.tianyuancha.cn/authorization</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.4</priority>
</url>
<url>
<loc>https://www.tianyuancha.cn/othersAuthorization</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.4</priority>
</url>
</urlset>

View File

@@ -0,0 +1,17 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="educationGradient" x1="12" y1="10" x2="56" y2="50" gradientUnits="userSpaceOnUse">
<stop stop-color="#4F46E5"/>
<stop offset="1" stop-color="#0EA5E9"/>
</linearGradient>
<linearGradient id="educationShadow" x1="32" y1="40" x2="32" y2="58" gradientUnits="userSpaceOnUse">
<stop stop-color="#0EA5E9" stop-opacity="0.25"/>
<stop offset="1" stop-color="#0EA5E9" stop-opacity="0"/>
</linearGradient>
</defs>
<rect x="10" y="42" width="44" height="14" rx="7" fill="url(#educationShadow)"/>
<path d="M7 20.5L32 8L57 20.5L32 33L7 20.5Z" fill="url(#educationGradient)"/>
<path d="M17 25.5V38C17 40.7614 19.2386 43 22 43H42C44.7614 43 47 40.7614 47 38V25.5" stroke="url(#educationGradient)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M32 33V44" stroke="url(#educationGradient)" stroke-width="4" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,19 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="enrollmentGradient" x1="18" y1="12" x2="54" y2="52" gradientUnits="userSpaceOnUse">
<stop stop-color="#3B82F6"/>
<stop offset="1" stop-color="#8B5CF6"/>
</linearGradient>
<linearGradient id="enrollmentShadow" x1="32" y1="44" x2="32" y2="60" gradientUnits="userSpaceOnUse">
<stop stop-color="#3B82F6" stop-opacity="0.25"/>
<stop offset="1" stop-color="#3B82F6" stop-opacity="0"/>
</linearGradient>
</defs>
<rect x="13" y="46" width="38" height="12" rx="6" fill="url(#enrollmentShadow)"/>
<rect x="14" y="16" width="36" height="32" rx="8" fill="url(#enrollmentGradient)"/>
<path d="M24 14V10M40 14V10" stroke="url(#enrollmentGradient)" stroke-width="4" stroke-linecap="round"/>
<rect x="20" y="24" width="8" height="8" rx="2" fill="white"/>
<rect x="20" y="36" width="24" height="3.5" rx="1.75" fill="white" fill-opacity="0.75"/>
<rect x="33" y="24" width="13" height="3.5" rx="1.75" fill="white" fill-opacity="0.9"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,19 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="graduationGradient" x1="16" y1="12" x2="52" y2="52" gradientUnits="userSpaceOnUse">
<stop stop-color="#FACC15"/>
<stop offset="1" stop-color="#F97316"/>
</linearGradient>
<linearGradient id="graduationShadow" x1="32" y1="44" x2="32" y2="60" gradientUnits="userSpaceOnUse">
<stop stop-color="#F59E0B" stop-opacity="0.25"/>
<stop offset="1" stop-color="#F59E0B" stop-opacity="0"/>
</linearGradient>
</defs>
<rect x="12" y="46" width="40" height="12" rx="6" fill="url(#graduationShadow)"/>
<path d="M16 22C16 16.4772 20.4772 12 26 12H38C43.5228 12 48 16.4772 48 22V34C48 39.5228 43.5228 44 38 44H26C20.4772 44 16 39.5228 16 34V22Z" fill="url(#graduationGradient)"/>
<path d="M32 18V39" stroke="white" stroke-width="4" stroke-linecap="round"/>
<path d="M25 27L32 20L39 27" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M24 42L22 49" stroke="url(#graduationGradient)" stroke-width="4" stroke-linecap="round"/>
<circle cx="22" cy="52" r="3" fill="url(#graduationGradient)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,18 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="learningGradient" x1="16" y1="10" x2="52" y2="54" gradientUnits="userSpaceOnUse">
<stop stop-color="#22C55E"/>
<stop offset="1" stop-color="#14B8A6"/>
</linearGradient>
<linearGradient id="learningShadow" x1="32" y1="44" x2="32" y2="60" gradientUnits="userSpaceOnUse">
<stop stop-color="#22C55E" stop-opacity="0.25"/>
<stop offset="1" stop-color="#22C55E" stop-opacity="0"/>
</linearGradient>
</defs>
<rect x="12" y="46" width="40" height="12" rx="6" fill="url(#learningShadow)"/>
<path d="M19 19C19 14.0294 23.0294 10 28 10H36C40.9706 10 45 14.0294 45 19V32C45 36.9706 40.9706 41 36 41H28C23.0294 41 19 36.9706 19 32V19Z" fill="url(#learningGradient)"/>
<path d="M22 46C22 42.6863 24.6863 40 28 40H36C39.3137 40 42 42.6863 42 46V50C42 51.6569 40.6569 53 39 53H25C23.3431 53 22 51.6569 22 50V46Z" fill="url(#learningGradient)"/>
<path d="M24 24H40" stroke="white" stroke-width="3" stroke-linecap="round"/>
<path d="M24 31H35" stroke="white" stroke-width="3" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,17 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="specialtyGradient" x1="14" y1="12" x2="54" y2="52" gradientUnits="userSpaceOnUse">
<stop stop-color="#F97316"/>
<stop offset="1" stop-color="#FB7185"/>
</linearGradient>
<linearGradient id="specialtyGlow" x1="32" y1="44" x2="32" y2="60" gradientUnits="userSpaceOnUse">
<stop stop-color="#FB7185" stop-opacity="0.25"/>
<stop offset="1" stop-color="#FB7185" stop-opacity="0"/>
</linearGradient>
</defs>
<rect x="11" y="46" width="42" height="12" rx="6" fill="url(#specialtyGlow)"/>
<path d="M14 22C14 15.9249 18.9249 11 25 11H39C45.0751 11 50 15.9249 50 22V34C50 40.0751 45.0751 45 39 45H25C18.9249 45 14 40.0751 14 34V22Z" fill="url(#specialtyGradient)"/>
<path d="M24 25H40M24 33H34" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="39" cy="33" r="3" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

View File

@@ -236,6 +236,7 @@ declare global {
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSEO: typeof import('./composables/useSEO.js')['useSEO']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']

View File

@@ -106,9 +106,7 @@
signature ? props.name : "____________"
}}</span>
<br />
手机号码<span class="underline">
{{ signature ? props.mobile : "____________" }}
</span>
<br />
签署时间<span class="underline">{{ signTime }}</span>
</p>

View File

@@ -54,7 +54,7 @@ const featureMap = {
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异、离异冷静期。如您对查询结果有疑问,请联系客服反馈。',
},
G27BJ05: {
name: "借贷申请记录",
name: "本人需求推测",
component: defineAsyncComponent(() =>
import("@/ui/CBankLoanApplication.vue")
),
@@ -82,13 +82,13 @@ const featureMap = {
component: defineAsyncComponent(() => import("@/ui/CLawsuitPP.vue")),
},
G05HZ01: {
name: "股东人企关系",
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CPersonEnterprisePro/index.vue")
),
},
PersonEnterprisePro: {
name: "人企关系加强版",
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CPersonEnterprisePro/index.vue")
),
@@ -248,14 +248,14 @@ const calculateScore = (reportData) => {
FIN019: 100, // 银行卡黑名单
// 高风险指标(中优先级)
G27BJ05: 40, // 借贷申请记录
G27BJ05: 40, // 本人需求推测
G28BJ05: 40, // 借贷行为记录
G03HZ01: 70, // 手机号码风险
// 中风险指标(低优先级)
G19BJ02: 50, // 手机二次卡
G02BJ02: 50, // 手机在网时长
G05HZ01: 50, // 人企关系
G05HZ01: 50, // 名下企业关联
// 验证指标(最低优先级)
G15BJ02: 25, // 手机三要素
@@ -302,7 +302,7 @@ const calculateScore = (reportData) => {
// 不计入风险
break;
case "G27BJ05": // 借贷申请记录
case "G27BJ05": // 本人需求推测
if (data) {
// 检查是否有申请记录(有则表示风险)
let hasRisk = false;
@@ -515,13 +515,7 @@ const calculateScore = (reportData) => {
<template>
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<template v-if="isDone">
<van-tabs
v-model:active="active"
shrink
scrollspy
sticky
:offset-top="46"
>
<van-tabs v-model:active="active" shrink scrollspy sticky :offset-top="46">
<div class="flex flex-col gap-y-4 p-4">
<LEmpty v-if="isEmpty" />
<van-tab title="分析指数">
@@ -536,49 +530,23 @@ const calculateScore = (reportData) => {
<div id="overdiv" class="title mb-4">基本信息</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<LTitle
title="报告信息"
type="blue-green"
></LTitle>
<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 class="flex justify-between border-b pb-2 pl-2">
<span class="text-gray-700 font-bold">报告时间</span>
<span class="text-gray-600">{{ reportTime }}</span>
</div>
<div
class="flex justify-between border-b pb-2 pl-2"
v-if="!isEmpty"
>
<span class="text-gray-700 font-bold"
>报告项目</span
>
<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
>
{{ reportName }}</span>
</div>
</div>
<template
v-if="Object.keys(reportParams).length != 0"
>
<LTitle
title="报告对象"
type="blue-green"
></LTitle>
<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
>
<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",
@@ -586,31 +554,20 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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
>
}}</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
>
<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",
@@ -618,14 +575,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -633,14 +585,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -648,14 +595,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -663,14 +605,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -678,14 +615,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -693,16 +625,10 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -710,14 +636,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -725,14 +646,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -740,14 +656,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -756,49 +667,33 @@ const calculateScore = (reportData) => {
}}</span>
</div>
<div class="flex flex-col gap-4">
<div
class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1"
>
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4"
>
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
<div
class="font-bold text-lg"
>
<div class="font-bold text-lg">
身份证检查结果
</div>
<div
class="text-sm text-gray-600"
>
<div class="text-sm text-gray-600">
身份证信息核验通过
</div>
</div>
</div>
<div
class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1"
>
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4"
>
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
<div
class="font-bold text-lg"
>
<div class="font-bold text-lg">
手机号检测结果
</div>
<div
class="text-sm text-gray-600"
>
<div class="text-sm text-gray-600">
被查询人姓名与运营商提供的一致
</div>
<div
class="text-sm text-gray-600"
>
<div class="text-sm text-gray-600">
被查询人身份证与运营商提供的一致
</div>
</div>
@@ -808,28 +703,18 @@ const calculateScore = (reportData) => {
</template>
</div>
</div>
<LRemark
content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况"
/>
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
</van-tab>
<van-tab
v-for="(item, index) in reportData"
:key="index"
:title="featureMap[item.data.apiID]?.name"
>
<van-tab v-for="(item, index) in reportData" :key="index"
:title="featureMap[item.data.apiID]?.name">
<div id="lawsuit" class="title mb-4">
{{ featureMap[item.data.apiID]?.name }}
</div>
<component
:is="featureMap[item.data.apiID]?.component"
:data="item.data.data"
:params="reportParams"
>
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
:params="reportParams">
</component>
<LRemark
v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark"
/>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</van-tab>
<div class="card">
<div>
@@ -841,10 +726,7 @@ const calculateScore = (reportData) => {
&nbsp;本报告的数据由用户本人明确授权后,我们才向相关合法存有用户个人数据的机构调取本报告相关内容,本平台只做大数据的获取与分析,仅向用户个人展示参考。
</div>
<p>
&nbsp; &nbsp; 报告有效期<strong
class="text-red-500"
>15天</strong
>,过期自动删除。
&nbsp; &nbsp; 报告有效期<strong class="text-red-500">15天</strong>,过期自动删除。
</p>
<p>
&nbsp; &nbsp;
@@ -863,20 +745,16 @@ const calculateScore = (reportData) => {
<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>
<img class="w-4 h-4 mr-2" src="@/assets/images/public_security_record_icon.png" alt="公安备案" />
<text>桂公网安备45010002451084号</text>
</div>
<div>
<a class="text-blue-500" href="https://beian.miit.gov.cn">
ICP备2024038584号-2
ICP备2024038462号
</a>
</div>
</div>
<div>海南省学宇思科技有限公司版权所有</div>
<div>广西福铭网络科技有限公司版权所有</div>
</div>
</template>
@@ -884,6 +762,7 @@ const calculateScore = (reportData) => {
.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;
}
@@ -898,6 +777,7 @@ const calculateScore = (reportData) => {
padding-bottom: 60px;
background: #ffffff;
}
:deep(.card) {
@apply p-3;
}

View File

@@ -85,7 +85,7 @@ async function getPayment() {
if (data.value && !error.value) {
orderId.value = data.value.data.order_id
const prepayUrl = data.value.data.prepay_id;
const prepayUrl = data.value.data.prepay_data;
const paymentForm = document.createElement('form');
paymentForm.method = 'POST';
paymentForm.action = prepayUrl;

View File

@@ -3,11 +3,11 @@
<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>
<text>公网安备45010002451084</text>
</div>
<div>
<a class="text-blue-500" href="https://beian.miit.gov.cn">
ICP备2024038584号-2
ICP备2024038462号
</a>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<template>
<div v-if="isWeChat" class="wechat-overlay">
<div v-if="shouldShowOverlay" class="wechat-overlay">
<div class="wechat-content">
<p class="wechat-message">
点击右上角的<van-icon class="ml-2" name="weapp-nav" /><br />然后点击在浏览器中打开
@@ -10,7 +10,11 @@
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { ref, onMounted, computed } from 'vue';
import { useRoute } from 'vue-router';
// 获取当前路由
const route = useRoute();
// 定义一个响应式变量,表示是否在微信环境
const isWeChat = ref(false);
@@ -21,6 +25,22 @@ const checkIfWeChat = () => {
isWeChat.value = /micromessenger/.test(userAgent);
};
// 计算属性:判断是否应该显示遮罩层
const shouldShowOverlay = computed(() => {
// 如果不在微信环境,不显示遮罩层
if (!isWeChat.value) {
return false;
}
// 如果路由的 meta.wechatOverlayHidden 为 true不显示遮罩层
if (route.meta?.wechatOverlayHidden) {
return false;
}
// 其他情况显示遮罩层
return true;
});
// 在组件挂载后检查环境
onMounted(() => {
checkIfWeChat();

View File

@@ -6,7 +6,7 @@ import router from "@/router"; // 假设你使用 Vue Router
const useApiFetch = createFetch({
baseUrl: "/api/v1", // 你的 API 基础路径
options: {
async beforeFetch({ options }) {
async beforeFetch({ url, options }) {
showLoadingToast({
message: "加载中...",
forbidClick: true,
@@ -16,6 +16,20 @@ const useApiFetch = createFetch({
// 获取平台信息
let platform = "h5";
const [rawPath, hash = ""] = url.split("#");
const separator = rawPath.includes("?") ? "&" : "?";
const timestampedUrl = `${rawPath}${separator}_ts=${Date.now()}${
hash ? `#${hash}` : ""
}`;
options.cache = "no-store";
options.headers = {
...options.headers,
"Cache-Control": "no-cache, no-store, must-revalidate",
Pragma: "no-cache",
Expires: "0",
};
// 在请求前添加通用的 Header例如 Authorization
const token = localStorage.getItem("token");
const webviewEnv = localStorage.getItem("webview_env");
@@ -42,7 +56,7 @@ const useApiFetch = createFetch({
"X-Promote-Key": promoteKey,
};
}
return { options };
return { url: timestampedUrl, options };
},
async afterFetch({ data, response }) {
closeToast();
@@ -58,13 +72,17 @@ const useApiFetch = createFetch({
if (data.code !== 200) {
if (data.code === 100009) {
// 改进的存储管理
localStorage.removeItem('token')
localStorage.removeItem("token");
// 重置状态
location.reload()
location.reload();
}
if (data.code !== 200002 && data.code !== 200003 && data.code !== 200004 && data.code !== 100009) {
if (
data.code !== 200002 &&
data.code !== 200003 &&
data.code !== 200004 &&
data.code !== 100009
) {
showToast({ message: data.msg });
}
}

View File

@@ -42,7 +42,7 @@ const allMenuItems = [
"通过查询个人的不良记录,评估其风险等级(低、中、高风险)。帮助您识别潜在的信用和法律风险,确保合作方的合法合规。",
},
{
title: "股东人企关系",
title: "名下企业关联",
icon: gdrqgxIcon,
product: "toc_ShareholderBusinessRelation",
category: "个人风险查询",
@@ -295,7 +295,7 @@ const allMenuItems = [
"车辆估值功能帮助用户评估车辆的市场价值,提供基于车型、年限、车况等因素的估值报告,帮助用户做出购买或出售决策。",
},
{
title: "婚姻状态",
title: "婚姻状态(登记时间版)",
icon: srhyIcon,
product: "toc_Marriage",
category: "个人风险查询",
@@ -327,51 +327,81 @@ const allMenuItems = [
icon: srhyIcon,
product: "marriage",
category: "风险报告",
description: "评估婚恋对象的潜在风险,提供全面的背景调查和风险分析,帮助用户做出明智的婚恋决策。",
description:
"评估婚恋对象的潜在风险,提供全面的背景调查和风险分析,帮助用户做出明智的婚恋决策。",
},
{
title: "老板企业风险",
icon: gdrqgxIcon,
product: "companyinfo",
category: "风险报告",
description: "全面评估企业老板的各类风险,包括信用风险、法律风险和经营风险,为商业合作提供决策依据。",
description:
"全面评估企业老板的各类风险,包括信用风险、法律风险和经营风险,为商业合作提供决策依据。",
},
{
title: "租赁风险",
icon: zlfxIcon,
product: "rentalinfo",
category: "风险报告",
description: "评估租赁关系中的潜在风险,对租户进行全面的信用调查,帮助房东降低租赁风险,保障租赁双方权益。",
description:
"评估租赁关系中的潜在风险,对租户进行全面的信用调查,帮助房东降低租赁风险,保障租赁双方权益。",
},
{
title: "个人风险",
icon: grblIcon,
product: "riskassessment",
category: "风险报告",
description: "提供全面的个人风险评估,包括信用风险、法律风险和行为风险,帮助用户了解个人的整体风险状况。",
description:
"提供全面的个人风险评估,包括信用风险、法律风险和行为风险,帮助用户了解个人的整体风险状况。",
},
{
title: "入职风险",
icon: rzfxIcon,
product: "backgroundcheck",
category: "风险报告",
description: "为企业提供求职者的背景调查服务,包括信用风险、法律风险和行为风险,降低企业用人风险。",
description:
"为企业提供求职者的背景调查服务,包括信用风险、法律风险和行为风险,降低企业用人风险。",
},
{
title: "贷前风险",
icon: dqfxIcon,
product: "preloanbackgroundcheck",
category: "风险报告",
description: "在贷款发放前评估借款人的风险状况,包括信用历史、还款能力和潜在违约风险,为贷款决策提供支持。",
description:
"在贷款发放前评估借款人的风险状况,包括信用历史、还款能力和潜在违约风险,为贷款决策提供支持。",
},
{
title: "家政风险",
icon: jzfxIcon,
product: "homeservice",
category: "风险报告",
description: "评估家政服务人员的背景和风险,确保家庭安全,为家庭雇主提供可靠的家政人员风险评估。",
description:
"评估家政服务人员的背景和风险,确保家庭安全,为家庭雇主提供可靠的家政人员风险评估。",
},
{
title: "婚姻状态(补证版)",
icon: srhyIcon,
product: "toc_MarriageReplenish",
category: "个人风险查询",
description:
"查询个人婚姻状态信息,包括补证版本的婚姻记录,帮助了解婚姻状况和风险。",
},
{
title: "学历信息查询(含学校名称)",
icon: xlhyIcon,
product: "toc_EducationInfoName",
category: "个人风险查询",
description:
"查询个人学历信息,包括学校名称等详细信息,验证教育背景的真实性和完整性。",
},
{
title: "携号转网查询",
icon: sjhmfxIcon,
product: "toc_NumberPortability",
category: "手机风险查询",
description:
"查询手机号码的携号转网记录,了解号码的运营商变更历史,帮助评估号码稳定性。",
},
];
// 定义 Composable返回过滤后的菜单项
@@ -417,8 +447,8 @@ export function useMenuItems() {
// 根据分类进行分组
const grouped = {};
filtered.forEach(item => {
const category = item.category || '其他';
filtered.forEach((item) => {
const category = item.category || "其他";
if (!grouped[category]) {
grouped[category] = [];
}

196
src/composables/useSEO.js Normal file
View File

@@ -0,0 +1,196 @@
import { onMounted, watch } from "vue";
import { useRoute } from "vue-router";
import {
initPageSEO,
generateWebsiteStructuredData,
generateOrganizationStructuredData,
} from "@/utils/seo";
/**
* SEO优化的Composable
*/
export function useSEO() {
const route = useRoute();
/**
* 设置页面SEO信息
* @param {Object} seoConfig - SEO配置
*/
const setPageSEO = (seoConfig = {}) => {
const defaultSEO = {
title: "天远查 - 专业司法涉诉查询平台",
description:
"天远查是专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询、被执行人查询、失信人查询等服务。",
keywords:
"天远查,司法涉诉查询,婚恋评估,判决书查询,婚姻状态查询,被执行人查询,失信人查询,限高查询,个人涉诉查询,企业涉诉查询,车辆核验,身份核验,手机核验,银行卡核验,学历核验,风险报告,法律风险,信用风险,在线查询平台",
ogData: {
title: "天远查 - 专业司法涉诉查询平台",
description:
"天远查是专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询、被执行人查询、失信人查询等服务。",
type: "website",
url: "https://www.tianyuancha.cn",
image: "https://www.tianyuancha.cn/og-image.jpg",
},
twitterData: {
title: "天远查 - 专业司法涉诉查询平台",
description: "提供婚恋评估、判决书查询、婚姻状态查询等专业服务",
image: "https://www.tianyuancha.cn/twitter-image.jpg",
},
canonicalUrl: "https://www.tianyuancha.cn",
};
const finalSEO = { ...defaultSEO, ...seoConfig };
initPageSEO(finalSEO);
};
/**
* 设置结构化数据
*/
const setStructuredData = () => {
// 设置网站结构化数据
const websiteData = generateWebsiteStructuredData();
const organizationData = generateOrganizationStructuredData();
// 将结构化数据添加到页面
const script1 = document.createElement("script");
script1.type = "application/ld+json";
script1.textContent = JSON.stringify(websiteData);
document.head.appendChild(script1);
const script2 = document.createElement("script");
script2.type = "application/ld+json";
script2.textContent = JSON.stringify(organizationData);
document.head.appendChild(script2);
};
/**
* 根据路由设置SEO
*/
const setRouteSEO = () => {
const routeMeta = route.meta;
if (routeMeta) {
const seoConfig = {
title: routeMeta.title,
description: routeMeta.description,
keywords: routeMeta.keywords,
ogData: {
title: routeMeta.title,
description: routeMeta.description,
url: `https://www.tianyuancha.cn${route.path}`,
},
twitterData: {
title: routeMeta.title,
description: routeMeta.description,
},
canonicalUrl: `https://www.tianyuancha.cn${route.path}`,
};
setPageSEO(seoConfig);
}
};
/**
* 设置页面加载性能监控
*/
const setPerformanceMonitoring = () => {
if (typeof window !== "undefined" && window.performance) {
window.addEventListener("load", () => {
const navigation =
performance.getEntriesByType("navigation")[0];
const paint = performance.getEntriesByType("paint");
// 记录关键性能指标
const performanceData = {
dns:
navigation.domainLookupEnd -
navigation.domainLookupStart,
tcp: navigation.connectEnd - navigation.connectStart,
ttfb: navigation.responseStart - navigation.requestStart,
domContentLoaded:
navigation.domContentLoadedEventEnd -
navigation.domContentLoadedEventStart,
load: navigation.loadEventEnd - navigation.loadEventStart,
firstPaint: paint.find((p) => p.name === "first-paint")
?.startTime,
firstContentfulPaint: paint.find(
(p) => p.name === "first-contentful-paint"
)?.startTime,
};
// 发送性能数据到分析服务
if (window.aplus_queue) {
aplus_queue.push({
action: "aplus.record",
arguments: ["performance", performanceData],
});
}
});
}
};
/**
* 设置错误监控
*/
const setErrorMonitoring = () => {
if (typeof window !== "undefined") {
window.addEventListener("error", (event) => {
const errorData = {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
error: event.error?.stack,
};
// 发送错误数据到分析服务
if (window.aplus_queue) {
aplus_queue.push({
action: "aplus.record",
arguments: ["error", errorData],
});
}
});
window.addEventListener("unhandledrejection", (event) => {
const errorData = {
message:
event.reason?.message || "Unhandled Promise Rejection",
stack: event.reason?.stack,
};
// 发送错误数据到分析服务
if (window.aplus_queue) {
aplus_queue.push({
action: "aplus.record",
arguments: ["error", errorData],
});
}
});
}
};
// 监听路由变化
watch(
() => route.path,
() => {
setRouteSEO();
}
);
// 组件挂载时初始化
onMounted(() => {
setRouteSEO();
setStructuredData();
setPerformanceMonitoring();
setErrorMonitoring();
});
return {
setPageSEO,
setRouteSEO,
setStructuredData,
setPerformanceMonitoring,
setErrorMonitoring,
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,14 @@
<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 class="flex justify-center gap-4 mt-4">
<van-button type="default" plain @click="showPopup = false" class="w-24" size="small">
关闭
</van-button>
<van-button type="primary" @click="goToWebsite" class="w-24" size="small">
前往
</van-button>
</div>
</div>
</van-popup>
@@ -88,6 +94,11 @@ watch(() => route.path, () => {
const onClickOverlay = () => {
showPopup.value = false
}
// 跳转到网站
const goToWebsite = () => {
window.open('https://www.zhinengcha.cn', '_blank')
}
</script>
<style lang="scss" scoped></style>

View File

@@ -2,11 +2,7 @@
<div class="home-layout min-h-screen flex flex-col">
<!-- Header -->
<div class="header">
<img
class="logo rounded-full"
src="@/assets/images/logo.jpg"
alt="Logo"
/>
<img class="logo rounded-full" src="@/assets/images/logo.jpg" alt="Logo" />
<div class="title">天远查</div>
</div>
@@ -18,12 +14,8 @@
<!-- 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 v-for="(item, index) in menu" :key="index" :name="item.name" :icon="item.icon">{{
item.title }}
</van-tabbar-item>
</van-tabbar>
@@ -33,6 +25,10 @@
<span>投诉</span>
</div>
<div class="disclaimer">
<div class="flex items-center">
<img class="w-4 h-4 mr-2" src="@/assets/images/public_security_record_icon.png" alt="公安备案" />
<text>桂公网安备45010002451084号</text>
</div>
<div class="flex flex-col items-center">
<div>
<a class="text-blue-500" href="https://beian.miit.gov.cn">
@@ -64,7 +60,8 @@ const menu = reactive([
{ title: "首页", icon: "home-o", name: "index" },
// { title: "AI律师", icon: "chat-o", name: "ai" },
{ title: "我的", icon: "user-o", name: "me" },
{ title: "推广代理", icon: "balance-o", name: "promote" },
{ title: "商务合作", icon: "chat-o", name: "business" },
{ title: "更多", icon: "more-o", name: "more" },
]);
// 根据当前路由设置 Tabbar 的高亮项
@@ -73,15 +70,18 @@ onMounted(() => {
tabbar.value = currentPage;
});
const onClickOverlay = () => {};
const onClickOverlay = () => { };
// 跳转到相应页面
const tabChange = (name) => {
if (name === "promote") {
window.location.href =
"https://www.tianyuandb.com?_um_campaign=67c15d4f8f232a05f1221b82&_um_channel=67c15d4f8f232a05f1221b83"; // 跳转到客服页面
} else {
router.push({ name }); // 使用 Vue Router 进行跳转
if (name === "business") {
window.location.href = "https://tianyuandata.com/";
return;
}
if (name === "more") {
window.location.href = "https://www.zhinengcha.cn";
return;
}
router.push({ name }); // 使用 Vue Router 进行跳转
};
// 跳转到投诉页面

View File

@@ -1,21 +1,27 @@
import 'nprogress/nprogress.css'; // 默认样式,可根据需要自定义样式
import './assets/main.css'
import { createApp } from 'vue'
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)
import "nprogress/nprogress.css"; // 默认样式,可根据需要自定义样式
import "./assets/main.css";
import { createApp } from "vue";
import { createHead } from "@vueuse/head";
import App from "./App.vue";
import router from "./router";
import { createPinia } from "pinia";
import "vant/lib/index.css";
app.mount('#app')
document.addEventListener('DOMContentLoaded', () => {
const loadingElement = document.getElementById('app-loading');
const app = createApp(App);
const head = createHead();
const pinia = createPinia();
app.use(head);
app.use(router);
app.use(pinia);
app.mount("#app");
document.addEventListener("DOMContentLoaded", () => {
const loadingElement = document.getElementById("app-loading");
if (loadingElement) {
loadingElement.style.opacity = '0';
loadingElement.style.opacity = "0";
setTimeout(() => {
loadingElement.parentNode.removeChild(loadingElement);
}, 500); // 动画过渡时间
}
});
});

View File

@@ -17,8 +17,8 @@ const router = createRouter({
// 调用处理函数,不等待其完成
handlePromotionLink(to.params.url);
// 直接跳转到首页
next('/');
}
next("/");
},
},
{
path: "/",
@@ -32,16 +32,36 @@ const router = createRouter({
path: "",
name: "index",
component: index,
meta: {
title: "天远查 - 专业司法涉诉查询平台",
description:
"天远查是专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询、被执行人查询、失信人查询等服务。",
keywords:
"天远查,司法涉诉查询,婚恋评估,判决书查询,婚姻状态查询,被执行人查询,失信人查询,限高查询,个人涉诉查询,企业涉诉查询,车辆核验,身份核验,手机核验,银行卡核验,学历核验,风险报告,法律风险,信用风险,在线查询平台",
},
},
{
path: "ai",
name: "ai",
component: () => import("@/views/Ai.vue"),
meta: {
title: "AI智能查询 - 天远查",
description:
"天远查AI智能查询服务提供智能化的司法涉诉查询、婚恋评估、风险分析等服务。",
keywords:
"AI智能查询,司法查询,婚恋评估,风险分析,智能分析",
},
},
{
path: "me",
name: "me",
component: () => import("@/views/Me.vue"),
meta: {
title: "个人中心 - 天远查",
description:
"天远查个人中心,管理您的查询记录、账户信息和设置。",
keywords: "个人中心,账户管理,查询记录,用户设置",
},
},
],
},
@@ -53,96 +73,246 @@ const router = createRouter({
path: "/historyQuery",
name: "history",
component: () => import("@/views/HistoryQuery.vue"),
meta: { title: "历史报告" },
meta: {
title: "历史报告 - 天远查",
description:
"查看您的历史查询报告,包括司法涉诉查询、婚恋评估、风险报告等历史记录。",
keywords:
"历史报告,查询记录,司法查询历史,婚恋评估历史,风险报告历史",
},
},
{
path: "/service",
name: "service",
component: () => import("@/views/Service.vue"),
meta: { title: "客服" },
meta: {
title: "客服服务 - 天远查",
description:
"天远查客服服务,为您提供专业的查询服务支持和帮助。",
keywords: "客服服务,在线客服,服务支持,帮助中心",
},
},
{
path: "/complaint",
name: "complaint",
component: () => import("@/views/Complaint.vue"),
meta: { title: "投诉" },
meta: {
title: "投诉建议 - 天远查",
description:
"天远查投诉建议平台,我们重视您的反馈,持续改进服务质量。",
keywords: "投诉建议,用户反馈,服务质量,改进建议",
},
},
{
path: "/report",
name: "report",
component: () => import("@/views/Report.vue"),
meta: { title: "报告结果" },
meta: {
title: "报告结果 - 天远查",
description:
"查看您的查询报告结果,包括详细的司法涉诉信息、风险评估等。",
keywords:
"报告结果,查询结果,司法信息,风险评估,详细报告",
},
},
{
path: "/example",
name: "example",
component: () => import("@/views/Example.vue"),
meta: { title: "示例报告" },
meta: {
title: "示例报告 - 天远查",
description:
"天远查示例报告,了解我们的查询服务内容和报告格式。",
keywords: "示例报告,报告格式,查询内容,服务展示",
},
},
{
path: "/authorization",
name: "authorization",
component: () =>
import("@/views/Authorization.vue"),
meta: { title: "授权书同意书" },
meta: {
title: "授权书同意书 - 天远查",
description:
"天远查授权书同意书,了解查询服务的授权条款和用户协议。",
keywords: "授权书,同意书,用户协议,授权条款",
},
},
{
path: "/othersAuthorization",
name: "othersAuthorization",
component: () =>
import("@/views/OthersAuthorization.vue"),
meta: { title: "他人授权同意书" },
meta: {
title: "他人授权同意书 - 天远查",
description:
"天远查他人授权同意书,了解查询他人信息的授权条款。",
keywords: "他人授权,同意书,授权条款,信息查询",
},
},
{
path: "/privacyPolicy",
name: "privacyPolicy",
component: () =>
import("@/views/PrivacyPolicy.vue"),
meta: { title: "隐私政策" },
meta: {
title: "隐私政策 - 天远查",
description:
"天远查隐私政策,了解我们如何保护您的个人信息和隐私。",
keywords:
"隐私政策,个人信息保护,隐私保护,数据安全",
},
},
{
path: "/userAgreement",
name: "userAgreement",
component: () =>
import("@/views/UserAgreement.vue"),
meta: { title: "用户协议" },
meta: {
title: "用户协议 - 天远查",
description:
"天远查用户协议,了解使用我们服务的条款和条件。",
keywords: "用户协议,服务条款,使用条件,协议条款",
},
},
{
path: "/listMarriage",
name: "listMarriage",
component: () =>
import("@/views/list_marriage.vue"),
meta: { title: "婚姻查询" },
meta: {
title: "婚姻查询 - 天远查",
description:
"天远查婚姻查询服务,提供婚姻状态查询、婚恋风险评估等专业服务。",
keywords:
"婚姻查询,婚姻状态查询,婚恋风险评估,婚姻信息,婚恋安全",
},
},
{
path: "/listRisk",
name: "listRisk",
component: () => import("@/views/list_risk.vue"),
meta: { title: "风险查询" },
meta: {
title: "风险查询 - 天远查",
description:
"天远查风险查询服务,提供全面的个人和企业风险评估服务。",
keywords:
"风险查询,风险评估,个人风险,企业风险,风险分析",
},
},
{
path: "/listCar",
name: "listCar",
component: () => import("@/views/list_car.vue"),
meta: { title: "查车辆" },
meta: {
title: "查车辆 - 天远查",
description:
"天远查车辆查询服务,提供车辆信息查询、人车关系核验等服务。",
keywords:
"查车辆,车辆查询,车辆信息,人车关系,车架号查询",
},
},
{
path: "/listLawsuit",
name: "listLawsuit",
component: () => import("@/views/list_lawsuit.vue"),
meta: { title: "诉讼查询" },
meta: {
title: "诉讼查询 - 天远查",
description:
"天远查诉讼查询服务,提供司法涉诉信息查询、判决书查询等专业服务。",
keywords:
"诉讼查询,司法查询,判决书查询,涉诉信息,法律查询",
},
},
{
path: "/listVerify",
name: "listVerify",
component: () => import("@/views/list_verify.vue"),
meta: { title: "核验查询" },
meta: {
title: "核验查询 - 天远查",
description:
"天远查核验查询服务,提供身份证、手机、银行卡等信息的核验服务。",
keywords:
"核验查询,身份核验,手机核验,银行卡核验,信息核验",
},
},
{
path: "/inquire/:feature",
name: "inquire",
component: () => import("@/views/Inquire.vue"),
meta: { title: "查询报告" },
meta: {
title: "查询报告 - 天远查",
description:
"天远查查询报告,提供详细的查询结果和风险评估报告。",
keywords:
"查询报告,查询结果,风险评估,详细报告,查询服务",
},
},
],
},
{
path: "app",
meta: { wechatOverlayHidden: true },
children: [
{
path: "authorization",
name: "appAuthorization",
component: () =>
import("@/views/Authorization.vue"),
meta: {
title: "授权书 - 天远查APP",
description:
"天远查APP授权书了解移动端查询服务的授权条款。",
keywords: "APP授权书,移动端授权,授权条款",
},
},
{
path: "privacyPolicy",
name: "appPrivacyPolicy",
component: () =>
import("@/views/PrivacyPolicy.vue"),
meta: {
title: "隐私政策 - 天远查APP",
description:
"天远查APP隐私政策了解移动端隐私保护政策。",
keywords: "APP隐私政策,移动端隐私,隐私保护",
},
},
{
path: "userAgreement",
name: "appUserAgreement",
component: () =>
import("@/views/UserAgreement.vue"),
meta: {
title: "用户协议 - 天远查APP",
description:
"天远查APP用户协议了解移动端服务条款。",
keywords: "APP用户协议,移动端协议,服务条款",
},
},
{
path: "agentManageAgreement",
name: "appAgentManageAgreement",
component: () =>
import("@/views/AgentManageAgreement.vue"),
meta: {
title: "代理管理协议 - 天远查APP",
description:
"天远查APP代理管理协议了解代理服务相关条款。",
keywords: "代理管理协议,代理服务,管理条款",
},
},
{
path: "agentSerivceAgreement",
name: "appAgentSerivceAgreement",
component: () =>
import("@/views/AgentServiceAgreement.vue"),
meta: {
title: "信息技术服务合同 - 天远查APP",
description:
"天远查APP信息技术服务合同了解技术服务相关条款。",
keywords: "技术服务合同,信息技术,服务条款",
},
},
],
},
@@ -153,20 +323,27 @@ const router = createRouter({
path: "/login",
name: "login",
component: () => import("@/views/Login.vue"),
meta: {
title: "登录 - 天远查",
description: "天远查用户登录页面,安全便捷的账户登录服务。",
keywords: "用户登录,账户登录,安全登录",
},
},
// {
// path: '/home',
// name: 'home',
// component: () => import('@/views/Home.vue'),
// },
{
path: "/:pathMatch(.*)*",
name: "NotFound",
component: () => import("@/views/NotFound.vue"),
meta: {
title: "页面未找到 - 天远查",
description:
"抱歉,您访问的页面不存在,请返回首页继续使用天远查服务。",
keywords: "404,页面未找到,错误页面",
},
},
],
});
NProgress.configure({
easing: "ease", // 动画方式
speed: 500, // 递增进度条的速度(毫秒)
@@ -178,6 +355,36 @@ NProgress.configure({
// 路由导航守卫
router.beforeEach((to, from, next) => {
NProgress.start(); // 启动进度条
// 动态设置页面标题和meta信息
if (to.meta.title) {
document.title = to.meta.title;
}
// 动态设置meta description
if (to.meta.description) {
let metaDescription = document.querySelector(
'meta[name="description"]'
);
if (!metaDescription) {
metaDescription = document.createElement("meta");
metaDescription.name = "description";
document.head.appendChild(metaDescription);
}
metaDescription.content = to.meta.description;
}
// 动态设置meta keywords
if (to.meta.keywords) {
let metaKeywords = document.querySelector('meta[name="keywords"]');
if (!metaKeywords) {
metaKeywords = document.createElement("meta");
metaKeywords.name = "keywords";
document.head.appendChild(metaKeywords);
}
metaKeywords.content = to.meta.keywords;
}
next();
});
@@ -192,4 +399,5 @@ router.afterEach(() => {
});
NProgress.done(); // 结束进度条
});
export default router;

View File

@@ -266,7 +266,7 @@ function initOrgPieChart() {
// 从当前显示的tableData中获取数据
const currentData =
transformedTableData.value?.[selectedDataSource.value]?.[
selectedStatType.value
selectedStatType.value
] || [];
if (!currentData || currentData.length === 0) {
@@ -1096,124 +1096,64 @@ watch(selectedDataSource, (newValue) => {
<div class="card">
<div class="flex flex-col gap-y-6">
<!-- 数据切换选项 -->
<div
class="p-6 bg-white rounded-lg shadow-sm border border-gray-100 relative overflow-hidden"
>
<div class="p-6 bg-white rounded-lg shadow-sm border border-gray-100 relative overflow-hidden">
<!-- 背景装饰元素 -->
<div
class="absolute top-0 right-0 w-32 h-32 bg-blue-50 rounded-full -mr-8 -mt-8 opacity-60"
></div>
<div
class="absolute bottom-0 left-0 w-20 h-20 bg-green-50 rounded-full -ml-10 -mb-10 opacity-50"
></div>
<div class="absolute top-0 right-0 w-32 h-32 bg-blue-50 rounded-full -mr-8 -mt-8 opacity-60"></div>
<div class="absolute bottom-0 left-0 w-20 h-20 bg-green-50 rounded-full -ml-10 -mb-10 opacity-50"></div>
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 relative z-10"
>
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 relative z-10">
<div class="space-y-2">
<h2
class="text-xl font-semibold text-gray-800 flex items-center"
>
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
借贷申请分析报告
</h2>
<p class="text-sm text-gray-600 ml-6">
本报告统计借贷申请记录和机构情况帮助评估信贷风险
本报告统计本人需求推测和机构情况帮助评估信贷风险
</p>
</div>
<div class="flex flex-wrap gap-6 w-full">
<template
v-if="
mode === 'full' &&
(hasDataSource('id') || hasDataSource('cell'))
"
>
<div
class="flex-1 flex rounded-md shadow-sm relative"
>
<template v-if="
mode === 'full' &&
(hasDataSource('id') || hasDataSource('cell'))
">
<div class="flex-1 flex rounded-md shadow-sm relative">
<!-- 图标装饰 -->
<button
v-if="hasDataSource('id')"
type="button"
<button v-if="hasDataSource('id')" type="button"
class="flex-1 py-2 px-4 text-sm font-medium rounded-l-md border transition-all duration-200 flex items-center flex-shrink-0"
:class="[
selectedDataSource === 'id'
? 'bg-gradient-to-r from-blue-500 to-blue-600 text-white border-blue-500 shadow-md'
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50',
]"
@click="selectedDataSource = 'id'"
>
<svg
v-if="selectedDataSource === 'id'"
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
]" @click="selectedDataSource = 'id'">
<svg v-if="selectedDataSource === 'id'" class="w-4 h-4 mr-1" fill="none"
stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<svg
v-else
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2"
></path>
<svg v-else class="w-4 h-4 mr-1" fill="none" stroke="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2">
</path>
</svg>
身份证匹配
</button>
<button
v-if="hasDataSource('cell')"
type="button"
<button v-if="hasDataSource('cell')" type="button"
class="flex-1 py-2 px-4 text-sm font-medium rounded-r-md border transition-all duration-200 flex items-center flex-shrink-0"
:class="[
selectedDataSource === 'cell'
? 'bg-gradient-to-r from-green-500 to-green-600 text-white border-green-500 shadow-md'
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50',
]"
@click="selectedDataSource = 'cell'"
>
<svg
v-if="selectedDataSource === 'cell'"
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
]" @click="selectedDataSource = 'cell'">
<svg v-if="selectedDataSource === 'cell'" class="w-4 h-4 mr-1" fill="none"
stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<svg
v-else
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"
></path>
<svg v-else class="w-4 h-4 mr-1" fill="none" stroke="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z">
</path>
</svg>
手机号匹配
</button>
@@ -1223,29 +1163,16 @@ watch(selectedDataSource, (newValue) => {
</div>
<!-- 数据类型说明 -->
<div
v-if="mode === 'full'"
class="mt-4 bg-blue-50 p-3 rounded-lg text-xs text-gray-700"
>
<div v-if="mode === 'full'" class="mt-4 bg-blue-50 p-3 rounded-lg text-xs text-gray-700">
<p class="font-medium text-blue-800 mb-1">数据类型说明:</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
<div class="flex items-start">
<span
class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-blue-500"
></span>
<span
><strong>身份证匹配:</strong
>通过身份证号码匹配获取的借贷申请记录,能够反映与身份证关联的所有金融机构申请行为</span
>
<span class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-blue-500"></span>
<span><strong>身份证匹配:</strong>通过身份证号码匹配获取的本人需求推测,能够反映与身份证关联的所有金融机构申请行为</span>
</div>
<div v-if="mode === 'full'" class="flex items-start">
<span
class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-green-500"
></span>
<span
><strong>手机号匹配:</strong
>通过手机号码匹配获取的借贷申请记录,能够反映与手机号关联的所有金融机构申请行为</span
>
<span class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-green-500"></span>
<span><strong>手机号匹配:</strong>通过手机号码匹配获取的本人需求推测,能够反映与手机号关联的所有金融机构申请行为</span>
</div>
</div>
</div>
@@ -1253,64 +1180,35 @@ watch(selectedDataSource, (newValue) => {
<template v-if="hasDataSource(selectedDataSource)">
<!-- 借贷申请总体情况概览 -->
<div
class="bg-gradient-to-br from-gray-50 to-gray-100 rounded-lg p-4 relative overflow-hidden"
>
<div class="bg-gradient-to-br from-gray-50 to-gray-100 rounded-lg p-4 relative overflow-hidden">
<!-- 装饰元素 -->
<div
class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-blue-400 to-green-400 opacity-70"
></div>
class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-blue-400 to-green-400 opacity-70">
</div>
<div class="absolute bottom-4 right-4 opacity-10">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-32 w-32"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1"
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
/>
<svg xmlns="http://www.w3.org/2000/svg" class="h-32 w-32" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1"
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
</div>
<div
class="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-4 gap-4 relative z-10"
>
<div class="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-4 gap-4 relative z-10">
<div
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1"
>
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
<div class="flex items-start">
<div
class="mr-2 md:mr-3 bg-blue-100 rounded-lg p-1 md:p-2 text-blue-600"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 md:h-6 md:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/>
<div class="mr-2 md:mr-3 bg-blue-100 rounded-lg p-1 md:p-2 text-blue-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 md:h-6 md:w-6" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
</div>
<div>
<div
class="text-xs md:text-sm text-gray-500"
>
<div class="text-xs md:text-sm text-gray-500">
近1年总申请次数
</div>
<div
class="text-lg md:text-2xl font-bold mt-1 text-gray-800"
>
<div class="text-lg md:text-2xl font-bold mt-1 text-gray-800">
{{
totalStatsData[selectedDataSource]
?.totalApplyCount[4] || 0
@@ -1321,36 +1219,20 @@ watch(selectedDataSource, (newValue) => {
</div>
<div
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1"
>
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
<div class="flex items-start">
<div
class="mr-2 md:mr-3 bg-green-100 rounded-lg p-1 md:p-2 text-green-600"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 md:h-6 md:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
/>
<div class="mr-2 md:mr-3 bg-green-100 rounded-lg p-1 md:p-2 text-green-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 md:h-6 md:w-6" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
</div>
<div>
<div
class="text-xs md:text-sm text-gray-500"
>
<div class="text-xs md:text-sm text-gray-500">
近1年总申请机构数
</div>
<div
class="text-lg md:text-2xl font-bold mt-1 text-gray-800"
>
<div class="text-lg md:text-2xl font-bold mt-1 text-gray-800">
{{
totalStatsData[selectedDataSource]
?.totalOrgCount[4] || 0
@@ -1361,39 +1243,23 @@ watch(selectedDataSource, (newValue) => {
</div>
<div
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1"
>
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
<div class="flex items-start">
<div
class="mr-2 md:mr-3 bg-yellow-100 rounded-lg p-1 md:p-2 text-yellow-600"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 md:h-6 md:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"
/>
<div class="mr-2 md:mr-3 bg-yellow-100 rounded-lg p-1 md:p-2 text-yellow-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 md:h-6 md:w-6" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
</svg>
</div>
<div>
<div
class="text-xs md:text-sm text-gray-500"
>
<div class="text-xs md:text-sm text-gray-500">
单月最高申请次数
</div>
<div
class="text-lg md:text-2xl font-bold mt-1 text-gray-800"
>
<div class="text-lg md:text-2xl font-bold mt-1 text-gray-800">
{{
data[
`als_m12_${selectedDataSource}_max_monnum`
`als_m12_${selectedDataSource}_max_monnum`
] || 0
}}
</div>
@@ -1402,39 +1268,23 @@ watch(selectedDataSource, (newValue) => {
</div>
<div
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1"
>
class="bg-white rounded-lg p-3 md:p-5 shadow-sm border border-gray-100 transform transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
<div class="flex items-start">
<div
class="mr-2 md:mr-3 bg-purple-100 rounded-lg p-1 md:p-2 text-purple-600"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 md:h-6 md:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"
/>
<div class="mr-2 md:mr-3 bg-purple-100 rounded-lg p-1 md:p-2 text-purple-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 md:h-6 md:w-6" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
</svg>
</div>
<div>
<div
class="text-xs md:text-sm text-gray-500"
>
<div class="text-xs md:text-sm text-gray-500">
月均申请次数
</div>
<div
class="text-lg md:text-2xl font-bold mt-1 text-gray-800"
>
<div class="text-lg md:text-2xl font-bold mt-1 text-gray-800">
{{
data[
`als_m12_${selectedDataSource}_avg_monnum`
`als_m12_${selectedDataSource}_avg_monnum`
] || 0
}}
</div>
@@ -1456,92 +1306,57 @@ watch(selectedDataSource, (newValue) => {
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
<!-- 借贷类型分布饼图 -->
<div class="relative">
<div
ref="orgPieChartRef"
class="chart-container-small"
></div>
<div ref="orgPieChartRef" class="chart-container-small"></div>
</div>
<!-- 借贷类型表格 -->
<div>
<div class="mb-2 flex justify-between items-center">
<LButtonGroup
v-model="selectedStatType"
:options="statTabOptions"
type="blue-green"
/>
<LButtonGroup v-model="selectedStatType" :options="statTabOptions" type="blue-green" />
</div>
<div class="overflow-x-auto">
<LTable
:data="
transformedTableData?.[
selectedDataSource
]?.[selectedStatType] || []
"
type="blue-green"
class="w-full whitespace-nowrap"
>
<LTable :data="transformedTableData?.[
selectedDataSource
]?.[selectedStatType] || []
" type="blue-green" class="w-full whitespace-nowrap">
<template #header>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[25%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[25%]">
借贷类别
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近7日
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近1月
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近3月
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近6月
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近1年
</th>
</template>
<template #default="{ row }">
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm font-medium whitespace-nowrap"
>
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm font-medium whitespace-nowrap">
{{ row.label }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.d7 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.m1 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.m3 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.m6 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.m12 }}
</td>
</template>
@@ -1555,35 +1370,23 @@ watch(selectedDataSource, (newValue) => {
<p class="font-medium text-blue-800 mb-1">
借贷类型说明:
</p>
<div
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2"
>
<div
v-for="(desc, key) in orgMappings"
:key="key"
class="flex items-start"
>
<span
class="inline-block w-3 h-3 mt-1 mr-2 rounded-full flex-shrink-0"
:style="{
backgroundColor:
opts.color[
Object.keys(
orgMappings
).indexOf(key)
],
}"
></span>
<span
><strong>{{ desc }}</strong
>{{
key === "bank"
? "包含各类银行贷款"
: tableGroup[key]
.map((i) => i.name)
.join("、")
}}</span
>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
<div v-for="(desc, key) in orgMappings" :key="key" class="flex items-start">
<span class="inline-block w-3 h-3 mt-1 mr-2 rounded-full flex-shrink-0" :style="{
backgroundColor:
opts.color[
Object.keys(
orgMappings
).indexOf(key)
],
}"></span>
<span><strong>{{ desc }}</strong>{{
key === "bank"
? "包含各类银行贷款"
: tableGroup[key]
.map((i) => i.name)
.join("、")
}}</span>
</div>
</div>
</div>
@@ -1596,83 +1399,51 @@ watch(selectedDataSource, (newValue) => {
此表格展示在周末或夜间时段的借贷申请情况,这类时段的高频申请可能需要额外关注
</div>
<div class="mb-2">
<LButtonGroup
v-model="selectedStatType"
:options="statTabOptions"
type="blue-green"
/>
<LButtonGroup v-model="selectedStatType" :options="statTabOptions" type="blue-green" />
</div>
<div class="overflow-x-auto">
<LTable
:data="
transformedDateTableData?.[
selectedDataSource
]?.[selectedStatType] || []
"
type="blue-green"
class="w-full whitespace-nowrap"
>
<LTable :data="transformedDateTableData?.[
selectedDataSource
]?.[selectedStatType] || []
" type="blue-green" class="w-full whitespace-nowrap">
<template #header>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[25%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[25%]">
时段类型
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近7日
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近1月
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近3月
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近6月
</th>
<th
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]"
>
<th class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm w-[15%]">
近1年
</th>
</template>
<template #default="{ row }">
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm font-medium whitespace-nowrap"
>
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm font-medium whitespace-nowrap">
{{ row.label }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.specialDisplay ? "-" : row.d7 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.specialDisplay ? "-" : row.m1 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.specialDisplay ? "-" : row.m3 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.specialDisplay ? "-" : row.m6 }}
</td>
<td
class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center"
>
<td class="border px-2 py-1 text-xs lg:px-3 lg:py-2 lg:text-sm text-center">
{{ row.m12 }}
</td>
</template>
@@ -1698,31 +1469,20 @@ watch(selectedDataSource, (newValue) => {
</template>
<template v-else>
<div
class="flex items-center justify-center h-60 bg-gray-50 rounded-lg"
>
<div class="flex items-center justify-center h-60 bg-gray-50 rounded-lg">
<div class="text-center">
<div class="text-gray-400 text-4xl mb-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-16 w-16 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 mx-auto" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="text-gray-600 text-xl font-medium">
暂无借贷申请数据
</div>
<div class="text-gray-500 mt-2">
当前没有匹配到任何借贷申请记录
当前没有匹配到任何本人需求推测
</div>
</div>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -672,118 +672,59 @@ onUnmounted(() => {
<div class="card">
<div class="flex flex-col gap-y-4">
<!-- 数据类型切换 -->
<div
class="p-6 bg-white rounded-lg shadow-sm border border-gray-100 relative overflow-hidden mb-4"
>
<div class="p-6 bg-white rounded-lg shadow-sm border border-gray-100 relative overflow-hidden mb-4">
<!-- 背景装饰元素 -->
<div
class="absolute top-0 right-0 w-32 h-32 bg-blue-50 rounded-full -mr-8 -mt-8 opacity-60"
></div>
<div
class="absolute bottom-0 left-0 w-20 h-20 bg-green-50 rounded-full -ml-10 -mb-10 opacity-50"
></div>
<div class="absolute top-0 right-0 w-32 h-32 bg-blue-50 rounded-full -mr-8 -mt-8 opacity-60"></div>
<div class="absolute bottom-0 left-0 w-20 h-20 bg-green-50 rounded-full -ml-10 -mb-10 opacity-50"></div>
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 relative z-10"
>
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 relative z-10">
<div class="space-y-2">
<h2
class="text-xl font-semibold text-gray-800 flex items-center"
>
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
借贷行为分析报告
</h2>
<p class="text-sm text-gray-600 ml-6">
本报告统计审批额度与应还情况帮助评估信贷风险
</p>
</div>
<div
v-if="mode === 'full'"
class="flex flex-wrap gap-6 w-full md:w-auto"
>
<div
class="flex-1 md:flex-none flex rounded-md shadow-sm relative"
>
<button
type="button"
<div v-if="mode === 'full'" class="flex flex-wrap gap-6 w-full md:w-auto">
<div class="flex-1 md:flex-none flex rounded-md shadow-sm relative">
<button type="button"
class="flex-1 py-2 px-4 text-sm font-medium rounded-l-md border transition-all duration-200 flex items-center"
:class="[
dataType === 'id'
? 'bg-gradient-to-r from-blue-500 to-blue-600 text-white border-blue-500 shadow-md'
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50',
]"
@click="dataType = 'id'"
>
<svg
v-if="dataType === 'id'"
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
]" @click="dataType = 'id'">
<svg v-if="dataType === 'id'" class="w-4 h-4 mr-1" fill="none" stroke="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<svg
v-else
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2"
></path>
<svg v-else class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2">
</path>
</svg>
身份证数据
</button>
<button
type="button"
<button type="button"
class="flex-1 py-2 px-4 text-sm font-medium rounded-r-md border transition-all duration-200 flex items-center"
:class="[
dataType === 'cell'
? 'bg-gradient-to-r from-green-500 to-green-600 text-white border-green-500 shadow-md'
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50',
]"
@click="dataType = 'cell'"
>
<svg
v-if="dataType === 'cell'"
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
]" @click="dataType = 'cell'">
<svg v-if="dataType === 'cell'" class="w-4 h-4 mr-1" fill="none" stroke="currentColor"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<svg
v-else
class="w-4 h-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"
></path>
<svg v-else class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z">
</path>
</svg>
手机号数据
</button>
@@ -792,29 +733,16 @@ onUnmounted(() => {
</div>
<!-- 数据类型说明 -->
<div
v-if="mode === 'full'"
class="mt-4 bg-blue-50 p-3 rounded-lg text-xs text-gray-700"
>
<div v-if="mode === 'full'" class="mt-4 bg-blue-50 p-3 rounded-lg text-xs text-gray-700">
<p class="font-medium text-blue-800 mb-1">数据类型说明</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
<div class="flex items-start">
<span
class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-blue-500"
></span>
<span
><strong>身份证数据</strong
>通过身份证号码匹配获取的借贷记录反映与身份证关联的所有借贷行为</span
>
<span class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-blue-500"></span>
<span><strong>身份证数据</strong>通过身份证号码匹配获取的借贷记录反映与身份证关联的所有借贷行为</span>
</div>
<div class="flex items-start">
<span
class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-green-500"
></span>
<span
><strong>手机号数据</strong
>通过手机号码匹配获取的借贷记录反映与手机号关联的所有借贷行为</span
>
<span class="inline-block w-2 h-2 mt-1 mr-2 rounded-full flex-shrink-0 bg-green-500"></span>
<span><strong>手机号数据</strong>通过手机号码匹配获取的借贷记录反映与手机号关联的所有借贷行为</span>
</div>
</div>
</div>
@@ -962,17 +890,14 @@ onUnmounted(() => {
<div class="risk-assessment p-4 bg-white rounded-md">
<div class="text-lg font-bold mb-2">
风险评估:
<span
:class="{
'text-red-500':
behaviorSummary.riskLevel === '高',
'text-yellow-500':
behaviorSummary.riskLevel === '中',
'text-green-500':
behaviorSummary.riskLevel === '低',
}"
>{{ behaviorSummary.riskLevel }}风险</span
>
<span :class="{
'text-red-500':
behaviorSummary.riskLevel === '高',
'text-yellow-500':
behaviorSummary.riskLevel === '中',
'text-green-500':
behaviorSummary.riskLevel === '低',
}">{{ behaviorSummary.riskLevel }}风险</span>
</div>
<div class="text-gray-700">
<p>

View File

@@ -1,4 +1,6 @@
<script setup>
import { computed } from 'vue'
const props = defineProps({
data: {
type: Object,
@@ -200,14 +202,17 @@ const getRiskSummary = () => {
// 检查反诈反赌核验
if (props.data.anti_fraud_gaming) {
props.data.anti_fraud_gaming.forEach(item => {
const levelNum = parseInt(item.riskLevel)
if (levelNum > 60) {
highRiskCount++
} else if (levelNum > 40) {
mediumRiskCount++
}
})
const gamingData = props.data.anti_fraud_gaming.value || props.data.anti_fraud_gaming
if (Array.isArray(gamingData)) {
gamingData.forEach(item => {
const levelNum = parseInt(item.riskLevel)
if (levelNum > 60) {
highRiskCount++
} else if (levelNum > 40) {
mediumRiskCount++
}
})
}
}
if (highRiskCount > 0) {
@@ -232,6 +237,17 @@ const getRiskSummary = () => {
}
const summary = getRiskSummary()
// 获取反诈反赌数据兼容有value和没有value的情况
const getAntiFraudGamingData = computed(() => {
if (!props.data?.anti_fraud_gaming) return []
// 如果有value属性使用value否则直接使用原数据
const gamingData = props.data.anti_fraud_gaming.value || props.data.anti_fraud_gaming
// 确保返回的是数组
return Array.isArray(gamingData) ? gamingData : []
})
</script>
<template>
@@ -241,26 +257,19 @@ const summary = getRiskSummary()
</div>
<div v-else class="risk-content">
<!-- 风险总结 -->
<div
class="summary-card"
:class="{
'border-red-500 glow-red': summary.level === 'high',
'border-yellow-500 glow-yellow': summary.level === 'medium',
'border-green-500 glow-green': summary.level === 'low',
}"
>
<div class="summary-card" :class="{
'border-red-500 glow-red': summary.level === 'high',
'border-yellow-500 glow-yellow': summary.level === 'medium',
'border-green-500 glow-green': summary.level === 'low',
}">
<div class="flex items-center">
<div class="summary-icon" :class="summary.color">
<i
class="fas"
:class="
summary.level === 'high'
? 'fa-exclamation-triangle'
: summary.level === 'medium'
? 'fa-exclamation-circle'
: 'fa-check-circle'
"
></i>
<i class="fas" :class="summary.level === 'high'
? 'fa-exclamation-triangle'
: summary.level === 'medium'
? 'fa-exclamation-circle'
: 'fa-check-circle'
"></i>
</div>
<div class="font-bold text-lg" :class="summary.color">风险评估总结</div>
</div>
@@ -271,7 +280,7 @@ const summary = getRiskSummary()
<!-- 左侧列 -->
<div class="grid-left">
<!-- 黑灰产等级 -->
<div class="risk-section hover-lift">
<!-- <div class="risk-section hover-lift">
<div class="section-title flex items-center">
<div class="title-icon bg-indigo-100 text-indigo-600">
<i class="fas fa-user-secret"></i>
@@ -282,32 +291,26 @@ const summary = getRiskSummary()
<div class="risk-level-indicator">
<div class="indicator-label">风险等级</div>
<div class="indicator-bar">
<div
class="indicator-value"
:class="riskLevelColor(data.black_gray_level || '', 'black_gray_level')"
<div class="indicator-value" :class="riskLevelColor(data.black_gray_level || '', 'black_gray_level')"
:style="{
width: data.black_gray_level ? `${Math.min(parseInt(data.black_gray_level) * 25, 100)}%` : '0%',
}"
></div>
}"></div>
</div>
<div
class="indicator-text"
:class="{
'text-green-500': (data.black_gray_level || '') === '' || (data.black_gray_level || '') === '1',
'text-yellow-500': (data.black_gray_level || '') === '2',
'text-orange-500': (data.black_gray_level || '') === '3',
'text-red-500': (data.black_gray_level || '') === '4',
}"
>
<div class="indicator-text" :class="{
'text-green-500': (data.black_gray_level || '') === '' || (data.black_gray_level || '') === '1',
'text-yellow-500': (data.black_gray_level || '') === '2',
'text-orange-500': (data.black_gray_level || '') === '3',
'text-red-500': (data.black_gray_level || '') === '4',
}">
{{ riskLevelText(data.black_gray_level || '', 'black_gray_level') }}
</div>
</div>
<div class="description">黑灰产等级评估用户是否参与非法活动等级越高风险越大</div>
</div>
</div>
</div> -->
<!-- 电诈风险预警 -->
<div class="risk-section hover-lift">
<!-- <div class="risk-section hover-lift">
<div class="section-title flex items-center">
<div class="title-icon bg-red-100 text-red-600">
<i class="fas fa-phone-slash"></i>
@@ -318,33 +321,27 @@ const summary = getRiskSummary()
<div class="risk-level-indicator">
<div class="indicator-label">风险等级</div>
<div class="indicator-bar">
<div
class="indicator-value"
:class="riskLevelColor(data.telefraud_level || '0', 'telefraud_level')"
:style="{ width: `${Math.min(parseInt(data.telefraud_level || '0') * 16.6, 100)}%` }"
></div>
<div class="indicator-value" :class="riskLevelColor(data.telefraud_level || '0', 'telefraud_level')"
:style="{ width: `${Math.min(parseInt(data.telefraud_level || '0') * 16.6, 100)}%` }"></div>
</div>
<div
class="indicator-text"
:class="{
'text-green-500':
(data.telefraud_level || '0') === '0' ||
(data.telefraud_level || '0') === '1' ||
(data.telefraud_level || '0') === '2',
'text-yellow-500': (data.telefraud_level || '0') === '3' || (data.telefraud_level || '0') === '4',
'text-orange-500': (data.telefraud_level || '0') === '5',
'text-red-500': (data.telefraud_level || '0') === '6',
}"
>
<div class="indicator-text" :class="{
'text-green-500':
(data.telefraud_level || '0') === '0' ||
(data.telefraud_level || '0') === '1' ||
(data.telefraud_level || '0') === '2',
'text-yellow-500': (data.telefraud_level || '0') === '3' || (data.telefraud_level || '0') === '4',
'text-orange-500': (data.telefraud_level || '0') === '5',
'text-red-500': (data.telefraud_level || '0') === '6',
}">
{{ riskLevelText(data.telefraud_level || '0', 'telefraud_level') }}
</div>
</div>
<div class="description">电诈风险预警评估用户是否涉及电信诈骗活动值越大风险越高</div>
</div>
</div>
</div> -->
<!-- 综合风险等级 -->
<div class="risk-section hover-lift">
<!-- <div class="risk-section hover-lift">
<div class="section-title flex items-center">
<div class="title-icon bg-emerald-100 text-emerald-600">
<i class="fas fa-shield-alt"></i>
@@ -384,13 +381,11 @@ const summary = getRiskSummary()
<div v-else class="text-center py-2 text-gray-500">暂无不良个人核查数据</div>
<div class="description">不良个人核查评估用户的风险状况从无风险到高风险分级</div>
</div>
</div>
</div> -->
</div>
<!-- 右侧列 -->
<div class="grid-right">
<!-- 团伙欺诈排查 -->
<div class="risk-section hover-lift">
<!-- <div class="risk-section hover-lift">
<div class="section-title flex items-center">
<div class="title-icon bg-amber-100 text-amber-600">
<i class="fas fa-users-slash"></i>
@@ -402,24 +397,18 @@ const summary = getRiskSummary()
<div class="risk-level-indicator flex-1">
<div class="indicator-label">团伙风险等级</div>
<div class="indicator-bar">
<div
class="indicator-value"
:class="riskLevelColor(data.fraud_group.frg_list_level || '3', 'frg_list_level')"
:style="{
<div class="indicator-value"
:class="riskLevelColor(data.fraud_group.frg_list_level || '3', 'frg_list_level')" :style="{
width: `${Math.min((parseInt(data.fraud_group.frg_list_level || '3') - 2) * 12.5, 100)}%`,
}"
></div>
}"></div>
</div>
<div
class="indicator-text"
:class="{
'text-green-500': parseInt(data.fraud_group.frg_list_level || '3') <= 5,
'text-yellow-500':
parseInt(data.fraud_group.frg_list_level || '3') >= 6 &&
parseInt(data.fraud_group.frg_list_level || '3') <= 7,
'text-red-500': parseInt(data.fraud_group.frg_list_level || '3') >= 8,
}"
>
<div class="indicator-text" :class="{
'text-green-500': parseInt(data.fraud_group.frg_list_level || '3') <= 5,
'text-yellow-500':
parseInt(data.fraud_group.frg_list_level || '3') >= 6 &&
parseInt(data.fraud_group.frg_list_level || '3') <= 7,
'text-red-500': parseInt(data.fraud_group.frg_list_level || '3') >= 8,
}">
{{ riskLevelText(data.fraud_group.frg_list_level || '3', 'frg_list_level') }}
</div>
</div>
@@ -435,9 +424,8 @@ const summary = getRiskSummary()
<div v-else class="text-center py-2 text-gray-500">暂无团伙欺诈数据</div>
<div class="description mt-1">团伙欺诈排查评估用户是否属于欺诈团伙及团伙规模大小</div>
</div>
</div>
</div> -->
<!-- 反诈反赌核验 -->
<div class="risk-section hover-lift">
<div class="section-title flex items-center">
<div class="title-icon bg-purple-100 text-purple-600">
@@ -446,55 +434,39 @@ const summary = getRiskSummary()
<span>反诈反赌核验</span>
</div>
<div class="section-content">
<div v-if="data.anti_fraud_gaming && data.anti_fraud_gaming.length > 0" class="grid grid-cols-1 gap-3">
<div
v-for="(item, index) in data.anti_fraud_gaming"
:key="index"
class="gaming-item"
:class="
parseInt(item.riskLevel) === 0
? 'border-green-500'
: parseInt(item.riskLevel) < 4
? 'border-green-400'
: parseInt(item.riskLevel) < 7
? 'border-yellow-500'
: 'border-red-500'
"
>
<div
class="gaming-icon"
:class="
parseInt(item.riskLevel) === 0
? 'bg-green-100 text-green-500'
: parseInt(item.riskLevel) < 4
? 'bg-green-100 text-green-500'
: parseInt(item.riskLevel) < 7
? 'bg-yellow-100 text-yellow-600'
: 'bg-red-100 text-red-500'
"
>
<div v-if="getAntiFraudGamingData && getAntiFraudGamingData.length > 0" class="grid grid-cols-1 gap-3">
<div v-for="(item, index) in getAntiFraudGamingData" :key="index" class="gaming-item" :class="parseInt(item.riskLevel) === 0
? 'border-green-500'
: parseInt(item.riskLevel) < 4
? 'border-green-400'
: parseInt(item.riskLevel) < 7
? 'border-yellow-500'
: 'border-red-500'
">
<div class="gaming-icon" :class="parseInt(item.riskLevel) === 0
? 'bg-green-100 text-green-500'
: parseInt(item.riskLevel) < 4
? 'bg-green-100 text-green-500'
: parseInt(item.riskLevel) < 7
? 'bg-yellow-100 text-yellow-600'
: 'bg-red-100 text-red-500'
">
<i class="fas" :class="getRiskIcon(item.riskType)"></i>
</div>
<div class="flex-1">
<div class="font-medium text-sm">{{ getRiskTypeName(item.riskType) }}</div>
<div class="flex items-center mt-2">
<div class="progress-container">
<div
class="progress-bar"
:class="riskLevelColor(item.riskLevel, 'gaming')"
:style="{ width: `${Math.min(parseInt(item.riskLevel), 100)}%` }"
></div>
<div class="progress-bar" :class="riskLevelColor(item.riskLevel, 'gaming')"
:style="{ width: `${Math.min(parseInt(item.riskLevel), 100)}%` }"></div>
</div>
<span
class="risk-level-text"
:class="{
'text-green-500': parseInt(item.riskLevel) <= 20,
'text-green-600': parseInt(item.riskLevel) > 20 && parseInt(item.riskLevel) <= 40,
'text-yellow-500': parseInt(item.riskLevel) > 40 && parseInt(item.riskLevel) <= 60,
'text-orange-500': parseInt(item.riskLevel) > 60 && parseInt(item.riskLevel) <= 80,
'text-red-500': parseInt(item.riskLevel) > 80,
}"
>
<span class="risk-level-text" :class="{
'text-green-500': parseInt(item.riskLevel) <= 20,
'text-green-600': parseInt(item.riskLevel) > 20 && parseInt(item.riskLevel) <= 40,
'text-yellow-500': parseInt(item.riskLevel) > 40 && parseInt(item.riskLevel) <= 60,
'text-orange-500': parseInt(item.riskLevel) > 60 && parseInt(item.riskLevel) <= 80,
'text-red-500': parseInt(item.riskLevel) > 80,
}">
{{ riskLevelText(item.riskLevel, 'gaming') }}
</span>
</div>
@@ -506,7 +478,6 @@ const summary = getRiskSummary()
</div>
</div>
<!-- 安全建议 -->
<div class="security-tips hover-lift">
<div class="flex items-center">
<div class="title-icon bg-blue-100 text-blue-600 mr-2">
@@ -659,9 +630,11 @@ const summary = getRiskSummary()
0% {
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.3);
}
70% {
box-shadow: 0 0 0 8px rgba(16, 185, 129, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
}
@@ -671,9 +644,11 @@ const summary = getRiskSummary()
0% {
box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.3);
}
70% {
box-shadow: 0 0 0 8px rgba(245, 158, 11, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(245, 158, 11, 0);
}
@@ -683,9 +658,11 @@ const summary = getRiskSummary()
0% {
box-shadow: 0 0 0 0 rgba(249, 115, 22, 0.3);
}
70% {
box-shadow: 0 0 0 8px rgba(249, 115, 22, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(249, 115, 22, 0);
}
@@ -695,9 +672,11 @@ const summary = getRiskSummary()
0% {
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.3);
}
70% {
box-shadow: 0 0 0 8px rgba(239, 68, 68, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0);
}

View File

@@ -5,16 +5,17 @@
<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 :class="[
'mb-6 p-2 rounded-3xl text-lg font-medium text-center text-white shadow-lg',
getStatusClass(actualData?.op_type),
]">
{{ getStatusText(actualData?.op_type) }}
</div>
<div class="text-sm text-gray-600">
<p>{{ statusDescription(data.status) }}</p>
<p>{{ statusDescription(actualData?.op_type) }}</p>
<p v-if="actualData?.op_date" class="mt-2 text-gray-500">
登记日期{{ formatDate(actualData.op_date) }}
</p>
</div>
</div>
</div>
@@ -33,36 +34,44 @@ const props = defineProps({
});
const { data } = toRefs(props);
// 状态背景色和图标
const getStatusClass = (status) => {
// 获取实际的数据对象
const actualData = data.value?.data;
// 日期格式化函数,将 2024-10-12 转换为 2024年10月12日
const formatDate = (dateStr) => {
if (!dateStr) return "";
const [year, month, day] = dateStr.split("-");
return `${year}${month}${day}`;
};
// 状态背景色和图标,根据 op_type 判断
const getStatusClass = (opType) => {
const statusClassMapping = {
0: "bg-yellow-500",
1: "bg-green-600",
2: "bg-red-500",
3: "bg-blue-400",
IA: "bg-green-600", // 结婚
IB: "bg-red-500", // 离婚
INR: "bg-yellow-500", // 未登记
};
return statusClassMapping[status] || "bg-gray-500";
return statusClassMapping[opType] || "bg-gray-500";
};
// 核验状态描述
const getStatusText = (status) => {
const getStatusText = (opType) => {
const statusMapping = {
0: "无婚姻关系",
1: "已婚",
2: "已离婚",
3: "离婚冷静期",
IA: "已婚",
IB: "已婚",
INR: "无婚姻关系",
};
return statusMapping[status] || "未知状态";
return statusMapping[opType] || "未知状态";
};
const statusDescription = (status) => {
const statusDescription = (opType) => {
const descriptionMapping = {
1: "双方是夫妻关系,目前处于已婚状态。",
2: "双方存在过婚姻关系,目前已离婚。",
3: "双方目前处于离婚冷静期。",
0: "双方不存在婚姻关系。",
IA: "双方是夫妻关系,目前处于已婚状态。",
IB: "双方存在过婚姻关系,目前已离婚。",
INR: "双方不存在婚姻关系。",
};
return descriptionMapping[status] || "无详细描述。";
return descriptionMapping[opType] || "无详细描述。";
};
// 对请求参数进行脱敏处理

593
src/ui/CFLXGDEA9.vue Normal file
View File

@@ -0,0 +1,593 @@
<script setup>
import { computed } from "vue";
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
params: {
type: Object,
default: () => ({}),
},
})
// 风险类型代码映射
const riskTypeMap = {
'0': {
text: '正常人员',
color: 'text-green-600',
bgColor: 'bg-green-50',
borderColor: 'border-green-200',
iconText: '✓',
description: '无不良记录,属于正常人员',
level: 'normal'
},
'A': {
text: '前科:侵犯公民人身权利,民主权利',
color: 'text-red-600',
bgColor: 'bg-red-50',
borderColor: 'border-red-200',
iconText: '⚠',
description: '存在侵犯公民人身权利、民主权利的前科记录',
level: 'high'
},
'A1': {
text: '盗窃',
color: 'text-red-600',
bgColor: 'bg-red-50',
borderColor: 'border-red-200',
iconText: '🔓',
description: '存在盗窃前科记录',
level: 'high'
},
'A2': {
text: '诈骗',
color: 'text-red-600',
bgColor: 'bg-red-50',
borderColor: 'border-red-200',
iconText: '💳',
description: '存在诈骗前科记录',
level: 'high'
},
'A3': {
text: '抢劫/夺',
color: 'text-red-600',
bgColor: 'bg-red-50',
borderColor: 'border-red-200',
iconText: '⚔',
description: '存在抢劫、抢夺前科记录',
level: 'high'
},
'A4': {
text: '故意伤害/杀人',
color: 'text-red-600',
bgColor: 'bg-red-50',
borderColor: 'border-red-200',
iconText: '🗡',
description: '存在故意伤害、杀人前科记录',
level: 'high'
},
'A5': {
text: '强奸/性侵/猥亵',
color: 'text-red-600',
bgColor: 'bg-red-50',
borderColor: 'border-red-200',
iconText: '🚫',
description: '存在强奸、性侵、猥亵前科记录',
level: 'high'
},
'B': {
text: '经济类前科',
color: 'text-orange-600',
bgColor: 'bg-orange-50',
borderColor: 'border-orange-200',
iconText: '💰',
description: '存在破坏金融秩序、非法吸存、违法贷款、金融诈骗等经济类前科记录',
level: 'medium'
},
'B1': {
text: '走私',
color: 'text-orange-600',
bgColor: 'bg-orange-50',
borderColor: 'border-orange-200',
iconText: '📦',
description: '存在走私前科记录',
level: 'medium'
},
'B2': {
text: '破坏金融管理秩序',
color: 'text-orange-600',
bgColor: 'bg-orange-50',
borderColor: 'border-orange-200',
iconText: '🏦',
description: '存在破坏金融管理秩序前科记录',
level: 'medium'
},
'B3': {
text: '金融诈骗',
color: 'text-orange-600',
bgColor: 'bg-orange-50',
borderColor: 'border-orange-200',
iconText: '💸',
description: '存在金融诈骗前科记录',
level: 'medium'
},
'B4': {
text: '洗钱',
color: 'text-orange-600',
bgColor: 'bg-orange-50',
borderColor: 'border-orange-200',
iconText: '🔄',
description: '存在洗钱前科记录',
level: 'medium'
},
'B5': {
text: '偷漏税',
color: 'text-orange-600',
bgColor: 'bg-orange-50',
borderColor: 'border-orange-200',
iconText: '📊',
description: '存在偷漏税前科记录',
level: 'medium'
},
'C': {
text: '妨害社会管理秩序',
color: 'text-yellow-600',
bgColor: 'bg-yellow-50',
borderColor: 'border-yellow-200',
iconText: '⚠',
description: '存在扰乱公共秩序、妨害司法、妨害国境管理、妨害文物管理、涉毒、涉黄等前科记录',
level: 'medium'
},
'C1': {
text: '扰乱公共秩序',
color: 'text-yellow-600',
bgColor: 'bg-yellow-50',
borderColor: 'border-yellow-200',
iconText: '📢',
description: '存在扰乱公共秩序前科记录',
level: 'medium'
},
'C2': {
text: '妨害司法',
color: 'text-yellow-600',
bgColor: 'bg-yellow-50',
borderColor: 'border-yellow-200',
iconText: '⚖',
description: '存在妨害司法前科记录',
level: 'medium'
},
'C3': {
text: '涉毒',
color: 'text-yellow-600',
bgColor: 'bg-yellow-50',
borderColor: 'border-yellow-200',
iconText: '💊',
description: '存在涉毒前科记录',
level: 'medium'
},
'C4': {
text: '涉黄刑案',
color: 'text-yellow-600',
bgColor: 'bg-yellow-50',
borderColor: 'border-yellow-200',
iconText: '🚫',
description: '存在涉黄刑案前科记录',
level: 'medium'
},
'C5': {
text: '帮信/掩隐/侵公',
color: 'text-yellow-600',
bgColor: 'bg-yellow-50',
borderColor: 'border-yellow-200',
iconText: '🔒',
description: '存在帮助信息网络犯罪活动、掩饰隐瞒犯罪所得、侵犯公民个人信息前科记录',
level: 'medium'
},
'D': {
text: '重点',
color: 'text-purple-600',
bgColor: 'bg-purple-50',
borderColor: 'border-purple-200',
iconText: '🔥',
description: '存在危害国家、公共安全,涉恐、疆藏,涉稳、涉黑、涉及境外等重点前科记录',
level: 'critical'
},
'D1': {
text: '危害国家、公共安全',
color: 'text-purple-600',
bgColor: 'bg-purple-50',
borderColor: 'border-purple-200',
iconText: '🛡',
description: '存在危害国家、公共安全前科记录',
level: 'critical'
},
'D2': {
text: '涉稳',
color: 'text-purple-600',
bgColor: 'bg-purple-50',
borderColor: 'border-purple-200',
iconText: '⚡',
description: '存在涉稳前科记录',
level: 'critical'
},
'D3': {
text: '涉及境外',
color: 'text-purple-600',
bgColor: 'bg-purple-50',
borderColor: 'border-purple-200',
iconText: '🌍',
description: '存在涉及境外前科记录',
level: 'critical'
},
'D4': {
text: '涉恐、疆藏',
color: 'text-purple-600',
bgColor: 'bg-purple-50',
borderColor: 'border-purple-200',
iconText: '🚨',
description: '存在涉恐、疆藏前科记录',
level: 'critical'
},
'D5': {
text: '涉黑',
color: 'text-purple-600',
bgColor: 'bg-purple-50',
borderColor: 'border-purple-200',
iconText: '👤',
description: '存在涉黑前科记录',
level: 'critical'
},
'E': {
text: '涉交通案件',
color: 'text-blue-600',
bgColor: 'bg-blue-50',
borderColor: 'border-blue-200',
iconText: '🚗',
description: '存在危险驾驶、交通肇事等交通案件前科记录',
level: 'low'
},
'F': {
text: '法院文书',
color: 'text-gray-600',
bgColor: 'bg-gray-50',
borderColor: 'border-gray-200',
iconText: '📄',
description: '存在法院文书记录',
level: 'low'
}
}
// 获取风险类型信息
const getRiskTypeInfo = (type) => {
return riskTypeMap[type] || riskTypeMap['F']
}
// 解析风险等级字符串
const riskTypes = computed(() => {
if (!props.data?.level) return []
const levelStr = props.data.level.toString()
const types = levelStr.split(',').map(type => type.trim()).filter(type => type)
return types.map(type => ({
code: type,
...getRiskTypeInfo(type)
}))
})
// 判断是否有风险数据
const hasRiskData = computed(() => {
return props.data?.level && props.data.level !== '0' && riskTypes.value.length > 0
})
// 判断是否为正常人员
const isNormalPerson = computed(() => {
return props.data?.level === '0'
})
</script>
<template>
<div class="card main-card">
<div v-if="!data || Object.keys(data).length === 0" class="py-8 text-center text-gray-500">
<div class="flex flex-col items-center">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-3">
<span class="text-2xl text-gray-400">📋</span>
</div>
<p>暂无本人不良数据</p>
</div>
</div>
<div v-else class="content">
<!-- 查询结果标题 -->
<div class="header-section">
<div class="flex items-center mb-4">
<div class="title-icon bg-gradient-to-r from-slate-500 to-slate-600">
<span class="text-white text-xl">📋</span>
</div>
<div>
<h3 class="section-title">本人不良记录查询结果</h3>
<p class="section-subtitle">个人不良记录风险评估</p>
</div>
</div>
</div>
<!-- 正常人员显示 -->
<div v-if="isNormalPerson" class="result-container">
<div class="normal-card">
<div class="status-header">
<div class="status-icon">
<span class="text-4xl"></span>
</div>
<div class="status-info">
<h4 class="status-title text-green-600">
正常人员
</h4>
<p class="status-description">
无不良记录属于正常人员
</p>
</div>
</div>
</div>
</div>
<!-- 风险记录显示 -->
<div v-else-if="hasRiskData" class="result-container">
<div v-for="(risk, index) in riskTypes" :key="index" class="risk-item">
<div class="risk-card" :class="[risk.bgColor, risk.borderColor]">
<!-- 风险类型图标和标题 -->
<div class="risk-header">
<div class="risk-icon">
<span class="text-xl">{{ risk.iconText }}</span>
</div>
<div class="risk-info">
<h4 class="risk-title" :class="risk.color">
{{ risk.text }}
</h4>
</div>
</div>
<!-- 风险描述 -->
<div class="risk-description">
<p class="description-text">
{{ risk.description }}
</p>
</div>
<!-- 风险等级标签 -->
<div class="risk-level">
<span class="level-badge" :class="{
'bg-green-100 text-green-700': risk.level === 'normal',
'bg-blue-100 text-blue-700': risk.level === 'low',
'bg-yellow-100 text-yellow-700': risk.level === 'medium',
'bg-orange-100 text-orange-700': risk.level === 'high',
'bg-purple-100 text-purple-700': risk.level === 'critical'
}">
{{
risk.level === 'normal' ? '正常' :
risk.level === 'low' ? '低风险' :
risk.level === 'medium' ? '中风险' :
risk.level === 'high' ? '高风险' :
'极高风险'
}}
</span>
</div>
</div>
</div>
</div>
<!-- 说明信息 -->
<div class="info-section">
<div class="info-card">
<div class="info-header">
<div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center">
<span class="text-blue-600 text-sm"></span>
</div>
<span class="info-title">查询说明</span>
</div>
<div class="info-content">
<p class="info-text">
本人不良记录查询结果来源于公安部门等权威机构包括各类违法犯罪前科记录
查询结果仅供参考具体信息以相关部门官方记录为准
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.main-card {
@apply bg-white shadow-lg rounded-2xl p-6 mb-4 border border-gray-100;
}
.content {
@apply space-y-6;
}
.header-section {
@apply mb-6;
}
.title-icon {
@apply w-12 h-12 rounded-xl flex items-center justify-center text-white mr-4 shadow-md;
}
.section-title {
@apply text-xl font-bold text-gray-800 mb-1;
}
.section-subtitle {
@apply text-sm text-gray-500;
}
.result-container {
@apply space-y-4 mb-6;
}
.normal-card {
@apply rounded-lg p-4 border-2 border-green-200 bg-green-50;
}
.risk-item {
@apply mb-4;
}
.risk-card {
@apply rounded-lg p-4 border-2 transition-all duration-300 hover:shadow-md;
}
.status-header,
.risk-header {
@apply flex items-start mb-3;
}
.status-icon,
.risk-icon {
@apply mr-4 flex-shrink-0;
}
.status-info,
.risk-info {
@apply flex-1;
}
.status-title,
.risk-title {
@apply text-lg font-bold mb-1;
}
.status-description {
@apply text-sm text-gray-600 leading-relaxed;
}
.risk-code {
@apply text-xs text-gray-500 mt-1;
}
.risk-description {
@apply mb-3 pt-3 border-t border-white border-opacity-50;
}
.description-text {
@apply text-sm text-gray-700 leading-relaxed;
}
.risk-level {
@apply mt-3;
}
.level-badge {
@apply text-xs font-bold px-3 py-1 rounded-full;
}
.info-section {
@apply mt-6;
}
.info-card {
@apply bg-slate-50 rounded-xl p-4 border border-slate-200;
}
.info-header {
@apply flex items-center mb-2;
}
.info-title {
@apply font-semibold text-slate-700 ml-2;
}
.info-content {
@apply mt-2;
}
.info-text {
@apply text-sm text-slate-600 leading-relaxed;
}
/* 风险等级颜色样式 */
.text-green-600 {
color: #059669;
}
.bg-green-50 {
background-color: #ecfdf5;
}
.border-green-200 {
border-color: #a7f3d0;
}
.text-red-600 {
color: #dc2626;
}
.bg-red-50 {
background-color: #fef2f2;
}
.border-red-200 {
border-color: #fecaca;
}
.text-orange-600 {
color: #ea580c;
}
.bg-orange-50 {
background-color: #fff7ed;
}
.border-orange-200 {
border-color: #fed7aa;
}
.text-yellow-600 {
color: #d97706;
}
.bg-yellow-50 {
background-color: #fffbeb;
}
.border-yellow-200 {
border-color: #fde68a;
}
.text-purple-600 {
color: #7c3aed;
}
.bg-purple-50 {
background-color: #faf5ff;
}
.border-purple-200 {
border-color: #ddd6fe;
}
.text-blue-600 {
color: #2563eb;
}
.bg-blue-50 {
background-color: #eff6ff;
}
.border-blue-200 {
border-color: #bfdbfe;
}
.text-gray-600 {
color: #4b5563;
}
.bg-gray-50 {
background-color: #f9fafb;
}
.border-gray-200 {
border-color: #e5e7eb;
}
</style>

View File

@@ -8,32 +8,41 @@ const props = defineProps({
default: () => null,
},
});
const { data } = props;
// 状态映射,包括显示的文字和样式
// 获取实际的数据对象
const actualData = props.data?.data;
// 日期格式化函数,将 2009-04-16 转换为 2009年04月16日
const formatDate = (dateStr) => {
if (!dateStr) return "";
const [year, month, day] = dateStr.split("-");
return `${year}${month}${day}`;
};
// 状态映射,根据 op_type 判断
const statusMap = {
0: {
text: "未婚或尚未登记结婚",
bgClass: "bg-yellow-100",
textClass: "text-yellow-700",
description: "未进行民政登记婚姻",
},
1: {
IA: {
text: "已婚",
bgClass: "bg-green-100",
textClass: "text-green-700",
description: "已登记婚姻,家庭幸福美满",
},
2: {
ICA: {
text: "已婚",
bgClass: "bg-green-100",
textClass: "text-green-700",
description: "已登记婚姻,家庭幸福美满",
},
IB: {
text: "离异",
bgClass: "bg-red-100",
textClass: "text-red-700",
description: "离异状态,未来生活可期",
},
3: {
text: "离婚冷静期",
bgClass: "bg-blue-100",
textClass: "text-blue-700",
description: "目前处于离婚冷静期,请谨慎决策",
INR: {
text: "未登记",
bgClass: "bg-yellow-100",
textClass: "text-yellow-700",
description: "未进行民政登记婚姻",
},
};
@@ -43,29 +52,28 @@ const noRecordStatus = {
bgClass: "bg-gray-200",
textClass: "text-gray-500",
description: "暂无婚姻相关记录",
// description: "可能由于民政部门系统正在升级,当前查无相关记录。<br />1. 当查询到相关结果时,我们将第一时间更新报告(您可以在我的历史查询记录中查看),并通过短信通知您。<br />2. 如果10个工作日内未能查询到相关信息我们承诺将为您退款26.8元的婚姻状态查询费用。",
opDate: null,
};
// 根据 `data.status` 确定当前状态,默认值为 "无相关记录"
const currentStatus = !data
// 根据 op_type 确定当前状态,默认值为 "无相关记录"
const currentStatus = !actualData
? noRecordStatus
: data.status !== undefined
? statusMap[data.status] || statusMap["0"]
: noRecordStatus;
: actualData.op_type
? { ...statusMap[actualData.op_type], opDate: formatDate(actualData.op_date) }
: noRecordStatus;
</script>
<template>
<div class="card">
<div class="status-info flex flex-col items-center">
<div
:class="`status-label rounded-full px-6 py-3 text-center font-bold shadow-md ${currentStatus.bgClass} ${currentStatus.textClass}`"
>
:class="`status-label rounded-full px-6 py-3 text-center font-bold shadow-md ${currentStatus.bgClass} ${currentStatus.textClass}`">
{{ currentStatus.text }}
</div>
<p
v-html="currentStatus.description"
class="status-description mt-3 text-sm text-gray-600"
></p>
<p v-html="currentStatus.description" class="status-description mt-3 text-sm text-gray-600"></p>
<p v-if="currentStatus.opDate" class="op-date mt-2 text-sm text-gray-500">
登记日期{{ currentStatus.opDate }}
</p>
</div>
</div>
</template>

270
src/ui/CIVYZ3A7F.vue Normal file
View File

@@ -0,0 +1,270 @@
<script setup>
import { computed } from "vue";
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
params: {
type: Object,
default: () => ({}),
},
})
// 格式化日期
const formatDate = (dateStr) => {
if (!dateStr) return "未知";
try {
const date = new Date(dateStr);
return date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long'
});
} catch {
return dateStr;
}
}
// 获取学历等级对应的描述
const getEducationDesc = (education) => {
const descriptions = {
"专科": "专科学历是高等教育的重要组成部分,培养具有专业知识和技能的应用型人才。",
"本科": "本科学历是高等教育的基础学位,培养具有系统专业知识和基本技能的高级人才。",
"硕士研究生": "硕士学位是较高层次的学位,培养具有较深厚理论基础和专业技能的高级专门人才。",
"博士研究生": "博士学位是最高学位,培养能够独立从事科学研究工作、具有创新能力的高级专门人才。",
};
return descriptions[education] || "";
}
// 根据学历等级获取时间线点的样式类
const getTimelinePointClass = (education) => {
const classes = {
"专科": "bg-gray-500",
"本科": "bg-blue-500",
"硕士研究生": "bg-green-500",
"博士研究生": "bg-amber-500",
};
return classes[education] || "bg-blue-500";
}
// 获取学历等级
const getEducationLevel = (education) => {
const levels = {
"专科": 1,
"本科": 2,
"硕士研究生": 3,
"博士研究生": 4,
};
return levels[education] || 0;
}
// 获取学历图标SVG
const getEducationSvgIcon = (education) => {
let svgIcon = `<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 14l9-5-9-5-9 5 9 5z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z"></path>
</svg>`;
if (education === "本科") {
svgIcon = `<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>`;
} else if (education === "硕士研究生") {
svgIcon = `<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
</svg>`;
} else if (education === "博士研究生") {
svgIcon = `<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
</svg>`;
}
return svgIcon;
}
// 计算排序后的学历数据
const sortedEducations = computed(() => {
const educationList = props.data?.dataList || [];
if (educationList.length <= 1) return educationList;
// 按照毕业时间从早到晚排序
return [...educationList].sort((a, b) => {
const dateA = new Date(a.graduationDate || "1900-01-01");
const dateB = new Date(b.graduationDate || "1900-01-01");
return dateA - dateB;
});
});
// 判断是否有学历数据
const hasEducationData = computed(() => {
return props.data?.result === "01" && sortedEducations.value.length > 0;
});
// 判断是否有多个学历
const hasMultipleEducations = computed(() => {
return sortedEducations.value.length > 1;
});
</script>
<template>
<div class="w-full max-w-md mx-auto bg-white rounded-xl overflow-hidden font-sans shadow-md">
<div v-if="hasEducationData" class="p-6 pl-2">
<!-- 学历时间线 -->
<div class="relative pb-4">
<!-- 垂直时间线 -->
<div v-if="hasMultipleEducations"
class="absolute left-0 top-14 h-[calc(100%-44px)] w-0.5 bg-gradient-to-b from-blue-400 to-blue-200 rounded-full ml-5">
</div>
<!-- 学历卡片列表 -->
<div class="space-y-10 relative">
<div v-for="(education, index) in sortedEducations" :key="index" class="relative">
<!-- 时间线点 -->
<div v-if="hasMultipleEducations" :class="[
'absolute left-5 w-10 h-10 rounded-full border-4 border-white shadow-md flex items-center justify-center text-white transform -translate-x-1/2',
getTimelinePointClass(education.educationalLevel),
]">
<span class="text-sm font-bold">{{ index + 1 }}</span>
</div>
<!-- 学历卡片 -->
<div
class="relative rounded-lg transition-all duration-300 ml-12 p-6 hover:-translate-y-1 hover:shadow-lg border border-gray-200 bg-gradient-to-br from-gray-50 to-white">
<!-- 顶部彩色条 -->
<div
class="absolute top-0 left-0 w-full h-1.5 rounded-t-lg bg-gradient-to-r from-blue-500 to-blue-300">
</div>
<!-- 学历标题区域 -->
<div class="flex items-start mb-6">
<div
class="w-14 h-14 rounded-full bg-blue-50 flex items-center justify-center mr-5 flex-shrink-0 text-blue-500">
<span v-html="getEducationSvgIcon(education.educationalLevel)"></span>
</div>
<div class="flex-1">
<div class="flex justify-between items-start">
<div>
<h3 class="text-xl font-semibold text-gray-800 mb-1">
{{ education.educationalLevel }}
</h3>
<p class="text-sm text-purple-600 font-medium">
{{ education.schoolName }}
</p>
</div>
<!-- 高级学历标签 -->
<div v-if="getEducationLevel(education.educationalLevel) >= 3"
class="bg-red-500 text-white text-xs font-bold px-2.5 py-1 rounded-md shadow ml-2 animate-pulse">
高级
</div>
</div>
</div>
</div>
<!-- 分隔线 -->
<div class="w-full h-px bg-gray-200 my-5"></div>
<!-- 学历详情 -->
<div class="space-y-4 mb-6">
<!-- 专业 -->
<div class="flex items-center text-gray-700">
<svg class="w-5 h-5 text-blue-400 mr-3 flex-shrink-0" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253">
</path>
</svg>
<span class="text-gray-500 mr-3 text-sm sm:text-base">专业</span>
<span class="text-gray-700 text-sm sm:text-base">{{ education.major }}</span>
</div>
<!-- 毕业时间 -->
<div class="flex items-center text-gray-700">
<svg class="w-5 h-5 text-red-500 mr-3 flex-shrink-0" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z">
</path>
</svg>
<span class="text-gray-500 mr-3 text-sm sm:text-base">毕业时间</span>
<span class="text-gray-700 text-sm sm:text-base font-medium">{{
formatDate(education.graduationDate) }}</span>
</div>
<!-- 学习形式 -->
<div class="flex items-center text-gray-700">
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span class="text-gray-500 mr-3 text-sm sm:text-base">学习形式</span>
<span class="text-gray-700 text-sm sm:text-base">{{ education.educationType
}}</span>
</div>
</div>
<!-- 学历描述 -->
<div class="relative overflow-hidden rounded-lg mt-5">
<!-- 背景效果 -->
<div class="absolute inset-0 bg-gradient-to-br from-blue-50 to-gray-50 rounded-lg">
</div>
<!-- 装饰性元素 - 只在高级学历显示 -->
<div v-if="getEducationLevel(education.educationalLevel) >= 3"
class="absolute -right-4 -top-4 w-16 h-16 bg-yellow-100 rounded-full opacity-50">
</div>
<div v-if="getEducationLevel(education.educationalLevel) >= 3"
class="absolute -left-4 -bottom-4 w-12 h-12 bg-blue-100 rounded-full opacity-50">
</div>
<!-- 内容 -->
<div class="relative z-10 p-5">
<h4 class="font-medium text-base text-gray-700 mb-2 flex items-center">
<span class="mr-2">{{ education.educationalLevel }}学历</span>
<span v-if="getEducationLevel(education.educationalLevel) >= 3"
class="text-xs bg-yellow-400 text-white px-2 py-0.5 rounded">高级</span>
</h4>
<p class="text-gray-600 text-sm leading-relaxed">
{{ getEducationDesc(education.educationalLevel) }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 无数据状态 -->
<div v-else class="flex flex-col items-center py-10 px-5 text-center bg-gray-50">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<span class="text-2xl text-gray-400">🎓</span>
</div>
<div class="text-gray-600 text-sm max-w-md">
暂无学历信息记录这可能是因为
<ul class="text-left mt-3 pl-5">
<li
class="mb-2 relative before:content-['•'] before:absolute before:left-[-15px] before:text-blue-500">
学历信息不公开
</li>
<li
class="mb-2 relative before:content-['•'] before:absolute before:left-[-15px] before:text-blue-500">
暂无高等教育学历
</li>
<li
class="mb-2 relative before:content-['•'] before:absolute before:left-[-15px] before:text-blue-500">
学历较早暂未被教育部门数字化收录
</li>
</ul>
</div>
</div>
</div>
</template>
<style scoped>
/* 复用CG11BJ06.vue的样式 */
</style>

320
src/ui/CIVYZ6G7H.vue Normal file
View File

@@ -0,0 +1,320 @@
<script setup>
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
params: {
type: Object,
default: () => ({}),
},
})
// 婚姻状态结果映射
const marriageStatusMap = {
'0': {
text: '结婚',
color: 'text-emerald-600',
bgColor: 'bg-emerald-50',
iconText: '💒',
description: '婚姻关系正常,已登记结婚'
},
'1': {
text: '补发结婚证',
color: 'text-blue-600',
bgColor: 'bg-blue-50',
iconText: '📜',
description: '已结婚,但因证件丢失或损坏需要补发结婚证'
},
'2': {
text: '离婚',
color: 'text-orange-600',
bgColor: 'bg-orange-50',
iconText: '📋',
description: '婚姻关系已解除,已办理离婚手续'
},
'3': {
text: '补发离婚证',
color: 'text-amber-600',
bgColor: 'bg-amber-50',
iconText: '📄',
description: '已离婚,但因证件丢失或损坏需要补发离婚证'
},
'4': {
text: '匹配不成功',
color: 'text-red-600',
bgColor: 'bg-red-50',
iconText: '❌',
description: '查询条件与数据库记录不匹配'
},
'5': {
text: '查无信息',
color: 'text-gray-600',
bgColor: 'bg-gray-50',
iconText: '🔍',
description: '在婚姻登记系统中未找到相关信息'
}
}
// 获取婚姻状态信息
const getMarriageStatusInfo = (result) => {
return marriageStatusMap[result] || marriageStatusMap['5']
}
// 获取状态对应的边框颜色
const getBorderColor = (result) => {
const statusInfo = getMarriageStatusInfo(result)
return statusInfo.bgColor.replace('bg-', 'border-').replace('-50', '-200')
}
</script>
<template>
<div class="card main-card">
<div v-if="!data || Object.keys(data).length === 0" class="py-8 text-center text-gray-500">
<div class="flex flex-col items-center">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-3">
<span class="text-2xl text-gray-400">💒</span>
</div>
<p>暂无婚姻状态数据</p>
</div>
</div>
<div v-else class="content">
<!-- 查询结果标题 -->
<div class="header-section">
<div class="flex items-center mb-4">
<div class="title-icon bg-gradient-to-r from-slate-500 to-slate-600">
<span class="text-white text-xl">💒</span>
</div>
<div>
<h3 class="section-title">婚姻状态查询结果</h3>
<p class="section-subtitle">婚姻登记状态查询(补证版)</p>
</div>
</div>
</div>
<!-- 查询结果展示 -->
<div class="result-container">
<div class="result-card"
:class="[getMarriageStatusInfo(data.result).bgColor, getBorderColor(data.result)]">
<!-- 状态图标和标题 -->
<div class="status-header">
<div class="status-icon">
<span class="text-3xl">{{ getMarriageStatusInfo(data.result).iconText }}</span>
</div>
<div class="status-info">
<h4 class="status-title" :class="getMarriageStatusInfo(data.result).color">
{{ getMarriageStatusInfo(data.result).text }}
</h4>
<p class="status-description">
{{ getMarriageStatusInfo(data.result).description }}
</p>
</div>
</div>
<!-- 详细信息 -->
<div class="detail-section">
<div class="detail-item">
<span class="detail-label">查询结果</span>
<span class="detail-value" :class="getMarriageStatusInfo(data.result).color">
{{ data.resultMsg }}
</span>
</div>
</div>
</div>
</div>
<!-- 说明信息 -->
<div class="info-section">
<div class="info-card">
<div class="info-header">
<div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center">
<span class="text-blue-600 text-sm"></span>
</div>
<span class="info-title">查询说明</span>
</div>
<div class="info-content">
<p class="info-text">
婚姻状态查询结果来源于民政部门婚姻登记系统包括结婚离婚等婚姻状态信息
补证版查询可显示是否需要补发结婚证或离婚证的情况
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.main-card {
@apply bg-white shadow-lg rounded-2xl p-6 mb-4 border border-gray-100;
}
.content {
@apply space-y-6;
}
.header-section {
@apply mb-6;
}
.title-icon {
@apply w-12 h-12 rounded-xl flex items-center justify-center text-white mr-4 shadow-md;
}
.section-title {
@apply text-xl font-bold text-gray-800 mb-1;
}
.section-subtitle {
@apply text-sm text-gray-500;
}
.result-container {
@apply mb-6;
}
.result-card {
@apply rounded-xl p-6 border-2 transition-all duration-300 hover:shadow-md;
}
.status-header {
@apply flex items-start mb-4;
}
.status-icon {
@apply mr-4 flex-shrink-0;
}
.status-info {
@apply flex-1;
}
.status-title {
@apply text-lg font-bold mb-1;
}
.status-description {
@apply text-sm text-gray-600 leading-relaxed;
}
.detail-section {
@apply space-y-3 pt-4 border-t border-white border-opacity-50;
}
.detail-item {
@apply flex items-center justify-between;
}
.detail-label {
@apply text-sm font-medium text-gray-700;
}
.detail-value {
@apply text-sm font-semibold;
}
.info-section {
@apply mt-6;
}
.info-card {
@apply bg-slate-50 rounded-xl p-4 border border-slate-200;
}
.info-header {
@apply flex items-center mb-2;
}
.info-title {
@apply font-semibold text-slate-700 ml-2;
}
.info-content {
@apply mt-2;
}
.info-text {
@apply text-sm text-slate-600 leading-relaxed mb-3;
}
.info-note {
@apply bg-amber-50 rounded-lg p-3 border border-amber-200;
}
.note-text {
@apply text-xs text-amber-800 leading-relaxed;
}
/* 状态颜色样式 */
.text-emerald-600 {
color: #059669;
}
.bg-emerald-50 {
background-color: #ecfdf5;
}
.border-emerald-200 {
border-color: #a7f3d0;
}
.text-blue-600 {
color: #2563eb;
}
.bg-blue-50 {
background-color: #eff6ff;
}
.border-blue-200 {
border-color: #bfdbfe;
}
.text-orange-600 {
color: #ea580c;
}
.bg-orange-50 {
background-color: #fff7ed;
}
.border-orange-200 {
border-color: #fed7aa;
}
.text-amber-600 {
color: #d97706;
}
.bg-amber-50 {
background-color: #fffbeb;
}
.border-amber-200 {
border-color: #fde68a;
}
.text-red-600 {
color: #dc2626;
}
.bg-red-50 {
background-color: #fef2f2;
}
.border-red-200 {
border-color: #fecaca;
}
.text-gray-600 {
color: #4b5563;
}
.bg-gray-50 {
background-color: #f9fafb;
}
.border-gray-200 {
border-color: #e5e7eb;
}
</style>

View File

@@ -9,16 +9,65 @@ const props = defineProps({
required: true,
},
});
console.log(props.data)
console.log('props.data:', props.data)
// 正确解构props.data中的字段并处理默认值
const {
entout: PropEntout = [],
sxbzxr: PropSxbzxr = [],
xgbzxr: PropXgbzxr = []
entout: PropEntout = {},
sxbzxr: PropSxbzxr = {},
xgbzxr: PropXgbzxr = {}
} = props.data || {}
// 兼容新旧两种数据结构
// 新结构: { data: { ... } }
// 旧结构: [{ entout: { ... } }]
let entoutData = {}
if (PropEntout?.data) {
// 新结构直接使用data属性
entoutData = PropEntout.data
} else if (Array.isArray(PropEntout) && PropEntout[0]?.entout) {
// 旧结构数组形式取第一个元素的entout属性
entoutData = PropEntout[0].entout
}
// 兼容新旧两种数据结构
let sxbzxrData = []
if (PropSxbzxr?.data) {
// 新结构有data属性
if (PropSxbzxr.data.sxbzxr) {
// 新结构data.sxbzxr 是数组
sxbzxrData = PropSxbzxr.data.sxbzxr
} else {
// 新结构data 本身就是数组
sxbzxrData = PropSxbzxr.data
}
} else if (Array.isArray(PropSxbzxr) && PropSxbzxr[0]?.sxbzxr) {
// 旧结构数组形式取第一个元素的sxbzxr属性
sxbzxrData = PropSxbzxr[0].sxbzxr
} else if (PropSxbzxr?.msg === "没有找到" || PropSxbzxr?.msg) {
// 新结构:没有找到的情况或其他消息
sxbzxrData = []
}
let xgbzxrData = []
if (PropXgbzxr?.data) {
// 新结构有data属性
if (PropXgbzxr.data.xgbzxr) {
// 新结构data.xgbzxr 是数组
xgbzxrData = PropXgbzxr.data.xgbzxr
} else {
// 新结构data 本身就是数组
xgbzxrData = PropXgbzxr.data
}
} else if (Array.isArray(PropXgbzxr) && PropXgbzxr[0]?.xgbzxr) {
// 旧结构数组形式取第一个元素的xgbzxr属性
xgbzxrData = PropXgbzxr[0].xgbzxr
} else if (PropXgbzxr?.msg === "没有找到" || PropXgbzxr?.msg) {
// 新结构:没有找到的情况或其他消息
xgbzxrData = []
}
// 安全获取entout数据(带响应式)
const entout = ref(PropEntout[0]?.entout || {
const entout = ref(entoutData || {
administrative: {},
bankrupt: {},
cases_tree: { criminal: [] },
@@ -30,8 +79,15 @@ const entout = ref(PropEntout[0]?.entout || {
})
// 获取其他字段(按需添加响应式)
const sx = ref(PropSxbzxr[0]?.sxbzxr || [])
const xg = ref(PropXgbzxr[0]?.xgbzxr || [])
const sx = ref(sxbzxrData || [])
const xg = ref(xgbzxrData || [])
// 调试信息(可选,用于排查问题)
console.log('entoutData:', entoutData)
console.log('sxbzxrData:', sxbzxrData)
console.log('xgbzxrData:', xgbzxrData)
console.log('sx.value:', sx.value)
console.log('xg.value:', xg.value)
const fieldLabel = [
// ================= 案件基础信息 =================
{ "field": "n_jbfy", "label": "经办法院" },
@@ -230,10 +286,10 @@ onMounted(() => {
name: `强制清算与破产${caseCounts.bankrupt}`,
},
{
value: caseCounts.bankrupt,
value: caseCounts.sx,
name: `失信${caseCounts.sx}`,
}, {
value: caseCounts.bankrupt,
value: caseCounts.xg,
name: `限高${caseCounts.xg}`,
},
],
@@ -305,53 +361,97 @@ function getCaseTypeName(caseType) {
<template v-else>
<van-collapse v-model="collapse">
<van-collapse-item v-for="(caseData, index) in caseType" :key="index" custom-class="collapse"
:name="index" :title="`案件: ${caseData.c_ah || caseData.ah}`">
<div class="case-row">
<div class="case-label">案号:</div>
<div class="case-value">
{{ caseData.c_ah || "-" }}
:name="index" :title="`案件: ${caseData.c_ah || caseData.ah || '未知案号'}`">
<!-- 失信和限高案件的特殊字段 -->
<template v-if="typeName === 'sx' || typeName === 'xg'">
<div class="case-row">
<div class="case-label">案号:</div>
<div class="case-value">{{ caseData.ah || "-" }}</div>
</div>
</div>
<div class="case-row">
<div class="case-label">案件类型:</div>
<div class="case-value">
{{ caseData.n_ajlx || "-" }}
<div class="case-row">
<div class="case-label">性别:</div>
<div class="case-value">{{ caseData.xb || "-" }}</div>
</div>
</div>
<div class="case-row">
<div class="case-label">经办法院:</div>
<div class="case-value">
{{ caseData.n_jbfy || "-" }}
<div class="case-row">
<div class="case-label">省份:</div>
<div class="case-value">{{ caseData.sf || "-" }}</div>
</div>
</div>
<div class="case-row">
<div class="case-label">立案日期:</div>
<div class="case-value">
{{ caseData.d_larq || "-" }}
<div class="case-row">
<div class="case-label">执行法院:</div>
<div class="case-value">{{ caseData.zxfy || "-" }}</div>
</div>
</div>
<div class="case-row">
<div class="case-label">结案方式:</div>
<div class="case-value">
{{ caseData.n_jafs || "-" }}
<div class="case-row">
<div class="case-label">立案日期:</div>
<div class="case-value">{{ caseData.larq || "-" }}</div>
</div>
</div>
<div class="case-row">
<div class="case-label">当事人信息:</div>
<div class="case-value">
<div v-for="dsr in caseData.c_dsrxx" :key="dsr.c_mc">
{{ dsr.c_mc }} -
{{
dsr.n_ssdw
}}
<div class="case-row">
<div class="case-label">发布日期:</div>
<div class="case-value">{{ caseData.fbrq || "-" }}</div>
</div>
<div class="case-row">
<div class="case-label">失信金额估计:</div>
<div class="case-value">{{ caseData.pjje_gj || "-" }}</div>
</div>
<div class="case-row">
<div class="case-label">失信行为情形:</div>
<div class="case-value">{{ caseData.xwqx || "-" }}</div>
</div>
<div class="case-row">
<div class="case-label">履行情况:</div>
<div class="case-value">{{ caseData.lxqk || "-" }}</div>
</div>
</template>
<!-- 其他案件的标准字段 -->
<template v-else>
<div class="case-row">
<div class="case-label">案号:</div>
<div class="case-value">
{{ caseData.c_ah || "-" }}
</div>
</div>
</div>
<template v-for="(item, index) in fieldLabel" :key="index">
<div class="case-row" v-if="caseData[item.field]">
<div class="case-label">{{ item.label }}:</div>
<div class="case-value">{{ caseData[item.field] || '无' }}</div>
<div class="case-row">
<div class="case-label">案件类型:</div>
<div class="case-value">
{{ caseData.n_ajlx || "-" }}
</div>
</div>
<div class="case-row">
<div class="case-label">经办法院:</div>
<div class="case-value">
{{ caseData.n_jbfy || "-" }}
</div>
</div>
<div class="case-row">
<div class="case-label">立案日期:</div>
<div class="case-value">
{{ caseData.d_larq || "-" }}
</div>
</div>
<div class="case-row">
<div class="case-label">结案方式:</div>
<div class="case-value">
{{ caseData.n_jafs || "-" }}
</div>
</div>
<div class="case-row">
<div class="case-label">当事人信息:</div>
<div class="case-value">
<div v-for="dsr in caseData.c_dsrxx" :key="dsr.c_mc">
{{ dsr.c_mc }} -
{{
dsr.n_ssdw
}}
</div>
</div>
</div>
<template v-for="(item, index) in fieldLabel" :key="index">
<div class="case-row" v-if="caseData[item.field]">
<div class="case-label">{{ item.label }}:</div>
<div class="case-value">{{ caseData[item.field] || '无' }}</div>
</div>
</template>
</template>
</van-collapse-item>
</van-collapse>
@@ -373,6 +473,4 @@ function getCaseTypeName(caseType) {
.case-value {
@apply text-left text-gray-500;
}
:deep(.van-cell) {}
</style>

View File

@@ -44,7 +44,7 @@ const getLevelDescription = computed(() => {
if (level === "[50,100)") return "月消费50-100元";
if (level === "[100,150)") return "月消费100-150元";
if (level === "[150,200)") return "月消费150-200元";
if (level === "[200,-)") return "月消费200元以上";
if (level === "[200,-1)") return "月消费200元以上";
}
// 电信运营商档次描述
@@ -54,7 +54,7 @@ const getLevelDescription = computed(() => {
if (level === "[100,200)") return "月消费100-200元";
if (level === "[200,300)") return "月消费200-300元";
if (level === "[300,400)") return "月消费300-400元";
if (level === "[400,-)") return "月消费400元以上";
if (level === "[400,-1)") return "月消费400元以上";
}
// 联通运营商档次描述
@@ -62,7 +62,7 @@ const getLevelDescription = computed(() => {
if (level === "[0,40)") return "月消费低于40元";
if (level === "[40,80)") return "月消费40-80元";
if (level === "[80,160)") return "月消费80-160元";
if (level === "[160,-)") return "月消费160元以上";
if (level === "[160,-1)") return "月消费160元以上";
}
return level; // 如果没有匹配到,返回原始值

View File

@@ -5,14 +5,34 @@ import * as echarts from "echarts";
const props = defineProps({
data: {
type: Array,
type: [Array, Object],
required: true,
},
});
console.log(props.data)
console.log('props.data:', props.data)
// 兼容新旧两种数据结构获取限高数据
let xgData = []
if (Array.isArray(props.data)) {
// 旧结构:直接是数组
xgData = props.data
} else if (props.data?.data?.xgbzxr) {
// 新结构:{ data: { xgbzxr: [...] } }
xgData = props.data.data.xgbzxr
} else if (props.data?.xgbzxr) {
// 新结构:{ xgbzxr: [...] }
xgData = props.data.xgbzxr
} else if (props.data?.msg === "没有找到") {
// 没有查到数据的情况
xgData = []
}
// 获取限高数据
const xg = ref(props.data || []);
const xg = ref(xgData || []);
// 调试信息
console.log('xgData:', xgData)
console.log('xg.value:', xg.value)
const fieldLabel = [
// ================= 案件基础信息 =================

View File

@@ -5,14 +5,34 @@ import * as echarts from "echarts";
const props = defineProps({
data: {
type: Array,
type: [Array, Object],
required: true,
},
});
console.log(props.data)
console.log('props.data:', props.data)
// 兼容新旧两种数据结构获取失信数据
let sxData = []
if (Array.isArray(props.data)) {
// 旧结构:直接是数组
sxData = props.data
} else if (props.data?.data?.sxbzxr) {
// 新结构:{ data: { sxbzxr: [...] } }
sxData = props.data.data.sxbzxr
} else if (props.data?.sxbzxr) {
// 新结构:{ sxbzxr: [...] }
sxData = props.data.sxbzxr
} else if (props.data?.msg === "没有找到") {
// 没有查到数据的情况
sxData = []
}
// 获取失信数据
const sx = ref(props.data || []);
const sx = ref(sxData || []);
// 调试信息
console.log('sxData:', sxData)
console.log('sx.value:', sx.value)
const fieldLabel = [
// ================= 案件基础信息 =================

130
src/ui/CQCXG9P1C.vue Normal file
View File

@@ -0,0 +1,130 @@
<template>
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<!-- 车辆总数统计 -->
<div class="flex justify-between items-center mb-6 pb-4 border-b border-gray-100">
<div class="flex items-center gap-3">
<div>
<div class="text-lg font-semibold text-gray-900">个人名下车辆</div>
</div>
</div>
<div class="bg-blue-50 text-blue-700 px-4 py-2 rounded-full text-sm font-medium">
{{ vehicleCount }}
</div>
</div>
<!-- 车辆列表 -->
<div class="space-y-3" v-if="vehicleList && vehicleList.length > 0">
<div class="bg-gray-50 rounded-lg p-4 border border-gray-200 hover:bg-blue-50 hover:border-blue-200 transition-colors duration-200"
v-for="(vehicle, index) in vehicleList" :key="index">
<div class="space-y-3">
<div class="text-xl font-bold text-gray-900 font-mono tracking-wider">
{{ vehicle.plateNum }}
</div>
<div class="flex items-center gap-3">
<div class="inline-flex items-center gap-1 px-3 py-1 rounded text-xs font-medium text-white"
:class="getPlateColorClass(vehicle.plateColor)">
<span>🏷</span>
<span>{{ getPlateColorText(vehicle.plateColor) }}</span>
</div>
<div class="text-sm text-gray-600">
<span class="text-gray-500">车辆类型:</span>
<span class="font-medium text-gray-900 ml-1">{{ getVehicleTypeText(vehicle.vehicleType)
}}</span>
</div>
</div>
</div>
</div>
</div>
<!-- 无数据状态 -->
<div class="text-center py-12 text-gray-500" v-else>
<div class="text-4xl mb-3">🚫</div>
<div class="text-lg font-medium mb-1">暂无车辆信息</div>
<div class="text-sm">No vehicle records found</div>
</div>
</div>
</template>
<script setup>
import { defineProps, computed } from 'vue';
// 接收父组件传入的 props
const props = defineProps({
data: Object,
params: Object,
});
// 车牌颜色映射
const plateColorMap = {
0: '蓝色 - 普通燃油车',
1: '黄色 - 大型车/货车',
2: '黑色 - 外籍车辆/港澳台车',
3: '白色 - 警车/军车/武警车',
4: '渐变绿色 - 新能源汽车',
5: '黄绿双拼色 - 大型新能源汽车',
6: '蓝白渐变色 - 临时牌照',
7: '临时牌照 - 临时行驶车辆',
11: '绿色 - 新能源汽车',
12: '红色 - 教练车/试验车'
};
// 车辆类型映射
const vehicleTypeMap = {
1: '一型客车',
2: '二型客车',
3: '三型客车',
4: '四型客车',
11: '一型货车',
12: '二型货车',
13: '三型货车',
14: '四型货车',
15: '五型货车',
16: '六型货车',
21: '一型专项作业车',
22: '二型专项作业车',
23: '三型专项作业车',
24: '四型专项作业车',
25: '五型专项作业车',
26: '六型专项作业车'
};
// 计算属性
const vehicleList = computed(() => props.data?.list || []);
const vehicleCount = computed(() => props.data?.vehicleCount || 0);
// 获取车牌颜色文本
const getPlateColorText = (plateColor) => {
return plateColorMap[plateColor] || '未知颜色 - 未知类型';
};
// 获取车牌颜色样式类
const getPlateColorClass = (plateColor) => {
const colorClassMap = {
0: 'bg-blue-500',
1: 'bg-yellow-500',
2: 'bg-gray-800',
3: 'bg-gray-200 text-gray-800',
4: 'bg-green-500',
5: 'bg-gradient-to-r from-yellow-500 to-green-500',
6: 'bg-gradient-to-r from-blue-500 to-white text-blue-800',
7: 'bg-red-500',
11: 'bg-green-500',
12: 'bg-red-500'
};
return colorClassMap[plateColor] || 'bg-gray-500';
};
// 获取车辆类型文本
const getVehicleTypeText = (vehicleType) => {
return vehicleTypeMap[vehicleType] || '未知类型';
};
onMounted(() => {
console.log('车辆数据:', props.data);
});
</script>
<style scoped>
/* 自定义样式 - 仅保留必要的样式 */
</style>

371
src/ui/CYYSY7D3E.vue Normal file
View File

@@ -0,0 +1,371 @@
<script setup>
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
params: {
type: Object,
default: () => ({}),
},
})
// 运营商类型映射
const operatorMap = {
'-1': { name: '未知', color: 'gray', text: '?' },
'1': { name: '中国移动', color: 'blue', text: '移' },
'2': { name: '中国联通', color: 'red', text: '联' },
'3': { name: '中国电信', color: 'green', text: '电' },
'4': { name: '中国广电', color: 'purple', text: '广' }
}
// 转网状态映射
const portabilityMap = {
'0': { text: '未转网', color: 'text-emerald-600', bgColor: 'bg-emerald-50', iconText: '✓' },
'1': { text: '已转网', color: 'text-amber-600', bgColor: 'bg-amber-50', iconText: '↔' }
}
// 获取运营商信息
const getOperatorInfo = (code) => {
return operatorMap[code] || operatorMap['-1']
}
// 获取转网状态信息
const getPortabilityInfo = (result) => {
return portabilityMap[result] || portabilityMap['0']
}
onMounted(() => {
console.log(props.data);
})
</script>
<template>
<div class="card main-card">
<div v-if="!data || Object.keys(data).length === 0 || !data.queryResult || data.queryResult.length === 0"
class="py-8 text-center text-gray-500">
<div class="flex flex-col items-center">
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-3">
<span class="text-2xl text-gray-400">📱</span>
</div>
<p>暂无携号转网数据</p>
</div>
</div>
<div v-else class="content">
<!-- 查询结果标题 -->
<div class="header-section">
<div class="flex items-center mb-4">
<div class="title-icon bg-gradient-to-r from-slate-500 to-slate-600">
<span class="text-white text-xl"></span>
</div>
<div>
<h3 class="section-title">携号转网查询结果</h3>
<p class="section-subtitle">号码运营商变更历史查询</p>
</div>
</div>
</div>
<!-- 查询结果列表 -->
<div class="results-container">
<div v-for="(item, index) in data.queryResult" :key="index" class="result-item">
<!-- 手机号显示 -->
<div class="mobile-section">
<div class="mobile-header">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
<span class="text-blue-600 text-sm">📱</span>
</div>
<span class="mobile-number">{{ item.mobile }}</span>
</div>
</div>
<!-- 转网状态 -->
<div class="status-section">
<div class="status-card" :class="getPortabilityInfo(item.result).bgColor">
<div class="status-icon" :class="getPortabilityInfo(item.result).color">
<span class="text-lg">{{ getPortabilityInfo(item.result).iconText }}</span>
</div>
<div class="status-info">
<span class="status-text" :class="getPortabilityInfo(item.result).color">
{{ getPortabilityInfo(item.result).text }}
</span>
<span class="status-label">转网状态</span>
</div>
</div>
</div>
<!-- 运营商信息 -->
<div class="operator-section">
<div class="operator-flow">
<!-- 转网前运营商 -->
<div class="operator-card before-operator">
<div class="operator-header">
<span class="text-gray-400 text-sm"></span>
<span class="operator-label">转网前</span>
</div>
<div class="operator-info">
<div class="operator-icon"
:class="`bg-${getOperatorInfo(item.before).color}-50 text-${getOperatorInfo(item.before).color}-700`">
<span class="text-sm font-bold">{{ getOperatorInfo(item.before).text }}</span>
</div>
<span class="operator-name">{{ getOperatorInfo(item.before).name }}</span>
</div>
</div>
<!-- 转网箭头 -->
<div class="transfer-arrow" v-if="item.result === '1'">
<div class="arrow-container">
<span class="text-amber-600"></span>
</div>
</div>
<!-- 转网后运营商 -->
<div class="operator-card after-operator" v-if="item.result === '1'">
<div class="operator-header">
<span class="operator-label">转网后</span>
<span class="text-gray-400 text-sm"></span>
</div>
<div class="operator-info">
<div class="operator-icon"
:class="`bg-${getOperatorInfo(item.after).color}-50 text-${getOperatorInfo(item.after).color}-700`">
<span class="text-sm font-bold">{{ getOperatorInfo(item.after).text }}</span>
</div>
<span class="operator-name">{{ getOperatorInfo(item.after).name }}</span>
</div>
</div>
<!-- 未转网显示 -->
<div class="operator-card no-transfer" v-else>
<div class="operator-header">
<span class="operator-label">当前运营商</span>
</div>
<div class="operator-info">
<div class="operator-icon"
:class="`bg-${getOperatorInfo(item.before).color}-50 text-${getOperatorInfo(item.before).color}-700`">
<span class="text-sm font-bold">{{ getOperatorInfo(item.before).text }}</span>
</div>
<span class="operator-name">{{ getOperatorInfo(item.before).name }}</span>
</div>
</div>
</div>
</div>
<!-- 分割线 -->
<div class="divider" v-if="index < data.queryResult.length - 1"></div>
</div>
</div>
<!-- 说明信息 -->
<div class="info-section">
<div class="info-card">
<div class="info-header">
<div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center">
<span class="text-blue-600 text-sm"></span>
</div>
<span class="info-title">查询说明</span>
</div>
<div class="info-content">
<p class="info-text">
携号转网查询显示手机号码的运营商变更历史包括转网前后的运营商信息
查询结果仅供参考具体信息以运营商官方记录为准
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.main-card {
@apply bg-white shadow-lg rounded-2xl p-6 mb-4 border border-gray-100;
}
.content {
@apply space-y-6;
}
.header-section {
@apply mb-6;
}
.title-icon {
@apply w-12 h-12 rounded-xl flex items-center justify-center text-white mr-4 shadow-md;
}
.section-title {
@apply text-xl font-bold text-gray-800 mb-1;
}
.section-subtitle {
@apply text-sm text-gray-500;
}
.results-container {
@apply space-y-4;
}
.result-item {
@apply bg-gradient-to-r from-gray-50 to-white rounded-xl p-5 border border-gray-100 shadow-sm;
}
.mobile-section {
@apply mb-4;
}
.mobile-header {
@apply flex items-center space-x-3;
}
.mobile-number {
@apply text-lg font-bold text-gray-800 tracking-wider;
}
.status-section {
@apply mb-4;
}
.status-card {
@apply flex items-center p-3 rounded-lg border;
}
.status-icon {
@apply w-8 h-8 rounded-full flex items-center justify-center mr-3 text-lg;
}
.status-info {
@apply flex flex-col;
}
.status-text {
@apply font-bold text-sm;
}
.status-label {
@apply text-xs text-gray-500 mt-1;
}
.operator-section {
@apply mb-4;
}
.operator-flow {
@apply flex items-center justify-between;
}
.operator-card {
@apply flex-1 bg-white rounded-lg p-4 border border-gray-200 shadow-sm;
}
.operator-header {
@apply flex items-center justify-between mb-3;
}
.operator-label {
@apply text-xs font-medium text-gray-500 uppercase tracking-wide;
}
.operator-info {
@apply flex items-center space-x-3;
}
.operator-icon {
@apply w-10 h-10 rounded-full flex items-center justify-center text-lg;
}
.operator-name {
@apply font-semibold text-gray-800;
}
.transfer-arrow {
@apply mx-4 flex-shrink-0;
}
.arrow-container {
@apply w-8 h-8 bg-orange-100 rounded-full flex items-center justify-center;
}
.divider {
@apply border-t border-gray-200 my-4;
}
.info-section {
@apply mt-6;
}
.info-card {
@apply bg-slate-50 rounded-xl p-4 border border-slate-200;
}
.info-header {
@apply flex items-center mb-2;
}
.info-title {
@apply font-semibold text-slate-700 ml-2;
}
.info-content {
@apply mt-2;
}
.info-text {
@apply text-sm text-slate-600 leading-relaxed;
}
/* 运营商颜色样式 - 柔和色调 */
.bg-blue-50 {
background-color: #eff6ff;
}
.text-blue-700 {
color: #1d4ed8;
}
.bg-red-50 {
background-color: #fef2f2;
}
.text-red-700 {
color: #b91c1c;
}
.bg-green-50 {
background-color: #f0fdf4;
}
.text-green-700 {
color: #15803d;
}
.bg-purple-50 {
background-color: #faf5ff;
}
.text-purple-700 {
color: #7c3aed;
}
.bg-gray-50 {
background-color: #f9fafb;
}
.text-gray-700 {
color: #374151;
}
.bg-emerald-50 {
background-color: #ecfdf5;
}
.text-emerald-600 {
color: #059669;
}
.bg-amber-50 {
background-color: #fffbeb;
}
.text-amber-600 {
color: #d97706;
}
</style>

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

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

268
src/utils/seo.js Normal file
View File

@@ -0,0 +1,268 @@
/**
* SEO优化工具函数
*/
/**
* 设置页面标题
* @param {string} title - 页面标题
*/
export function setPageTitle(title) {
if (title) {
document.title = title;
}
}
/**
* 设置页面描述
* @param {string} description - 页面描述
*/
export function setPageDescription(description) {
if (description) {
let metaDescription = document.querySelector(
'meta[name="description"]'
);
if (!metaDescription) {
metaDescription = document.createElement("meta");
metaDescription.name = "description";
document.head.appendChild(metaDescription);
}
metaDescription.content = description;
}
}
/**
* 设置页面关键词
* @param {string} keywords - 页面关键词
*/
export function setPageKeywords(keywords) {
if (keywords) {
let metaKeywords = document.querySelector('meta[name="keywords"]');
if (!metaKeywords) {
metaKeywords = document.createElement("meta");
metaKeywords.name = "keywords";
document.head.appendChild(metaKeywords);
}
metaKeywords.content = keywords;
}
}
/**
* 设置Open Graph标签
* @param {Object} ogData - Open Graph数据
*/
export function setOpenGraph(ogData) {
const { title, description, type = "website", url, image } = ogData;
if (title) {
setMetaProperty("og:title", title);
}
if (description) {
setMetaProperty("og:description", description);
}
if (type) {
setMetaProperty("og:type", type);
}
if (url) {
setMetaProperty("og:url", url);
}
if (image) {
setMetaProperty("og:image", image);
}
}
/**
* 设置Twitter Card标签
* @param {Object} twitterData - Twitter Card数据
*/
export function setTwitterCard(twitterData) {
const {
title,
description,
image,
card = "summary_large_image",
} = twitterData;
setMetaProperty("twitter:card", card);
if (title) {
setMetaProperty("twitter:title", title);
}
if (description) {
setMetaProperty("twitter:description", description);
}
if (image) {
setMetaProperty("twitter:image", image);
}
}
/**
* 设置meta属性
* @param {string} property - 属性名
* @param {string} content - 属性值
*/
function setMetaProperty(property, content) {
let meta = document.querySelector(`meta[property="${property}"]`);
if (!meta) {
meta = document.createElement("meta");
meta.setAttribute("property", property);
document.head.appendChild(meta);
}
meta.content = content;
}
/**
* 设置结构化数据
* @param {Object} structuredData - 结构化数据对象
*/
export function setStructuredData(structuredData) {
// 移除现有的结构化数据
const existingScripts = document.querySelectorAll(
'script[type="application/ld+json"]'
);
existingScripts.forEach((script) => {
if (script.textContent.includes("@context")) {
script.remove();
}
});
// 添加新的结构化数据
const script = document.createElement("script");
script.type = "application/ld+json";
script.textContent = JSON.stringify(structuredData);
document.head.appendChild(script);
}
/**
* 设置规范链接
* @param {string} url - 规范URL
*/
export function setCanonicalUrl(url) {
let canonical = document.querySelector('link[rel="canonical"]');
if (!canonical) {
canonical = document.createElement("link");
canonical.rel = "canonical";
document.head.appendChild(canonical);
}
canonical.href = url;
}
/**
* 生成面包屑导航的结构化数据
* @param {Array} breadcrumbs - 面包屑数组
* @returns {Object} 结构化数据对象
*/
export function generateBreadcrumbStructuredData(breadcrumbs) {
const items = breadcrumbs.map((item, index) => ({
"@type": "ListItem",
position: index + 1,
name: item.name,
item: item.url,
}));
return {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: items,
};
}
/**
* 生成FAQ的结构化数据
* @param {Array} faqs - FAQ数组
* @returns {Object} 结构化数据对象
*/
export function generateFAQStructuredData(faqs) {
const mainEntity = faqs.map((faq) => ({
"@type": "Question",
name: faq.question,
acceptedAnswer: {
"@type": "Answer",
text: faq.answer,
},
}));
return {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: mainEntity,
};
}
/**
* 生成组织的结构化数据
* @returns {Object} 结构化数据对象
*/
export function generateOrganizationStructuredData() {
return {
"@context": "https://schema.org",
"@type": "Organization",
name: "天远查",
url: "https://www.tianyuancha.cn",
logo: "https://www.tianyuancha.cn/logo.png",
description:
"专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询等服务",
contactPoint: {
"@type": "ContactPoint",
contactType: "customer service",
availableLanguage: "Chinese",
},
sameAs: ["https://www.tianyuanapi.com/", "https://www.tybigdata.com/"],
};
}
/**
* 生成网站的结构化数据
* @returns {Object} 结构化数据对象
*/
export function generateWebsiteStructuredData() {
return {
"@context": "https://schema.org",
"@type": "WebSite",
name: "天远查",
url: "https://www.tianyuancha.cn",
description:
"专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询等服务",
potentialAction: {
"@type": "SearchAction",
target: "https://www.tianyuancha.cn/search?q={search_term_string}",
"query-input": "required name=search_term_string",
},
};
}
/**
* 初始化页面SEO
* @param {Object} seoData - SEO数据
*/
export function initPageSEO(seoData) {
const {
title,
description,
keywords,
ogData,
twitterData,
structuredData,
canonicalUrl,
} = seoData;
if (title) {
setPageTitle(title);
}
if (description) {
setPageDescription(description);
}
if (keywords) {
setPageKeywords(keywords);
}
if (ogData) {
setOpenGraph(ogData);
}
if (twitterData) {
setTwitterCard(twitterData);
}
if (structuredData) {
setStructuredData(structuredData);
}
if (canonicalUrl) {
setCanonicalUrl(canonicalUrl);
}
}

View File

@@ -0,0 +1,505 @@
<template>
<div class="container mx-auto p-4 text-gray-800">
<div class="box">
<p class="text-center font-bold text-xl mb-4">代理管理制度</p>
<p class="indent-8 mb-2"><span></span><strong>前言</strong></p>
<p class="indent-8 mb-2">
广西福铭网络科技有限公司为加强对全国代理的统一管理规范各代理行为确保"天远查"的顺利推广特依据如下原则制定代理管理制度望各级代理认真贯彻严格遵守
</p>
<p class="indent-8 mb-2">1.谨慎性原则</p>
<p class="indent-8 mb-2">本着对双方负责的态度请各级代理务必认真贯彻执行本管理制度的工作程序不可草率行事</p>
<p class="indent-8 mb-2">2.用心协助原则</p>
<p class="indent-8 mb-2">
广西福铭网络科技有限公司配合各代理的工作对于代理在推广工作中遇到的问题用心配合解决
</p>
<p class="indent-8 mb-2">3.诚信的原则</p>
<p class="indent-8 mb-2">双方务必诚实有信用决不提供虚假信息</p>
<p class="indent-8 mb-2">4.严格管理原则</p>
<p class="indent-8 mb-2">
认真贯彻执行各项管理制度对违反管理制度的代理坚决按制度规定予以处罚直至取消代理资格决不姑息迁就
</p>
<p class="indent-8 mb-2">5.双方共赢原则</p>
<p class="indent-8 mb-2">广西福铭网络科技有限公司的目标是与代理共赢共同发展</p>
<p class="indent-8 mb-2">6.长期性原则</p>
<p class="indent-8 mb-2">立足市场与代理长期协作确保代理用心放心地进行市场推广工作</p>
<p class="indent-8 mb-2"><strong>总则</strong></p>
<p class="indent-8 mb-2">第一条 代理期限为一年代理协议实行一年一签制</p>
<p class="indent-8 mb-2">
第二条
本制度规定广西福铭网络科技有限公司代理(以下称代理)权限运作及业务处理等相关事项旨在使广西福铭网络科技有限公司与各代理之间持续良好合作关系促进双方共同发展;
</p>
<p class="indent-8 mb-2">
第三条
代理经广西福铭网络科技有限公司授权并自代理协议书生效之日起应严格依照代理协议及本制度的规定履行义务享受权利
</p>
<p class="indent-8 mb-2">
第四条
广西福铭网络科技有限公司确定的代理应遵循广西福铭网络科技有限公司的规定从事代理活动不得做出损害广西福铭网络科技有限公司利益和形象的行为;
</p>
<p class="indent-8 mb-2">第五条 代理在代理推广过程中应妥善处理做好售前售中售后的咨询维护工作</p>
<p class="indent-8 mb-2"><strong>开通代理账户要求</strong></p>
<p class="indent-8 mb-2"><strong>个人类</strong></p>
<p class="indent-8 mb-2">1完全民事行为能力人</p>
<p class="indent-8 mb-2">2本人实名认证的手机号</p>
<p class="indent-8 mb-2">3首次提现时必须进行本人实名认证并进行人脸识别</p>
<p class="indent-8 mb-2">4全面赞同天远查的各项制度并能积极参加天远查为各代理所举办的各种活动;</p>
<p class="indent-8 mb-2">企业类</p>
<p class="indent-8 mb-2">
1具有独立法人资格并能提供有效营业执照组织代码证等相关文件复印件经审查合格签定代理协议后即成为广西福铭网络科技有限公司认证代理
</p>
<p class="indent-8 mb-2">
2应具备良好的经营规模办公条件设备及人员有固定的营业场所良好的资信潜力和商业信誉并提供以下资料
</p>
<p class="indent-8 mb-2">营业执照复印件</p>
<p class="indent-8 mb-2">身份证复印件</p>
<p class="indent-8 mb-2">代理合作协议</p>
<p class="indent-8 mb-2">业务场景展示</p>
<p class="indent-8 mb-2">3全面赞同天远查的各项制度并能积极参加天远查为各代理所举办的各种活动;</p>
<p class="indent-8 mb-4"><strong>代理权利和义务</strong></p>
<p class="indent-8 mb-2">在成为广西福铭网络科技有限公司的认证代理后可享有如下权利并承担相应的义务:</p>
<p class="indent-8 mb-2">1使用天远查开展广告宣传市场推广活动;</p>
<p class="indent-8 mb-2">2维护广西福铭网络科技有限公司及其产品的良好形象;</p>
<p class="indent-8 mb-2">3开拓下级业务推广并负责对其定期进行业务培训;</p>
<p class="indent-8 mb-2">4推广过程中做好售前售中售后工作</p>
<p class="indent-8 mb-2">
5如用户需要开具发票代理则需向用户开具咨询费发票如代理未开具发票天远查有义务配合税务机关采取相关措施
</p>
<p class="indent-8 mb-2">
6代理业务推广过程中未经广西福铭网络科技有限公司授权不得使用"天远查官方"词汇用于广告宣传
</p>
<p class="font-bold mb-2">推广管理</p>
<p class="indent-8 mb-2">
1天远查负责建立与代理之间的沟通与联系渠道不定期地向代理提供宣传资料信息政策以及推广方案与管理制度等方面的支持
</p>
<p class="indent-8 mb-2">
2广西福铭网络科技有限公司充分尊重代理代理推广权但有下列状况之一时广西福铭网络科技有限公司将保留或者取消该代理的权利:
</p>
<p class="indent-8 mb-2">a代理经营管理不善造成工作无法正常开展的;</p>
<p class="indent-8 mb-2">b国家政策变化等不可抗力发生时;</p>
<p class="indent-8 mb-2">c遇有客户投诉经确认属代理操作不当的;</p>
<p class="indent-8 mb-2">d其他严重损害广西福铭网络科技有限公司形象与产品形象的行为发生时;</p>
<p class="indent-8 mb-2">e违反国家法律法规时;</p>
<p class="indent-8 mb-2">
3当代理名下发生投诉时代理需配合相关的协调否则广西福铭网络科技有限公司有权无条件取消其代理资格终止其代理协议
</p>
<p class="indent-8 mb-2">4代理应合规宣传广西福铭网络科技有限公司产品形象</p>
<p class="indent-8 mb-2">
5市场运作过程中各代理在接到市场投诉时应及时做好记录并报广西福铭网络科技有限公司相关部门妥善处理
</p>
<p class="indent-8 mb-2"><strong>违规处罚</strong></p>
<p class="indent-8 mb-2">
1各代理在推广广西福铭网络科技有限公司过程中有损害广西福铭网络科技有限公司产品信誉行为时视情节轻重广西福铭网络科技有限公司将对其提出书面警告直至取消其代理资格;
</p>
<p class="indent-8 mb-2">
2未按广西福铭网络科技有限公司有关规定和本制度开展工作的广西福铭网络科技有限公司将提出书面警告并限期整改;
</p>
<p class="indent-8 mb-2">
3不遵守广西福铭网络科技有限公司的相关规章制度造成与其他推广代理纠纷时广西福铭网络科技有限公司将视其情节轻重处以20000元以上50000元以下的罚款并取消其代理资格
</p>
<p class="indent-8 mb-2">
4违反保密义务导致广西福铭网络科技有限公司重大损失的广西福铭网络科技有限公司将对其处以5000-20000元罚款情节严重者将直接取消其代理资格
</p>
<p class="indent-8 mb-2">
5代理如严重违反广西福铭网络科技有限公司相关规章制度广西福铭网络科技有限公司可随时解除双方约定的部分或全部协议
</p>
<p class="indent-8 mb-2"><strong>推广收益及提现</strong></p>
<p class="indent-8 mb-2">1用户通过平台推广产品/服务所获得的佣金收益须在平台规定的条件下申请提现</p>
<p class="indent-8 mb-2">2平台有权根据国家税收法律法规对用户佣金收入依法代扣代缴个人所得税</p>
<p class="indent-8 mb-4">3若用户未通过实名认证或未完成相关信息认证平台有权暂缓或拒绝佣金发放</p>
<p class="indent-8 mb-2"><strong>税务处理说明</strong></p>
<p class="indent-8 mb-2">
1用户确认并同意其通过本平台获得的推广佣金奖励分润等收入依法属于"个人所得税"征收范畴
</p>
<p class="indent-8 mb-2">
2用户同意授权平台代为完成相关税务申报及代扣代缴义务平台有权依据国家相关税收标准在佣金发放前先行扣除应缴税款
</p>
<p class="indent-8 mb-2">
3用户理解因未能完成实名认证税务资料提交或不配合税务处理流程所导致的提现延迟失败或法律后果平台不承担任何责任
</p>
<p class="indent-8 mb-4">
4在法律允许的范围内平台有权委托第三方如税务服务平台灵活用工平台等代为完成税务申报发放结算等合规流程
</p>
<p class="indent-8 mb-2"><strong>信息收集与使用说明</strong></p>
<p class="indent-8 mb-2">
1用户在申请提现实名认证或佣金结算过程中需向平台提供包括但不限于姓名身份证号银行卡号手机号税务身份信息等个人资料
</p>
<p class="indent-8 mb-2">
2用户同意平台为履行合同义务税务申报身份核验财务结算等必要目的收集使用存储并在必要范围内共享该等信息
</p>
<p class="indent-8 mb-2">
3平台承诺遵守国家相关法律法规在取得用户同意的前提下对用户个人信息进行合理保护和使用
</p>
<p class="indent-8 mb-2">
4在进行税务代扣代缴结算服务时平台有权将必要信息提供给依法合作的第三方税务服务商结算服务商前提是该第三方承担同等信息保护义务
</p>
<p class="indent-8 mb-4">
5用户有权查询更正其个人信息也可以根据平台流程申请注销账户或停止使用相关服务平台将根据法律要求妥善处理相关信息
</p>
<p class="indent-8 mb-4"><strong>投诉类处罚</strong></p>
<p class="indent-8 mb-2">1代理账户累计投诉率处罚措施</p>
<p class="indent-8 mb-2">a.月查询报告数量200</p>
<div class="mb-4 overflow-x-auto">
<table class="w-full border-collapse border border-gray-300">
<thead>
<tr class="bg-gray-100">
<th class="border border-gray-300 p-2 w-40">处理类型</th>
<th class="border border-gray-300 p-2">提高底价</th>
<th class="border border-gray-300 p-2">限制修改查询售价</th>
<th class="border border-gray-300 p-2">罚款</th>
<th class="border border-gray-300 p-2">禁止提现</th>
<th class="border border-gray-300 p-2">封号</th>
<th class="border border-gray-300 p-2">黑名单</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border border-gray-300 p-2">投诉率5%8%</td>
<td class="border border-gray-300 p-2 text-center">+1</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
<tr>
<td class="border border-gray-300 p-2">投诉率8%10%</td>
<td class="border border-gray-300 p-2 text-center">+3</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
<tr>
<td class="border border-gray-300 p-2">投诉率10%</td>
<td class="border border-gray-300 p-2 text-center">+5</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
</tbody>
</table>
</div>
<p class="indent-8 mb-2">b.月查询报告数量100</p>
<div class="mb-4 overflow-x-auto">
<table class="w-full border-collapse border border-gray-300">
<thead>
<tr class="bg-gray-100">
<th class="border border-gray-300 p-2 w-40">处理类型</th>
<th class="border border-gray-300 p-2">提高底价</th>
<th class="border border-gray-300 p-2">限制修改查询售价</th>
<th class="border border-gray-300 p-2">罚款</th>
<th class="border border-gray-300 p-2">禁止提现</th>
<th class="border border-gray-300 p-2">封号</th>
<th class="border border-gray-300 p-2">黑名单</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border border-gray-300 p-2">投诉率6%8%</td>
<td class="border border-gray-300 p-2 text-center">+1</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
<tr>
<td class="border border-gray-300 p-2">投诉率8%15%</td>
<td class="border border-gray-300 p-2 text-center">+5</td>
<td class="border border-gray-300 p-2 text-center">49</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
</tr>
<tr>
<td class="border border-gray-300 p-2">投诉率15%</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
</tbody>
</table>
</div>
<p class="indent-8 mb-2">c.月查询报告数量50</p>
<div class="mb-4 overflow-x-auto">
<table class="w-full border-collapse border border-gray-300">
<thead>
<tr class="bg-gray-100">
<th class="border border-gray-300 p-2 w-40">处理类型</th>
<th class="border border-gray-300 p-2">提高底价</th>
<th class="border border-gray-300 p-2">限制修改查询售价</th>
<th class="border border-gray-300 p-2">罚款</th>
<th class="border border-gray-300 p-2">禁止提现</th>
<th class="border border-gray-300 p-2">封号</th>
<th class="border border-gray-300 p-2">黑名单</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border border-gray-300 p-2">投诉率15%20%</td>
<td class="border border-gray-300 p-2 text-center">+3</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
<tr>
<td class="border border-gray-300 p-2">投诉率20%50%</td>
<td class="border border-gray-300 p-2 text-center">+5</td>
<td class="border border-gray-300 p-2 text-center">39</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
</tr>
<tr>
<td class="border border-gray-300 p-2">投诉率50%</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
</tbody>
</table>
</div>
<p class="indent-8 mb-2">
备注针对客户自身原因投诉对于产生投诉的代理账户只有三次加底价机会底价只加不减到第四次时直接封号
</p>
<p class="indent-8 mb-4">执行时间每月1号出数据统计2号执行</p>
<p class="indent-8 mb-2">2代理单笔投诉处罚措施</p>
<div class="mb-4 overflow-x-auto">
<table class="w-full border-collapse border border-gray-300">
<thead>
<tr class="bg-gray-100">
<th class="border border-gray-300 p-2 w-40">处理类型</th>
<th class="border border-gray-300 p-2">提高底价</th>
<th class="border border-gray-300 p-2">冻结推广收益</th>
<th class="border border-gray-300 p-2">单笔风险资金冻结</th>
<th class="border border-gray-300 p-2">罚款</th>
<th class="border border-gray-300 p-2">禁止提现</th>
<th class="border border-gray-300 p-2">封号</th>
<th class="border border-gray-300 p-2">黑名单</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border border-gray-300 p-2">网络公开恶意投诉非欺诈类可解</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
<tr>
<td class="border border-gray-300 p-2">支付宝投诉</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
<tr>
<td class="border border-gray-300 p-2">政务部门投诉</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
</tr>
<tr>
<td class="border border-gray-300 p-2">非产品质量类客户一般退款</td>
<td class="border border-gray-300 p-2 text-center">1+退款次数最高10元</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
<tr>
<td class="border border-gray-300 p-2">受代理教唆客户恶意退款</td>
<td class="border border-gray-300 p-2 text-center">5+退款次数</td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center"></td>
<td class="border border-gray-300 p-2 text-center">×</td>
<td class="border border-gray-300 p-2 text-center">×</td>
</tr>
</tbody>
</table>
</div>
<p class="indent-8 mb-2">3扬言给客户做"数据修复"类投诉措施</p>
<p class="indent-8 mb-2">第一步每接到此类投诉一次所属代理底价+10/并警告</p>
<p class="indent-8 mb-2">第二步警告无效后依旧发生则采取直接封号并加入黑名单</p>
<p class="indent-8 mb-2 text-red-600">备注</p>
<p class="indent-8 mb-2 text-red-600">1为执行项 &nbsp;×为不执行项</p>
<p class="indent-8 mb-2 text-red-600">
2一般投诉罚款投诉金额1倍除退还投诉金额外另行按投诉金额1倍的标准进行罚款
</p>
<p class="indent-8 mb-2 text-red-600">投诉金额为45元则退还用户投诉金额45代理罚款45*1=45</p>
<p class="indent-8 mb-2 text-red-600">
3公开投诉代理罚款2倍/封号依据具体严重情况而定除退还投诉金额外另行按投诉金额2倍的标准进行罚款
</p>
<p class="indent-8 mb-2 text-red-600">投诉金额为45元退还用户金额45则代理罚款45*2=90</p>
<p class="indent-8 mb-2 text-red-600">
4如代理发生单笔投诉涉及到本制度第六条所规定的事由将按第六条第七条处罚规则合并执行
</p>
<p class="indent-8 mb-2">4冻结封禁类代理处罚措施</p>
<p class="indent-8 mb-2">
a.自冻结封禁之日起3个月之内无任何新的投诉舆情升级违法犯罪情形代理可向平台提交"提现申请函"平台根据处罚规则先行处罚后对可提现余额再追加10%的罚款代理可在7个工作日内完成相关的提现操作但该代理账户的推广功能则进入到审核期
</p>
<p class="indent-8 mb-2">
b.自冻结封禁之日起3个月之内有新的投诉舆情升级违法犯罪情形则平台对该账户的审查期将会延长审查期间无法提现
</p>
<p class="indent-8 mb-4"><strong>十一封号规则</strong></p>
<p class="mb-2">
1同一个设备频繁更换账号登录或同一个账号频繁在多个设备登陆系统自动自动检测手机登录IP和设备信息有封号风险一机一号不要频繁切换设备或者账户;
</p>
<p class="mb-2">2欺诈用户诱导用户;</p>
<p class="mb-2">3先付款后退款等承诺;</p>
<p class="mb-2">4保证高额下款;</p>
<p class="mb-2">5使用数据优化征信优化等骗取用户钱财</p>
<p class="mb-2">6发布涉嫌性骚扰的文字图片;</p>
<p class="mb-2">7使用含色情淫秽意味或其他令人不适的头像或资料;</p>
<p class="mb-2">8触犯新广告法;</p>
<p class="mb-2">9在朋友圈中使用辱骂恐吓威胁等言论;</p>
<p class="mb-2">10发布各类垃圾广告恶意信息诱骗信息;</p>
<p class="mb-2">11盗用他人头像或资料伪装他人身份;</p>
<p class="mb-2">12多人举报的账号并涉及恶意诈骗;</p>
<p class="mb-2">13频繁被举报每月超过20次以上的代理账户</p>
<p class="mb-2">14恶意投诉比如没有异议非说有异议且无法提供有效证明材料各种奇葩投诉</p>
<p class="mb-2">15租用账号发布不良言论诈骗信息</p>
<p class="mb-4">16发布不当政治言论或者任何违反国家法规政策的言论</p>
<p class="mb-4">更多详细内容请认真阅读天远查代理协议</p>
<h3 class="font-bold mb-2">退款的规则及途径</h3>
<h4 class="font-bold mb-2">退款规则</h4>
<p class="mb-2">1自订单支付完成后30天内为有效期在30天内可申请退款</p>
<p class="mb-2">2超过报告有效期30天则无法办理退款</p>
<p class="mb-2">3符合相关退款条件的用户退款时仅退还实付金额</p>
<p class="mb-2">
4用户购买报告成功后因不可抗力等法定原因或平台原因导致平台无法提供服务用户可联系客服发起退款
</p>
<p class="mb-2">5若因用户的失误重复付款则支持退款重复金额</p>
<p class="mb-2">6服务已发生且不符合退款情形的费用不予退款</p>
<p class="mb-2">7如代理在市场推广中存在欺诈等相关行为用户可提供有效的凭证办理退款事宜</p>
<p class="mb-4">8产品呈现的情况与用户本人实际情况不符用户可提供有效的凭证发起退款申请</p>
<h4 class="font-bold mb-2">用户发起投诉</h4>
<p class="mb-2">1.当代理拒绝退款用户与代理双方线下也未达成一致时用户可联系客服发起投诉</p>
<p class="mb-2">2.用户提交投诉后请用户和代理按照相关提示举证完成举证后客服将介入处理纠纷</p>
<p class="mb-2">
3.平台客服介入前若用户与代理双方已对退款协商一致商家可直接联系平台客服说明情况或者用户联系平台提供撤销投诉函并说明情况即可同时投诉会关闭
</p>
<p class="mb-2">4.平台客服介入后若需要用户与代理提供举证信息可发送相关材料至邮箱方便客服及时处理</p>
<p class="mb-4">5.平台客服会根据举证信息联系用户与代理双方处理投诉</p>
<h5 class="indent-8 font-bold mb-2">十二退款服务以及流程</h5>
<p class="indent-8 mb-4">
自用户购买查询报告成功之日起无论由于何种原因用户均可向平台申请退款不适用退款服务的情况除外
</p>
<div class="flex flex-col items-center mb-4">
<p class="mb-2">用户发起退款申请</p>
<p class="mb-2"></p>
<p class="mb-2">提供有效证明凭证</p>
<p class="mb-2"></p>
<p class="mb-2">平台审核是否符合退款标准</p>
<p class="mb-2"></p>
<p class="mb-2">确认无误后退款完成</p>
<p class="mb-2">预计1-7个工作日内完成</p>
</div>
<h4 class="font-bold mb-2">退款流程说明</h4>
<p class="indent-8 mb-2">
原路返回----直接把金额退回到用户付款的来源方包括但不限于支付宝帐户暂不收取手续费
</p>
<p class="indent-8 mb-4">
具体操作流程在发生退款时用户可在查询页面点击"联系客服"发起"申请退款"申请并提供有效的证明凭证客服提交至平台系统系统通过审核后相关的退款金额将在1-7个工作日内原路返回对应的付款账户中通过网银或支付宝等第三方支付平台进行支付的费用将直接退到原账户
</p>
<h4 class="font-bold mb-2">不适用退款服务的情况</h4>
<p class="indent-8 mb-2">1已超过退款期限</p>
<p class="indent-8 mb-2">2恶意投诉</p>
<p class="indent-8 mb-4">3违反用户使用协议相关规则</p>
<h4 class="font-bold mb-2">补充说明</h4>
<p class="indent-8 mb-4">
如您需要退款的产品类型不在以上30天或者超出了30
天限制则无法办理退款如您有产品使用方面的疑问您可以通过联系客服进行反馈
</p>
<p class="indent-8 mb-2"><strong>十三附则</strong></p>
<p class="indent-8 mb-2">1本制度作为代理协议之附件与代理协议具有同等法律效力</p>
<p class="indent-8 mb-2">
2广西福铭网络科技有限公司将本着"诚信为本、长期服务"的宗旨和"公平合理"的原则对代理进行合理布局和调整以实现互利互惠共同快速发展的目的
</p>
<p class="indent-8 mb-2">3因其他原因需终止代理关系需向广西福铭网络科技有限公司提出书面申请</p>
<p class="indent-8 mb-2">
4代理之间发生业务竞争和冲突广西福铭网络科技有限公司将依据公平公正公开的原则按相关制度予以调解处理
</p>
<p class="indent-8 mb-2">
5如广西福铭网络科技有限公司与各代理之间出现协议上的纠纷由广西福铭网络科技有限公司所在地法院裁决
</p>
<p class="indent-8 mb-2">
6本制度的制定修改与废止皆经由广西福铭网络科技有限公司讨论决定解释权归广西福铭网络科技有限公司所有
</p>
<p class="indent-8 mb-4">7本制度于2022年1月1日起实施公司将根据实施情况对本制度进行修正和调整</p>
<p class="indent-8 mb-8">本制度一经网上点击/勾选即代表理解并同意勾选遵守</p>
<p class="text-right">本制度于 {{ effectiveDate }} 生效</p>
</div>
</div>
</template>
<script setup>
// 获取当前日期并格式化为中文格式
const getFormattedDate = () => {
const date = new Date()
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
return `${year}${month}${day}`
}
const effectiveDate = ref(getFormattedDate())
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,327 @@
<template>
<div>
<div class="container mx-auto p-4 text-gray-800">
<p class="text-center font-bold text-lg">信息技术服务合同</p>
<p class="text-left"><span></span></p>
<p class="text-left"><span class="text-black">甲方</span></p>
<p class="text-left">
<span class="text-black">乙方</span><span class="text-black">广西福铭网络科技有限公司</span>
</p>
<p class="text-left">&nbsp;</p>
<p class="text-left"><span class="text-black">鉴于</span></p>
<p class="text-left">
<span class="text-black">1. 甲方为其合法合规经营之业务依法需对甲方最终用户或有关交易和交往利害关系主体有关信息进行识别</span>
</p>
<p class="text-left">
<span class="text-black">2. 乙方具备相关信息技术之专业能力能够为甲方提供相应服务</span>
</p>
<p class="text-left"></p>
<p class="text-left">
<span class="text-black"> 现双方根据中华人民共和国</span><span class="text-black">民法典</span><span
class="text-black">等相关法律法规本着诚实信用公平促进社会诚信发展为原则经友好协商就</span><span
class="text-black">广西福铭网络科技有限公司</span><span class="text-black">信息技术服务事宜达成一致签订本合同</span>
</p>
<p class="text-left"><span></span></p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 释义</span></p>
<p class="text-left">
<span class="text-black"> 除上下文另有约定外下列用语具有如下含义</span>
</p>
<p class="text-left">
<span class="text-black">1.1 &nbsp; &nbsp;</span><span class="text-black">广西福铭网络科技有限公司</span><span
class="text-black">信息技术服务服务 指乙方通过信息化人工智能和信息科技等技术手段对</span><span class="text-black">大数据</span><span
class="text-black">进行以公众号小程序APPweb页面以下简称平台或标准接口形式为客户提供的服务协助客户完成信息的整理管理等业务流程</span>
</p>
<p class="text-left">
<span class="text-black">1.2 &nbsp; &nbsp;本合同 指本文本协议及其形成本合同不可分割的附件</span>
</p>
<p class="text-left">
<span class="text-black">1.3 &nbsp; &nbsp;本合同标题仅供方便参考之用不影响本合同的含义与解释</span>
</p>
<p class="text-left">
<span class="text-black">1.4 &nbsp; &nbsp;本合同甲方乙方单独称为一方合称为双方</span>
</p>
<p class="text-left">
<span class="text-black">1.5 &nbsp; &nbsp;法律法规
指中国法律行政法规部门规章地方性法规地方性政府部门规章以及由政府机构颁布的其他规范性文件</span>
</p>
<p class="text-left">
<span class="text-black">1.6 &nbsp; &nbsp;工作日 指法定节假日休息日之外的日期</span>
</p>
<p class="text-left">
<span class="text-black">1.7 &nbsp; &nbsp;服务有效期 指乙方依据本合同提供服务的期限</span>
</p>
<p class="text-left">
<span class="text-black">1.8 &nbsp; &nbsp;授权
指甲方最终用户以书面签名或法律效力等同于书面的电子签名等方式明确同意甲方向第三方服务商指乙方并含其关联方下同提供本人单位相关数据信息包括但不限于个人信息行为交易设备不良信息下同及同意该第三方服务提供商查询核实搜集处理共享使用含合法业务应用其本人单位相关数据的行为但是法律法规规定可以不经同意的除外</span>
</p>
<p class="text-left">
<span class="text-black">1.9 &nbsp; &nbsp;APIApplication Programming Interface,应用程序编程接口
指一些预先定义的函数目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力而又无需访问源码或理解内部工作机制的细节</span>
</p>
<p class="text-left">
<span class="text-black">1.10 &nbsp; &nbsp;Web应用 指一种可以通过Web访问的应用程序由完成特定任务的各种Web组件web
components构成的并通过Web将服务展示给客户</span>
</p>
<p class="text-left">
<span class="text-black">1.11 &nbsp; &nbsp;SFTP(Secure File Transfer Protocol,安全文件传送协议)
指可以为传输文件提供一种安全的加密方法</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 合作内容与方式</span></p>
<p class="text-left">
<span class="text-black">2.1 &nbsp; &nbsp;根据本合同约定的条件和条款甲方使用乙方提供的</span><span
class="text-black">广西福铭网络科技有限公司</span><span class="text-black">相关</span><span
class="text-black">信息技术服务简称乙方服务本服务</span>
</p>
<p class="text-left">
<span class="text-black">2.2 &nbsp; &nbsp;
乙方负责提供服务平台或接口供甲方通过平台或接口使用本服务乙方向甲方提供的平台或接口是使用本服务的重要凭证除非另有约定或说明甲方通过该平台或接口向乙方所发出的指令及相关行为均视为甲方的行为</span>
</p>
<p class="text-left">
<span class="text-black">2.3 &nbsp; &nbsp;
甲方通过乙方提供的平台或APIWeb应用向乙方发起服务需求乙方通过平台或APIWeb应用将服务结果返回给甲方</span>
</p>
<p class="text-left"><span class="text-black"> 费用及支付</span></p>
<p class="text-left">
<span class="text-black">3.1 &nbsp; &nbsp;
本合同采用先付费后使用的计价模式甲方依据自主选择的服务项目对应费用向乙方支付服务费用</span>
</p>
<p class="text-left">
<span class="text-black">3.2 &nbsp; &nbsp;服务有效期及支付方式</span>
</p>
<p class="text-left">
<span class="text-black">3.2.1 服务有效期以1年为准
除非另有约定充值金额使用完毕/流量限额全部用完或服务有效期届满之日以先到者为准且未在服务有效期内续费或者续流量的则本合同即终止在服务有效期内继续充值的则续充的服务有效期为该次充值之后12个月如当期服务有效期届满而预付金额/流量限额未用完乙方无需退还服务费并不予以延期使用</span>
</p>
<p class="text-left"><span class="text-black">3.3 &nbsp; &nbsp;支付方式</span></p>
<p class="text-left">
<span class="text-black">3.3.1 甲方向乙方一次性</span><span class="text-black">或分多次</span><span
class="text-black">支付服务费</span>
</p>
<p class="text-left">
<span class="text-black">3.3.2 乙方根据甲方使用功能和次数实时计费并从甲方已支付费用中扣除</span>
</p>
<p class="text-left">
<span class="text-black">3.3.3
若甲方拟继续使用服务的则须在预付费/流量使用完毕后继续充值具体充值的服务项目和价格见平台展示</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 权利与义务</span></p>
<p class="text-left"><span class="text-black">4.1 &nbsp; &nbsp;甲方权利与义务</span></p>
<p class="text-left">
<span class="text-black">4.1.1 甲方有权根据本合同约定向乙方提起服务需求</span>
</p>
<p class="text-left">
<span class="text-black">4.1.2 甲方</span><span
class="text-black">使用乙方服务不得违反中华人民共和国个人信息保护法征信业务管理办法的相关规定</span><span
class="text-black">对乙方所提供的服务信息予以保密且严格遵守法律法规不从事任何侵犯个人信息或商业秘密的活动</span>
</p>
<p class="text-left">
<span class="text-black">4.1.3
甲方向乙方提交的服务需求及相关数据均已经过被查询用户最终用户充分有效的书面或电子授权同意乙方及乙方的关联合作方对相关数据进行获取并在乙方系统中或提交数据源方用于该合同项下的识别并进行储存分析处理及使用含业务应用等合法行为甲方对此充分理解并认可</span>
</p>
<p class="text-left">
<span
class="text-black">根据乙方要求甲方应当向乙方提供由最终用户签字的授权文件乙方仅予以形式审查乙方对授权文件的审查不免除甲方就授权的真实性合法性完整性与本合同约定的一致性所承担的责任</span>
</p>
<p class="text-left">
<span class="text-black">4.1.4 甲方需向乙方提供经乙方服务识别有相关用户之信息及验证结果反馈</span>
</p>
<p class="text-left">
<span class="text-black">4.1.5 未经乙方同意甲方不得将乙方提供的服务进行宣传或使用乙方名称业务介绍标识商标知识产权等</span>
</p>
<p class="text-left">
<span class="text-black">4.1.6 甲方应限于自身使用乙方提供的产品和服务不得从事与乙方有竞争关系的业务</span>
</p>
<p class="text-left">
<span class="text-black">4.1.7 除为实现本合同目的确有必要外甲方不将获得的服务信息进行存储复制下载打印</span>
</p>
<p class="text-left">
<span class="text-black">4.2 &nbsp; &nbsp;乙方的权利和义务</span>
</p>
<p class="text-left">
<span class="text-black">4.2.1 负责提供服务向甲方提供标准平台服务或接口文件为甲方开通服务账号</span>
</p>
<p class="text-left">
<span class="text-black">4.2.2
乙方负责其系统的设计开发使系统能够支撑合作业务正常运行并有义务对甲方提出的维护请求给予支持</span>
</p>
<p class="text-left">
<span class="text-black">4.2.3 乙方为优化对甲方提供的服务可对其服务系统进行升级调试等处理</span>
</p>
<p class="text-left">
<span class="text-black">4.2.4
在乙方受甲方委托为甲方提供信息技术服务中所产生的后果包括但不限于因甲方提供数据缺乏真实性或准确性导致服务偏差乙方在受托服务中与甲方用户发生纠纷或遭投诉的由甲方负责处理与承担</span>
</p>
<p class="text-left">
<span class="text-black">4.2.5 如甲方未按约定支付服务费时乙方有权中止服务</span>
</p>
<p class="text-left">
<span class="text-black">4.2.6
因甲方违反合同保密授权条款或违反约定使用本服务包括但不限于5.1.65.1.75.1.8乙方可以中止或终止服务并向甲方索赔对乙方造成损失的违约费用</span>
</p>
<p class="text-left">
<span class="text-black">4.2.7 乙方为履行本合同在不影响甲方权利的前提下可以通过乙方关联公司向甲方提供服务</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 知识产权</span></p>
<p class="text-left">
<span class="text-black">5.1 &nbsp; &nbsp;
乙方享有本合同产品和服务相关内容之知识产权与所有权包括但不限于软件程序源代码文档专利商标著作权域名专有技术商业秘密文字表达及其组合数据数据变量数据算法数据模型图标图饰图表色彩界面设计除非经乙方许可本合同并不赋予甲方享有乙方任何知识产权上的权利</span>
</p>
<p class="text-left">
<span class="text-black">5.2 &nbsp; &nbsp;
除非另有约定任何一方均不可凭借本合同取得另一方所拥有的著作权专利权商标权或其他知识产权</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 保密与信息安全</span></p>
<p class="text-left">
<span class="text-black">
除非双方签订商业保密协议对保密另有约定外需履行以下保密约定 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp;
</span>
</p>
<p class="text-left">
<span class="text-black">6.1 &nbsp; &nbsp;
保密信息提供方或其母公司子公司关联公司向接受方披露的信息包括但不限于本合同内容合作模式商业计划投资经营方案分析或计算方法系统数据数据变量数据算法数据模型程序装置规格序列设计研究或开发活动和方案知识产权专有技术服务信息与服务说明业务与营销方案推广方法销售额客户名单商业机会成本价格及其他财务信息</span>
</p>
<p class="text-left">
<span class="text-black">6.2 &nbsp; &nbsp;
保密信息不包括1在收到保密信息之时或之前已合法知悉的信息且该信息不受保密义务约束2非因接受方违约而成为公众信息的信息3接受方从披露方及其关联方以外的其他信息源所获知的信息4提供方未明示为保密信息的信息5接受方未利用任何保密信息而合法独立开发的信息或通过接受方信息数据分析而获知的信息</span>
</p>
<p class="text-left">
<span class="text-black">6.3 &nbsp; &nbsp;
上述保密信息可以以数据文字及记载上述内容的书面资料图书录音资料录像资料光盘软件网页客户端等有形媒介体现也可通过口头等形式体现</span>
</p>
<p class="text-left">
<span class="text-black">6.4
任何一方在提供保密信息时如以书面形式提供应注明保密等相关字样如以口头或可视形式透露应在披露前明示接受方为保密信息</span>
</p>
<p class="text-left">
<span class="text-black">6.5 &nbsp; &nbsp;
除另有约定外未经披露方书面同意须将保密信息严格保密并不得直接或间接导致准许或容许向任何第三方披露公布转移挪用或泄露保密信息接受方均不向第三方及其不必要知悉的员工披露保密信息</span>
</p>
<p class="text-left">
<span class="text-black">6.6 &nbsp; &nbsp;
除另有约定外承担保密义务的范围不包括1由乙方提供给数据源方的2提供给乙方关联公司的3将经适当汇总编辑修改整理的保密信息在必要与合理范围内提供给律师和会计师及其他专业服务提供者4按照法律法规监管有管辖权的法院要求须提供的信息但在不禁止的情况下应立即向保密信息提供方予以通报</span>
</p>
<p class="text-left">
<span class="text-black">6.7 &nbsp; &nbsp;
双方确认除非保密信息依法公开保密义务自本合同签订时开始持续有效甲方是否继续使用乙方的服务不影响保密义务的承担</span>
</p>
<p class="text-left">
<span class="text-black">6.8 &nbsp; &nbsp;
双方均应当遵守法律法规关于信息安全的管理规定并采取有效措施保障信息安全包括但不限于保障计算机系统及其相关配套设备设施含网络运行环境信息系统功能的安全运行等</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 反商业贿赂</span></p>
<p class="text-left">
<span class="text-black">7.1 &nbsp; &nbsp;
双方都清楚并愿意严格遵守反商业贿赂的法律规定任何形式的贿赂和贪渎行为都将触犯法律并将受到不利后果</span>
</p>
<p class="text-left">
<span class="text-black">7.2 &nbsp; &nbsp;
双方均不得向对方或对方经办人或其他相关人员索要收受提供给予本合同约定外的任何利益包括但不限于明扣暗扣现金购物卡实物有价证券旅游或其他非物质利益等但如该等利益属于行业惯例或通常礼仪做法的除外</span>
</p>
<p class="text-left">
<span class="text-black">本款相关人员是指双方经办人以外的与本合同有直接或间接利益关系的人员如经办人的亲友等</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 违约责任</span></p>
<p class="text-left">
<span class="text-black">8.1 &nbsp; &nbsp;
除非另有约定任何一方未履行本合同或违反约定且未及时改正或采取补救措施的违约方应向守约方按照已发生合同金额的</span><span
class="text-black">30</span><span
class="text-black">%向守约方承担违约责任并赔偿守约方因此受到的直接经济损失包括调查仲裁诉讼律师等合理费用</span>
</p>
<p class="text-left">
<span class="text-black">8.2 &nbsp; &nbsp;
如因甲方原因导致本合同终止的其无权要求乙方退回已收取而未使用的服务费若一方因对方或其它非己方原因未能履行本合同下的义务一方无需赔偿对方承受的损失</span>
</p>
<p class="text-left">
<span class="text-black">8.3 &nbsp; &nbsp;
一方未行使迟延行使或部分行使其权利并不意味该权利被放弃某一权利不行使并不意味着其它权利被放弃</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 免责事由</span></p>
<p class="text-left">
<span class="text-black">除特别指明外一方无须就下列情形承担责任</span>
</p>
<p class="text-left">
<span class="text-black">9.1 &nbsp; &nbsp;
不可抗力不可抗力是指合同双方当事人不能预见不能避免并不能克服的客观情况包括但不限于战争骚乱恐怖主义洪水地震台风国家公布的疫情等事件</span>
</p>
<p class="text-left">
<span class="text-black">9.2 &nbsp; &nbsp;
因法律法规规章规定指引通知政策命令及其他规范性文件或政府行为原因导致本合同不能履行的适用关于不可抗力的规定</span>
</p>
<p class="text-left">
<span class="text-black">9.3 &nbsp; &nbsp;
乙方为改善服务质量或数据源方对系统进行调整升级扩容等措施而导致服务中断延时等情况</span>
</p>
<p class="text-left">
<span class="text-black">9.4 &nbsp; &nbsp;
因网络设备黑客攻击计算机病毒侵入或发作通信或电力故障等不可预测因素造成不能提供服务的情形</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black"> 争议解决与法律适用</span></p>
<p class="text-left">
<span class="text-black">10.1 &nbsp;
因履行本合同而发生的一切争议甲乙双方应协商解决协商不成的任何一方均有权向乙方所在地有管辖权法院提起诉讼</span>
</p>
<p class="text-left"><span class="text-black">十一 通知与送达</span></p>
<p class="text-left">
<span class="text-black">11.1 &nbsp;
本合同项下的通知应以电子邮件快递传真专人递送按合同签署页所列示联系方式发出,除非任何一方已书面通知对方变更联系方式并经对方确认</span>
</p>
<p class="text-left">
<span class="text-black">11.2 &nbsp;
书面通知的形式包括在网站公告电子邮件站内信微信手机短信和传真等电子方式及纸质文件通知在下列日期视为送达被通知方如以电子邮件发送显示成功发送确认时或发送后第一个工作日内未被退回如是以快递发送以交邮后第五个工作日如以传真发送于发件人传真机记录传输确认时如以专人递送被通知方签收日</span>
</p>
<p class="text-left"></p>
<p class="text-left"><span class="text-black">十二 其他</span></p>
<p class="text-left">
<span class="text-black">12.1 &nbsp;
本合同附件作为本合同的组成部分与本合同具有同等的法律效力未尽事宜经双方协商后签订补充合同补充合同与本合同条款如有冲突以补充合同为准</span>
</p>
<p class="text-left">
<span class="text-black">12.2 &nbsp; 本合同终止日与服务有效期终止日相同在合同期限届满前由双方友好协商是否续约</span>
</p>
<p class="text-left">
<span class="text-black">12.3 &nbsp;
本合同终止不影响合同中有关授权付款保密知识产权反商业贿赂违约责任争议解决与法律适用等可以独立存在的条款的效力一方未履行完毕的义务仍需继续履行</span>
</p>
<p class="text-left">
<span class="text-black">12.4 &nbsp; 本合同自甲方支付/充值费用之日</span><span class="text-black">计算服务期限</span><span
class="text-black">合同期限为12个月</span>
</p>
<p style="text-indent: 24pt">
<span>本协议通过点击同意/勾选的方式签署自签署之日生效</span>
</p>
<p style="text-indent: 24pt; text-align: right">
<span>本协议于 {{ effectiveDate }}生效</span>
</p>
<p class="text-center"></p>
<p></p>
</div>
</div>
</template>
<script setup>
const getFormattedDate = () => {
const date = new Date()
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
return `${year}${month}${day}`
}
const effectiveDate = ref(getFormattedDate())
</script>
<style lang="scss" scoped>
p {
@apply my-1;
}
</style>

View File

@@ -68,6 +68,27 @@
本服务是虚拟数据服务一经提交查询则会产生后台信息服务
</li>
</ul>
<p class="mt-2 font-bold">个人信息处理说明</p>
<ul class="list-decimal pl-6">
<li>
<span
class="font-semibold">处理目的</span>贵司收集和处理本人的个人信息主要用于进行报告的查询生成和提供保留一定时间供本人查看和下载报告内容提供账户管理和客户服务改进和优化服务体验以及保障账户安全和系统安全
</li>
<li>
<span
class="font-semibold">处理方式</span>贵司采用AES加密技术对所有个人信息进行加密存储在生成报告和展示时对敏感信息进行脱敏处理严格限制对个人信息的访问权限并在数据传输过程中采用SSL/TLS加密技术确保安全传输
</li>
<li>
<span
class="font-semibold">处理的个人信息种类</span>包括本人查询时输入的信息姓名身份证号手机号银行卡号等登录注册时的手机号码生成报告的相关信息查询记录报告内容查询时间等以及系统操作日志登录记录操作行为设备信息等
</li>
<li>
<span
class="font-semibold">保存期限</span>查询报告的信息以及报告内容保留15天到期后自动删除账户信息在本人注销账户时立即删除用户操作日志记录按照法律要求保留半年以上其他个人信息在服务目的达成后或法律规定的期限内删除
</li>
</ul>
<p class="mt-2 font-bold">附加说明</p>
<ul class="list-decimal pl-6">
<li>

View File

@@ -15,7 +15,7 @@ const featureMap = {
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
G27BJ05: {
name: "借贷申请记录",
name: "本人需求推测",
component: defineAsyncComponent(() =>
import("@/ui/CBankLoanApplication.vue")
),
@@ -43,7 +43,7 @@ const featureMap = {
component: defineAsyncComponent(() => import("@/ui/CLawsuitPP.vue")),
},
G05HZ01: {
name: "股东人企关系",
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CRelatedEnterprises.vue")
),
@@ -118,6 +118,10 @@ const featureMap = {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CCAR061.vue")),
},
QCXG9P1C: {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CQCXG9P1C.vue")),
},
COM187: {
name: "限制出境查询",
component: defineAsyncComponent(() => import("@/ui/CCOM187.vue")),
@@ -179,7 +183,7 @@ const featureMap = {
),
},
PersonEnterprisePro: {
name: "人企关系加强版",
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CPersonEnterprisePro/index.vue")
),
@@ -192,6 +196,27 @@ const featureMap = {
name: "学历信息查询",
component: defineAsyncComponent(() => import("@/ui/CG11BJ06.vue")),
},
FLXGDEA9: {
name: "本人不良",
component: defineAsyncComponent(() => import("@/ui/CFLXGDEA9.vue")),
},
IVYZ6G7H: {
name: "婚姻状态(补证版)",
component: defineAsyncComponent(() => import("@/ui/CIVYZ6G7H.vue")),
},
IVYZ3A7F: {
name: "学历信息查询(含学校名称)",
component: defineAsyncComponent(() => import("@/ui/CIVYZ3A7F.vue")),
},
YYSY7D3E: {
name: "携号转网查询",
component: defineAsyncComponent(() => import("@/ui/CYYSY7D3E.vue")),
},
IVYZ3P9M: {
name: "学历信息",
component: defineAsyncComponent(() => import("@/ui/IVYZ3P9M.vue")),
remark: '学历信息展示学生姓名、身份证号、学校、专业、入学与毕业时间、学历层次以及学习形式等字段,可结合字典编码了解具体含义。',
},
};
import LEmpty from "@/components/LEmpty.vue";
@@ -358,14 +383,14 @@ const calculateScore = (reportData) => {
FIN019: 100, // 银行卡黑名单
// 高风险指标(中优先级)
G27BJ05: 40, // 借贷申请记录
G27BJ05: 40, // 本人需求推测
G28BJ05: 40, // 借贷行为记录
G03HZ01: 70, // 手机号码风险
// 中风险指标(低优先级)
G19BJ02: 50, // 手机二次卡
G02BJ02: 50, // 手机在网时长
G05HZ01: 50, // 人企关系
G05HZ01: 50, // 名下企业关联
// 验证指标(最低优先级)
G15BJ02: 25, // 手机三要素
@@ -412,7 +437,7 @@ const calculateScore = (reportData) => {
// 不计入风险
break;
case "G27BJ05": // 借贷申请记录
case "G27BJ05": // 本人需求推测
if (data) {
// 检查是否有申请记录(有则表示风险)
let hasRisk = false;
@@ -624,20 +649,10 @@ const calculateScore = (reportData) => {
<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暂未上线建议将此网站加入收藏夹或书签或关注微信天远查公众号"
/>
<van-notice-bar color="#e03131" background="#ecf9ff" left-icon="info-o"
text="由于天远查APP暂未上线建议将此网站加入收藏夹或书签或关注微信天远查公众号" />
<template v-if="isDone">
<van-tabs
v-if="reportData.length > 1"
v-model:active="active"
scrollspy
sticky
:offset-top="46"
>
<van-tabs v-if="reportData.length > 1" v-model:active="active" scrollspy sticky :offset-top="46">
<div class="flex flex-col gap-y-4 p-4">
<LEmpty v-if="isEmpty" />
<LPendding v-if="isPending" />
@@ -654,54 +669,29 @@ const calculateScore = (reportData) => {
<div id="overdiv" class="title mb-4">基本信息</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<LTitle
title="报告信息"
type="blue-green"
></LTitle>
<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
>
<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
>
<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
>
{{ reportName }}</span>
</div>
</div>
<template
v-if="
Object.keys(reportParams).length !=
0
"
>
<LTitle
title="报告对象"
type="blue-green"
></LTitle>
<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
>
<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",
@@ -709,31 +699,20 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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
>
}}</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
>
<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",
@@ -741,14 +720,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -756,14 +730,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -771,14 +740,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -786,14 +750,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -801,14 +760,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -816,16 +770,10 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -833,14 +781,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -848,14 +791,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -863,14 +801,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -879,23 +812,16 @@ const calculateScore = (reportData) => {
}}</span>
</div>
<div class="flex flex-col gap-4">
<div
class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1"
>
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4"
>
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
<div
class="font-bold text-lg"
>
<div class="font-bold text-lg">
身份证检查结果
</div>
<div
class="text-sm text-gray-600"
>
<div class="text-sm text-gray-600">
身份证信息核验通过
</div>
</div>
@@ -905,32 +831,20 @@ const calculateScore = (reportData) => {
</template>
</div>
</div>
<LRemark
content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况"
/>
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
</van-tab>
<van-tab
v-for="(item, index) in reportData"
:key="index"
:title="featureMap[item.data.apiID]?.name"
>
<van-tab v-for="(item, index) in reportData" :key="index"
:title="featureMap[item.data.apiID]?.name">
<div id="lawsuit" class="title mb-4">
{{ featureMap[item.data.apiID]?.name }}
</div>
<component
:is="featureMap[item.data.apiID]?.component"
:data="item.data.data"
:params="reportParams"
:isMerriageProduct="
item.data.apiID === 'G09SC02' ||
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
:params="reportParams" :isMerriageProduct="item.data.apiID === 'G09SC02' ||
item.data.apiID === 'IDV044'
"
>
">
</component>
<LRemark
v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark"
/>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</van-tab>
</template>
</div>
@@ -941,38 +855,23 @@ const calculateScore = (reportData) => {
<div class="flex flex-col gap-y-2">
<LTitle title="报告信息" type="blue-green"></LTitle>
<div class="flex flex-col gap-2 my-2">
<div
class="flex justify-between border-b pb-2 pl-2"
>
<span class="text-gray-700 font-bold"
>报告时间:</span
>
<span class="text-gray-600"
>2025-1-1 12:00:00</span
>
<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
>
<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
>
{{ 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?.keyword &&
reportParams?.type
"
>
<div class="flex justify-between border-b pb-2 pl-2" v-if="
reportParams?.keyword &&
reportParams?.type
">
<span class="text-gray-700 font-bold">{{
typeMap[reportParams.type] || "查询对象"
}}</span>
@@ -985,51 +884,30 @@ const calculateScore = (reportData) => {
)
}}</span>
</div>
<div
class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.name"
>
<span class="text-gray-700 font-bold"
>姓名</span
>
<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
>
<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
>
}}</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
>
<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
>
<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",
@@ -1037,13 +915,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1051,13 +924,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1065,13 +933,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1079,13 +942,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1093,13 +951,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1107,13 +961,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1121,13 +970,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1135,13 +979,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1149,13 +988,9 @@ const calculateScore = (reportData) => {
)
}}</span>
</div>
<div
class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.certificate_number"
>
<span class="text-gray-700 font-bold"
>证书编号</span
>
<div class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.certificate_number">
<span class="text-gray-700 font-bold">证书编号</span>
<span class="text-gray-600">{{
maskValue(
"certificate_number",
@@ -1163,13 +998,8 @@ const calculateScore = (reportData) => {
)
}}</span>
</div>
<div
class="flex justify-between border-b pb-2 pl-2"
v-if="reportParams?.vin_code"
>
<span class="text-gray-700 font-bold"
>车架号</span
>
<div class="flex justify-between border-b pb-2 pl-2" v-if="reportParams?.vin_code">
<span class="text-gray-700 font-bold">车架号</span>
<span class="text-gray-600">{{
maskValue(
"vin_code",
@@ -1178,12 +1008,9 @@ const calculateScore = (reportData) => {
}}</span>
</div>
<div class="flex flex-col gap-4">
<div
class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1"
>
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4"
>
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
@@ -1200,29 +1027,20 @@ const calculateScore = (reportData) => {
</template>
</div>
</div>
<LRemark
content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况"
/>
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
<LEmpty v-if="isEmpty" />
<template v-for="(item, index) in reportData" :key="index">
<div id="lawsuit" class="title">
{{ featureMap[item.data.apiID]?.name }}
</div>
<component
:is="featureMap[item.data.apiID]?.component"
:data="item.data.data"
:params="reportParams"
:isMerriageProduct="
item.data.apiID === 'G09SC02' ||
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
:params="reportParams" :isMerriageProduct="item.data.apiID === 'G09SC02' ||
item.data.apiID === 'IDV044'
"
>
">
</component>
<LRemark
v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark"
/>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</template>
<div class="card">
<div>
@@ -1232,9 +1050,7 @@ const calculateScore = (reportData) => {
&nbsp;本报告的数据由用户本人明确授权后,我们才向相关合法存有用户个人数据的机构调取本报告相关内容,本平台只做大数据的获取与分析,仅向用户个人展示参考。
</div>
<p>
&nbsp; &nbsp; 报告有效期<strong class="text-red-500"
>15天</strong
>,过期自动删除。
&nbsp; &nbsp; 报告有效期<strong class="text-red-500">15天</strong>,过期自动删除。
</p>
<p>
&nbsp; &nbsp;
@@ -1251,6 +1067,10 @@ const calculateScore = (reportData) => {
</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>桂公网安备45010002451084号</text>
</div>
<div>
<a class="text-blue-500" href="https://beian.miit.gov.cn">
桂ICP备2024038462号

View File

@@ -54,11 +54,18 @@
<!-- 页脚 -->
<footer class="bg-blue-200 text-gray-700 text-center py-4">
<div class="flex items-center justify-center gap-2">
<p class="text-sm">
桂ICP备2024038462号
</p>
<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>桂公网安备45010002451084号</text>
</div>
<div>
<a class="text-blue-500" href="https://beian.miit.gov.cn">
桂ICP备2024038462号
</a>
</div>
</div>
<div>广西福铭网络科技有限公司版权所有</div>
</footer>
</div>
</template>

954
src/views/Inquire copy.vue Normal file
View File

@@ -0,0 +1,954 @@
<script setup>
import { ref, reactive, computed, onMounted, onUnmounted } from "vue";
import { aesEncrypt } from "@/utils/crypto";
import { useRoute } from "vue-router";
import Authorization from "@/components/Authorization.vue";
import Payment from "@/components/Payment.vue";
import CarNumberInput from "@/components/CarNumberInput.vue";
const route = useRoute();
const router = useRouter();
const showAuthorizationPopup = ref(false);
const authorization = ref(true);
const showPayment = ref(false);
const queryId = ref(null);
const name = ref("");
const nameMan = ref("");
const nameWoman = ref("");
const idCard = ref("");
const idCardMan = ref("");
const idCardWoman = ref("");
const mobile = ref("");
const bankCard = ref("");
const certificateNumber = ref("");
const startDate = ref([]);
const dateVal = ref("");
const showDatePicker = ref(false);
// 新增车架号和行驶证照片
const vinCode = ref("");
const carDrivingPermit = ref("");
const carDrivingPermitFile = ref(null);
// 当前日期
const today = new Date();
const maxDate = today; // 最大日期为当前日期
// 最小日期为2000年1月1日
const minDate = new Date("2000-01-01");
const entName = ref("");
const entCode = ref("");
const verificationCode = ref("");
const agreeToTerms = ref(false);
// 新增特殊API的授权书勾选
const agreeToAuthorization = ref(false);
const isCountingDown = ref(false);
const countdown = ref(60);
const feature = ref(route.params.feature);
const featureData = ref({});
const carLicense = ref("");
const carType = ref("小型汽车");
const carPickerVal = ref([{ value: "02", text: "小型汽车" }]);
const showCarTypePicker = ref(false);
const carTypeColumns = [
{ value: "01", text: "大型汽车" },
{ value: "02", text: "小型汽车" },
{ value: "03", text: "使馆汽车" },
{ value: "04", text: "领馆汽车" },
{ value: "05", text: "境外汽车" },
{ value: "06", text: "外籍汽车" },
{ value: "07", text: "普通摩托车" },
{ value: "08", text: "轻便摩托车" },
{ value: "09", text: "使馆摩托车" },
{ value: "10", text: "领馆摩托车" },
{ value: "11", text: "境外摩托车" },
{ value: "12", text: "外籍摩托车" },
{ value: "13", text: "低速车" },
{ value: "14", text: "拖拉机" },
{ value: "15", text: "挂车" },
{ value: "16", text: "教练汽车" },
{ value: "17", text: "教练摩托车" },
{ value: "20", text: "临时入境汽车" },
{ value: "21", text: "临时入境摩托车" },
{ value: "22", text: "临时行驶车" },
{ value: "23", text: "警用汽车" },
{ value: "24", text: "警用摩托车" },
{ value: "51", text: "新能源大型车" },
{ value: "52", text: "新能源小型车" },
];
const formatterDate = (type, option) => {
if (type === "year") {
option.text += "年";
}
if (type === "month") {
option.text += "月";
}
if (type === "day") {
option.text += "日";
}
return option;
};
const onConfirmDate = ({ selectedValues, selectedOptions }) => {
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;
};
// 用于欺诈赌博查询的字段选择
const fraudGamblingCheckType = ref("mobile"); // 默认选择手机号
onMounted(() => {
isFinishPayment();
getProduct();
initAuthorization();
});
function isFinishPayment() {
const query = new URLSearchParams(window.location.search);
let orderNo = query.get("out_trade_no");
if (orderNo) {
router.push({ path: "/report", query: { orderNo } });
}
}
async function getProduct() {
const { data, error } = await useApiFetch(`/product/en/${feature.value}`)
.get()
.json();
if (data.value) {
featureData.value = data.value.data;
// 在获取产品数据后设置授权勾选状态
setAuthorizationCheckboxes();
}
}
// 设置授权勾选状态
function setAuthorizationCheckboxes() {
// 移除默认勾选逻辑,让用户必须手动勾选
// 仅保留函数作为以后可能需要的扩展点
}
function initAuthorization() {
if (NeedAuthorization.includes(feature.value)) {
authorization.value = false;
}
}
const isPhoneNumberValid = computed(() => {
return /^1[3-9]\d{9}$/.test(mobile.value);
});
const isIdCardValid = computed(() => /^\d{17}[\dX]$/i.test(idCard.value));
const isIdCardManValid = computed(() => /^\d{17}[\dX]$/i.test(idCardMan.value));
const isIdCardWomanValid = computed(() =>
/^\d{17}[\dX]$/i.test(idCardWoman.value)
);
const isCreditCodeValid = computed(() => /^.{18}$/.test(entCode.value));
const isCarLicense = computed(() => carLicense.value.trim().length > 6);
// 车架号校验逻辑
const isVinCodeValid = computed(() => {
// VIN码规则校验17位字母数字组合不包含I、O、Q
if (!vinCode.value || vinCode.value.length !== 17) {
return false;
}
// 不能包含I、O、Q字母
if (/[IOQ]/.test(vinCode.value)) {
return false;
}
// 只能包含数字和字母
if (!/^[A-HJ-NPR-Z0-9]+$/.test(vinCode.value)) {
return false;
}
return true;
});
// 图片压缩和转base64函数
const compressAndConvertToBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (event) => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
const MAX_SIZE = 1 * 1024 * 1024; // 1MB
// 如果文件小于1MB直接处理不压缩
if (file.size <= MAX_SIZE) {
// 去除base64前缀
const base64String = event.target.result.split(",")[1];
resolve(base64String);
return;
}
// 需要压缩
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// 计算压缩比例
let ratio = 1;
// 如果需要压缩先尝试0.8的压缩率
ratio = 0.8;
const width = img.width * ratio;
const height = img.height * ratio;
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
// 尝试压缩为JPEG格式效果更好
const compressedBase64 = canvas
.toDataURL("image/jpeg", 0.8)
.split(",")[1];
// 如果还是太大,继续压缩
if (compressedBase64.length * 0.75 > MAX_SIZE) {
// 递归尝试更大压缩率,这里简化处理,直接设置更高压缩率
const smallerRatio = ratio * 0.7;
canvas.width = img.width * smallerRatio;
canvas.height = img.height * smallerRatio;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
const moreCompressedBase64 = canvas
.toDataURL("image/jpeg", 0.7)
.split(",")[1];
resolve(moreCompressedBase64);
} else {
resolve(compressedBase64);
}
};
img.onerror = (err) => {
reject(err);
};
};
reader.onerror = (err) => {
reject(err);
};
});
};
// 处理行驶证照片上传
const handleCarDrivingPermitUpload = async (event) => {
const file = event.target.files[0];
if (!file) return;
// 检查是否是图片
if (!file.type.match("image.*")) {
showToast({ message: "请上传图片文件" });
return;
}
try {
carDrivingPermitFile.value = file;
const base64String = await compressAndConvertToBase64(file);
carDrivingPermit.value = base64String;
showToast({ message: "行驶证上传成功", type: "success" });
} catch (error) {
console.error("图片处理失败", error);
showToast({ message: "图片处理失败,请重试" });
}
};
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 整除,则银行卡号有效
});
// 判断是否包含特殊API ID需要单独勾选授权书
const needSeparateAuthorization = computed(() => {
const specialApiIds = [
// "G22SC01",
// "Q03SC01",
// "G37SC01",
// "G36SC01",
// "G05HZ01",
];
if (!featureData.value.features || !featureData.value.features.length) {
return false;
}
return featureData.value.features.some((feature) =>
specialApiIds.includes(feature.api_id)
);
});
// 修改验证函数来检查授权书的勾选状态
function handleSubmit() {
// 基本协议验证
if (!agreeToTerms.value) {
// 根据不同情况显示不同的提示信息
if (NeedAuthorization.includes(feature.value)) {
// 不需要授权书的产品
showToast({ message: `请阅读并同意用户协议和隐私政策` });
} else if (needSeparateAuthorization.value) {
// 已经有单独的授权书勾选,这里只提示用户协议和隐私政策
showToast({ message: `请阅读并同意用户协议和隐私政策` });
} else {
// 常规情况:需要授权书但不需要单独勾选
showToast({
message: `请阅读并同意用户协议、隐私政策和授权书同意书`,
});
}
return;
}
// 特殊API需要单独验证授权书勾选状态
if (needSeparateAuthorization.value && !agreeToAuthorization.value) {
showToast({ message: `请阅读并同意授权书同意书和他人授权承诺书` });
return;
}
// 欺诈赌博查询的特殊验证
if (
feature.value === "toc_FraudGamblingCheck" ||
feature.value === "toc_MobileDrugFraudRiskCheck"
) {
if (
fraudGamblingCheckType.value === "mobile" &&
!isPhoneNumberValid.value
) {
showToast({ message: "请输入有效的手机号" });
return;
} else if (
fraudGamblingCheckType.value === "idCard" &&
!isIdCardValid.value
) {
showToast({ message: "请输入有效的身份证号码" });
return;
} else if (
fraudGamblingCheckType.value === "bankCard" &&
!isBankCardValid.value
) {
showToast({ message: "请输入有效的银行卡号码" });
return;
}
} else {
// 常规验证逻辑
if (
!validateField("name", name.value, (v) => v, "请输入姓名") ||
!validateField(
"nameMan",
nameMan.value,
(v) => v,
"请输入男方姓名"
) ||
!validateField(
"nameWoman",
nameWoman.value,
(v) => v,
"请输入女方姓名"
) ||
!validateField(
"mobile",
mobile.value,
(v) => isPhoneNumberValid.value,
"请输入有效的手机号"
) ||
!validateField(
"idCard",
idCard.value,
(v) => isIdCardValid.value,
"请输入有效的身份证号码"
) ||
!validateField(
"idCardMan",
idCardMan.value,
(v) => isIdCardManValid.value,
"请输入有效的男方身份证号码"
) ||
!validateField(
"idCardWoman",
idCardWoman.value,
(v) => isIdCardWomanValid.value,
"请输入有效的女方身份证号码"
) ||
!validateField(
"bankCard",
bankCard.value,
(v) => isBankCardValid.value,
"请输入有效的银行卡号码"
) ||
!validateField(
"verificationCode",
verificationCode.value,
(v) => v,
"请输入验证码"
) ||
!validateField(
"carPickerVal",
carPickerVal.value,
(v) => v,
"请选择车辆类型"
) ||
!validateField(
"carLicense",
carLicense.value,
(v) => isCarLicense.value,
"请输入正确的车牌号"
) ||
!validateField(
"entName",
entName.value,
(v) => v,
"请输入企业名称"
) ||
!validateField(
"entCode",
entCode.value,
(v) => isCreditCodeValid.value,
"请输入统一社会信用代码"
) ||
!validateField("date", dateVal.value, (v) => v, "请选择日期") ||
!validateField(
"certificateNumber",
certificateNumber.value,
(v) => v,
"请输入证书编号"
) ||
!validateField(
"vinCode",
vinCode.value,
(v) => isVinCodeValid.value,
"请输入有效的车架号"
) ||
!validateField(
"CarDrivingPermit",
carDrivingPermit.value,
(v) => v,
"请上传行驶证照片"
)
) {
return;
}
}
submitRequest();
}
const validateField = (field, value, validationFn, errorMessage) => {
if (isHasInput(field) && !validationFn(value)) {
showToast({ message: errorMessage });
return false;
}
return true;
};
const defaultInput = ["name", "idCard", "mobile", "verificationCode"];
const specialProduct = {
toc_EnterpriseLawsuit: ["entName", "entCode", "mobile", "verificationCode"],
toc_PhoneThreeElements: ["name", "idCard", "mobile"],
toc_IDCardTwoElements: ["name", "idCard"],
toc_PhoneTwoElements: ["name", "mobile"],
toc_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"],
toc_ExitRestriction: ["name"],
toc_MonthlyMobileConsumptionLevel: ["mobile"],
toc_MobileNumberValidation: ["mobile"],
toc_BankCardLocation: ["bankCard"],
toc_BankCardNameElementVerification: ["name", "bankCard"],
toc_BankCardIDElementVerification: ["idCard", "bankCard"],
toc_BankCardThreeElementsVerification: ["name", "idCard", "bankCard"],
toc_MobileRiskAssessment: ["mobile"],
toc_MobileLocation: ["mobile"],
toc_IDCardLocation: ["idCard"],
toc_EducationVerification: ["name", "idCard", "certificateNumber"],
toc_FraudGamblingCheck: ["fraudGamblingCheckType"], // 添加欺诈赌博查询,只用这个特殊字段标记
toc_MobileDrugFraudRiskCheck: ["fraudGamblingCheckType"], // 药品欺诈风险查询,使用相同的单选框逻辑
toc_DebtRepayStress: ["name", "idCard", "mobile"],
toc_EducationInfo: ["name", "idCard"],
//车辆
toc_PersonVehicleVerification: ["name", "carType", "carLicense"], // 人车核验
toc_VehiclesUnderName: ["name", "idCard"], // 名下车辆
toc_vehicleInsuranceSummary: ["vinCode"], // 车辆出险查询
toc_vehicleMaintenanceRecord: ["vinCode", "CarDrivingPermit"], // 车辆维保查询
toc_vehicleValuation: ["vinCode", "carLicense"], // 车辆估价
toc_chassisNumberCheck: ["vinCode"], // 车辆车架号查车
toc_vehicleTransferCount: ["vinCode"], // 车辆过户次数
};
const NeedAuthorization = ["toc_Marriage"];
const isHasInput = (input) => {
if (specialProduct[feature.value]) {
// 欺诈赌博查询的特殊处理
if (
feature.value === "toc_FraudGamblingCheck" ||
feature.value === "toc_MobileDrugFraudRiskCheck"
) {
if (input === "fraudGamblingCheckType") {
return true; // 让单选框组显示
}
// 根据用户选择决定显示哪个输入框
if (input === fraudGamblingCheckType.value) {
return true;
}
return false;
}
return specialProduct[feature.value].includes(input);
} else {
return defaultInput.includes(input);
}
};
async function submitRequest() {
const req = {};
// 针对欺诈赌博查询和药品欺诈风险查询的特殊处理
if (
feature.value === "toc_FraudGamblingCheck" ||
feature.value === "toc_MobileDrugFraudRiskCheck"
) {
// 只添加用户选择的那个字段
if (fraudGamblingCheckType.value === "mobile") {
req.mobile = mobile.value;
} else if (fraudGamblingCheckType.value === "idCard") {
req.id_card = idCard.value;
} else if (fraudGamblingCheckType.value === "bankCard") {
req.bank_card = bankCard.value.replace(/\D/g, "");
}
} else {
// 原有的逻辑
if (isHasInput("name")) {
req.name = name.value;
}
if (isHasInput("idCard")) {
req.id_card = idCard.value;
}
if (isHasInput("nameMan")) {
req.name_man = nameMan.value;
}
if (isHasInput("idCardMan")) {
req.id_card_man = idCardMan.value;
}
if (isHasInput("nameWoman")) {
req.name_woman = nameWoman.value;
}
if (isHasInput("idCardWoman")) {
req.id_card_woman = idCardWoman.value;
}
if (isHasInput("bankCard")) {
req.bank_card = bankCard.value.replace(/\D/g, "");
}
if (isHasInput("mobile")) {
req.mobile = mobile.value;
}
if (isHasInput("verificationCode")) {
req.code = verificationCode.value;
}
if (isHasInput("carType")) {
req.car_type = carPickerVal.value[0].value;
}
if (isHasInput("carLicense")) {
req.car_license = carLicense.value.trim();
}
if (isHasInput("date")) {
req.start_date = startDate.value.map((item) => item).join("");
}
if (isHasInput("entName")) {
req.ent_name = entName.value;
}
if (isHasInput("entCode")) {
req.ent_code = entCode.value;
}
if (isHasInput("certificateNumber")) {
req.certificate_number = certificateNumber.value;
}
if (isHasInput("vinCode")) {
req.vin_code = vinCode.value;
}
if (isHasInput("CarDrivingPermit")) {
req.car_driving_permit = carDrivingPermit.value;
}
}
console.log("req", req);
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;
if (authorization.value) {
showPayment.value = true;
} else {
showAuthorizationPopup.value = true;
}
}
}
async function sendVerificationCode() {
if (isCountingDown.value || !isPhoneNumberValid.value) return;
if (!isPhoneNumberValid.value) {
showToast({ message: "请输入有效的手机号" });
return;
}
const { data, error } = await useApiFetch("/auth/sendSms")
.post({ mobile: mobile.value, actionType: "query" })
.json();
if (!error.value && data.value.code === 200) {
showToast({ message: "验证码发送成功", type: "success" });
startCountdown();
} else {
showToast({ message: "验证码发送失败,请重试" });
}
}
let timer = null;
function startCountdown() {
isCountingDown.value = true;
countdown.value = 60;
timer = setInterval(() => {
if (countdown.value > 0) {
countdown.value--;
} else {
clearInterval(timer);
isCountingDown.value = false;
}
}, 1000);
}
function toUserAgreement() {
router.push(`/userAgreement`);
}
function toPrivacyPolicy() {
router.push(`/privacyPolicy`);
}
function toAuthorization() {
router.push(`/authorization`);
}
function toOthersAuthorization() {
router.push(`/othersAuthorization`);
}
// 用户同意
const agreed = () => {
showAuthorizationPopup.value = false;
authorization.value = true;
showPayment.value = true;
};
// 用户取消
const cancel = () => {
showAuthorizationPopup.value = false;
};
const toExample = () => {
router.push(`/example?feature=${feature.value}`);
};
onUnmounted(() => {
if (timer) {
clearInterval(timer);
}
});
</script>
<template>
<div class="inquire-bg min-h-screen p-6">
<div class="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-6" v-if="isHasInput('fraudGamblingCheckType')">
<div class="mb-2 text-sm font-medium text-gray-700">
请选择查询对象
</div>
<div class="flex space-x-2">
<div @click="fraudGamblingCheckType = 'mobile'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors" :class="fraudGamblingCheckType === 'mobile'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
">
手机号
</div>
<div @click="fraudGamblingCheckType = 'idCard'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors" :class="fraudGamblingCheckType === 'idCard'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
">
身份证号
</div>
<div @click="fraudGamblingCheckType = 'bankCard'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors" :class="fraudGamblingCheckType === 'bankCard'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
">
银行卡号
</div>
</div>
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('name')">
<label for="name" class="form-label">姓名</label>
<input v-model="name" id="name" type="text" placeholder="请输入姓名" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('idCard')">
<label for="idCard" class="form-label">身份证号</label>
<input v-model="idCard" id="idCard" type="text" placeholder="请输入身份证号" class="form-input" />
</div>
<!-- 双人婚姻 -->
<div class="mb-4 flex items-center" v-if="isHasInput('nameMan')">
<label for="nameMan" class="form-label">男方姓名</label>
<input v-model="nameMan" id="nameMan" type="text" placeholder="请输入男方姓名" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('idCardMan')">
<label for="idCardMan" class="form-label">男方身份证号</label>
<input v-model="idCardMan" id="idCardMan" type="text" placeholder="请输入男方身份证号" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('nameWoman')">
<label for="nameWoman" class="form-label">女方姓名</label>
<input v-model="nameWoman" id="nameWoman" type="text" placeholder="请输入女方姓名" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('idCardWoman')">
<label for="idCardWoman" class="form-label">女方身份证号</label>
<input v-model="idCardWoman" id="idCardWoman" type="text" placeholder="请输入女方身份证号" class="form-input" />
</div>
<!-- 双人婚姻 -->
<div class="mb-4 flex items-center" v-if="isHasInput('entName')">
<label for="entName" class="form-label">企业名称</label>
<input v-model="entName" id="entName" type="text" placeholder="请输入企业名称" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('entCode')">
<label for="entCode" class="form-label">统一社会信用代码</label>
<input v-model="entCode" id="entCode" type="text" placeholder="请输入统一社会信用代码" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('carType')">
<label for="carType" class="form-label">汽车类型</label>
<van-field id="carType" v-model="carType" is-link readonly placeholder="点击选择汽车类型"
@click="showCarTypePicker = true" class="form-input" />
<van-popup v-model:show="showCarTypePicker" destroy-on-close round position="bottom">
<van-picker :model-value="carPickerVal" :columns="carTypeColumns"
@cancel="showCarTypePicker = false" @confirm="onConfirmCarType" />
</van-popup>
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('carLicense')">
<label for="carLicense" class="form-label !w-12">车牌号</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('certificateNumber')">
<label for="certificateNumber" class="form-label">证书编号</label>
<input v-model="certificateNumber" id="certificateNumber" type="text" placeholder="请输入证书编号"
class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('vinCode')">
<label for="vinCode" class="form-label">车架号</label>
<input v-model="vinCode" id="vinCode" type="text" placeholder="请输入17位车架号" class="form-input"
maxlength="17" />
</div>
<div class="mb-4" v-if="isHasInput('CarDrivingPermit')">
<div class="mb-2">
<label class="form-label block mb-2">行驶证照片</label>
<div class="relative w-full h-40 border-2 border-dashed border-gray-300 rounded-lg flex flex-col items-center justify-center bg-gray-50 cursor-pointer overflow-hidden"
@click="$refs.fileInput.click()">
<!-- 未上传时显示提示 -->
<template v-if="!carDrivingPermitFile">
<svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none"
viewBox="0 0 48 48">
<path
d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<p class="mt-2 text-sm text-gray-600">
点击或拖拽上传行驶证照片
</p>
<p class="mt-1 text-xs text-gray-500">
(支持JPGPNG格式)
</p>
</template>
<!-- 上传后显示图片预览 -->
<img v-else :src="`data:image/jpeg;base64,${carDrivingPermit}`"
class="absolute inset-0 w-full h-full object-contain" alt="行驶证照片" />
</div>
<input ref="fileInput" type="file" accept="image/*" @change="handleCarDrivingPermitUpload"
class="hidden" />
</div>
<div v-if="carDrivingPermitFile" class="mt-2 text-xs text-gray-500 flex justify-between">
<span>文件: {{ carDrivingPermitFile.name }}</span>
<span>{{
(carDrivingPermitFile.size / 1024).toFixed(2)
}}KB</span>
</div>
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('verificationCode')">
<label for="verificationCode" class="form-label">验证码</label>
<div class="flex-1 flex items-center">
<input v-model="verificationCode" id="verificationCode" type="text" placeholder="请输入验证码"
class="form-input flex-1" />
<button class="ml-2 px-4 py-2 text-sm text-blue-500 disabled:text-gray-400"
:disabled="isCountingDown || !isPhoneNumberValid" @click="sendVerificationCode">
{{
isCountingDown
? `${countdown}s重新获取`
: "获取验证码"
}}
</button>
</div>
</div>
<div class="mb-4 flex items-center">
<input type="checkbox" v-model="agreeToTerms" />
<span class="ml-2 text-xs text-gray-400">
我已阅读并同意
<span @click="toUserAgreement" class="text-blue-500">用户协议</span>
<span @click="toPrivacyPolicy" class="text-blue-500">隐私政策</span>
<template v-if="
!NeedAuthorization.includes(feature) &&
!needSeparateAuthorization
">
<span @click="toAuthorization" class="text-blue-500">《授权书同意书》</span>
</template>
</span>
</div>
<!-- 特殊API需要单独勾选授权书 -->
<div class="mb-4 flex items-center" v-if="needSeparateAuthorization">
<input type="checkbox" v-model="agreeToAuthorization" />
<span class="ml-2 text-xs text-gray-400">
我已阅读并同意
<span @click="toAuthorization" class="text-blue-500">《授权书同意书》</span>
<span @click="toOthersAuthorization" class="text-blue-500">《他人授权承诺书》</span>
</span>
</div>
<div class="flex items-center">
<button class="w-24 rounded-l-xl bg-blue-400 py-2 text-white" @click="toExample">
示例报告
</button>
<button class="flex-1 rounded-r-xl bg-blue-500 py-2 text-white" @click="handleSubmit">
立即查询
</button>
</div>
</div>
<div class="card mt-4">
<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 class="text-2xl text-red-600 font-semibold">
¥{{ featureData.sell_price }}
</div>
</div>
</div>
<div class="mb-4 text-gray-600 leading-relaxed" v-html="featureData.description"></div>
<div class="mb-2 text-xs text-red-500 italic">
为保证用户的隐私以及数据安全查询的结果生成15天之后将自动清除。
</div>
<template v-if="featureData.features && featureData.features.length > 1">
<div class="mb-4 text-lg text-gray-800 font-semibold">
报告包含内容
</div>
<div class="grid grid-cols-2 gap-4">
<div
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium bg-gradient-to-r from-blue-200 via-blue-200 to-blue-100">
分析指数
</div>
<div
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium bg-gradient-to-r from-sky-200 via-sky-200 to-sky-100">
基本信息
</div>
<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>
<!-- 底部弹出 -->
<van-popup v-model:show="showAuthorizationPopup" position="bottom" :style="{ height: '80%' }">
<Authorization :style="{ height: '100%' }" :name="name" :id-card="idCard" :mobile="mobile" @agreed="agreed"
@cancel="cancel" />
</van-popup>
<Payment v-model="showPayment" :data="featureData" :id="queryId" @close="showPayment = false" />
</template>
<style scoped>
.form-label {
@apply w-20 text-sm font-medium text-gray-700 flex-shrink-0;
}
.form-input::placeholder {
color: var(--van-text-color-3);
}
.form-input {
@apply w-full border-b border-gray-200 px-2 py-2 focus:outline-none;
}
.inquire-bg {
background: url("@/assets/images/bg_2.png") no-repeat;
background-position: center;
background-size: cover;
}
</style>

View File

@@ -295,11 +295,11 @@ const isBankCardValid = computed(() => {
// 判断是否包含特殊API ID需要单独勾选授权书
const needSeparateAuthorization = computed(() => {
const specialApiIds = [
"G22SC01",
"Q03SC01",
"G37SC01",
"G36SC01",
"G05HZ01",
// "G22SC01",
// "Q03SC01",
// "G37SC01",
// "G36SC01",
// "G05HZ01",
];
if (!featureData.value.features || !featureData.value.features.length) {
@@ -498,6 +498,8 @@ const specialProduct = {
toc_MobileDrugFraudRiskCheck: ["fraudGamblingCheckType"], // 药品欺诈风险查询,使用相同的单选框逻辑
toc_DebtRepayStress: ["name", "idCard", "mobile"],
toc_EducationInfo: ["name", "idCard"],
toc_EducationInfoName: ["name", "idCard"],
toc_NumberPortability: ["mobile"],
//车辆
toc_PersonVehicleVerification: ["name", "carType", "carLicense"], // 人车核验
@@ -696,37 +698,25 @@ onUnmounted(() => {
请选择查询对象
</div>
<div class="flex space-x-2">
<div
@click="fraudGamblingCheckType = 'mobile'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors"
:class="
fraudGamblingCheckType === 'mobile'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
"
>
<div @click="fraudGamblingCheckType = 'mobile'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors" :class="fraudGamblingCheckType === 'mobile'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
">
手机号
</div>
<div
@click="fraudGamblingCheckType = 'idCard'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors"
:class="
fraudGamblingCheckType === 'idCard'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
"
>
<div @click="fraudGamblingCheckType = 'idCard'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors" :class="fraudGamblingCheckType === 'idCard'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
">
身份证号
</div>
<div
@click="fraudGamblingCheckType = 'bankCard'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors"
:class="
fraudGamblingCheckType === 'bankCard'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
"
>
<div @click="fraudGamblingCheckType = 'bankCard'"
class="flex-1 rounded-md py-1 px-2 text-center text-sm cursor-pointer transition-colors" :class="fraudGamblingCheckType === 'bankCard'
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
">
银行卡号
</div>
</div>
@@ -734,222 +724,95 @@ onUnmounted(() => {
<div class="mb-4 flex items-center" v-if="isHasInput('name')">
<label for="name" class="form-label">姓名</label>
<input
v-model="name"
id="name"
type="text"
placeholder="请输入姓名"
class="form-input"
/>
<input v-model="name" id="name" type="text" placeholder="请输入姓名" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('idCard')">
<label for="idCard" class="form-label">身份证号</label>
<input
v-model="idCard"
id="idCard"
type="text"
placeholder="请输入身份证号"
class="form-input"
/>
<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"
/>
<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"
/>
<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"
/>
<input v-model="nameWoman" id="nameWoman" type="text" placeholder="请输入女方姓名" class="form-input" />
</div>
<div
class="mb-4 flex items-center"
v-if="isHasInput('idCardWoman')"
>
<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"
/>
<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"
/>
<input v-model="entName" id="entName" type="text" placeholder="请输入企业名称" class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('entCode')">
<label for="entCode" class="form-label">统一社会信用代码</label>
<input
v-model="entCode"
id="entCode"
type="text"
placeholder="请输入统一社会信用代码"
class="form-input"
/>
<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-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="carLicense" class="form-label !w-12">车牌号</label>
<CarNumberInput
class="form-input"
@number-input-result="carLicenseChange"
:default-str="carLicense"
>
<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"
/>
<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"
/>
<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-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('certificateNumber')"
>
<label for="certificateNumber" class="form-label"
>证书编号</label
>
<input
v-model="certificateNumber"
id="certificateNumber"
type="text"
placeholder="请输入证书编号"
class="form-input"
/>
<div class="mb-4 flex items-center" v-if="isHasInput('certificateNumber')">
<label for="certificateNumber" class="form-label">证书编号</label>
<input v-model="certificateNumber" id="certificateNumber" type="text" placeholder="请输入证书编号"
class="form-input" />
</div>
<div class="mb-4 flex items-center" v-if="isHasInput('vinCode')">
<label for="vinCode" class="form-label">车架号</label>
<input
v-model="vinCode"
id="vinCode"
type="text"
placeholder="请输入17位车架号"
class="form-input"
maxlength="17"
/>
<input v-model="vinCode" id="vinCode" type="text" placeholder="请输入17位车架号" class="form-input"
maxlength="17" />
</div>
<div class="mb-4" v-if="isHasInput('CarDrivingPermit')">
<div class="mb-2">
<label class="form-label block mb-2">行驶证照片</label>
<div
class="relative w-full h-40 border-2 border-dashed border-gray-300 rounded-lg flex flex-col items-center justify-center bg-gray-50 cursor-pointer overflow-hidden"
@click="$refs.fileInput.click()"
>
<div class="relative w-full h-40 border-2 border-dashed border-gray-300 rounded-lg flex flex-col items-center justify-center bg-gray-50 cursor-pointer overflow-hidden"
@click="$refs.fileInput.click()">
<!-- 未上传时显示提示 -->
<template v-if="!carDrivingPermitFile">
<svg
class="mx-auto h-12 w-12 text-gray-400"
stroke="currentColor"
fill="none"
viewBox="0 0 48 48"
>
<svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none"
viewBox="0 0 48 48">
<path
d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<p class="mt-2 text-sm text-gray-600">
点击或拖拽上传行驶证照片
@@ -960,52 +823,27 @@ onUnmounted(() => {
</template>
<!-- 上传后显示图片预览 -->
<img
v-else
:src="`data:image/jpeg;base64,${carDrivingPermit}`"
class="absolute inset-0 w-full h-full object-contain"
alt="行驶证照片"
/>
<img v-else :src="`data:image/jpeg;base64,${carDrivingPermit}`"
class="absolute inset-0 w-full h-full object-contain" alt="行驶证照片" />
</div>
<input
ref="fileInput"
type="file"
accept="image/*"
@change="handleCarDrivingPermitUpload"
class="hidden"
/>
<input ref="fileInput" type="file" accept="image/*" @change="handleCarDrivingPermitUpload"
class="hidden" />
</div>
<div
v-if="carDrivingPermitFile"
class="mt-2 text-xs text-gray-500 flex justify-between"
>
<div v-if="carDrivingPermitFile" class="mt-2 text-xs text-gray-500 flex justify-between">
<span>文件: {{ carDrivingPermitFile.name }}</span>
<span
>{{
(carDrivingPermitFile.size / 1024).toFixed(2)
}}KB</span
>
<span>{{
(carDrivingPermitFile.size / 1024).toFixed(2)
}}KB</span>
</div>
</div>
<div
class="mb-4 flex items-center"
v-if="isHasInput('verificationCode')"
>
<div class="mb-4 flex items-center" v-if="isHasInput('verificationCode')">
<label for="verificationCode" class="form-label">验证码</label>
<div class="flex-1 flex items-center">
<input
v-model="verificationCode"
id="verificationCode"
type="text"
placeholder="请输入验证码"
class="form-input flex-1"
/>
<button
class="ml-2 px-4 py-2 text-sm text-blue-500 disabled:text-gray-400"
:disabled="isCountingDown || !isPhoneNumberValid"
@click="sendVerificationCode"
>
<input v-model="verificationCode" id="verificationCode" type="text" placeholder="请输入验证码"
class="form-input flex-1" />
<button class="ml-2 px-4 py-2 text-sm text-blue-500 disabled:text-gray-400"
:disabled="isCountingDown || !isPhoneNumberValid" @click="sendVerificationCode">
{{
isCountingDown
? `${countdown}s重新获取`
@@ -1019,52 +857,31 @@ onUnmounted(() => {
<input type="checkbox" v-model="agreeToTerms" />
<span class="ml-2 text-xs text-gray-400">
我已阅读并同意
<span @click="toUserAgreement" class="text-blue-500"
>用户协议</span
>
<span @click="toPrivacyPolicy" class="text-blue-500"
>隐私政策</span
>
<template
v-if="
!NeedAuthorization.includes(feature) &&
!needSeparateAuthorization
"
>
<span @click="toAuthorization" class="text-blue-500"
>《授权书同意书》</span
>
<span @click="toUserAgreement" class="text-blue-500">用户协议</span>
<span @click="toPrivacyPolicy" class="text-blue-500">隐私政策</span>
<template v-if="
!NeedAuthorization.includes(feature) &&
!needSeparateAuthorization
">
<span @click="toAuthorization" class="text-blue-500">《授权书同意书》</span>
</template>
</span>
</div>
<!-- 特殊API需要单独勾选授权书 -->
<div
class="mb-4 flex items-center"
v-if="needSeparateAuthorization"
>
<div class="mb-4 flex items-center" v-if="needSeparateAuthorization">
<input type="checkbox" v-model="agreeToAuthorization" />
<span class="ml-2 text-xs text-gray-400">
我已阅读并同意
<span @click="toAuthorization" class="text-blue-500"
>《授权书同意书》</span
>
<span @click="toOthersAuthorization" class="text-blue-500"
>《他人授权承诺书》</span
>
<span @click="toAuthorization" class="text-blue-500">《授权书同意书》</span>
<span @click="toOthersAuthorization" class="text-blue-500">《他人授权承诺书》</span>
</span>
</div>
<div class="flex items-center">
<button
class="w-24 rounded-l-xl bg-blue-400 py-2 text-white"
@click="toExample"
>
<button class="w-24 rounded-l-xl bg-blue-400 py-2 text-white" @click="toExample">
示例报告
</button>
<button
class="flex-1 rounded-r-xl bg-blue-500 py-2 text-white"
@click="handleSubmit"
>
<button class="flex-1 rounded-r-xl bg-blue-500 py-2 text-white" @click="handleSubmit">
立即查询
</button>
</div>
@@ -1081,40 +898,29 @@ onUnmounted(() => {
</div>
</div>
</div>
<div
class="mb-4 text-gray-600 leading-relaxed"
v-html="featureData.description"
></div>
<div class="mb-4 text-gray-600 leading-relaxed" v-html="featureData.description"></div>
<div class="mb-2 text-xs text-red-500 italic">
为保证用户的隐私以及数据安全查询的结果生成15天之后将自动清除。
</div>
<template
v-if="featureData.features && featureData.features.length > 1"
>
<template v-if="featureData.features && featureData.features.length > 1">
<div class="mb-4 text-lg text-gray-800 font-semibold">
报告包含内容
</div>
<div class="grid grid-cols-2 gap-4">
<div
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium bg-gradient-to-r from-blue-200 via-blue-200 to-blue-100"
>
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium bg-gradient-to-r from-blue-200 via-blue-200 to-blue-100">
分析指数
</div>
<div
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium bg-gradient-to-r from-sky-200 via-sky-200 to-sky-100"
>
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium bg-gradient-to-r from-sky-200 via-sky-200 to-sky-100">
基本信息
</div>
<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="[
<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>
@@ -1122,26 +928,11 @@ onUnmounted(() => {
</div>
</div>
<!-- 底部弹出 -->
<van-popup
v-model:show="showAuthorizationPopup"
position="bottom"
:style="{ height: '80%' }"
>
<Authorization
:style="{ height: '100%' }"
:name="name"
:id-card="idCard"
:mobile="mobile"
@agreed="agreed"
@cancel="cancel"
/>
<van-popup v-model:show="showAuthorizationPopup" position="bottom" :style="{ height: '80%' }">
<Authorization :style="{ height: '100%' }" :name="name" :id-card="idCard" :mobile="mobile" @agreed="agreed"
@cancel="cancel" />
</van-popup>
<Payment
v-model="showPayment"
:data="featureData"
:id="queryId"
@close="showPayment = false"
/>
<Payment v-model="showPayment" :data="featureData" :id="queryId" @close="showPayment = false" />
</template>
<style scoped>

View File

@@ -16,14 +16,14 @@
</div>
<div class="leading-relaxed">
我们深知个人信息对您的重要性我们将按法律法规要求采取相应安全保护措施尽力保护您的个人信息安全可控
有鉴于此广西福铭网络科技有限公司以下简称我们天远查作为天远查产品及服务的提供者制定本隐私政策下称本政策并提醒您
有鉴于此广西福铭网络科技有限公司以下简称"我们""天远查"作为天远查产品及服务的提供者制定本隐私政策下称"本政策"并提醒您
</div>
<div class="leading-relaxed">
本政策适用于全部天远查产品及服务如我们关联公司的产品或服务中使用了天远查提供的产品或服务但未设独立的隐私政策的
该部分天远查提供的产品或服务同样适用于本政策
</div>
<div class="leading-relaxed">
需要特别说明的是本政策不适用于其他第三方通过网页或天远查客户端直接向您提供的服务统称第三方服务
需要特别说明的是本政策不适用于其他第三方通过网页或天远查客户端直接向您提供的服务统称"第三方服务"
您向该第三方服务提供者提供的信息不适用于本政策您在选择使用第三方服务前应充分了解第三方服务的产品功能及隐私保护政策再选择是否开通功能
</div>
<div class="leading-relaxed">
@@ -32,6 +32,49 @@
</div>
</div>
<div class="mb-4">
<!-- 个人信息处理说明 -->
<div class="mb-2 font-bold leading-relaxed">
个人信息处理说明
</div>
<div class="leading-relaxed">
为了更好地为您提供服务我们需要收集和处理您的个人信息请您仔细阅读以下个人信息处理说明
</div>
<div class="leading-relaxed">
<div class="font-semibold">处理目的</div>
<div>我们收集和处理您的个人信息主要用于以下目的</div>
<div>1. 进行报告的查询生成和提供</div>
<div>2. 保留一定时间供您查看和下载报告内容</div>
<div>3. 提供账户管理和客户服务</div>
<div>4. 改进和优化我们的服务体验</div>
<div>5. 保障账户安全和系统安全</div>
</div>
<div class="leading-relaxed">
<div class="font-semibold">处理方式</div>
<div>我们采用以下方式处理您的个人信息</div>
<div>1. 加密存储所有个人信息均采用AES加密技术进行存储确保数据安全</div>
<div>2. 脱敏处理在生成报告和展示时对敏感信息进行脱敏处理</div>
<div>3. 访问控制严格限制对个人信息的访问权限仅授权人员可访问</div>
<div>4. 安全传输在数据传输过程中采用SSL/TLS加密技术</div>
</div>
<div class="leading-relaxed">
<div class="font-semibold">处理的个人信息种类</div>
<div>我们收集和处理的个人信息包括</div>
<div>1. 用户查询时输入的信息姓名身份证号手机号银行卡号等</div>
<div>2. 登录注册时的手机号码</div>
<div>3. 生成报告的相关信息查询记录报告内容查询时间等</div>
<div>4. 系统操作日志登录记录操作行为设备信息等</div>
</div>
<div class="leading-relaxed">
<div class="font-semibold">保存期限</div>
<div>我们按照以下期限保存您的个人信息</div>
<div>1. 查询报告的信息以及报告内容保留15天到期后自动删除</div>
<div>2. 账户信息在您注销账户时立即删除</div>
<div>3. 用户操作日志记录按照法律要求保留半年以上</div>
<div>4. 其他个人信息在服务目的达成后或法律规定的期限内删除</div>
</div>
</div>
<div class="mb-2 font-bold leading-relaxed">第一部分 定义</div>
<div class="mb-4">
<!-- 第一部分 -->
@@ -242,7 +285,7 @@
2与公共安全公共卫生重大公共利益有关的
</div>
<div>
3与犯罪侦查起诉审判和判决执行等有关的
3与犯罪侦查起诉和审判等有关的
</div>
<div>
4出于维护您或其他个人的生命财产等重大合法权益但又很难得到本人同意的

View File

@@ -1,6 +1,4 @@
<script setup>
import CG11BJ06 from "@/ui/CG11BJ06.vue";
import CG29BJ05 from "@/ui/CG29BJ05.vue";
const featureMap = {
G09SC02: {
name: "婚姻状态",
@@ -17,7 +15,7 @@ const featureMap = {
remark: '查询结果为"未婚或尚未登记结婚"时,表示婚姻登记处暂无相关的登记记录。婚姻状态信息由婚姻登记处逐级上报,可能存在数据遗漏或更新滞后。当前可查询的婚姻状态包括:未婚或尚未登记结婚、已婚、离异。如您对查询结果有疑问,请联系客服反馈。',
},
G27BJ05: {
name: "借贷申请记录",
name: "本人需求推测",
component: defineAsyncComponent(() =>
import("@/ui/CBankLoanApplication.vue")
),
@@ -45,7 +43,7 @@ const featureMap = {
component: defineAsyncComponent(() => import("@/ui/CLawsuitPP.vue")),
},
G05HZ01: {
name: "股东人企关系",
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CRelatedEnterprises.vue")
),
@@ -120,6 +118,10 @@ const featureMap = {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CCAR061.vue")),
},
QCXG9P1C: {
name: "名下车辆",
component: defineAsyncComponent(() => import("@/ui/CQCXG9P1C.vue")),
},
COM187: {
name: "限制出境查询",
component: defineAsyncComponent(() => import("@/ui/CCOM187.vue")),
@@ -181,7 +183,7 @@ const featureMap = {
),
},
PersonEnterprisePro: {
name: "人企关系加强版",
name: "名下企业关联",
component: defineAsyncComponent(() =>
import("@/ui/CPersonEnterprisePro/index.vue")
),
@@ -195,6 +197,27 @@ const featureMap = {
component: defineAsyncComponent(() => import("@/ui/CG11BJ06.vue")),
remark: "暂无学历信息记录可能是因为学历信息不公开、暂无高等教育学历(大专及以上学历)或学历较早未被数字化收录。",
},
FLXGDEA9: {
name: "本人不良",
component: defineAsyncComponent(() => import("@/ui/CFLXGDEA9.vue")),
},
IVYZ6G7H: {
name: "婚姻状态(补证版)",
component: defineAsyncComponent(() => import("@/ui/CIVYZ6G7H.vue")),
},
IVYZ3A7F: {
name: "学历信息查询(含学校名称)",
component: defineAsyncComponent(() => import("@/ui/CIVYZ3A7F.vue")),
},
YYSY7D3E: {
name: "携号转网查询",
component: defineAsyncComponent(() => import("@/ui/CYYSY7D3E.vue")),
},
IVYZ3P9M: {
name: "学历信息",
component: defineAsyncComponent(() => import("@/ui/IVYZ3P9M.vue")),
remark: '学历信息展示学生姓名、身份证号、学校、专业、入学与毕业时间、学历层次以及学习形式等字段,可结合字典编码了解具体含义。',
},
};
import LEmpty from "@/components/LEmpty.vue";
@@ -215,6 +238,8 @@ const orderNo = ref("");
const isEmpty = ref(false);
const isPending = ref(false);
const reportScore = ref(0);
const queryState = ref("");
const pollingInterval = ref(null);
onMounted(() => {
const query = new URLSearchParams(window.location.search);
@@ -225,10 +250,15 @@ onMounted(() => {
orderNo.value = route.query.orderNo;
}
if (!orderId.value && !orderNo.value) return;
getReport();
});
onBeforeUnmount(() => {
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
}
});
const getReport = async () => {
let queryUrl = "";
if (orderNo.value) {
@@ -242,20 +272,57 @@ const getReport = async () => {
if (data.value && !error.value) {
if (data.value.code === 200) {
reportData.value = data.value.data.query_data.sort((a, b) => {
return a.feature.sort - b.feature.sort;
});
productId.value = data.value.data.product_id;
reportParams.value = data.value.data.query_params;
reportName.value = data.value.data.product_name;
reportDateTime.value = data.value.data.create_time;
reportScore.value = calculateScore(reportData.value);
queryState.value = data.value.data.query_state;
if (queryState.value === "paid" || queryState.value === "success") {
reportData.value = data.value.data.query_data.sort((a, b) => {
return a.feature.sort - b.feature.sort;
});
productId.value = data.value.data.product_id;
reportParams.value = data.value.data.query_params;
reportName.value = data.value.data.product_name;
reportDateTime.value = data.value.data.create_time;
reportScore.value = calculateScore(reportData.value);
isDone.value = true;
console.log("reportData", reportData.value);
// 如果成功,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
} else if (queryState.value === "pending") {
// 如果是pending状态且没有轮询启动轮询
if (!pollingInterval.value) {
pollingInterval.value = setInterval(() => {
getReport();
}, 1000); // 每1秒轮询一次
}
} else if (queryState.value === "failed") {
isEmpty.value = true;
isDone.value = true;
// 如果失败,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
} else if (queryState.value === "refunded") {
isEmpty.value = true;
isDone.value = true;
// 如果已退款,清除轮询
if (pollingInterval.value) {
clearInterval(pollingInterval.value);
pollingInterval.value = null;
}
}
} else if (data.value.code === 200003) {
isEmpty.value = true;
isDone.value = true;
} else if (data.value.code === 200002) {
isPending.value = true;
isDone.value = true;
}
isDone.value = true;
}
};
// 对请求参数进行脱敏处理
@@ -364,14 +431,14 @@ const calculateScore = (reportData) => {
FIN019: 100, // 银行卡黑名单
// 高风险指标(中优先级)
G27BJ05: 40, // 借贷申请记录
G27BJ05: 40, // 本人需求推测
G28BJ05: 40, // 借贷行为记录
G03HZ01: 70, // 手机号码风险
// 中风险指标(低优先级)
G19BJ02: 50, // 手机二次卡
G02BJ02: 50, // 手机在网时长
G05HZ01: 50, // 人企关系
G05HZ01: 50, // 名下企业关联
// 验证指标(最低优先级)
G15BJ02: 25, // 手机三要素
@@ -418,7 +485,7 @@ const calculateScore = (reportData) => {
// 不计入风险
break;
case "G27BJ05": // 借贷申请记录
case "G27BJ05": // 本人需求推测
if (data) {
// 检查是否有申请记录(有则表示风险)
let hasRisk = false;
@@ -629,16 +696,18 @@ const calculateScore = (reportData) => {
</script>
<template>
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<div v-if="queryState === 'pending'" class="loading-container">
<div class="loading-spinner"></div>
<p>报告生成中请稍候...</p>
</div>
<div v-else-if="queryState === 'failed' || queryState === 'refunded'" class="p-4">
<LEmpty />
</div>
<div v-else-if="queryState === 'paid' || queryState === 'success'"
class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<template v-if="isDone">
<!-- 当reportData.length > 1时使用van-tabs -->
<van-tabs
v-if="reportData.length > 1"
v-model:active="active"
scrollspy
sticky
:offset-top="46"
>
<van-tabs v-if="reportData.length > 1" v-model:active="active" scrollspy sticky :offset-top="46">
<div class="flex flex-col gap-y-4 p-4">
<LEmpty v-if="isEmpty" />
<LPendding v-if="isPending" />
@@ -655,54 +724,29 @@ const calculateScore = (reportData) => {
<div id="overdiv" class="title mb-4">基本信息</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<LTitle
title="报告信息"
type="blue-green"
></LTitle>
<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
>
<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
>
<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
>
{{ reportName }}</span>
</div>
</div>
<template
v-if="
Object.keys(reportParams).length !=
0
"
>
<LTitle
title="报告对象"
type="blue-green"
></LTitle>
<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
>
<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",
@@ -710,31 +754,20 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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
>
}}</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
>
<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",
@@ -742,14 +775,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -757,14 +785,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -772,14 +795,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -787,14 +805,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -802,14 +815,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -817,16 +825,10 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -834,14 +836,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -849,14 +846,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -864,14 +856,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -880,23 +867,16 @@ const calculateScore = (reportData) => {
}}</span>
</div>
<div class="flex flex-col gap-4">
<div
class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1"
>
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4"
>
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
<div
class="font-bold text-lg"
>
<div class="font-bold text-lg">
身份证检查结果
</div>
<div
class="text-sm text-gray-600"
>
<div class="text-sm text-gray-600">
身份证信息核验通过
</div>
</div>
@@ -906,32 +886,20 @@ const calculateScore = (reportData) => {
</template>
</div>
</div>
<LRemark
content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况"
/>
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
</van-tab>
<van-tab
v-for="(item, index) in reportData"
:key="index"
:title="featureMap[item.data.apiID]?.name"
>
<van-tab v-for="(item, index) in reportData" :key="index"
:title="featureMap[item.data.apiID]?.name">
<div id="lawsuit" class="title mb-4">
{{ featureMap[item.data.apiID]?.name }}
</div>
<component
:is="featureMap[item.data.apiID]?.component"
:data="item.data.data"
:params="reportParams"
:isMerriageProduct="
item.data.apiID === 'G09SC02' ||
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
:params="reportParams" :isMerriageProduct="item.data.apiID === 'G09SC02' ||
item.data.apiID === 'IDV044'
"
>
">
</component>
<LRemark
v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark"
/>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</van-tab>
</template>
</div>
@@ -946,43 +914,23 @@ const calculateScore = (reportData) => {
<div class="flex flex-col gap-y-2">
<LTitle title="报告信息" type="blue-green"></LTitle>
<div class="flex flex-col gap-2 my-2">
<div
class="flex justify-between border-b pb-2 pl-2"
>
<span class="text-gray-700 font-bold"
>报告时间:</span
>
<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
>
<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
>
{{ reportName }}</span>
</div>
</div>
<template
v-if="Object.keys(reportParams).length != 0"
>
<LTitle
title="报告对象"
type="blue-green"
></LTitle>
<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
>
<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",
@@ -990,29 +938,18 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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
>
}}</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
>
<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",
@@ -1020,13 +957,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1034,13 +966,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1048,13 +975,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1062,13 +985,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1076,13 +994,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1090,13 +1003,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1104,13 +1013,9 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1118,13 +1023,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1132,13 +1032,8 @@ const calculateScore = (reportData) => {
)
}}</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
>
<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",
@@ -1147,21 +1042,16 @@ const calculateScore = (reportData) => {
}}</span>
</div>
<div class="flex flex-col gap-4">
<div
class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1"
>
<div class="flex items-center bg-blue-100 rounded-xl px-4 py-2 flex-1">
<div
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4"
>
class="bg-green-500 w-12 h-12 text-white text-xl flex items-center justify-center rounded-full mr-4">
</div>
<div>
<div class="font-bold text-lg">
身份证检查结果
</div>
<div
class="text-sm text-gray-600"
>
<div class="text-sm text-gray-600">
身份证信息核验通过
</div>
</div>
@@ -1171,28 +1061,20 @@ const calculateScore = (reportData) => {
</template>
</div>
</div>
<LRemark
content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况"
/>
<LRemark content="如查询的姓名/身份证与运营商提供的不一致,可能会存在报告内容不匹配的情况" />
<!-- 显示报告数据 -->
<template v-for="(item, index) in reportData" :key="index">
<div id="lawsuit" class="title">
{{ featureMap[item.data.apiID]?.name }}
</div>
<component
:is="featureMap[item.data.apiID]?.component"
:data="item.data.data"
:params="reportParams"
:isMerriageProduct="
item.data.apiID === 'G09SC02' ||
<component :is="featureMap[item.data.apiID]?.component" :data="item.data.data"
:params="reportParams" :isMerriageProduct="item.data.apiID === 'G09SC02' ||
item.data.apiID === 'IDV044'
"
>
">
</component>
<LRemark
v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark"
/>
<LRemark v-if="featureMap[item.data.apiID]?.remark"
:content="featureMap[item.data.apiID]?.remark" />
</template>
</template>
</div>
@@ -1207,9 +1089,7 @@ const calculateScore = (reportData) => {
&nbsp;本报告的数据由用户本人明确授权后,我们才向相关合法存有用户个人数据的机构调取本报告相关内容,本平台只做大数据的获取与分析,仅向用户个人展示参考。
</div>
<p>
&nbsp; &nbsp; 报告有效期<strong class="text-red-500"
>15天</strong
>,过期自动删除。
&nbsp; &nbsp; 报告有效期<strong class="text-red-500">15天</strong>,过期自动删除。
</p>
<p>
&nbsp; &nbsp;
@@ -1226,6 +1106,10 @@ const calculateScore = (reportData) => {
</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>桂公网安备45010002451084号</text>
</div>
<div>
<a class="text-blue-500" href="https://beian.miit.gov.cn">
桂ICP备2024038462号
@@ -1255,4 +1139,37 @@ const calculateScore = (reportData) => {
padding-bottom: 60px;
background: #ffffff;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
.loading-spinner {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
p {
color: #666;
font-size: 16px;
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@@ -27,7 +27,7 @@
<div class="leading-relaxed">
<div>A.您已注册成为本服务的会员</div>
<div>
B.您已在服务页面对应框中填写被查询主体的姓名身份证号手机号银行卡号和被查询主体的手机号收到的动态验证码以下称被查询主体信息
B.您已在服务页面对应框中填写被查询主体的姓名身份证号手机号银行卡号和被查询主体的手机号收到的动态验证码以下称"被查询主体信息"
</div>
<div>
C.您确保被查询主体信息是您本人的信息或者被查询主体已授权您本人使用被查询主体信息进行查询授权内容应包括本条D项所述内容并且被查询主体已知悉该授权的风险
@@ -44,6 +44,47 @@
</div>
</div>
</div>
<div class="mb-4">
<div class="mb-2 font-bold leading-relaxed">个人信息处理说明</div>
<div class="leading-relaxed">
为了更好地为您提供服务我们需要收集和处理您的个人信息请您仔细阅读以下个人信息处理说明
</div>
<div class="leading-relaxed">
<div class="font-semibold">处理目的</div>
<div>我们收集和处理您的个人信息主要用于以下目的</div>
<div>1. 进行报告的查询生成和提供</div>
<div>2. 保留一定时间供您查看和下载报告内容</div>
<div>3. 提供账户管理和客户服务</div>
<div>4. 改进和优化我们的服务体验</div>
<div>5. 保障账户安全和系统安全</div>
</div>
<div class="leading-relaxed">
<div class="font-semibold">处理方式</div>
<div>我们采用以下方式处理您的个人信息</div>
<div>1. 加密存储所有个人信息均采用AES加密技术进行存储确保数据安全</div>
<div>2. 脱敏处理在生成报告和展示时对敏感信息进行脱敏处理</div>
<div>3. 访问控制严格限制对个人信息的访问权限仅授权人员可访问</div>
<div>4. 安全传输在数据传输过程中采用SSL/TLS加密技术</div>
</div>
<div class="leading-relaxed">
<div class="font-semibold">处理的个人信息种类</div>
<div>我们收集和处理的个人信息包括</div>
<div>1. 用户查询时输入的信息姓名身份证号手机号银行卡号等</div>
<div>2. 登录注册时的手机号码</div>
<div>3. 生成报告的相关信息查询记录报告内容查询时间等</div>
<div>4. 系统操作日志登录记录操作行为设备信息等</div>
</div>
<div class="leading-relaxed">
<div class="font-semibold">保存期限</div>
<div>我们按照以下期限保存您的个人信息</div>
<div>1. 查询报告的信息以及报告内容保留15天到期后自动删除</div>
<div>2. 账户信息在您注销账户时立即删除</div>
<div>3. 用户操作日志记录按照法律要求保留半年以上</div>
<div>4. 其他个人信息在服务目的达成后或法律规定的期限内删除</div>
</div>
</div>
<div class="mb-4">
<div class="mb-2 font-bold leading-relaxed">
服务中断或故障

View File

@@ -1,4 +1,47 @@
<script setup>
import { useHead } from '@vueuse/head'
// SEO优化的头部信息
useHead({
title: '天远查 - 专业司法涉诉查询平台 | 婚恋评估、判决书查询、婚姻状态查询',
meta: [
{
name: 'description',
content: '天远查是专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询、被执行人查询、失信人查询等服务。依托大数据技术,精准查询司法风险,多维防控财产、信用、身份风险。'
},
{
name: 'keywords',
content: '天远查,司法涉诉查询,婚恋评估,判决书查询,婚姻状态查询,被执行人查询,失信人查询,限高查询,个人涉诉查询,企业涉诉查询,车辆核验,身份核验,手机核验,银行卡核验,学历核验,风险报告,法律风险,信用风险,在线查询平台'
},
{
property: 'og:title',
content: '天远查 - 专业司法涉诉查询平台 | 婚恋评估、判决书查询、婚姻状态查询'
},
{
property: 'og:description',
content: '天远查是专业的司法涉诉查询平台,提供婚恋评估、判决书查询、婚姻状态查询、被执行人查询、失信人查询等服务。'
},
{
property: 'og:type',
content: 'website'
},
{
property: 'og:url',
content: 'https://www.tianyuancha.cn'
},
{
property: 'og:image',
content: 'https://www.tianyuancha.cn/og-image.jpg'
}
],
link: [
{
rel: 'canonical',
href: 'https://www.tianyuancha.cn'
}
]
})
const router = useRouter();
function toInquire(name) {
@@ -15,7 +58,9 @@ function toInquire(name) {
function toHistory() {
router.push(`/historyQuery`);
}
const toBigData = () => {
window.location.href = "https://www.tianyuandata.com/";
};
function toPromote() {
window.location.href =
"https://www.tianyuandb.com?_um_campaign=67c15d4f8f232a05f1221b82&_um_channel=67c15d4f8f232a05f1221b83"; // 跳转到客服页面
@@ -24,26 +69,16 @@ function toPromote() {
<template>
<div class="relative p-4">
<img
class="h-full w-full overflow-hidden rounded-xl"
src="@/assets/images/banner.png"
/>
<img class="h-full w-full overflow-hidden rounded-xl" src="@/assets/images/banner.png" alt="天远查平台横幅" />
</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('Lawsuit')"
>
<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"
>
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_2.png" alt="司法涉诉图标" />
<div class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
司法涉诉
</div>
</div>
@@ -53,21 +88,14 @@ function toPromote() {
</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="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 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"
/>
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_1.png" alt="婚恋风险图标" />
</div>
<div class="max-w-max text-left text-xs text-gray-600">
全面评估婚恋对象潜在风险包含个人不良司法涉诉婚姻状态借贷行为等多维数据分析帮您识别隐藏风险守护情感安全
@@ -75,19 +103,12 @@ function toPromote() {
</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('Risk')"
>
<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"
>
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_3.png" alt="风险报告图标" />
<div class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
风险报告
</div>
</div>
@@ -96,40 +117,27 @@ function toPromote() {
</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="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 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"
/>
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_4.png" alt="核验工具图标" />
</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('Car')"
>
<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('Car')">
<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_index_chacheliang.svg"
/>
<div
class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold"
>
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_index_chacheliang.svg"
alt="查车辆图标" />
<div class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
查车辆
</div>
</div>
@@ -138,21 +146,15 @@ function toPromote() {
</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('Api')"
>
<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('Api')">
<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 class="mt-1 max-w-max flex-shrink-0 text-left text-lg text-gray-600 font-bold">
API商店
</div>
<img
class="h-12 w-12 flex-shrink-0"
src="@/assets/images/icon_index_apistore.svg"
/>
<img class="h-12 w-12 flex-shrink-0" src="@/assets/images/icon_index_apistore.svg"
alt="API商店图标" />
</div>
<div class="max-w-max text-left text-xs text-gray-600">
提供婚姻司法核验等高效便捷的API服务帮助企业快速获取数据提升业务效率
@@ -161,26 +163,16 @@ function toPromote() {
</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="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" alt="历史记录图标" mode="widthFix" />
<div class="">
<div class="font-bold">我的历史查询记录</div>
<div class="text-xs">查询记录有效期为15天</div>
</div>
</div>
<div class="shadow-3xl mt-8 w-full" @click="toPromote">
<img
class="shadow-3xl w-full overflow-hidden rounded-xl"
src="@/assets/images/liu.png"
mode="widthFix"
/>
<div class="mt-4 rounded-xl overflow-hidden bg-white shadow-xl" @click="toBigData">
<img src="@/assets/images/index_a_banner.png" class="w-full h-full" alt="大数据服务横幅" mode="widthFix" />
</div>
</div>
</template>

View File

@@ -1,31 +1,16 @@
<template>
<div class="bg-gradient-to-b from-[#aeceff] to-white min-h-screen relative">
<!-- banner -->
<div
class="w-full flex justify-center"
style="clip-path: ellipse(100% 95% at 50% 0%)"
>
<img
src="@/assets/images/sfss_banner.png"
alt="司法涉诉"
class="w-full h-auto"
/>
<div class="w-full flex justify-center" style="clip-path: ellipse(100% 95% at 50% 0%)">
<img src="@/assets/images/sfss_banner.png" alt="司法涉诉" class="w-full h-auto" />
</div>
<div class="p-6 -my-24 z-1000 absolute">
<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"
@click="toInquire(item.product)"
>
<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"
/>
<img :src="item.icon" :alt="item.title" class="w-10 h-10" />
</div>
<p class="mt-2 text-sm text-center font-semibold">
{{ item.title }}
@@ -50,23 +35,22 @@
查看企业是否涉及诉讼失信限高案件了解企业的法律风险及潜在的经营问题帮助您评估与该企业合作的安全性
</li>
<li>
<strong>个人失信</strong
>个人限高功能帮助您查询个人是否被法院采取限制高消费措施了解其是否因未履行法院判决而受到出行消费等方面的限制通过该功能您可以评估该个人的履约能力和信用状况帮助您在商业合作雇佣关系或其他交易场景中规避潜在风险做出更加明智的决策
<strong>个人失信</strong>个人限高功能帮助您查询个人是否被法院采取限制高消费措施了解其是否因未履行法院判决而受到出行消费等方面的限制通过该功能您可以评估该个人的履约能力和信用状况帮助您在商业合作雇佣关系或其他交易场景中规避潜在风险做出更加明智的决策
</li>
<li>
<strong>个人限高</strong>
个人失信功能帮助您查看个人是否被列入失信被执行人名单了解其是否存在严重违约拒不履行生效法律文书确定义务的情况通过该功能您可以全面评估该个人的信用状况和诚信水平帮助您在融资合作或其他重要决策场景中识别潜在风险保护自身权益避免不必要的损失
</li>
<li>
<strong>股东人企关系</strong>
股东人企关系功能帮助您查看个人为哪些企业的股东了解其与该企业的关系以及企业所涉诉讼失信限高案件情况帮助您评估与该企业的合作风险
<!-- <li>
<strong>名下企业关联</strong>
名下企业关联功能帮助您查看个人为哪些企业的股东了解其与该企业的关系以及企业所涉诉讼失信限高案件情况帮助您评估与该企业的合作风险
</li>
<li>
<strong>人企关系加强版</strong>
<strong>名下企业关联</strong>
<p>
人企关系加强版功能通过查询个人关联的企业帮助您了解该个人可能涉及的风险特别是与高风险企业有联系的个人查询结果包括投资企业详情高管任职记录以及企业涉诉情况全面展示个人商业网络该功能帮助您评估个人的风险水平确保在合作过程中识别潜在的法律财务或信誉风险
名下企业关联功能通过查询个人关联的企业帮助您了解该个人可能涉及的风险特别是与高风险企业有联系的个人查询结果包括投资企业详情高管任职记录以及企业涉诉情况全面展示个人商业网络该功能帮助您评估个人的风险水平确保在合作过程中识别潜在的法律财务或信誉风险
</p>
</li>
</li> -->
</ul>
</div>
</div>
@@ -90,16 +74,16 @@ const menuItems = [
icon: xgIcon,
product: "toc_PersonalConsumptionRestriction",
},
{
title: "股东人企关系",
icon: gdrqgxIcon,
product: "toc_ShareholderBusinessRelation",
},
{
title: "人企关系加强版",
icon: rqgxProIcon,
product: "toc_PersonEnterprisePro",
},
// {
// title: "名下企业关联",
// icon: gdrqgxIcon,
// product: "toc_ShareholderBusinessRelation",
// },
// {
// title: "名下企业关联",
// icon: rqgxProIcon,
// product: "toc_PersonEnterprisePro",
// },
];
const toInquire = (product) => {

View File

@@ -14,10 +14,10 @@ export default defineConfig({
port: 5678, // 自定义端口号,可选
strictPort: true, // 如果端口被占用则抛出错误而不是使用下一个可用端口
proxy: {
// '/api/v1': {
// target: 'https://www.tianyuancha.cn', // 本地接口地址
// changeOrigin: true,
// },
"/api/v1": {
target: "https://www.tianyuancha.cn", // 本地接口地址
changeOrigin: true,
},
"/api/v1/chat": {
target: "https://www.tianyuancha.cn", // 本地接口地址
@@ -25,11 +25,34 @@ export default defineConfig({
// rewrite: (path) => path.replace(/^\/api\/v1\/chat/, '/chat')
},
"/api/v1": {
target: "https://6m4685017o.goho.co", // 本地接口地址
changeOrigin: true,
// "/api/v1": {
// target: "http://127.0.0.1:8888", // 本地接口地址
// changeOrigin: true,
// },
},
},
build: {
// 生产环境优化
minify: "terser",
terserOptions: {
compress: {
drop_console: true, // 移除console
drop_debugger: true, // 移除debugger
},
},
rollupOptions: {
output: {
// 代码分割优化
manualChunks: {
vendor: ["vue", "vue-router", "pinia"],
vant: ["vant"],
echarts: ["echarts", "vue-echarts"],
},
},
},
// 启用gzip压缩
assetsInlineLimit: 4096,
chunkSizeWarningLimit: 1000,
},
plugins: [
vue(),
@@ -54,4 +77,9 @@ export default defineConfig({
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
// SEO优化配置
define: {
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false,
},
});