This commit is contained in:
Mrx
2026-02-28 10:52:35 +08:00
parent c742f97fa2
commit 1934fb1789
3 changed files with 335 additions and 18 deletions

View File

@@ -6,7 +6,10 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"build:seo": "node scripts/seo-static-generator/run.js",
"build:all": "pnpm run build && pnpm run build:seo",
"config:nginx": "node scripts/seo-static-generator/generateNginxConfig.js"
},
"dependencies": {
"@vant/area-data": "^2.0.0",

View File

@@ -0,0 +1,310 @@
# ========================================
# 天远查 Nginx 配置 - 带 SEO 爬虫检测
# 生成时间: 2026-02-25
# ========================================
server {
listen 80;
listen 443 ssl http2;
server_name www.tianyuancha.cn tianyuancha.cn;
# 网站根目录SPA
root /www/sites/www.tianyuancha.cn/index;
# SEO 静态页面目录
set $static_root /www/sites/www.tianyuancha.cn/static-pages;
# 默认首页
index index.php index.html index.htm default.php default.htm default.html;
# ========================================
# 爬虫检测(核心 SEO 逻辑)
# ========================================
set $is_bot 0;
# Google 爬虫
if ($http_user_agent ~* (googlebot|googlebot-image|googlebot-news|googlebot-video|mediapartners-google|adsbot-google)) {
set $is_bot 1;
}
# 百度爬虫
if ($http_user_agent ~* (baiduspider|baiduspider-mobile|baiduspider-image|baiduspider-video|baiduspider-news)) {
set $is_bot 1;
}
# 必应爬虫
if ($http_user_agent ~* (bingbot|msnbot|bingpreview)) {
set $is_bot 1;
}
# 360 爬虫
if ($http_user_agent ~* "360spider|360Spider") {
set $is_bot 1;
}
# 搜狗爬虫
if ($http_user_agent ~* "(sogou spider|sogou-orion|Sogou web spider)") {
set $is_bot 1;
}
# 头条爬虫
if ($http_user_agent ~* "bytespider|Bytespider") {
set $is_bot 1;
}
# 神马爬虫
if ($http_user_agent ~* "yisouspider|YisouSpider") {
set $is_bot 1;
}
# 其他常见爬虫
if ($http_user_agent ~* "(spider|crawl|bot|slurp|yandex|duckduckbot|facebookexternalhit|twitterbot|linkedinbot|pinterest|applebot)") {
set $is_bot 1;
}
# ========================================
# 通用代理头设置
# ========================================
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
# ========================================
# 日志配置
# ========================================
access_log /www/sites/www.tianyuancha.cn/log/access.log main;
error_log /www/sites/www.tianyuancha.cn/log/error.log;
# ========================================
# SSL 证书配置
# ========================================
ssl_certificate /www/sites/www.tianyuancha.cn/ssl/fullchain.pem;
ssl_certificate_key /www/sites/www.tianyuancha.cn/ssl/privkey.pem;
ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
error_page 497 https://$host$request_uri;
proxy_set_header X-Forwarded-Proto https;
add_header Strict-Transport-Security "max-age=31536000";
# ========================================
# Let's Encrypt 验证
# ========================================
location ^~ /.well-known/acme-challenge {
allow all;
root /usr/share/nginx/html;
}
# ========================================
# SEO 静态文件sitemap.xml, robots.txt
# ========================================
location = /sitemap.xml {
root /www/sites/www.tianyuancha.cn/static-pages;
default_type application/xml;
}
location = /robots.txt {
root /www/sites/www.tianyuancha.cn/static-pages;
default_type text/plain;
}
# ========================================
# 首页处理(爬虫检测)
# ========================================
location = / {
# 爬虫访问静态页面
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /index.html break;
}
# 正常用户访问 SPA
try_files $uri $uri/ /index.html;
}
# ========================================
# SEO 关键页面(爬虫检测)
# ========================================
# 司法涉诉核验页
location = /inquire/category/lawsuit {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /inquire-category-lawsuit.html break;
}
try_files $uri $uri/ /index.html;
}
# 婚前背景核验页
location = /inquire/marriage {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /inquire-marriage.html break;
}
try_files $uri $uri/ /index.html;
}
# 车辆档案报告页
location = /inquire/category/vehicle {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /inquire-category-vehicle.html break;
}
try_files $uri $uri/ /index.html;
}
# 婚姻关联风险核验页
location = /inquire/category/marriageStatus {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /inquire-category-marriageStatus.html break;
}
try_files $uri $uri/ /index.html;
}
# 代理中心页
location = /agent {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /agent.html break;
}
try_files $uri $uri/ /index.html;
}
# 帮助中心页
location = /help {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /help.html break;
}
try_files $uri $uri/ /index.html;
}
# 示例报告页
location = /example {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /example.html break;
}
try_files $uri $uri/ /index.html;
}
# 客服中心页
location = /service {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /service.html break;
}
try_files $uri $uri/ /index.html;
}
# 核验工具页
location = /inquire {
if ($is_bot = 1) {
root /www/sites/www.tianyuancha.cn/static-pages;
rewrite ^ /inquire.html break;
}
try_files $uri $uri/ /index.html;
}
# ========================================
# API 代理 - 主服务
# ========================================
location /api/v1 {
proxy_pass http://127.0.0.1:21004;
proxy_set_header Host 127.0.0.1:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
proxy_set_header X-Host $host:$server_port;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 30s;
proxy_read_timeout 86400s;
proxy_send_timeout 30s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# ========================================
# API 代理 - Chat 服务
# ========================================
location ^~ /api/v1/chat {
resolver 8.8.8.8 114.114.114.114 valid=10s;
resolver_timeout 5s;
set $backend "chat.guimiaokeji.com";
rewrite ^/api/v1/(.*)$ /$1 break;
proxy_pass https://$backend;
proxy_set_header Host $backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
proxy_ssl_server_name off;
proxy_buffering off;
}
# ========================================
# 静态资源缓存(图片、字体等)
# ========================================
location ~* \.(png|jpg|jpeg|gif|ico|svg|webp|woff|woff2|ttf|eot|otf)$ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
# ========================================
# HTML/JS/CSS 无缓存策略
# ========================================
location ~* \.(html|htm|js|css|json|xml)$ {
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
add_header Pragma "no-cache";
add_header Expires "0";
}
# ========================================
# SPA 路由回退(其他所有路由)
# ========================================
location / {
try_files $uri $uri/ /index.html;
}
# ========================================
# 错误页面
# ========================================
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
# ========================================
# Gzip 压缩
# ========================================
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json image/svg+xml;
# ========================================
# 安全头
# ========================================
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# ========================================
# 引入重定向配置
# ========================================
include /www/sites/www.tianyuancha.cn/redirect/*.conf;
}

View File

@@ -122,6 +122,9 @@ const router = useRouter();
const show = defineModel("show");
import { useCascaderAreaData } from "@vant/area-data";
import { showToast } from "vant"; // 引入 showToast 方法
import { useAliyunCaptcha } from "@/composables/useAliyunCaptcha";
const { runWithCaptcha } = useAliyunCaptcha();
const emit = defineEmits(); // 确保 emit 可以正确使用
const props = defineProps({
ancestor: {
@@ -146,7 +149,6 @@ const form = ref({
const showCascader = ref(false);
const cascaderValue = ref("");
const options = useCascaderAreaData();
const loadingSms = ref(false); // 控制验证码按钮的loading状态
const isCountingDown = ref(false);
const isAgreed = ref(false);
const countdown = ref(60);
@@ -158,7 +160,7 @@ const isPhoneNumberValid = computed(() => {
return /^1[3-9]\d{9}$/.test(form.value.mobile);
});
const getSmsCode = async () => {
const getSmsCode = () => {
if (!form.value.mobile) {
showToast({ message: "请输入手机号" });
return;
@@ -169,22 +171,24 @@ const getSmsCode = async () => {
return;
}
loadingSms.value = true;
const { data, error } = await useApiFetch("auth/sendSms")
.post({ mobile: form.value.mobile, actionType: "agentApply" })
.json();
loadingSms.value = false;
if (data.value && !error.value) {
if (data.value.code === 200) {
showToast({ message: "获取成功" });
startCountdown(); // 启动倒计时
} else {
showToast(data.value.msg);
runWithCaptcha(
(captchaVerifyParam) =>
useApiFetch("auth/sendSms")
.post({
mobile: form.value.mobile,
actionType: "agentApply",
captchaVerifyParam,
})
.json(),
(res) => {
if (res?.code === 200) {
showToast({ message: "获取成功" });
startCountdown();
} else {
showToast(res?.msg || "获取失败");
}
}
}
);
};
let timer = null;