- https://www.zhinengcha.cn/authorization
+ https://www.tianyuancha.cn/authorization
2025-08-01
yearly
0.3
diff --git a/scripts/seo-static-generator/.htaccess b/scripts/seo-static-generator/.htaccess
new file mode 100644
index 0000000..a75de91
--- /dev/null
+++ b/scripts/seo-static-generator/.htaccess
@@ -0,0 +1,46 @@
+# Apache .htaccess 配置 - 天远查 SPA + SEO 静态页面
+# 自动生成时间: 2026/2/25 11:04:50
+
+# 启用重写引擎
+RewriteEngine On
+
+# 爬虫检测
+RewriteCond %{HTTP_USER_AGENT} (googlebot|googlebot-image|googlebot-news|mediapartners-google|adsbot-google) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (baiduspider|baiduspider-mobile) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (bingbot|msnbot) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} "360spider" [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (sogou spider|sogou-orion) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (spider|crawl|bot|slurp|yandex|duckduckbot|bytespider|yisouspider) [NC]
+
+# 爬虫访问静态页面
+RewriteRule ^$ /static-pages/index.html [L]
+RewriteRule ^([^/]+)/?$ /static-pages/$1.html [L]
+RewriteRule ^([^/]+)/(.+)$ /static-pages/$1.html [L]
+
+# 正常用户访问 SPA
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule . /index.html [L]
+
+# Gzip 压缩
+
+ AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
+
+
+# 缓存控制
+
+ ExpiresActive On
+ ExpiresByType image/jpg "access plus 1 year"
+ ExpiresByType image/jpeg "access plus 1 year"
+ ExpiresByType image/gif "access plus 1 year"
+ ExpiresByType image/png "access plus 1 year"
+ ExpiresByType text/css "access plus 1 month"
+ ExpiresByType application/javascript "access plus 1 month"
+
+
+# 安全头
+
+ Header set X-Frame-Options "SAMEORIGIN"
+ Header set X-Content-Type-Options "nosniff"
+ Header set X-XSS-Protection "1; mode=block"
+
diff --git a/scripts/seo-static-generator/README.md b/scripts/seo-static-generator/README.md
new file mode 100644
index 0000000..0fe01bb
--- /dev/null
+++ b/scripts/seo-static-generator/README.md
@@ -0,0 +1,332 @@
+# 天远查 SEO 静态页面生成器
+
+为 Vue SPA 应用生成 SEO 友好的静态 HTML 页面,解决爬虫无法抓取客户端渲染内容的问题。
+
+## 功能特性
+
+- ✅ 自动根据路由和 SEO 配置生成静态 HTML 页面
+- ✅ 完整的 TDK(Title、Description、Keywords)优化
+- ✅ 支持 Open Graph 和 Twitter Cards
+- ✅ 包含 Schema.org 结构化数据
+- ✅ 自动生成 sitemap.xml
+- ✅ 自动生成 robots.txt
+- ✅ Nginx 和 Apache 配置生成
+- ✅ 爬虫检测中间件
+- ✅ 复用现有的 useSEO.js 配置
+
+## 目录结构
+
+```
+scripts/seo-static-generator/
+├── package.json # 项目配置
+├── README.md # 使用说明
+├── pageTemplates.js # 页面模板生成器
+├── generateStaticPages.js # 静态页面生成主脚本
+├── crawlerMiddleware.js # 爬虫检测中间件
+├── generateNginxConfig.js # 配置文件生成脚本
+└── static-pages/ # 生成的静态页面(自动创建)
+ ├── index.html
+ ├── inquire-category-lawsuit.html
+ ├── inquire-marriage.html
+ ├── ...
+ ├── sitemap.xml
+ └── robots.txt
+```
+
+## 快速开始
+
+### 1. 安装依赖
+
+```bash
+cd scripts/seo-static-generator
+```
+
+注意:本工具使用 Node.js 原生模块,无需安装额外依赖。
+
+### 2. 生成静态页面
+
+```bash
+# 生成所有静态页面
+node generateStaticPages.js
+
+# 或使用 npm script
+npm run generate
+```
+
+生成成功后,静态页面将保存在 `static-pages/` 目录中。
+
+### 3. 生成服务器配置
+
+```bash
+# 生成 Nginx 配置
+npm run nginx
+
+# 或生成 Apache .htaccess 配置
+npm run htaccess
+```
+
+## 配置说明
+
+### SEO 配置
+
+SEO 配置在 `generateStaticPages.js` 中定义,可以直接复用 `useSEO.js` 中的配置:
+
+```javascript
+const seoConfigs = {
+ '/': {
+ title: '天远查官网_企业与婚姻关联风险核验_综合履约背景核验',
+ description: '天远查官网(TianYuanCha)聚合官方公示数据...',
+ keywords: '天远查,婚姻状态风险, 配偶背景核验...'
+ },
+ '/inquire/category/lawsuit': {
+ title: '司法涉诉核验_个人及企业法律诉讼记录...',
+ description: '天远查司法风险检测中心...',
+ keywords: '司法案件核验,法律诉讼记录...'
+ },
+ // ... 更多路由配置
+};
+```
+
+### Nginx 配置
+
+在 `generateNginxConfig.js` 中修改配置:
+
+```javascript
+const config = {
+ serverName: 'www.tianyuancha.cn', // 你的域名
+ spaRoot: '/var/www/tyc-webview-v2/dist', // SPA 静态文件目录
+ staticRoot: '/var/www/tyc-webview-v2/static-pages', // SEO 静态页面目录
+ sslEnabled: false, // 是否启用 HTTPS
+ sslCertPath: '/etc/nginx/ssl/cert.pem', // SSL 证书路径
+ sslKeyPath: '/etc/nginx/ssl/key.pem' // SSL 密钥路径
+};
+```
+
+## 部署步骤
+
+### 方式一:Nginx 部署(推荐)
+
+1. **生成静态页面**
+
+```bash
+npm run generate
+```
+
+2. **生成 Nginx 配置**
+
+```bash
+npm run nginx
+```
+
+3. **部署配置文件**
+
+```bash
+# 复制生成的 nginx.conf 到 Nginx 配置目录
+sudo cp scripts/seo-static-generator/nginx.conf /etc/nginx/sites-available/tyc-webview
+
+# 创建软链接
+sudo ln -s /etc/nginx/sites-available/tyc-webview /etc/nginx/sites-enabled/
+
+# 测试配置
+sudo nginx -t
+
+# 重载 Nginx
+sudo nginx -s reload
+```
+
+4. **部署静态文件**
+
+```bash
+# 将生成的静态页面复制到服务器
+scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+```
+
+### 方式二:Apache 部署
+
+1. **生成静态页面**
+
+```bash
+npm run generate
+```
+
+2. **生成 .htaccess 配置**
+
+```bash
+npm run htaccess
+```
+
+3. **部署配置文件**
+
+```bash
+# 复制 .htaccess 到网站根目录
+cp scripts/seo-static-generator/.htaccess /var/www/tyc-webview-v2/
+```
+
+4. **部署静态文件**
+
+```bash
+# 将生成的静态页面复制到服务器
+scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+```
+
+## 工作原理
+
+### 爬虫检测流程
+
+```
+用户请求
+ ↓
+Nginx 检测 User-Agent
+ ↓
+ ├─ 是爬虫 → 返回静态页面(static-pages/)
+ └─ 否 → 返回 SPA 应用(dist/)
+```
+
+### 爬虫 User-Agent 列表
+
+工具内置了以下爬虫的识别:
+
+- **Google**: googlebot, googlebot-image, googlebot-news
+- **百度**: baiduspider, baiduspider-mobile
+- **必应**: bingbot, msnbot
+- **360**: 360spider
+- **搜狗**: sogou spider, sogou-orion
+- **头条**: bytespider
+- **神马**: yisouspider
+- **其他**: yandex, duckduckbot, slurp 等
+
+## 自定义页面内容
+
+### 修改页面模板
+
+编辑 `pageTemplates.js` 中的模板函数:
+
+```javascript
+export function generateStaticHTML(seoConfig, options = {}) {
+ // 自定义 HTML 模板
+}
+```
+
+### 添加新的路由页面
+
+1. 在 `generateStaticPages.js` 中添加路由配置:
+
+```javascript
+const seoConfigs = {
+ '/new-route': {
+ title: '新页面标题',
+ description: '新页面描述',
+ keywords: '关键词1,关键词2'
+ }
+};
+```
+
+2. 在 `pageTemplates.js` 中添加内容生成函数:
+
+```javascript
+function generateNewRouteContent(seoConfig) {
+ return `
+ 新页面内容
+ 这里写页面的具体内容...
+ `;
+}
+
+// 添加到路由映射
+export function generateContentByRoute(path, seoConfig) {
+ const routeContentMap = {
+ '/new-route': generateNewRouteContent(seoConfig),
+ // ... 其他路由
+ };
+ return routeContentMap[path] || generateDefaultContent(seoConfig);
+}
+```
+
+## 集成到构建流程
+
+在项目的 `package.json` 中添加构建脚本:
+
+```json
+{
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "build:seo": "node scripts/seo-static-generator/generateStaticPages.js",
+ "build:all": "npm run build && npm run build:seo"
+ }
+}
+```
+
+现在运行 `npm run build:all` 就可以同时构建 SPA 和生成静态页面。
+
+## 测试
+
+### 测试爬虫检测
+
+使用 curl 模拟爬虫访问:
+
+```bash
+# 模拟百度爬虫
+curl -A "Baiduspider" http://www.tianyuancha.cn/
+
+# 模拟 Google 爬虫
+curl -A "Googlebot" http://www.tianyuancha.cn/
+
+# 正常浏览器访问
+curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" http://www.tianyuancha.cn/
+```
+
+### 验证 SEO
+
+使用在线工具验证生成的页面:
+
+- Google Rich Results Test: https://search.google.com/test/rich-results
+- 百度移动适配测试: http://ziyuan.baidu.com/
+- Schema Markup Validator: https://validator.schema.org/
+
+## 常见问题
+
+### Q: 如何添加新的爬虫识别?
+
+A: 在 `crawlerMiddleware.js` 的 `SEARCH_ENGINE_BOTS` 数组中添加:
+
+```javascript
+const SEARCH_ENGINE_BOTS = [
+ // ... 现有爬虫
+ 'new-bot-name',
+];
+```
+
+### Q: 静态页面如何保持最新?
+
+A: 每次更新 SEO 配置后,重新运行:
+
+```bash
+npm run generate
+```
+
+建议将此步骤集成到 CI/CD 流程中。
+
+### Q: 如何处理动态内容?
+
+A: 对于需要动态内容的页面,可以考虑:
+
+1. 使用定时任务定期重新生成静态页面
+2. 使用方案三(动态渲染服务)
+3. 在静态页面中添加 JavaScript,让正常用户访问时加载动态内容
+
+### Q: Nginx 配置不生效怎么办?
+
+A: 检查以下几点:
+
+1. 确保 Nginx 已重启:`sudo nginx -s reload`
+2. 检查配置文件语法:`sudo nginx -t`
+3. 查看 Nginx 错误日志:`sudo tail -f /var/log/nginx/error.log`
+4. 确保静态文件路径正确
+
+## 技术支持
+
+如有问题,请联系技术团队或提交 Issue。
+
+## 许可证
+
+MIT
diff --git a/scripts/seo-static-generator/SEO_INTEGRATION.md b/scripts/seo-static-generator/SEO_INTEGRATION.md
new file mode 100644
index 0000000..affc430
--- /dev/null
+++ b/scripts/seo-static-generator/SEO_INTEGRATION.md
@@ -0,0 +1,367 @@
+# SEO 静态页面集成指南
+
+本文档说明如何将 SEO 静态页面生成器集成到天远查项目中。
+
+## 快速开始
+
+### 1. 生成静态页面
+
+在项目根目录运行:
+
+```bash
+# Windows PowerShell
+node scripts\seo-static-generator\generateStaticPages.js
+
+# 或者使用 cmd
+node scripts\seo-static-generator\generateStaticPages.js
+```
+
+这将生成所有 SEO 优化的静态页面到 `scripts/seo-static-generator/static-pages/` 目录。
+
+### 2. 生成服务器配置
+
+```bash
+# 生成 Nginx 配置
+node scripts\seo-static-generator\generateNginxConfig.js
+```
+
+这将生成:
+- `scripts/seo-static-generator/nginx.conf` - Nginx 配置文件
+- `scripts/seo-static-generator/.htaccess` - Apache 配置文件
+
+### 3. 集成到构建流程
+
+更新 `package.json`,添加以下脚本:
+
+```json
+{
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "build:seo": "node scripts/seo-static-generator/generateStaticPages.js",
+ "build:all": "npm run build && npm run build:seo",
+ "config:nginx": "node scripts/seo-static-generator/generateNginxConfig.js"
+ }
+}
+```
+
+现在可以使用:
+
+```bash
+# 构建项目并生成 SEO 页面
+npm run build:all
+
+# 只生成 SEO 页面
+npm run build:seo
+
+# 生成 Nginx 配置
+npm run config:nginx
+```
+
+## 部署步骤
+
+### 开发环境测试
+
+1. **生成静态页面**
+
+```bash
+npm run build:seo
+```
+
+2. **在浏览器中打开测试**
+
+```bash
+# 在浏览器中打开示例页面
+start scripts\seo-static-generator\index.html
+```
+
+### 生产环境部署
+
+#### 使用 Nginx(推荐)
+
+1. **构建项目**
+
+```bash
+npm run build:all
+```
+
+2. **生成 Nginx 配置**
+
+```bash
+npm run config:nginx
+```
+
+3. **上传文件到服务器**
+
+```bash
+# 上传 SPA 构建文件
+scp -r dist/* user@server:/var/www/tyc-webview-v2/dist/
+
+# 上传 SEO 静态页面
+scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+
+# 上传 Nginx 配置
+scp scripts/seo-static-generator/nginx.conf user@server:/etc/nginx/sites-available/tyc-webview
+```
+
+4. **配置 Nginx**
+
+```bash
+# 在服务器上执行
+
+# 创建软链接
+sudo ln -s /etc/nginx/sites-available/tyc-webview /etc/nginx/sites-enabled/
+
+# 测试配置
+sudo nginx -t
+
+# 重载 Nginx
+sudo nginx -s reload
+```
+
+#### 使用 Apache
+
+1. **构建项目**
+
+```bash
+npm run build:all
+```
+
+2. **生成 Apache 配置**
+
+生成的 `.htaccess` 文件在 `scripts/seo-static-generator/.htaccess`
+
+3. **上传文件到服务器**
+
+```bash
+# 上传 SPA 构建文件
+scp -r dist/* user@server:/var/www/tyc-webview-v2/
+
+# 上传 SEO 静态页面
+scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+
+# 上传 .htaccess
+scp scripts/seo-static-generator/.htaccess user@server:/var/www/tyc-webview-v2/
+```
+
+4. **确保 Apache 启用了 mod_rewrite**
+
+```bash
+# 在服务器上执行
+sudo a2enmod rewrite
+sudo systemctl restart apache2
+```
+
+## 配置说明
+
+### 修改服务器配置
+
+#### Nginx 配置
+
+编辑 `scripts/seo-static-generator/generateNginxConfig.js`:
+
+```javascript
+const config = {
+ serverName: 'www.tianyuancha.cn', // 修改为你的域名
+ spaRoot: '/var/www/tyc-webview-v2/dist', // SPA 静态文件目录
+ staticRoot: '/var/www/tyc-webview-v2/static-pages', // SEO 静态页面目录
+ sslEnabled: false, // 是否启用 HTTPS
+ sslCertPath: '/etc/nginx/ssl/cert.pem', // SSL 证书路径
+ sslKeyPath: '/etc/nginx/ssl/key.pem' // SSL 密钥路径
+};
+```
+
+#### Apache 配置
+
+Apache 使用 `.htaccess` 文件,无需额外配置,确保:
+
+- `static-pages/` 目录与网站根目录同级
+- Apache 启用了 `mod_rewrite` 模块
+
+### 修改 SEO 配置
+
+SEO 配置在 `scripts/seo-static-generator/generateStaticPages.js` 中:
+
+```javascript
+const seoConfigs = {
+ '/': {
+ title: '天远查官网_企业与婚姻关联风险核验_综合履约背景核验',
+ description: '天远查官网(TianYuanCha)聚合官方公示数据...',
+ keywords: '天远查,婚姻状态风险, 配偶背景核验...'
+ },
+ // ... 添加更多路由
+};
+```
+
+## 测试验证
+
+### 1. 测试爬虫检测
+
+使用 curl 模拟爬虫访问:
+
+```bash
+# 模拟百度爬虫(应该返回静态页面)
+curl -A "Baiduspider" http://www.tianyuancha.cn/
+
+# 模拟 Google 爬虫(应该返回静态页面)
+curl -A "Googlebot" http://www.tianyuancha.cn/
+
+# 正常浏览器访问(应该返回 SPA)
+curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" http://www.tianyuancha.cn/
+```
+
+### 2. 验证 SEO
+
+使用在线工具验证:
+
+- **Google Rich Results Test**: https://search.google.com/test/rich-results
+- **百度移动适配测试**: http://ziyuan.baidu.com/
+- **Schema Markup Validator**: https://validator.schema.org/
+
+### 3. 检查生成的文件
+
+```bash
+# 检查静态页面目录
+ls -la scripts/seo-static-generator/static-pages/
+
+# 检查 sitemap.xml
+cat scripts/seo-static-generator/static-pages/sitemap.xml
+
+# 检查 robots.txt
+cat scripts/seo-static-generator/static-pages/robots.txt
+```
+
+## 维护和更新
+
+### 更新 SEO 配置
+
+1. 修改 `scripts/seo-static-generator/generateStaticPages.js` 中的 `seoConfigs`
+
+2. 重新生成静态页面:
+
+```bash
+npm run build:seo
+```
+
+3. 部署到服务器:
+
+```bash
+# 上传更新的静态页面
+scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+```
+
+### 添加新路由
+
+1. 在 `scripts/seo-static-generator/generateStaticPages.js` 中添加路由:
+
+```javascript
+const seoConfigs = {
+ // ... 现有路由
+ '/new-route': {
+ title: '新页面标题',
+ description: '新页面描述',
+ keywords: '关键词1,关键词2'
+ }
+};
+```
+
+2. 在 `scripts/seo-static-generator/pageTemplates.js` 中添加内容生成函数:
+
+```javascript
+function generateNewRouteContent(seoConfig) {
+ return `
+ 新页面内容
+ 这里写页面的具体内容...
+ `;
+}
+
+// 添加到路由映射
+export function generateContentByRoute(path, seoConfig) {
+ const routeContentMap = {
+ // ... 现有路由
+ '/new-route': generateNewRouteContent(seoConfig),
+ };
+ return routeContentMap[path] || generateDefaultContent(seoConfig);
+}
+```
+
+3. 重新生成静态页面:
+
+```bash
+npm run build:seo
+```
+
+## 集成到 CI/CD
+
+在 CI/CD 流程中添加静态页面生成:
+
+```yaml
+# .github/workflows/deploy.yml 示例
+name: Deploy
+
+on:
+ push:
+ branches: [ main ]
+
+jobs:
+ build-and-deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v2
+ with:
+ node-version: '18'
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Build project
+ run: npm run build:all
+
+ - name: Deploy to server
+ run: |
+ scp -r dist/* user@server:/var/www/tyc-webview-v2/dist/
+ scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+```
+
+## 常见问题
+
+### Q: 静态页面没有生成?
+
+A: 检查以下几点:
+
+1. 确保 Node.js 版本 >= 14
+2. 检查是否有文件写入权限
+3. 查看控制台错误信息
+
+### Q: Nginx 配置不生效?
+
+A: 检查以下几点:
+
+1. 确保 Nginx 已重启:`sudo nginx -s reload`
+2. 检查配置文件语法:`sudo nginx -t`
+3. 查看 Nginx 错误日志:`sudo tail -f /var/log/nginx/error.log`
+4. 确保静态文件路径正确
+
+### Q: 如何处理动态内容?
+
+A: 对于需要动态内容的页面,可以考虑:
+
+1. 使用定时任务定期重新生成静态页面
+2. 在静态页面中添加 JavaScript,让正常用户访问时加载动态内容
+3. 考虑使用动态渲染服务(方案三)
+
+### Q: 爬虫仍然看到的是 SPA?
+
+A: 检查以下几点:
+
+1. 确认 User-Agent 匹配规则正确
+2. 检查 Nginx/Apache 配置是否正确加载
+3. 使用 curl 测试爬虫访问
+
+## 技术支持
+
+如有问题,请参考详细文档:`scripts/seo-static-generator/README.md`
diff --git a/scripts/seo-static-generator/SEO_QUICKSTART.md b/scripts/seo-static-generator/SEO_QUICKSTART.md
new file mode 100644
index 0000000..ae02a20
--- /dev/null
+++ b/scripts/seo-static-generator/SEO_QUICKSTART.md
@@ -0,0 +1,352 @@
+# SEO 静态页面方案一 - 快速开始
+
+## ✅ 方案已实现
+
+**方案一:Nginx中间件 + 预渲染静态页面** 已完整实现!
+
+---
+
+## 🎯 核心功能
+
+- ✅ 自动生成SEO优化的静态HTML页面
+- ✅ 完整的TDK(Title、Description、Keywords)
+- ✅ 支持Open Graph和Twitter Cards
+- ✅ 包含Schema.org结构化数据
+- ✅ 自动生成sitemap.xml和robots.txt
+- ✅ 爬虫检测和路由区分
+- ✅ Nginx和Apache配置生成
+- ✅ 复用现有的useSEO.js配置
+
+---
+
+## 📁 生成的文件
+
+```
+tyc-webview-v2/
+├── scripts/seo-static-generator/
+│ ├── run.js # 主生成脚本
+│ ├── generateStaticPages.js # 完整生成脚本
+│ ├── pageTemplates.js # 页面模板
+│ ├── crawlerMiddleware.js # 爬虫检测中间件
+│ ├── generateNginxConfig.js # 配置生成脚本
+│ ├── nginx.conf # Nginx配置
+│ ├── .htaccess # Apache配置
+│ ├── static-pages/ # 生成的静态页面
+│ │ ├── index.html # 首页
+│ │ ├── inquire-category-lawsuit.html
+│ │ ├── inquire-marriage.html
+│ │ ├── inquire-category-vehicle.html
+│ │ ├── inquire-category-marriageStatus.html
+│ │ ├── agent.html
+│ │ ├── help.html
+│ │ ├── example.html
+│ │ ├── service.html
+│ │ ├── inquire.html
+│ │ ├── sitemap.xml # 站点地图
+│ │ └── robots.txt # 爬虫规则
+│ ├── README.md # 详细文档
+│ └── index.html # 示例页面
+├── SEO_INTEGRATION.md # 集成指南
+├── DEPLOYMENT_GUIDE.md # 部署指南
+└── SEO_QUICKSTART.md # 本文档
+```
+
+---
+
+## 🚀 快速开始(3步完成)
+
+### 步骤 1:生成静态页面
+
+```bash
+cd C:\Users\a1726\Desktop\tyc\tyc-webview-v2
+node scripts\seo-static-generator\run.js
+```
+
+**输出:**
+```
+========================================
+ 天远查 - 静态页面生成器
+========================================
+
+📂 输出目录: C:\Users\a1726\Desktop\tyc\tyc-webview-v2\scripts\seo-static-generator\static-pages
+
+📝 生成静态页面:
+
+✅ index.html
+✅ inquire-category-lawsuit.html
+✅ inquire-marriage.html
+✅ inquire-category-vehicle.html
+✅ inquire-category-marriageStatus.html
+✅ agent.html
+✅ help.html
+✅ example.html
+✅ service.html
+✅ inquire.html
+
+📝 生成SEO文件:
+
+✅ sitemap.xml
+✅ robots.txt
+
+========================================
+✨ 完成! 共生成 10 个静态页面
+========================================
+```
+
+### 步骤 2:生成服务器配置
+
+```bash
+node scripts\seo-static-generator\generateNginxConfig.js
+```
+
+**输出:**
+```
+============================================================
+ 生成 Nginx 配置文件
+============================================================
+
+✅ Nginx配置文件生成成功!
+📁 保存路径: C:\Users\a1726\Desktop\tyc\tyc-webview-v2\scripts\seo-static-generator\nginx.conf
+
+📝 使用说明:
+1. 将生成的 nginx.conf 复制到 Nginx 配置目录
+2. 修改配置中的路径(spaRoot、staticRoot等)为实际路径
+3. 测试配置: nginx -t
+4. 重载Nginx: nginx -s reload
+
+✅ Apache .htaccess 配置文件生成成功!
+📁 保存路径: C:\Users\a1726\Desktop\tyc\tyc-webview-v2\scripts\seo-static-generator\.htaccess
+
+📝 使用说明:
+1. 将生成的 .htaccess 复制到网站根目录
+2. 确保 Apache 启用了 mod_rewrite 模块
+3. 重启Apache服务
+```
+
+### 步骤 3:部署到服务器
+
+#### Nginx 部署(推荐)
+
+```bash
+# 1. 上传静态页面
+scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+
+# 2. 上传Nginx配置(先修改配置文件中的路径)
+scp scripts/seo-static-generator/nginx.conf user@server:/etc/nginx/sites-available/tyc-webview
+
+# 3. 在服务器上配置
+ssh user@server
+sudo ln -s /etc/nginx/sites-available/tyc-webview /etc/nginx/sites-enabled/
+sudo nginx -t
+sudo nginx -s reload
+```
+
+#### Apache 部署
+
+```bash
+# 1. 上传静态页面
+scp -r scripts/seo-static-generator/static-pages/* user@server:/var/www/tyc-webview-v2/static-pages/
+
+# 2. 上传.htaccess
+scp scripts/seo-static-generator/.htaccess user@server:/var/www/tyc-webview-v2/
+
+# 3. 在服务器上启用mod_rewrite
+ssh user@server
+sudo a2enmod rewrite
+sudo systemctl restart apache2
+```
+
+---
+
+## ✅ 验证部署
+
+### 测试爬虫检测
+
+```bash
+# 模拟百度爬虫(应该返回静态页面)
+curl -A "Baiduspider" http://www.tianyuancha.cn/
+
+# 模拟 Google 爬虫(应该返回静态页面)
+curl -A "Googlebot" http://www.tianyuancha.cn/
+
+# 正常浏览器访问(应该返回 SPA)
+curl -A "Mozilla/5.0" http://www.tianyuancha.cn/
+```
+
+### 查看生成的页面
+
+```bash
+# 在浏览器中打开示例页面
+start scripts\seo-static-generator\index.html
+
+# 或直接查看生成的文件
+cat scripts\seo-static-generator\static-pages\index.html
+```
+
+---
+
+## 📋 生成的静态页面列表
+
+| 路由 | 文件名 | 页面说明 |
+|------|--------|----------|
+| / | index.html | 首页 |
+| /inquire/category/lawsuit | inquire-category-lawsuit.html | 司法涉诉核验 |
+| /inquire/marriage | inquire-marriage.html | 婚前背景核验 |
+| /inquire/category/vehicle | inquire-category-vehicle.html | 车辆档案报告 |
+| /inquire/category/marriageStatus | inquire-category-marriageStatus.html | 婚姻关联风险核验 |
+| /agent | agent.html | 代理中心 |
+| /help | help.html | 帮助中心 |
+| /example | example.html | 示例报告 |
+| /service | service.html | 客服中心 |
+| /inquire | inquire.html | 核验工具 |
+
+---
+
+## 🌟 支持的爬虫
+
+- ✅ Google (googlebot)
+- ✅ 百度 (baiduspider)
+- ✅ 必应 (bingbot)
+- ✅ 360 (360spider)
+- ✅ 搜狗 (sogou spider)
+- ✅ 头条 (bytespider)
+- ✅ 神马 (yisouspider)
+- ✅ Yandex (yandex)
+- ✅ DuckDuckGo (duckduckbot)
+- ✅ 其他常见爬虫
+
+---
+
+## 📚 文档导航
+
+- **快速开始** - 本文档
+- **部署指南** - [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md)
+- **集成指南** - [SEO_INTEGRATION.md](SEO_INTEGRATION.md)
+- **详细文档** - [scripts/seo-static-generator/README.md](scripts/seo-static-generator/README.md)
+
+---
+
+## 🔧 自定义配置
+
+### 修改 SEO 配置
+
+编辑 `scripts\seo-static-generator\run.js` 中的 `seoConfigs`:
+
+```javascript
+const seoConfigs = {
+ '/': {
+ title: '你的页面标题',
+ description: '你的页面描述',
+ keywords: '关键词1,关键词2,关键词3'
+ },
+ // ... 其他路由
+};
+```
+
+### 修改 Nginx 配置
+
+编辑 `scripts\seo-static-generator\generateNginxConfig.js` 中的配置:
+
+```javascript
+const config = {
+ serverName: 'www.tianyuancha.cn',
+ spaRoot: '/var/www/tyc-webview-v2/dist',
+ staticRoot: '/var/www/tyc-webview-v2/static-pages',
+ sslEnabled: false,
+ // ... 其他配置
+};
+```
+
+---
+
+## 🔄 更新和维护
+
+### 更新 SEO 内容
+
+1. 修改 `run.js` 中的 `seoConfigs`
+2. 重新运行:`node scripts\seo-static-generator\run.js`
+3. 部署到服务器
+
+### 添加新页面
+
+1. 在 `run.js` 的 `seoConfigs` 中添加新路由
+2. 在 `pageTemplates.js` 中添加内容生成函数
+3. 重新生成并部署
+
+---
+
+## 📊 SEO 优化特性
+
+每个生成的静态页面都包含:
+
+- ✅ 完整的 TDK 标签
+- ✅ Canonical URL
+- ✅ Open Graph 标签(Facebook、LinkedIn)
+- ✅ Twitter Cards
+- ✅ Schema.org 结构化数据
+- ✅ Robots Meta 标签
+- ✅ 响应式设计
+- ✅ 美观的页面样式
+- ✅ 链接到主站
+
+---
+
+## 🎉 工作原理
+
+```
+用户请求
+ ↓
+Nginx 检测 User-Agent
+ ↓
+ ├─ 是爬虫 → 返回静态页面(static-pages/)
+ └─ 否 → 返回 SPA 应用(dist/)
+```
+
+**优势:**
+- 爬虫看到完整的SEO内容
+- 正常用户看到完整的SPA应用
+- 不影响用户体验
+- 性能优异
+
+---
+
+## ❓ 常见问题
+
+**Q: 生成的静态页面在哪里?**
+A: 在 `scripts\seo-static-generator\static-pages\` 目录
+
+**Q: 如何修改页面内容?**
+A: 编辑 `pageTemplates.js` 中的内容生成函数
+
+**Q: 支持哪些服务器?**
+A: 支持 Nginx 和 Apache
+
+**Q: 如何测试爬虫检测?**
+A: 使用 `curl -A "Baiduspider" http://your-domain.com/` 测试
+
+**Q: 如何集成到 CI/CD?**
+A: 参考 `DEPLOYMENT_GUIDE.md` 中的 CI/CD 集成部分
+
+---
+
+## 🆘 技术支持
+
+- 📖 查看详细文档:[scripts/seo-static-generator/README.md](scripts/seo-static-generator/README.md)
+- 📖 查看部署指南:[DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md)
+- 📖 查看集成指南:[SEO_INTEGRATION.md](SEO_INTEGRATION.md)
+
+---
+
+## 📝 下一步
+
+1. ✅ 运行生成器创建静态页面
+2. ✅ 查看生成的页面效果
+3. ✅ 根据需要修改SEO配置
+4. ✅ 生成服务器配置文件
+5. ✅ 部署到测试服务器验证
+6. ✅ 部署到生产环境
+7. ✅ 使用在线工具验证SEO效果
+
+---
+
+**🎊 恭喜!方案一已完成!现在你可以开始部署了!**
diff --git a/scripts/seo-static-generator/SEO_SOLUTION_SUMMARY.md b/scripts/seo-static-generator/SEO_SOLUTION_SUMMARY.md
new file mode 100644
index 0000000..c70154a
--- /dev/null
+++ b/scripts/seo-static-generator/SEO_SOLUTION_SUMMARY.md
@@ -0,0 +1,347 @@
+# 🎉 方案一实现完成!
+
+## ✅ 已完成的工作
+
+### 1. 核心功能实现
+
+#### ✅ 静态页面生成器
+- 📄 `pageTemplates.js` - 页面模板生成器
+ - 完整的HTML模板
+ - 支持TDK(Title、Description、Keywords)
+ - 支持Open Graph和Twitter Cards
+ - 包含Schema.org结构化数据
+ - 针对不同路由的定制内容
+
+#### ✅ 主生成脚本
+- 📄 `run.js` - 简化版生成脚本(推荐使用)
+ - 自动生成10个静态页面
+ - 自动生成sitemap.xml
+ - 自动生成robots.txt
+ - 兼容性更好,错误处理完善
+
+- 📄 `generateStaticPages.js` - 完整版生成脚本
+ - 包含所有功能
+ - 支持更多路由
+
+#### ✅ 爬虫检测中间件
+- 📄 `crawlerMiddleware.js` - 爬虫检测
+ - 支持10+种主流爬虫识别
+ - Nginx配置生成器
+ - Apache .htaccess配置生成器
+
+#### ✅ 配置文件生成器
+- 📄 `generateNginxConfig.js` - 配置生成脚本
+ - 自动生成Nginx配置
+ - 自动生成Apache .htaccess配置
+ - 包含详细的使用说明
+
+### 2. 生成的静态页面
+
+已成功生成 **10个** SEO优化的静态HTML页面:
+
+| 路由 | 文件名 | 页面说明 |
+|------|--------|----------|
+| / | index.html | 首页 |
+| /inquire/category/lawsuit | inquire-category-lawsuit.html | 司法涉诉核验 |
+| /inquire/marriage | inquire-marriage.html | 婚前背景核验 |
+| /inquire/category/vehicle | inquire-category-vehicle.html | 车辆档案报告 |
+| /inquire/category/marriageStatus | inquire-category-marriageStatus.html | 婚姻关联风险核验 |
+| /agent | agent.html | 代理中心 |
+| /help | help.html | 帮助中心 |
+| /example | example.html | 示例报告 |
+| /service | service.html | 客服中心 |
+| /inquire | inquire.html | 核验工具 |
+
+### 3. SEO文件
+
+- ✅ sitemap.xml - 站点地图
+- ✅ robots.txt - 爬虫规则
+
+### 4. 服务器配置
+
+- ✅ nginx.conf - Nginx配置文件
+- ✅ .htaccess - Apache配置文件
+
+### 5. 文档
+
+- ✅ README.md - 详细使用文档
+- ✅ DEPLOYMENT_GUIDE.md - 部署指南
+- ✅ SEO_INTEGRATION.md - 集成指南
+- ✅ SEO_QUICKSTART.md - 快速开始
+- ✅ SEO_SOLUTION_SUMMARY.md - 本文档
+
+---
+
+## 📁 文件结构
+
+```
+tyc-webview-v2/
+├── scripts/
+│ └── seo-static-generator/
+│ ├── 📄 run.js # 主生成脚本(推荐)
+│ ├── 📄 generateStaticPages.js # 完整生成脚本
+│ ├── 📄 pageTemplates.js # 页面模板
+│ ├── 📄 crawlerMiddleware.js # 爬虫检测中间件
+│ ├── 📄 generateNginxConfig.js # 配置生成脚本
+│ ├── 📄 package.json # 项目配置
+│ ├── 📄 README.md # 详细文档
+│ ├── 📄 index.html # 示例页面
+│ ├── 📄 nginx.conf # Nginx配置
+│ ├── 📄 .htaccess # Apache配置
+│ └── 📁 static-pages/ # 生成的静态页面
+│ ├── index.html
+│ ├── inquire-category-lawsuit.html
+│ ├── inquire-marriage.html
+│ ├── inquire-category-vehicle.html
+│ ├── inquire-category-marriageStatus.html
+│ ├── agent.html
+│ ├── help.html
+│ ├── example.html
+│ ├── service.html
+│ ├── inquire.html
+│ ├── sitemap.xml
+│ └── robots.txt
+├── 📄 SEO_INTEGRATION.md # 集成指南
+├── 📄 DEPLOYMENT_GUIDE.md # 部署指南
+├── 📄 SEO_QUICKSTART.md # 快速开始
+└── 📄 SEO_SOLUTION_SUMMARY.md # 本文档
+```
+
+---
+
+## 🚀 快速使用
+
+### 1. 生成静态页面
+
+```bash
+cd C:\Users\a1726\Desktop\tyc\tyc-webview-v2
+node scripts\seo-static-generator\run.js
+```
+
+### 2. 生成服务器配置
+
+```bash
+node scripts\seo-static-generator\generateNginxConfig.js
+```
+
+### 3. 查看生成的页面
+
+```bash
+# 在浏览器中打开
+start scripts\seo-static-generator\index.html
+```
+
+---
+
+## 🌟 核心特性
+
+### ✅ SEO优化
+
+- 完整的TDK标签(Title、Description、Keywords)
+- Canonical URL
+- Open Graph标签(Facebook、LinkedIn)
+- Twitter Cards
+- Schema.org结构化数据
+- Robots Meta标签
+- sitemap.xml
+- robots.txt
+
+### ✅ 爬虫检测
+
+支持识别10+种主流爬虫:
+- Google (googlebot)
+- 百度 (baiduspider)
+- 必应 (bingbot)
+- 360 (360spider)
+- 搜狗 (sogou spider)
+- 头条 (bytespider)
+- 神马 (yisouspider)
+- Yandex
+- DuckDuckGo
+- 其他常见爬虫
+
+### ✅ 服务器支持
+
+- ✅ Nginx配置(推荐)
+- ✅ Apache配置
+- ✅ Express中间件(Node.js)
+
+### ✅ 集成方便
+
+- 复用现有的useSEO.js配置
+- 自动化生成
+- 易于维护和更新
+- 支持CI/CD集成
+
+---
+
+## 🎯 工作原理
+
+```
+用户请求
+ ↓
+Nginx/Apache 检测 User-Agent
+ ↓
+ ├─ 是爬虫 → 返回静态页面(static-pages/)
+ │ ├─ 完整的TDK
+ │ ├─ Open Graph
+ │ ├─ 结构化数据
+ │ └─ SEO优化的内容
+ │
+ └─ 否 → 返回 SPA 应用(dist/)
+ ├─ 完整的Vue SPA
+ ├─ 交互功能
+ └─ 动态内容
+```
+
+---
+
+## 📚 文档导航
+
+| 文档 | 说明 | 适用场景 |
+|------|------|----------|
+| **SEO_QUICKSTART.md** | 快速开始 | 首次使用,快速上手 |
+| **DEPLOYMENT_GUIDE.md** | 部署指南 | 部署到生产环境 |
+| **SEO_INTEGRATION.md** | 集成指南 | 集成到现有项目 |
+| **scripts/seo-static-generator/README.md** | 详细文档 | 深入了解所有功能 |
+
+---
+
+## 🔄 下一步建议
+
+### 1. 本地测试
+
+```bash
+# 1. 生成静态页面
+node scripts\seo-static-generator\run.js
+
+# 2. 在浏览器中查看
+start scripts\seo-static-generator\index.html
+
+# 3. 检查TDK标签
+# 在浏览器中按F12查看源代码
+```
+
+### 2. 配置修改
+
+根据实际需求修改:
+- SEO配置:编辑 `run.js` 中的 `seoConfigs`
+- 服务器配置:编辑 `generateNginxConfig.js` 中的 `config`
+
+### 3. 测试环境部署
+
+先部署到测试环境,验证功能正常后再部署到生产环境。
+
+### 4. 生产环境部署
+
+参考 `DEPLOYMENT_GUIDE.md` 进行生产环境部署。
+
+### 5. SEO验证
+
+使用以下工具验证SEO效果:
+- Google Rich Results Test
+- 百度移动适配测试
+- Schema Markup Validator
+
+---
+
+## 📊 生成的页面示例
+
+### index.html(首页)
+
+包含:
+- ✅ 完整的HTML结构
+- ✅ 所有meta标签
+- ✅ Open Graph标签
+- ✅ Twitter Cards
+- ✅ Schema.org结构化数据
+- ✅ 响应式CSS样式
+- ✅ 优化的页面内容
+- ✅ 链接到主站
+
+### 其他页面
+
+每个页面都包含:
+- 针对该路由的定制内容
+- 完整的SEO标签
+- 相关的服务介绍
+- 使用场景说明
+- 联系方式
+
+---
+
+## 🔧 自定义和扩展
+
+### 修改页面内容
+
+编辑 `pageTemplates.js` 中的内容生成函数:
+
+```javascript
+function generateCustomContent(seoConfig) {
+ return `
+ 自定义内容
+ 这里写你的自定义内容...
+ `;
+}
+```
+
+### 添加新路由
+
+1. 在 `run.js` 中添加路由配置
+2. 在 `pageTemplates.js` 中添加内容生成函数
+3. 重新生成静态页面
+
+### 修改样式
+
+编辑 `pageTemplates.js` 中的CSS样式部分。
+
+---
+
+## ✨ 优势总结
+
+### 与其他方案对比
+
+| 特性 | 方案一(本方案) | 方案二(Puppeteer) | 方案三(动态渲染) | 方案四(Nuxt.js) |
+|------|-----------------|---------------------|-------------------|-------------------|
+| 实现难度 | ⭐⭐ 简单 | ⭐⭐⭐⭐ 复杂 | ⭐⭐⭐⭐⭐ 非常复杂 | ⭐⭐⭐⭐⭐ 非常复杂 |
+| 性能 | ⭐⭐⭐⭐⭐ 优秀 | ⭐⭐⭐ 一般 | ⭐⭐ 较差 | ⭐⭐⭐⭐⭐ 优秀 |
+| 维护成本 | ⭐⭐ 低 | ⭐⭐⭐ 中等 | ⭐⭐⭐⭐ 较高 | ⭐⭐⭐⭐⭐ 很高 |
+| SEO效果 | ⭐⭐⭐⭐ 优秀 | ⭐⭐⭐⭐⭐ 完美 | ⭐⭐⭐⭐⭐ 完美 | ⭐⭐⭐⭐⭐ 完美 |
+| 灵活性 | ⭐⭐⭐⭐ 高 | ⭐⭐⭐ 中等 | ⭐⭐⭐⭐⭐ 很高 | ⭐⭐⭐⭐⭐ 很高 |
+| 成本 | ⭐⭐⭐⭐⭐ 很低 | ⭐⭐⭐ 中等 | ⭐⭐ 较高 | ⭐⭐⭐⭐⭐ 很高 |
+
+### 推荐理由
+
+✅ **实现简单** - 无需重构现有代码
+✅ **性能优异** - 静态页面响应速度快
+✅ **易于维护** - 静态页面模板结构清晰
+✅ **成本可控** - 不增加服务器负担
+✅ **效果良好** - 满足大部分SEO需求
+✅ **灵活扩展** - 支持自定义和扩展
+
+---
+
+## 🎊 恭喜!
+
+方案一已经完整实现并可以直接使用!
+
+现在你可以:
+1. ✅ 查看生成的静态页面
+2. ✅ 根据需要修改配置
+3. ✅ 部署到测试环境
+4. ✅ 部署到生产环境
+5. ✅ 验证SEO效果
+
+---
+
+## 📞 技术支持
+
+如有问题,请参考:
+- 📖 详细文档:`scripts/seo-static-generator/README.md`
+- 📖 部署指南:`DEPLOYMENT_GUIDE.md`
+- 📖 集成指南:`SEO_INTEGRATION.md`
+- 📖 快速开始:`SEO_QUICKSTART.md`
+
+---
+
+**🎉 祝部署成功!**
diff --git a/scripts/seo-static-generator/crawlerMiddleware.js b/scripts/seo-static-generator/crawlerMiddleware.js
new file mode 100644
index 0000000..9f62869
--- /dev/null
+++ b/scripts/seo-static-generator/crawlerMiddleware.js
@@ -0,0 +1,324 @@
+/**
+ * 爬虫检测中间件
+ * 用于识别和区分搜索引擎爬虫和正常用户访问
+ */
+
+// 常见搜索引擎爬虫的User-Agent列表
+const SEARCH_ENGINE_BOTS = [
+ // Google
+ 'googlebot',
+ 'googlebot-image',
+ 'googlebot-news',
+ 'mediapartners-google',
+ 'adsbot-google',
+
+ // 百度
+ 'baiduspider',
+ 'baiduspider-mobile',
+
+ // 必应
+ 'bingbot',
+ 'msnbot',
+
+ // 360
+ '360spider',
+
+ // 搜狗
+ 'sogou spider',
+ 'sogou-orion',
+
+ // 雅虎
+ 'slurp',
+ 'yahoo',
+
+ // Yandex
+ 'yandex',
+
+ // DuckDuckGo
+ 'duckduckbot',
+
+ // 头头条
+ 'bytespider',
+
+ // 神马
+ 'yisouspider',
+
+ // 其他
+ 'spider',
+ 'crawl',
+ 'bot',
+ 'curl',
+ 'wget',
+];
+
+// 爬虫检测函数
+export function isCrawler(userAgent) {
+ if (!userAgent) {
+ return false;
+ }
+
+ const ua = userAgent.toLowerCase();
+
+ // 检查是否匹配已知的爬虫User-Agent
+ return SEARCH_ENGINE_BOTS.some(bot => ua.includes(bot));
+}
+
+// Node.js Express 中间件
+export function crawlerMiddleware(options = {}) {
+ const {
+ staticPagesPath = '../static-pages',
+ fallbackPath = '/index.html',
+ debug = false
+ } = options;
+
+ return (req, res, next) => {
+ const userAgent = req.headers['user-agent'];
+
+ // 检测是否是爬虫
+ if (isCrawler(userAgent)) {
+ if (debug) {
+ console.log(`🕷️ 检测到爬虫: ${userAgent}`);
+ console.log(`📍 请求路径: ${req.path}`);
+ }
+
+ // 尝试返回对应的静态页面
+ const path = require('path');
+ const fs = require('fs');
+
+ const staticDir = path.join(__dirname, staticPagesPath);
+
+ // 将路径转换为文件名
+ let filename = req.path
+ .replace(/^\//, '')
+ .replace(/\/+/g, '-')
+ .replace(/:/g, '-');
+
+ if (!filename) {
+ filename = 'index';
+ }
+
+ const filepath = path.join(staticDir, `${filename}.html`);
+
+ // 检查静态文件是否存在
+ if (fs.existsSync(filepath)) {
+ if (debug) {
+ console.log(`📄 返回静态页面: ${filepath}`);
+ }
+
+ const html = fs.readFileSync(filepath, 'utf-8');
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
+ res.send(html);
+ return;
+ } else {
+ if (debug) {
+ console.log(`⚠️ 静态页面不存在: ${filepath}`);
+ }
+ }
+ }
+
+ // 正常用户或未找到静态页面,继续处理
+ next();
+ };
+}
+
+// Nginx 配置生成器
+export function generateNginxConfig(options = {}) {
+ const {
+ serverName = 'www.tianyuancha.cn',
+ spaRoot = '/var/www/tyc-webview-v2/dist',
+ staticRoot = '/var/www/tyc-webview-v2/static-pages',
+ sslEnabled = false,
+ sslCertPath = '',
+ sslKeyPath = ''
+ } = options;
+
+ const protocol = sslEnabled ? 'https' : 'http';
+ const listenPort = sslEnabled ? '443 ssl' : '80';
+ const sslConfig = sslEnabled ? `
+ ssl_certificate ${sslCertPath};
+ ssl_certificate_key ${sslKeyPath};
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+` : '';
+
+ const httpRedirect = sslEnabled ? `
+# HTTP 重定向到 HTTPS
+server {
+ listen 80;
+ server_name ${serverName};
+ return 301 https://$server_name$request_uri;
+}
+` : '';
+
+ return `# Nginx 配置文件 - 天远查 SPA + SEO 静态页面
+# 自动生成时间: ${new Date().toLocaleString('zh-CN')}
+
+${httpRedirect}
+
+server {
+ listen ${listenPort};
+ server_name ${serverName};
+ charset utf-8;
+
+${sslConfig}
+ # 日志配置
+ access_log /var/log/nginx/${serverName}-access.log;
+ error_log /var/log/nginx/${serverName}-error.log;
+
+ # 爬虫检测
+ set $is_bot 0;
+
+ # Google
+ if ($http_user_agent ~* (googlebot|googlebot-image|googlebot-news|mediapartners-google|adsbot-google)) {
+ set $is_bot 1;
+ }
+
+ # 百度
+ if ($http_user_agent ~* (baiduspider|baiduspider-mobile)) {
+ set $is_bot 1;
+ }
+
+ # 必应
+ if ($http_user_agent ~* (bingbot|msnbot)) {
+ set $is_bot 1;
+ }
+
+ # 360
+ if ($http_user_agent ~* "360spider") {
+ set $is_bot 1;
+ }
+
+ # 搜狗
+ if ($http_user_agent ~* "(sogou spider|sogou-orion)") {
+ set $is_bot 1;
+ }
+
+ # 其他爬虫
+ if ($http_user_agent ~* "(spider|crawl|bot|slurp|yandex|duckduckbot|bytespider|yisouspider)") {
+ set $is_bot 1;
+ }
+
+ # 根路径处理
+ location = / {
+ if ($is_bot = 1) {
+ root ${staticRoot};
+ try_files /index.html /index.html;
+ break;
+ }
+ root ${spaRoot};
+ try_files $uri $uri/ /index.html;
+ }
+
+ # 静态页面处理
+ location ~ ^/([^/]+)(/.*)?$ {
+ # 将路径转换为文件名
+ set $static_filename $1;
+ set $rest_path $2;
+
+ if ($is_bot = 1) {
+ root ${staticRoot};
+ try_files /$static_filename.html /index.html;
+ break;
+ }
+ root ${spaRoot};
+ try_files $uri $uri/ /index.html;
+ }
+
+ # SPA 路由回退
+ location / {
+ root ${spaRoot};
+ try_files $uri $uri/ /index.html;
+ add_header Cache-Control "no-cache";
+ }
+
+ # 静态资源缓存
+ location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+ root ${spaRoot};
+ expires 1y;
+ add_header Cache-Control "public, immutable";
+ }
+
+ # API 代理
+ location /api/ {
+ proxy_pass http://localhost:8080;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection 'upgrade';
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_cache_bypass $http_upgrade;
+ }
+
+ # Gzip 压缩
+ gzip on;
+ gzip_vary on;
+ gzip_min_length 1024;
+ gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;
+
+ # 安全头
+ add_header X-Frame-Options "SAMEORIGIN";
+ add_header X-Content-Type-Options "nosniff";
+ add_header X-XSS-Protection "1; mode=block";
+}
+`;
+}
+
+// 生成 .htaccess 文件(Apache)
+export function generateHtaccessConfig(options = {}) {
+ const {
+ staticRoot = '/static-pages',
+ spaRoot = '/'
+ } = options;
+
+ return `# Apache .htaccess 配置 - 天远查 SPA + SEO 静态页面
+# 自动生成时间: ${new Date().toLocaleString('zh-CN')}
+
+# 启用重写引擎
+RewriteEngine On
+
+# 爬虫检测
+RewriteCond %{HTTP_USER_AGENT} (googlebot|googlebot-image|googlebot-news|mediapartners-google|adsbot-google) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (baiduspider|baiduspider-mobile) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (bingbot|msnbot) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} "360spider" [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (sogou spider|sogou-orion) [NC,OR]
+RewriteCond %{HTTP_USER_AGENT} (spider|crawl|bot|slurp|yandex|duckduckbot|bytespider|yisouspider) [NC]
+
+# 爬虫访问静态页面
+RewriteRule ^$ ${staticRoot}/index.html [L]
+RewriteRule ^([^/]+)/?$ ${staticRoot}/$1.html [L]
+RewriteRule ^([^/]+)/(.+)$ ${staticRoot}/$1.html [L]
+
+# 正常用户访问 SPA
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule . ${spaRoot}index.html [L]
+
+# Gzip 压缩
+
+ AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
+
+
+# 缓存控制
+
+ ExpiresActive On
+ ExpiresByType image/jpg "access plus 1 year"
+ ExpiresByType image/jpeg "access plus 1 year"
+ ExpiresByType image/gif "access plus 1 year"
+ ExpiresByType image/png "access plus 1 year"
+ ExpiresByType text/css "access plus 1 month"
+ ExpiresByType application/javascript "access plus 1 month"
+
+
+# 安全头
+
+ Header set X-Frame-Options "SAMEORIGIN"
+ Header set X-Content-Type-Options "nosniff"
+ Header set X-XSS-Protection "1; mode=block"
+
+`;
+}
+
+// 导出工具函数
+export { SEARCH_ENGINE_BOTS };
diff --git a/scripts/seo-static-generator/debug.js b/scripts/seo-static-generator/debug.js
new file mode 100644
index 0000000..a59b587
--- /dev/null
+++ b/scripts/seo-static-generator/debug.js
@@ -0,0 +1,39 @@
+/**
+ * 调试脚本
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+console.log('当前工作目录:', process.cwd());
+console.log('脚本目录:', __dirname);
+console.log('输出目录:', path.resolve(__dirname, 'static-pages'));
+
+const OUTPUT_DIR = path.resolve(__dirname, 'static-pages');
+
+console.log('\n创建目录...');
+try {
+ if (!fs.existsSync(OUTPUT_DIR)) {
+ fs.mkdirSync(OUTPUT_DIR, { recursive: true });
+ console.log('目录创建成功:', OUTPUT_DIR);
+ } else {
+ console.log('目录已存在:', OUTPUT_DIR);
+ }
+
+ // 写入测试文件
+ const testFile = path.join(OUTPUT_DIR, 'test.html');
+ fs.writeFileSync(testFile, '测试', 'utf-8');
+ console.log('测试文件写入成功:', testFile);
+
+ // 读取文件验证
+ const content = fs.readFileSync(testFile, 'utf-8');
+ console.log('文件内容:', content);
+
+} catch (error) {
+ console.error('错误:', error.message);
+ console.error('错误堆栈:', error.stack);
+}
diff --git a/scripts/seo-static-generator/generateNginxConfig.js b/scripts/seo-static-generator/generateNginxConfig.js
new file mode 100644
index 0000000..c0e1e12
--- /dev/null
+++ b/scripts/seo-static-generator/generateNginxConfig.js
@@ -0,0 +1,74 @@
+/**
+ * Nginx配置生成脚本
+ */
+
+import { generateNginxConfig, generateHtaccessConfig } from './crawlerMiddleware.js';
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+// 配置选项
+const config = {
+ serverName: 'www.tianyuancha.cn',
+ spaRoot: '/var/www/tyc-webview-v2/dist',
+ staticRoot: '/var/www/tyc-webview-v2/static-pages',
+ sslEnabled: false, // 如果使用HTTPS,设置为true
+ sslCertPath: '/etc/nginx/ssl/cert.pem',
+ sslKeyPath: '/etc/nginx/ssl/key.pem'
+};
+
+// 生成Nginx配置
+function main() {
+ console.log('='.repeat(60));
+ console.log(' 生成 Nginx 配置文件');
+ console.log('='.repeat(60));
+ console.log();
+
+ try {
+ // 生成Nginx配置
+ const nginxConfig = generateNginxConfig(config);
+
+ const nginxConfigPath = path.join(__dirname, 'nginx.conf');
+ fs.writeFileSync(nginxConfigPath, nginxConfig, 'utf-8');
+
+ console.log('✅ Nginx配置文件生成成功!');
+ console.log(`📁 保存路径: ${nginxConfigPath}`);
+ console.log();
+
+ console.log('📝 使用说明:');
+ console.log('1. 将生成的 nginx.conf 复制到 Nginx 配置目录');
+ console.log(`2. 修改配置中的路径(spaRoot、staticRoot等)为实际路径`);
+ console.log('3. 测试配置: nginx -t');
+ console.log('4. 重载Nginx: nginx -s reload');
+ console.log();
+
+ // 生成Apache .htaccess配置
+ const htaccessConfig = generateHtaccessConfig({
+ staticRoot: '/static-pages',
+ spaRoot: '/'
+ });
+
+ const htaccessPath = path.join(__dirname, '.htaccess');
+ fs.writeFileSync(htaccessPath, htaccessConfig, 'utf-8');
+
+ console.log('✅ Apache .htaccess 配置文件生成成功!');
+ console.log(`📁 保存路径: ${htaccessPath}`);
+ console.log();
+
+ console.log('📝 使用说明:');
+ console.log('1. 将生成的 .htaccess 复制到网站根目录');
+ console.log('2. 确保 Apache 启用了 mod_rewrite 模块');
+ console.log('3. 重启Apache服务');
+ console.log();
+
+ } catch (error) {
+ console.error('❌ 生成失败:', error);
+ process.exit(1);
+ }
+}
+
+// 运行
+main();
diff --git a/scripts/seo-static-generator/generateStaticPages.js b/scripts/seo-static-generator/generateStaticPages.js
new file mode 100644
index 0000000..2591403
--- /dev/null
+++ b/scripts/seo-static-generator/generateStaticPages.js
@@ -0,0 +1,261 @@
+/**
+ * 静态页面生成器
+ * 基于路由和SEO配置自动生成静态HTML页面
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import { generateStaticHTML, generateContentByRoute } from './pageTemplates.js';
+
+// 获取当前文件的目录
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+// SEO配置 - 直接从useSEO.js复制过来
+const seoConfigs = {
+ '/': {
+ title: '天远查官网_企业与婚姻关联风险核验_综合履约背景核验',
+ description: '天远查官网(TianYuanCha)聚合官方公示数据,专注于商业安全与资产背调。提供企业工商画像、婚姻状态关联风险、司法涉诉筛查及配偶债务核验。数据实时同步,助您精准规避投资、交易及家庭结合中的经济与法律风险。',
+ keywords: '天远查,婚姻状态风险, 配偶背景核验,企业信用查询,司法诉讼记录,资产风险评估'
+ },
+ '/inquire/category/lawsuit': {
+ title: '司法涉诉核验_个人及企业法律诉讼记录_履约风险评估_天远查',
+ description: '天远查司法风险检测中心,聚合全国法院公开公示数据。一键筛查开庭公告、裁判文书、立案信息及执行记录。帮助用户快速识别法律纠纷隐患,全方位扫除合作盲区。',
+ keywords: '司法案件核验,法律诉讼记录,个人涉诉详情,法院公告查询,案件执行状态'
+ },
+ '/inquire/marriage': {
+ title: '婚前背景核验_婚姻关联司法风险筛查_情感综合保障_天远查',
+ description: '天远查婚恋风险报告为您提供深度的背景核实服务。基于合法公开数据,排查对象的重婚司法记录、家庭暴力涉诉历史、潜在债务风险及不良嗜好风险。拒绝盲目信任,用数据守护您的情感与财产安全。',
+ keywords: '婚前背景核实,婚恋对象评估,婚姻司法风险,个人情感风险,婚前背调工具'
+ },
+ '/inquire/category/vehicle': {
+ title: '车辆档案报告_二手车车况与产权风险检测_机动车报告_天远查',
+ description: '天远查车辆数据中心,让车辆交易更透明。支持通过车牌号或VIN码,核验车辆的初次登记信息、抵押查封状态、事故维修记录及产权属性。数据同步权威行业系统,精准识别问题车。',
+ keywords: '车辆维修记录,二手车出险报告,车辆抵押报告,车况报告,机动车档案'
+ },
+ '/inquire/category/marriageStatus': {
+ title: '个人婚姻关联风险核验_家庭背景合规报告_天远查',
+ description: '天远查提供基于大数据的婚姻关联风险评估。通过分析司法文书及公开社会关系,辅助判断目标的真实家庭状况与情感履历。合法合规,保障知情权。',
+ keywords: '婚史风险排查,家庭背景核实,婚姻诚信评估,情感状态评估,涉婚法律记录'
+ },
+ '/agent': {
+ title: '天远查代理 - 免费开通代理权限 | 大数据风险报告代理',
+ description: '天远查代理平台,免费开通代理权限,享受大数据风险报告查询服务代理收益。专业的大数据风险报告、婚姻查询、个人信用评估等服务的代理合作。',
+ keywords: '天远查代理, 免费代理, 大数据风险报告代理, 代理权限, 代理收益'
+ },
+ '/help': {
+ title: '帮助中心 - 天远查使用指南 | 常见问题解答',
+ description: '天远查帮助中心,提供详细的使用指南、常见问题解答、操作教程等,帮助用户更好地使用大数据风险报告查询服务。',
+ keywords: '天远查帮助, 使用指南, 常见问题, 操作教程, 客服支持'
+ },
+ '/help/guide': {
+ title: '使用指南 - 天远查操作教程 | 功能说明',
+ description: '天远查详细使用指南,包含各功能模块的操作教程、功能说明、注意事项等,让用户快速上手使用。',
+ keywords: '使用指南, 操作教程, 功能说明, 快速上手, 天远查教程'
+ },
+ '/example': {
+ title: '示例报告 - 天远查报告展示 | 大数据风险报告样例',
+ description: '天远查示例报告展示,包含大数据风险报告、婚姻状况查询、个人信用评估等服务的报告样例,让用户了解报告内容和格式。',
+ keywords: '示例报告, 报告展示, 报告样例, 大数据风险报告, 婚姻查询报告'
+ },
+ '/service': {
+ title: '客服中心 - 天远查在线客服 | 技术支持',
+ description: '天远查客服中心,提供在线客服支持、技术咨询、问题反馈等服务,确保用户获得及时有效的帮助。',
+ keywords: '客服中心, 在线客服, 技术支持, 问题反馈, 天远查客服'
+ },
+ '/inquire': {
+ title: '核验工具多场景数据核验服务天远查',
+ description: '提供车辆、企业、个人等多场景核验,包括状态、信用、身份等查询,权威高效,保护隐私。',
+ keywords: '核验工具,数据核验服务,车辆核验,企业核验,天远查'
+ },
+};
+
+// 额外的路由配置(从router.js提取)
+const additionalRoutes = [
+ { path: '/historyQuery', title: '历史报告' },
+ { path: '/withdraw', title: '提现' },
+ { path: '/complaint', title: '投诉' },
+ { path: '/report', title: '报告结果' },
+ { path: '/agent/promote', title: '代理推广' },
+ { path: '/me', title: '个人中心' },
+];
+
+// 输出目录配置
+const OUTPUT_DIR = path.resolve(__dirname, 'static-pages');
+
+// 确保输出目录存在
+function ensureOutputDir() {
+ try {
+ if (!fs.existsSync(OUTPUT_DIR)) {
+ fs.mkdirSync(OUTPUT_DIR, { recursive: true });
+ console.log(`📁 创建输出目录: ${OUTPUT_DIR}`);
+ }
+ console.log(`📂 输出目录已存在: ${OUTPUT_DIR}`);
+ } catch (error) {
+ console.error(`❌ 创建目录失败: ${error.message}`);
+ throw error;
+ }
+}
+
+// 将路径转换为文件名
+function pathToFilename(routePath) {
+ // 替换特殊字符
+ let filename = routePath
+ .replace(/^\//, '') // 移除开头的 /
+ .replace(/\/+/g, '-') // 将 / 替换为 -
+ .replace(/:/g, '-') // 将 : 替换为 -
+
+ // 如果是根路径,使用 index
+ if (!filename) {
+ filename = 'index';
+ }
+
+ return `${filename}.html`;
+}
+
+// 生成静态页面
+function generatePage(routePath, seoConfig) {
+ const filename = pathToFilename(routePath);
+ const filepath = path.join(OUTPUT_DIR, filename);
+
+ // 生成页面内容
+ const content = generateContentByRoute(routePath, seoConfig);
+
+ // 生成完整的HTML
+ const html = generateStaticHTML(seoConfig, {
+ path: routePath,
+ content: content,
+ canonical: 'https://www.tianyuancha.cn'
+ });
+
+ // 写入文件
+ fs.writeFileSync(filepath, html, 'utf-8');
+ process.stdout.write(`✅ 生成成功: ${filename}\n`);
+
+ return filepath;
+}
+
+// 生成所有静态页面
+function generateAllPages() {
+ console.log('🚀 开始生成静态页面...\n');
+
+ ensureOutputDir();
+
+ // 生成主要路由的页面
+ console.log('📝 生成主要路由页面:');
+ let count = 0;
+ for (const [routePath, seoConfig] of Object.entries(seoConfigs)) {
+ try {
+ generatePage(routePath, seoConfig);
+ count++;
+ } catch (error) {
+ console.error(`❌ 生成失败 [${routePath}]:`, error.message);
+ }
+ }
+
+ // 生成额外路由的页面
+ console.log('\n📝 生成额外路由页面:');
+ for (const route of additionalRoutes) {
+ try {
+ const seoConfig = {
+ title: `${route.title} - 天远查`,
+ description: `天远查${route.title}页面,提供专业的大数据风险管控服务。`,
+ keywords: `天远查,${route.title}`
+ };
+ generatePage(route.path, seoConfig);
+ count++;
+ } catch (error) {
+ console.error(`❌ 生成失败 [${route.path}]:`, error.message);
+ }
+ }
+
+ // 生成sitemap
+ generateSitemap();
+
+ console.log(`\n✨ 完成!共生成 ${count} 个静态页面`);
+ console.log(`📁 输出目录: ${OUTPUT_DIR}`);
+}
+
+// 生成sitemap.xml
+function generateSitemap() {
+ const sitemapPath = path.join(OUTPUT_DIR, 'sitemap.xml');
+
+ const baseUrl = 'https://www.tianyuancha.cn';
+ const currentDate = new Date().toISOString().split('T')[0];
+
+ let sitemap = `
+
+`;
+
+ // 添加主要路由
+ for (const [routePath] of Object.entries(seoConfigs)) {
+ const priority = routePath === '/' ? '1.0' : '0.8';
+ sitemap += `
+ ${baseUrl}${routePath}
+ ${currentDate}
+ weekly
+ ${priority}
+
+`;
+ }
+
+ // 添加额外路由
+ for (const route of additionalRoutes) {
+ sitemap += `
+ ${baseUrl}${route.path}
+ ${currentDate}
+ weekly
+ 0.6
+
+`;
+ }
+
+ sitemap += ``;
+
+ fs.writeFileSync(sitemapPath, sitemap, 'utf-8');
+ console.log(`✅ 生成成功: ${sitemapPath}`);
+}
+
+// 生成robots.txt
+function generateRobots() {
+ const robotsPath = path.join(OUTPUT_DIR, 'robots.txt');
+
+ const robotsContent = `User-agent: *
+Allow: /
+
+# 禁止爬取后台管理页面
+Disallow: /admin
+Disallow: /api
+
+# Sitemap
+Sitemap: https://www.tianyuancha.cn/sitemap.xml
+`;
+
+ fs.writeFileSync(robotsPath, robotsContent, 'utf-8');
+ console.log(`✅ 生成成功: ${robotsPath}`);
+}
+
+// 主函数
+function main() {
+ console.log('='.repeat(60));
+ console.log(' 天远查 - 静态页面生成器');
+ console.log('='.repeat(60));
+ console.log();
+
+ try {
+ generateAllPages();
+ generateRobots();
+ console.log('\n🎉 所有文件生成完成!');
+ } catch (error) {
+ console.error('\n❌ 生成失败:', error);
+ process.exit(1);
+ }
+}
+
+// 如果直接运行此脚本
+if (import.meta.url === `file://${process.argv[1]}`) {
+ main();
+}
+
+export { generateAllPages, generatePage };
diff --git a/scripts/seo-static-generator/index.html b/scripts/seo-static-generator/index.html
new file mode 100644
index 0000000..1bd7a38
--- /dev/null
+++ b/scripts/seo-static-generator/index.html
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+ 天远查官网_企业与婚姻关联风险核验_综合履约背景核验
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 关于天远查官网_企业与婚姻关联风险核验_综合履约背景核验
+ 天远查官网(TianYuanCha)聚合官方公示数据,专注于商业安全与资产背调。提供企业工商画像、婚姻状态关联风险、司法涉诉筛查及配偶债务核验。数据实时同步,助您精准规避投资、交易及家庭结合中的经济与法律风险。
+
+ 核心功能
+
+ - 企业工商信息查询 - 实时获取企业注册信息、股东信息、经营状况等
+ - 婚姻状态风险核验 - 通过公开数据查询个人婚姻相关司法风险
+ - 司法涉诉筛查 - 查询个人及企业的法律诉讼记录、执行信息等
+ - 车辆档案报告 - 二手车车况检测、抵押查封状态查询
+ - 个人信用评估 - 全方位的个人信用风险评估
+
+
+ 为什么选择天远查?
+
+ - 数据权威 - 聚合官方公示数据,确保信息准确可靠
+ - 更新及时 - 数据实时同步,第一时间获取最新信息
+ - 隐私安全 - 严格保护用户隐私,数据传输加密
+ - 专业服务 - 多年行业经验,专业技术团队支持
+
+
+ 应用场景
+
+ - 投资尽调 - 投资前全面了解目标企业和个人的风险状况
+ - 合作风控 - 商业合作前评估潜在风险,保护自身利益
+ - 婚恋背调 - 婚前了解对方背景,避免情感和财产风险
+ - 招聘核查 - 企业招聘时核实候选人信息真实性
+ - 二手车交易 - 购买二手车前全面了解车辆历史和车况
+
+
+ 数据来源
+ 天远查的数据来源于以下官方渠道:
+
+ - 国家企业信用信息公示系统
+ - 中国裁判文书网
+ - 执行信息公开网
+ - 各省市法院公开信息
+ - 其他权威官方数据平台
+
+
+ 联系我们
+ 如果您有任何问题或需要帮助,请通过以下方式联系我们:
+
+
+
+
💡 这是静态页面的示例,实际部署时爬虫会看到此页面,正常用户会访问完整的 SPA 应用。
+
+
+
+
+
+
+
diff --git a/scripts/seo-static-generator/nginx-production.conf b/scripts/seo-static-generator/nginx-production.conf
new file mode 100644
index 0000000..c16ffb8
--- /dev/null
+++ b/scripts/seo-static-generator/nginx-production.conf
@@ -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;
+}
diff --git a/scripts/seo-static-generator/nginx.conf b/scripts/seo-static-generator/nginx.conf
new file mode 100644
index 0000000..aa5b6f3
--- /dev/null
+++ b/scripts/seo-static-generator/nginx.conf
@@ -0,0 +1,111 @@
+# Nginx 配置文件 - 天远查 SPA + SEO 静态页面
+# 自动生成时间: 2026/2/25 11:04:50
+
+
+
+server {
+ listen 80;
+ server_name www.tianyuancha.cn;
+ charset utf-8;
+
+
+ # 日志配置
+ access_log /var/log/nginx/www.tianyuancha.cn-access.log;
+ error_log /var/log/nginx/www.tianyuancha.cn-error.log;
+
+ # 爬虫检测
+ set $is_bot 0;
+
+ # Google
+ if ($http_user_agent ~* (googlebot|googlebot-image|googlebot-news|mediapartners-google|adsbot-google)) {
+ set $is_bot 1;
+ }
+
+ # 百度
+ if ($http_user_agent ~* (baiduspider|baiduspider-mobile)) {
+ set $is_bot 1;
+ }
+
+ # 必应
+ if ($http_user_agent ~* (bingbot|msnbot)) {
+ set $is_bot 1;
+ }
+
+ # 360
+ if ($http_user_agent ~* "360spider") {
+ set $is_bot 1;
+ }
+
+ # 搜狗
+ if ($http_user_agent ~* "(sogou spider|sogou-orion)") {
+ set $is_bot 1;
+ }
+
+ # 其他爬虫
+ if ($http_user_agent ~* "(spider|crawl|bot|slurp|yandex|duckduckbot|bytespider|yisouspider)") {
+ set $is_bot 1;
+ }
+
+ # 根路径处理
+ location = / {
+ if ($is_bot = 1) {
+ root /var/www/tyc-webview-v2/static-pages;
+ try_files /index.html /index.html;
+ break;
+ }
+ root /var/www/tyc-webview-v2/dist;
+ try_files $uri $uri/ /index.html;
+ }
+
+ # 静态页面处理
+ location ~ ^/([^/]+)(/.*)?$ {
+ # 将路径转换为文件名
+ set $static_filename $1;
+ set $rest_path $2;
+
+ if ($is_bot = 1) {
+ root /var/www/tyc-webview-v2/static-pages;
+ try_files /$static_filename.html /index.html;
+ break;
+ }
+ root /var/www/tyc-webview-v2/dist;
+ try_files $uri $uri/ /index.html;
+ }
+
+ # SPA 路由回退
+ location / {
+ root /var/www/tyc-webview-v2/dist;
+ try_files $uri $uri/ /index.html;
+ add_header Cache-Control "no-cache";
+ }
+
+ # 静态资源缓存
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+ root /var/www/tyc-webview-v2/dist;
+ expires 1y;
+ add_header Cache-Control "public, immutable";
+ }
+
+ # API 代理
+ location /api/ {
+ proxy_pass http://localhost:8080;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection 'upgrade';
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_cache_bypass $http_upgrade;
+ }
+
+ # Gzip 压缩
+ gzip on;
+ gzip_vary on;
+ gzip_min_length 1024;
+ gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;
+
+ # 安全头
+ add_header X-Frame-Options "SAMEORIGIN";
+ add_header X-Content-Type-Options "nosniff";
+ add_header X-XSS-Protection "1; mode=block";
+}
diff --git a/scripts/seo-static-generator/package.json b/scripts/seo-static-generator/package.json
new file mode 100644
index 0000000..5563a07
--- /dev/null
+++ b/scripts/seo-static-generator/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "seo-static-generator",
+ "version": "1.0.0",
+ "description": "天远查静态页面生成器 - 为SPA应用生成SEO友好的静态页面",
+ "type": "module",
+ "scripts": {
+ "generate": "node generateStaticPages.js",
+ "nginx": "node generateNginxConfig.js",
+ "htaccess": "node generateHtaccessConfig.js"
+ },
+ "keywords": [
+ "seo",
+ "static-site-generator",
+ "spa",
+ "crawler",
+ "vue"
+ ],
+ "author": "天远查",
+ "license": "MIT"
+}
diff --git a/scripts/seo-static-generator/pageTemplates.js b/scripts/seo-static-generator/pageTemplates.js
new file mode 100644
index 0000000..c910088
--- /dev/null
+++ b/scripts/seo-static-generator/pageTemplates.js
@@ -0,0 +1,577 @@
+/**
+ * 静态页面模板
+ * 基于SEO配置生成优化的静态HTML页面
+ */
+
+/**
+ * 生成静态页面的HTML内容
+ * @param {Object} seoConfig - SEO配置对象
+ * @param {Object} options - 额外配置
+ * @returns {string} - 完整的HTML字符串
+ */
+export function generateStaticHTML(seoConfig, options = {}) {
+ const {
+ path = '/',
+ content = '',
+ customCSS = '',
+ canonical = 'https://www.tianyuancha.cn',
+ ogImage = 'https://www.tianyuancha.cn/logo.png'
+ } = options;
+
+ const fullCanonical = `${canonical}${path}`;
+
+ return `
+
+
+
+
+
+
+
+ ${seoConfig.title || '天远查'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${content || generateDefaultContent(seoConfig)}
+
+
+
+
+
+
+
+`;
+}
+
+/**
+ * 生成默认页面内容
+ * @param {Object} seoConfig - SEO配置
+ * @returns {string} - HTML内容字符串
+ */
+function generateDefaultContent(seoConfig) {
+ const title = seoConfig.title || '天远查';
+ const description = seoConfig.description || '天远查 - 专业大数据风险报告查询与代理平台';
+ const keywords = seoConfig.keywords || '天远查';
+
+ return `
+ 关于${title}
+ ${description}
+
+ 核心功能
+
+ - 企业工商信息查询 - 实时获取企业注册信息、股东信息、经营状况等
+ - 婚姻状态风险核验 - 通过公开数据查询个人婚姻相关司法风险
+ - 司法涉诉筛查 - 查询个人及企业的法律诉讼记录、执行信息等
+ - 车辆档案报告 - 二手车车况检测、抵押查封状态查询
+ - 个人信用评估 - 全方位的个人信用风险评估
+
+
+ 为什么选择天远查?
+
+ - 数据权威 - 聚合官方公示数据,确保信息准确可靠
+ - 更新及时 - 数据实时同步,第一时间获取最新信息
+ - 隐私安全 - 严格保护用户隐私,数据传输加密
+ - 专业服务 - 多年行业经验,专业技术团队支持
+
+
+ 应用场景
+
+ - 投资尽调 - 投资前全面了解目标企业和个人的风险状况
+ - 合作风控 - 商业合作前评估潜在风险,保护自身利益
+ - 婚恋背调 - 婚前了解对方背景,避免情感和财产风险
+ - 招聘核查 - 企业招聘时核实候选人信息真实性
+ - 二手车交易 - 购买二手车前全面了解车辆历史和车况
+
+
+ 数据来源
+ 天远查的数据来源于以下官方渠道:
+
+ - 国家企业信用信息公示系统
+ - 中国裁判文书网
+ - 执行信息公开网
+ - 各省市法院公开信息
+ - 其他权威官方数据平台
+
+
+ 联系我们
+ 如果您有任何问题或需要帮助,请通过以下方式联系我们:
+
+ `;
+}
+
+/**
+ * 针对不同路由生成定制内容
+ * @param {string} path - 路由路径
+ * @param {Object} seoConfig - SEO配置
+ * @returns {string} - HTML内容字符串
+ */
+export function generateContentByRoute(path, seoConfig) {
+ const routeContentMap = {
+ '/': generateHomeContent(seoConfig),
+ '/inquire/category/lawsuit': generateLawsuitContent(seoConfig),
+ '/inquire/marriage': generateMarriageContent(seoConfig),
+ '/inquire/category/vehicle': generateVehicleContent(seoConfig),
+ '/inquire/category/marriageStatus': generateMarriageStatusContent(seoConfig),
+ '/agent': generateAgentContent(seoConfig),
+ '/help': generateHelpContent(seoConfig),
+ '/example': generateExampleContent(seoConfig),
+ '/service': generateServiceContent(seoConfig),
+ '/inquire': generateInquireContent(seoConfig),
+ };
+
+ return routeContentMap[path] || generateDefaultContent(seoConfig);
+}
+
+// 各个页面的定制内容生成函数
+function generateHomeContent(seoConfig) {
+ return `
+ 欢迎使用天远查
+ 天远查(TianYuanCha)是专业的大数据风险报告查询与代理平台,聚合官方公示数据,为个人和企业提供全方位的风险管控服务。
+
+ 我们的服务
+
+ - 企业信息查询 - 查询企业工商信息、经营状况、司法风险等
+ - 婚姻风险核验 - 通过公开数据查询婚姻相关司法风险
+ - 司法涉诉筛查 - 全面筛查个人及企业的法律纠纷
+ - 车辆档案报告 - 二手车交易前的全面车况检测
+ - 个人信用评估 - 多维度个人信用风险分析
+
+
+ 立即开始
+ 访问天远查官网,开始您的风险查询之旅:https://www.tianyuancha.cn
+ `;
+}
+
+function generateLawsuitContent(seoConfig) {
+ return `
+ 司法涉诉核验服务
+ 天远查司法风险检测中心,聚合全国法院公开公示数据,为您提供全面的司法涉诉筛查服务。
+
+ 服务内容
+
+ - 开庭公告查询 - 查询即将开庭的案件信息
+ - 裁判文书查询 - 获取历史裁判文书详情
+ - 立案信息查询 - 了解案件立案情况
+ - 执行记录查询 - 查询强制执行相关信息
+ - 失信被执行人查询 - 核实失信被执行人名单
+
+
+ 应用场景
+
+ - 商业合作前了解对方法律纠纷情况
+ - 投资前的法律风险评估
+ - 招聘时核实候选人背景
+ - 婚恋前了解对方法律风险
+
+
+ 数据来源
+ 数据来源于全国各级法院公开公示信息,确保权威准确。
+ `;
+}
+
+function generateMarriageContent(seoConfig) {
+ return `
+ 婚前背景核验服务
+ 天远查婚恋风险报告为您提供深度的背景核实服务,帮助您在婚恋前全面了解对方的真实情况。
+
+ 服务内容
+
+ - 重婚司法记录查询 - 查询是否有重婚相关司法记录
+ - 家庭暴力涉诉历史 - 查询家庭暴力相关的法律纠纷
+ - 潜在债务风险 - 通过司法文书分析潜在债务情况
+ - 不良嗜好风险 - 了解是否有相关不良记录
+
+
+ 为什么需要婚前背景核验?
+
+ - 保护自己的情感安全
+ - 避免经济损失和债务纠纷
+ - 了解对方的真实家庭状况
+ - 建立坦诚的婚恋关系
+
+
+ 服务特点
+
+ - 基于合法公开数据
+ - 数据真实可靠
+ - 保护隐私安全
+ - 快速获取报告
+
+ `;
+}
+
+function generateVehicleContent(seoConfig) {
+ return `
+ 车辆档案报告服务
+ 天远查车辆数据中心,让车辆交易更透明。通过车牌号或VIN码,全面了解车辆的真实状况。
+
+ 服务内容
+
+ - 初次登记信息 - 查询车辆的初次登记时间、地点
+ - 抵押查封状态 - 了解车辆是否被抵押或查封
+ - 事故维修记录 - 获取车辆的事故和维修历史
+ - 产权属性核验 - 核实车辆的产权归属
+ - 过户记录查询 - 查询车辆的历史过户情况
+
+
+ 应用场景
+
+ - 购买二手车前全面了解车况
+ - 出售二手车时提供车况证明
+ - 车辆抵押前核实车辆状况
+
+
+ 数据来源
+ 数据同步权威行业系统,包括车管所、保险公司等,信息准确可靠。
+ `;
+}
+
+function generateMarriageStatusContent(seoConfig) {
+ return `
+ 个人婚姻关联风险核验
+ 天远查提供基于大数据的婚姻关联风险评估,通过分析司法文书及公开社会关系,辅助判断目标的真实家庭状况。
+
+ 服务内容
+
+ - 婚史风险排查 - 通过公开数据排查婚姻历史风险
+ - 家庭背景核实 - 核实家庭背景相关信息
+ - 婚姻诚信评估 - 评估婚姻相关的诚信记录
+ - 情感状态评估 - 通过多维度数据分析情感状态
+ - 涉婚法律记录 - 查询与婚姻相关的法律记录
+
+
+ 服务优势
+
+ - 合法合规 - 仅使用合法公开数据
+ - 数据权威 - 来源于官方公开渠道
+ - 分析全面 - 多维度综合评估
+ - 保护隐私 - 严格保护用户隐私
+
+ `;
+}
+
+function generateAgentContent(seoConfig) {
+ return `
+ 天远查代理 - 免费开通代理权限
+ 天远查代理平台,免费开通代理权限,享受大数据风险报告查询服务代理收益。
+
+ 代理权益
+
+ - 免费开通代理权限
+ - 享受丰厚佣金收益
+ - 专属推广链接
+ - 实时数据统计
+ - 专业培训支持
+
+
+ 代理产品
+
+ - 企业信息查询代理
+ - 婚姻状态风险核验代理
+ - 司法涉诉筛查代理
+ - 车辆档案报告代理
+ - 个人信用评估代理
+
+
+ 申请流程
+
+ - 注册天远查账号
+ - 提交代理申请
+ - 审核通过后开通权限
+ - 开始推广并获取收益
+
+
+ 立即加入
+ 访问天远查代理页面,免费开通代理权限:https://www.tianyuancha.cn/agent
+ `;
+}
+
+function generateHelpContent(seoConfig) {
+ return `
+ 帮助中心
+ 天远查帮助中心,提供详细的使用指南、常见问题解答、操作教程等,帮助用户更好地使用大数据风险报告查询服务。
+
+ 热门问题
+
+ - 如何查询企业信息?
+ - 婚姻风险核验需要什么信息?
+ - 如何获取报告?
+ - 报告准确性如何保证?
+ - 如何成为代理?
+
+
+ 使用指南
+
+ - 新手入门指南
+ - 各功能模块使用教程
+ - 常见问题解答
+ - 注意事项说明
+
+
+ 联系我们
+ 如果您有其他问题,可以通过以下方式联系我们:
+
+ `;
+}
+
+function generateExampleContent(seoConfig) {
+ return `
+ 示例报告展示
+ 天远查示例报告展示,包含大数据风险报告、婚姻状况查询、个人信用评估等服务的报告样例。
+
+ 报告类型
+
+ - 企业工商画像报告示例
+ - 婚姻状态风险报告示例
+ - 司法涉诉筛查报告示例
+ - 车辆档案报告示例
+ - 个人信用评估报告示例
+
+
+ 报告内容
+
+ - 基本信息展示
+ - 风险分析说明
+ - 数据来源标注
+ - 评估结果解读
+
+
+ 查看示例
+ 访问天远查示例页面,查看详细的报告样例:https://www.tianyuancha.cn/example
+ `;
+}
+
+function generateServiceContent(seoConfig) {
+ return `
+ 客服中心
+ 天远查客服中心,提供在线客服支持、技术咨询、问题反馈等服务,确保用户获得及时有效的帮助。
+
+ 服务内容
+
+ - 在线客服支持
+ - 技术咨询解答
+ - 问题反馈处理
+ - 使用指导服务
+
+
+ 服务时间
+
+ - 工作日:9:00 - 18:00
+ - 周末:10:00 - 17:00
+ - 节假日:以公告为准
+
+
+ 联系我们
+ 通过以下方式联系我们的客服团队:
+
+ `;
+}
+
+function generateInquireContent(seoConfig) {
+ return `
+ 核验工具多场景数据核验服务
+ 天远查提供车辆、企业、个人等多场景核验服务,包括状态、信用、身份等查询,权威高效,保护隐私。
+
+ 核验服务
+
+ - 车辆核验 - 车牌号/VIN码查询车辆档案
+ - 企业核验 - 企业工商信息查询
+ - 个人核验 - 个人身份和信用查询
+ - 婚姻核验 - 婚姻状态风险核验
+ - 司法核验 - 司法涉诉筛查
+
+
+ 服务特点
+
+ - 权威数据来源
+ - 快速查询响应
+ - 全面信息覆盖
+ - 严格隐私保护
+
+
+ 立即查询
+ 访问天远查核验页面,开始您的查询:https://www.tianyuancha.cn/inquire
+ `;
+}
diff --git a/scripts/seo-static-generator/run.js b/scripts/seo-static-generator/run.js
new file mode 100644
index 0000000..aa3ce20
--- /dev/null
+++ b/scripts/seo-static-generator/run.js
@@ -0,0 +1,194 @@
+/**
+ * 简化的静态页面生成器 - Windows兼容版本
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import { generateStaticHTML } from './pageTemplates.js';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+// 简化的SEO配置
+const seoConfigs = {
+ '/': {
+ title: '天远查官网_企业与婚姻关联风险核验_综合履约背景核验',
+ description: '天远查官网(TianYuanCha)聚合官方公示数据,专注于商业安全与资产背调。提供企业工商画像、婚姻状态关联风险、司法涉诉筛查及配偶债务核验。数据实时同步,助您精准规避投资、交易及家庭结合中的经济与法律风险。',
+ keywords: '天远查,婚姻状态风险, 配偶背景核验,企业信用查询,司法诉讼记录,资产风险评估'
+ },
+ '/inquire/category/lawsuit': {
+ title: '司法涉诉核验_个人及企业法律诉讼记录_履约风险评估_天远查',
+ description: '天远查司法风险检测中心,聚合全国法院公开公示数据。一键筛查开庭公告、裁判文书、立案信息及执行记录。帮助用户快速识别法律纠纷隐患,全方位扫除合作盲区。',
+ keywords: '司法案件核验,法律诉讼记录,个人涉诉详情,法院公告查询,案件执行状态'
+ },
+ '/inquire/marriage': {
+ title: '婚前背景核验_婚姻关联司法风险筛查_情感综合保障_天远查',
+ description: '天远查婚恋风险报告为您提供深度的背景核实服务。基于合法公开数据,排查对象的重婚司法记录、家庭暴力涉诉历史、潜在债务风险及不良嗜好风险。拒绝盲目信任,用数据守护您的情感与财产安全。',
+ keywords: '婚前背景核实,婚恋对象评估,婚姻司法风险,个人情感风险,婚前背调工具'
+ },
+ '/inquire/category/vehicle': {
+ title: '车辆档案报告_二手车车况与产权风险检测_机动车报告_天远查',
+ description: '天远查车辆数据中心,让车辆交易更透明。支持通过车牌号或VIN码,核验车辆的初次登记信息、抵押查封状态、事故维修记录及产权属性。数据同步权威行业系统,精准识别问题车。',
+ keywords: '车辆维修记录,二手车出险报告,车辆抵押报告,车况报告,机动车档案'
+ },
+ '/inquire/category/marriageStatus': {
+ title: '个人婚姻关联风险核验_家庭背景合规报告_天远查',
+ description: '天远查提供基于大数据的婚姻关联风险评估。通过分析司法文书及公开社会关系,辅助判断目标的真实家庭状况与情感履历。合法合规,保障知情权。',
+ keywords: '婚史风险排查,家庭背景核实,婚姻诚信评估,情感状态评估,涉婚法律记录'
+ },
+ '/agent': {
+ title: '天远查代理 - 免费开通代理权限 | 大数据风险报告代理',
+ description: '天远查代理平台,免费开通代理权限,享受大数据风险报告查询服务代理收益。专业的大数据风险报告、婚姻查询、个人信用评估等服务的代理合作。',
+ keywords: '天远查代理, 免费代理, 大数据风险报告代理, 代理权限, 代理收益'
+ },
+ '/help': {
+ title: '帮助中心 - 天远查使用指南 | 常见问题解答',
+ description: '天远查帮助中心,提供详细的使用指南、常见问题解答、操作教程等,帮助用户更好地使用大数据风险报告查询服务。',
+ keywords: '天远查帮助, 使用指南, 常见问题, 操作教程, 客服支持'
+ },
+ '/example': {
+ title: '示例报告 - 天远查报告展示 | 大数据风险报告样例',
+ description: '天远查示例报告展示,包含大数据风险报告、婚姻状况查询、个人信用评估等服务的报告样例,让用户了解报告内容和格式。',
+ keywords: '示例报告, 报告展示, 报告样例, 大数据风险报告, 婚姻查询报告'
+ },
+ '/service': {
+ title: '客服中心 - 天远查在线客服 | 技术支持',
+ description: '天远查客服中心,提供在线客服支持、技术咨询、问题反馈等服务,确保用户获得及时有效的帮助。',
+ keywords: '客服中心, 在线客服, 技术支持, 问题反馈, 天远查客服'
+ },
+ '/inquire': {
+ title: '核验工具多场景数据核验服务天远查',
+ description: '提供车辆、企业、个人等多场景核验,包括状态、信用、身份等查询,权威高效,保护隐私。',
+ keywords: '核验工具,数据核验服务,车辆核验,企业核验,天远查'
+ },
+};
+
+const OUTPUT_DIR = path.resolve(__dirname, 'static-pages');
+
+// 确保目录存在
+if (!fs.existsSync(OUTPUT_DIR)) {
+ fs.mkdirSync(OUTPUT_DIR, { recursive: true });
+}
+
+// 转换路径为文件名
+function pathToFilename(routePath) {
+ let filename = routePath
+ .replace(/^\//, '')
+ .replace(/\/+/g, '-')
+ .replace(/:/g, '-');
+
+ if (!filename) {
+ filename = 'index';
+ }
+
+ return `${filename}.html`;
+}
+
+// 生成单个页面
+function generatePage(routePath, seoConfig) {
+ const filename = pathToFilename(routePath);
+ const filepath = path.join(OUTPUT_DIR, filename);
+
+ // 动态导入generateContentByRoute
+ const content = generateContentByRoute(routePath, seoConfig);
+
+ const html = generateStaticHTML(seoConfig, {
+ path: routePath,
+ content: content,
+ canonical: 'https://www.tianyuancha.cn'
+ });
+
+ fs.writeFileSync(filepath, html, 'utf-8');
+ console.log(`✅ ${filename}`);
+ return filepath;
+}
+
+// 动态导入内容生成函数
+async function generateContentByRoute(routePath, seoConfig) {
+ const { generateContentByRoute: generateContent } = await import('./pageTemplates.js');
+ return generateContent(routePath, seoConfig);
+}
+
+// 生成sitemap
+function generateSitemap() {
+ const sitemapPath = path.join(OUTPUT_DIR, 'sitemap.xml');
+ const baseUrl = 'https://www.tianyuancha.cn';
+ const currentDate = new Date().toISOString().split('T')[0];
+
+ let sitemap = `
+
+`;
+
+ for (const [routePath] of Object.entries(seoConfigs)) {
+ const priority = routePath === '/' ? '1.0' : '0.8';
+ sitemap += `
+ ${baseUrl}${routePath}
+ ${currentDate}
+ weekly
+ ${priority}
+
+`;
+ }
+
+ sitemap += ``;
+
+ fs.writeFileSync(sitemapPath, sitemap, 'utf-8');
+ console.log(`✅ sitemap.xml`);
+}
+
+// 生成robots.txt
+function generateRobots() {
+ const robotsPath = path.join(OUTPUT_DIR, 'robots.txt');
+ const robotsContent = `User-agent: *
+Allow: /
+Disallow: /admin
+Disallow: /api
+Sitemap: https://www.tianyuancha.cn/sitemap.xml
+`;
+
+ fs.writeFileSync(robotsPath, robotsContent, 'utf-8');
+ console.log(`✅ robots.txt`);
+}
+
+// 主函数
+async function main() {
+ console.log('========================================');
+ console.log(' 天远查 - 静态页面生成器');
+ console.log('========================================');
+ console.log('');
+ console.log('📂 输出目录:', OUTPUT_DIR);
+ console.log('');
+ console.log('📝 生成静态页面:');
+ console.log('');
+
+ let count = 0;
+ for (const [routePath, seoConfig] of Object.entries(seoConfigs)) {
+ try {
+ await generatePage(routePath, seoConfig);
+ count++;
+ } catch (error) {
+ console.error(`❌ ${routePath}: ${error.message}`);
+ }
+ }
+
+ console.log('');
+ console.log('📝 生成SEO文件:');
+ console.log('');
+ try {
+ generateSitemap();
+ generateRobots();
+ } catch (error) {
+ console.error(`❌ 生成SEO文件失败: ${error.message}`);
+ }
+
+ console.log('');
+ console.log('========================================');
+ console.log(`✨ 完成! 共生成 ${count} 个静态页面`);
+ console.log('========================================');
+}
+
+main().catch(error => {
+ console.error('❌ 生成失败:', error);
+ process.exit(1);
+});
diff --git a/scripts/seo-static-generator/static-pages/agent.html b/scripts/seo-static-generator/static-pages/agent.html
new file mode 100644
index 0000000..3dc5f0e
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/agent.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 天远查代理 - 免费开通代理权限 | 大数据风险报告代理
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/example.html b/scripts/seo-static-generator/static-pages/example.html
new file mode 100644
index 0000000..9e14ee5
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/example.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 示例报告 - 天远查报告展示 | 大数据风险报告样例
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/help.html b/scripts/seo-static-generator/static-pages/help.html
new file mode 100644
index 0000000..b3ff03d
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/help.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 帮助中心 - 天远查使用指南 | 常见问题解答
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/index.html b/scripts/seo-static-generator/static-pages/index.html
new file mode 100644
index 0000000..f313f2a
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/index.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 天远查官网_企业与婚姻关联风险核验_综合履约背景核验
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/inquire-category-lawsuit.html b/scripts/seo-static-generator/static-pages/inquire-category-lawsuit.html
new file mode 100644
index 0000000..c123e37
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/inquire-category-lawsuit.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 司法涉诉核验_个人及企业法律诉讼记录_履约风险评估_天远查
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/inquire-category-marriageStatus.html b/scripts/seo-static-generator/static-pages/inquire-category-marriageStatus.html
new file mode 100644
index 0000000..5f6615a
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/inquire-category-marriageStatus.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 个人婚姻关联风险核验_家庭背景合规报告_天远查
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/inquire-category-vehicle.html b/scripts/seo-static-generator/static-pages/inquire-category-vehicle.html
new file mode 100644
index 0000000..2084c44
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/inquire-category-vehicle.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 车辆档案报告_二手车车况与产权风险检测_机动车报告_天远查
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/inquire-marriage.html b/scripts/seo-static-generator/static-pages/inquire-marriage.html
new file mode 100644
index 0000000..94df3ba
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/inquire-marriage.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 婚前背景核验_婚姻关联司法风险筛查_情感综合保障_天远查
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/inquire.html b/scripts/seo-static-generator/static-pages/inquire.html
new file mode 100644
index 0000000..23a2b0d
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/inquire.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 核验工具多场景数据核验服务天远查
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/robots.txt b/scripts/seo-static-generator/static-pages/robots.txt
new file mode 100644
index 0000000..60d25e0
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/robots.txt
@@ -0,0 +1,5 @@
+User-agent: *
+Allow: /
+Disallow: /admin
+Disallow: /api
+Sitemap: https://www.tianyuancha.cn/sitemap.xml
diff --git a/scripts/seo-static-generator/static-pages/service.html b/scripts/seo-static-generator/static-pages/service.html
new file mode 100644
index 0000000..cc9f222
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/service.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ 客服中心 - 天远查在线客服 | 技术支持
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [object Promise]
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/static-pages/sitemap.xml b/scripts/seo-static-generator/static-pages/sitemap.xml
new file mode 100644
index 0000000..c46bf8c
--- /dev/null
+++ b/scripts/seo-static-generator/static-pages/sitemap.xml
@@ -0,0 +1,63 @@
+
+
+
+ https://www.tianyuancha.cn/
+ 2026-02-25
+ weekly
+ 1.0
+
+
+ https://www.tianyuancha.cn/inquire/category/lawsuit
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/inquire/marriage
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/inquire/category/vehicle
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/inquire/category/marriageStatus
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/agent
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/help
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/example
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/service
+ 2026-02-25
+ weekly
+ 0.8
+
+
+ https://www.tianyuancha.cn/inquire
+ 2026-02-25
+ weekly
+ 0.8
+
+
\ No newline at end of file
diff --git a/scripts/seo-static-generator/testGenerator.js b/scripts/seo-static-generator/testGenerator.js
new file mode 100644
index 0000000..3312c05
--- /dev/null
+++ b/scripts/seo-static-generator/testGenerator.js
@@ -0,0 +1,280 @@
+/**
+ * 静态页面生成器测试脚本
+ */
+
+import { generateAllPages, generatePage } from './generateStaticPages.js';
+import { generateStaticHTML } from './pageTemplates.js';
+import fs from 'fs';
+import path from 'path';
+
+console.log('='.repeat(60));
+console.log(' 天远查 - 静态页面生成器测试');
+console.log('='.repeat(60));
+console.log();
+
+// 测试结果统计
+let passedTests = 0;
+let failedTests = 0;
+
+// 测试函数
+function test(name, fn) {
+ try {
+ fn();
+ console.log(`✅ ${name}`);
+ passedTests++;
+ } catch (error) {
+ console.log(`❌ ${name}`);
+ console.log(` 错误: ${error.message}`);
+ failedTests++;
+ }
+}
+
+// 断言函数
+function assert(condition, message) {
+ if (!condition) {
+ throw new Error(message || '断言失败');
+ }
+}
+
+console.log('🧪 开始测试...\n');
+
+// 测试 1: 测试基本的 HTML 生成
+test('测试基本的 HTML 生成', () => {
+ const seoConfig = {
+ title: '测试标题',
+ description: '测试描述',
+ keywords: '测试关键词'
+ };
+
+ const html = generateStaticHTML(seoConfig, { path: '/test' });
+
+ assert(html.includes(''), '应该包含 DOCTYPE 声明');
+ assert(html.includes('测试标题'), '应该包含标题');
+ assert(html.includes('测试描述'), '应该包含描述');
+ assert(html.includes('测试关键词'), '应该包含关键词');
+ assert(html.includes('og:title'), '应该包含 Open Graph 标签');
+ assert(html.includes('twitter:card'), '应该包含 Twitter Cards 标签');
+ assert(html.includes('application/ld+json'), '应该包含结构化数据');
+});
+
+// 测试 2: 测试默认内容生成
+test('测试默认内容生成', () => {
+ const seoConfig = {
+ title: '测试页面',
+ description: '这是一个测试页面',
+ keywords: '测试'
+ };
+
+ const html = generateStaticHTML(seoConfig, { path: '/test' });
+
+ assert(html.includes('关于测试页面'), '应该包含关于标题');
+ assert(html.includes('核心功能'), '应该包含核心功能');
+ assert(html.includes('为什么选择天远查?'), '应该包含选择理由');
+ assert(html.includes('应用场景'), '应该包含应用场景');
+});
+
+// 测试 3: 测试路由内容生成
+test('测试路由内容生成', () => {
+ const seoConfig = {
+ title: '司法涉诉核验',
+ description: '司法风险检测中心',
+ keywords: '司法,诉讼'
+ };
+
+ const html = generateStaticHTML(seoConfig, {
+ path: '/inquire/category/lawsuit',
+ content: generateContentByRoute('/inquire/category/lawsuit', seoConfig)
+ });
+
+ assert(html.includes('司法涉诉核验服务'), '应该包含司法涉诉标题');
+ assert(html.includes('开庭公告查询'), '应该包含开庭公告');
+ assert(html.includes('裁判文书查询'), '应该包含裁判文书');
+});
+
+// 测试 4: 测试文件名生成
+test('测试文件名生成', () => {
+ const paths = [
+ { input: '/', expected: 'index.html' },
+ { input: '/help', expected: 'help.html' },
+ { input: '/inquire/category/lawsuit', expected: 'inquire-category-lawsuit.html' },
+ { input: '/agent/promote', expected: 'agent-promote.html' }
+ ];
+
+ paths.forEach(({ input, expected }) => {
+ const filename = input
+ .replace(/^\//, '')
+ .replace(/\/+/g, '-')
+ .replace(/:/g, '-');
+ const result = filename ? `${filename}.html` : 'index.html';
+
+ assert(result === expected, `路径 ${input} 应该生成文件名 ${expected}`);
+ });
+});
+
+// 测试 5: 测试静态页面目录创建
+test('测试静态页面目录创建', () => {
+ const outputDir = path.join(__dirname, '../static-pages-test');
+
+ // 清理测试目录(如果存在)
+ if (fs.existsSync(outputDir)) {
+ fs.rmSync(outputDir, { recursive: true, force: true });
+ }
+
+ // 创建目录
+ if (!fs.existsSync(outputDir)) {
+ fs.mkdirSync(outputDir, { recursive: true });
+ }
+
+ assert(fs.existsSync(outputDir), '应该创建输出目录');
+
+ // 清理测试目录
+ fs.rmSync(outputDir, { recursive: true, force: true });
+});
+
+// 测试 6: 测试单个页面生成
+test('测试单个页面生成', () => {
+ const testDir = path.join(__dirname, '../static-pages-test');
+
+ // 清理测试目录(如果存在)
+ if (fs.existsSync(testDir)) {
+ fs.rmSync(testDir, { recursive: true, force: true });
+ }
+
+ fs.mkdirSync(testDir, { recursive: true });
+
+ const seoConfig = {
+ title: '测试页面',
+ description: '测试描述',
+ keywords: '测试'
+ };
+
+ const filepath = path.join(testDir, 'test.html');
+
+ // 临时修改 generatePage 的输出目录
+ const originalDir = path.join(__dirname, '../static-pages');
+
+ // 生成测试文件
+ const content = generateStaticHTML(seoConfig, { path: '/test' });
+ fs.writeFileSync(filepath, content, 'utf-8');
+
+ assert(fs.existsSync(filepath), '应该生成测试文件');
+
+ // 验证文件内容
+ const fileContent = fs.readFileSync(filepath, 'utf-8');
+ assert(fileContent.includes('测试页面'), '文件应该包含标题');
+
+ // 清理测试目录
+ fs.rmSync(testDir, { recursive: true, force: true });
+});
+
+// 测试 7: 测试 SEO 配置完整性
+test('测试 SEO 配置完整性', () => {
+ const seoConfigs = {
+ '/': {
+ title: '天远查官网_企业与婚姻关联风险核验_综合履约背景核验',
+ description: '天远查官网(TianYuanCha)聚合官方公示数据...',
+ keywords: '天远查,婚姻状态风险, 配偶背景核验'
+ },
+ '/inquire/category/lawsuit': {
+ title: '司法涉诉核验_个人及企业法律诉讼记录_履约风险评估_天远查',
+ description: '天远查司法风险检测中心...',
+ keywords: '司法案件核验,法律诉讼记录'
+ }
+ };
+
+ for (const [path, config] of Object.entries(seoConfigs)) {
+ assert(config.title, `路由 ${path} 应该有 title`);
+ assert(config.description, `路由 ${path} 应该有 description`);
+ assert(config.keywords, `路由 ${path} 应该有 keywords`);
+ }
+});
+
+// 测试 8: 测试 Open Graph 标签
+test('测试 Open Graph 标签', () => {
+ const seoConfig = {
+ title: '测试标题',
+ description: '测试描述',
+ keywords: '测试'
+ };
+
+ const html = generateStaticHTML(seoConfig, { path: '/test' });
+
+ assert(html.includes('og:type'), '应该包含 og:type');
+ assert(html.includes('og:url'), '应该包含 og:url');
+ assert(html.includes('og:title'), '应该包含 og:title');
+ assert(html.includes('og:description'), '应该包含 og:description');
+ assert(html.includes('og:site_name'), '应该包含 og:site_name');
+ assert(html.includes('og:locale'), '应该包含 og:locale');
+});
+
+// 测试 9: 测试结构化数据
+test('测试结构化数据', () => {
+ const seoConfig = {
+ title: '测试标题',
+ description: '测试描述',
+ keywords: '测试'
+ };
+
+ const html = generateStaticHTML(seoConfig, { path: '/test' });
+
+ assert(html.includes('@context'), '应该包含 @context');
+ assert(html.includes('@type'), '应该包含 @type');
+ assert(html.includes('WebPage'), '应该包含 WebPage 类型');
+ assert(html.includes('Organization'), '应该包含 Organization 类型');
+});
+
+// 测试 10: 测试 canonical URL
+test('测试 canonical URL', () => {
+ const seoConfig = {
+ title: '测试标题',
+ description: '测试描述',
+ keywords: '测试'
+ };
+
+ const html = generateStaticHTML(seoConfig, {
+ path: '/test/page',
+ canonical: 'https://www.tianyuancha.cn'
+ });
+
+ assert(html.includes('https://www.tianyuancha.cn/test/page'), '应该包含完整的 canonical URL');
+});
+
+// 运行实际生成测试
+console.log('\n🚀 运行实际生成测试...\n');
+
+test('生成所有静态页面', () => {
+ try {
+ generateAllPages();
+
+ const staticDir = path.join(__dirname, '../static-pages');
+ assert(fs.existsSync(staticDir), '应该生成 static-pages 目录');
+
+ const files = fs.readdirSync(staticDir);
+ assert(files.length > 0, '应该生成至少一个文件');
+ assert(files.includes('index.html'), '应该生成 index.html');
+ assert(files.includes('sitemap.xml'), '应该生成 sitemap.xml');
+ assert(files.includes('robots.txt'), '应该生成 robots.txt');
+
+ console.log(` 生成了 ${files.length} 个文件`);
+ } catch (error) {
+ console.log(` 错误: ${error.message}`);
+ throw error;
+ }
+});
+
+// 输出测试结果
+console.log('\n' + '='.repeat(60));
+console.log(' 测试结果');
+console.log('='.repeat(60));
+console.log(`✅ 通过: ${passedTests}`);
+console.log(`❌ 失败: ${failedTests}`);
+console.log(`📊 总计: ${passedTests + failedTests}`);
+console.log();
+
+if (failedTests === 0) {
+ console.log('🎉 所有测试通过!');
+ process.exit(0);
+} else {
+ console.log('⚠️ 部分测试失败,请检查错误信息');
+ process.exit(1);
+}
diff --git a/server/README-SEO.md b/server/README-SEO.md
new file mode 100644
index 0000000..fe17b4f
--- /dev/null
+++ b/server/README-SEO.md
@@ -0,0 +1,351 @@
+# SPA SEO 优化解决方案
+
+## 📋 方案概述
+
+针对 SPA 应用 SEO 问题,采用**爬虫检测 + 静态 HTML 回退**方案:
+
+1. **爬虫检测**:识别搜索引擎爬虫(百度、Google、必应、搜狗等)
+2. **静态 HTML**:为爬虫提供预渲染的 HTML 模板,包含完整 TDK、OG、canonical、结构化数据
+3. **正常用户**:继续使用 SPA,体验不受影响
+
+**配置统一**:服务端 SEO 模板内容与前端 `src/composables/useSEO.js` 保持一致(标题、描述、关键词、域名),域名默认为 `https://www.tianyuancha.cn`(天远查)。可通过环境变量 `SEO_BASE_URL` 覆盖。
+
+## 🏗️ 项目结构
+
+```
+server/
+├── crawler-detector.js # 爬虫检测模块
+├── middleware.js # SEO 中间件(Express/Koa),路由与 useSEO.js 一致
+├── generate-seo-templates.cjs # SEO 模板生成器(与 useSEO.js 同步)
+├── server-example-express.js # Express 服务器示例
+├── nginx-www.tianyuandb.com.conf # 天远数据 Nginx 配置(tianyuandb.com)
+├── nginx-www.xingfucha.cn.conf # 幸福查 Nginx 配置示例
+├── nginx-seo-location-替换片段.conf # Nginx SEO 片段
+├── test-seo.js # SEO 端到端检测脚本
+└── README-SEO.md # 本文档
+
+public/
+└── seo-templates/ # SEO 静态模板目录(运行 generate 后生成)
+ ├── index.html
+ ├── inquire.html
+ ├── inquire-category-lawsuit.html
+ ├── inquire-category-vehicle.html
+ ├── inquire-category-marriageStatus.html
+ ├── inquire-marriage.html
+ ├── agent.html
+ ├── help.html
+ ├── help-guide.html
+ ├── example.html
+ ├── service.html
+ └── ...
+```
+
+## 🚀 快速开始
+
+### 步骤1:生成 SEO 模板
+
+```bash
+cd server
+node generate-seo-templates.cjs
+# 或 npm run generate
+```
+
+这会在 `public/seo-templates/` 下生成所有页面的静态 HTML 模板,内容与 `src/composables/useSEO.js` 一致。
+
+### 步骤2:集成到你的服务器
+
+#### 选项A:使用Express服务器
+
+```javascript
+const express = require('express')
+const SEOMiddleware = require('./server/middleware')
+
+const app = express()
+
+// 初始化SEO中间件
+const seoMiddleware = new SEOMiddleware({
+ templateDir: path.join(__dirname, 'public/seo-templates'),
+ debug: true // 开发环境开启调试日志
+})
+
+// 应用SEO中间件(必须在静态文件服务之前)
+app.use(seoMiddleware.express())
+
+// 静态文件服务
+app.use(express.static(path.join(__dirname, 'dist')))
+
+// SPA路由处理
+app.get('*', (req, res) => {
+ res.sendFile(path.join(__dirname, 'dist/index.html'))
+})
+```
+
+#### 选项B:使用 Nginx
+
+- 天远数据站点:参考 `server/nginx-www.tianyuandb.com.conf`,将 `root` 和 `server_name`、证书路径改为你的服务器路径。
+- 幸福查站点:参考 `server/nginx-www.xingfucha.cn.conf`。
+- 部署时把 `public/seo-templates/` 整目录上传到服务器 `root` 下的 `seo-templates/`。
+
+```bash
+# 复制并修改配置
+cp server/nginx-www.tianyuandb.com.conf /etc/nginx/sites-available/zhinengcha
+nano /etc/nginx/sites-available/zhinengcha # 修改 root、证书等
+
+# 启用并重载
+ln -s /etc/nginx/sites-available/zhinengcha /etc/nginx/sites-enabled/
+nginx -t && systemctl restart nginx
+```
+
+#### 选项C:使用Koa
+
+```javascript
+const Koa = require('koa')
+const serve = require('koa-static')
+const SEOMiddleware = require('./server/middleware')
+
+const app = new Koa()
+
+// 应用SEO中间件
+const seoMiddleware = new SEOMiddleware({
+ templateDir: path.join(__dirname, 'public/seo-templates'),
+ debug: true
+})
+
+app.use(seoMiddleware.koa())
+
+// 静态文件服务
+app.use(serve(path.join(__dirname, 'dist')))
+
+app.listen(3000)
+```
+
+### 步骤3:测试爬虫检测
+
+```bash
+# 模拟百度爬虫
+curl -A "Baiduspider" http://localhost:3000/
+
+# 模拟Google爬虫
+curl -A "Googlebot/2.1" http://localhost:3000/
+
+# 模拟普通用户
+curl http://localhost:3000/
+```
+
+## 🔧 配置说明
+
+### 爬虫检测器配置
+
+`crawler-detector.js` 包含以下爬虫识别:
+
+- **中文搜索引擎**:百度、360、搜狗、必应、有道、搜搜、头条搜索
+- **国际搜索引擎**:Google、Bing、Yahoo
+- **社交媒体爬虫**:Facebook、Twitter、LinkedIn、WhatsApp等
+
+你可以根据需要添加或修改爬虫模式:
+
+```javascript
+// 在crawler-detector.js中添加新的爬虫模式
+this.crawlerPatterns.push('your-custom-bot')
+```
+
+### 路由到模板映射
+
+在 `middleware.js` 中配置路由与模板的对应关系:
+
+```javascript
+this.routeTemplateMap = {
+ '/': 'index.html',
+ '/agent': 'agent.html',
+ // 添加新的路由映射
+ '/new-route': 'new-template.html'
+}
+```
+
+### 模板生成配置
+
+**推荐**:页面 SEO 以 `src/composables/useSEO.js` 为唯一来源;修改标题/描述/关键词时只改 `useSEO.js` 中的 `routeConfigs`,然后同步到服务端:
+
+- 在 `server/generate-seo-templates.cjs` 的 `pageSEOConfigs` 中保持与 `useSEO.js` 一致(含新增路由与 `BASE_URL`)。
+- 在 `server/middleware.js` 的 `routeTemplateMap` 中为新路由添加映射。
+- 若用 Nginx,在对应 conf 的 `$seo_file` 中增加 `if ($uri = '/新路径') { set $seo_file 新模板.html; }`。
+
+新增页面示例(`generate-seo-templates.cjs`):
+
+```javascript
+'new-template.html': {
+ title: '页面标题',
+ description: '页面描述',
+ keywords: '关键词1,关键词2',
+ url: 'https://www.tianyuandb.com/new-route'
+}
+```
+
+## 📝 自定义模板
+
+### 修改模板样式
+
+编辑 `generate-seo-templates.js` 中的 `generateHTMLTemplate` 函数:
+
+```javascript
+function generateHTMLTemplate(config) {
+ return `
+
+
+
+
+
+
+
+
+ `
+}
+```
+
+### 添加结构化数据
+
+模板已包含基本的结构化数据(JSON-LD格式),如需扩展:
+
+```javascript
+const structuredData = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ // 添加更多字段
+ "breadcrumb": {
+ "@type": "BreadcrumbList",
+ "itemListElement": [...]
+ }
+}
+```
+
+## 🧪 验证SEO效果
+
+### 使用在线工具
+
+1. **百度资源平台**:https://ziyuan.baidu.com/
+2. **Google Search Console**:https://search.google.com/search-console
+3. **必应网站管理员工具**:https://www.bing.com/webmasters
+
+### 使用命令行工具与检测脚本
+
+```bash
+# 本地/线上 SEO 检测(会请求爬虫 UA 与普通 UA)
+cd server
+SEO_TEST_URL=http://localhost:3000 node test-seo.js
+# 或线上:SEO_TEST_URL=https://www.tianyuandb.com node test-seo.js
+```
+
+```bash
+# 查看爬虫看到的标题
+curl -s -A "Baiduspider/2.0" https://www.tianyuandb.com/ | grep -o '.*'
+
+# 检查 meta 与 canonical
+curl -s -A "Googlebot" https://www.tianyuandb.com/ | grep -E ' {
+ return userAgent.includes(pattern.toLowerCase())
+ })
+ }
+
+ /**
+ * 检查请求头
+ * @param {Object} headers
+ * @returns {Boolean}
+ */
+ checkHeaders(headers) {
+ for (const header of this.crawlerHeaders) {
+ const headerValue = headers[header]?.toLowerCase()
+ if (headerValue && (headerValue.includes('bot') || headerValue.includes('crawler'))) {
+ return true
+ }
+ }
+ return false
+ }
+
+ /**
+ * 检查IP地址是否为已知爬虫IP
+ * @param {String} ip
+ * @returns {Boolean}
+ */
+ checkIP(ip) {
+ // 这里可以添加已知爬虫IP段的检测
+ // 需要定期更新爬虫IP列表
+ return false
+ }
+
+ /**
+ * 获取爬虫类型
+ * @param {String} userAgent
+ * @returns {String} 爬虫类型
+ */
+ getCrawlerType(userAgent) {
+ const ua = userAgent.toLowerCase()
+
+ if (ua.includes('baiduspider')) return 'baidu'
+ if (ua.includes('googlebot')) return 'google'
+ if (ua.includes('bingbot') || ua.includes('msnbot')) return 'bing'
+ if (ua.includes('360spider')) return '360'
+ if (ua.includes('sogou spider')) return 'sogou'
+ if (ua.includes('facebookexternalhit')) return 'facebook'
+ if (ua.includes('twitterbot')) return 'twitter'
+ if (ua.includes('linkedinbot')) return 'linkedin'
+
+ return 'unknown'
+ }
+}
+
+module.exports = CrawlerDetector
diff --git a/server/generate-seo-templates.cjs b/server/generate-seo-templates.cjs
new file mode 100644
index 0000000..7c33c6f
--- /dev/null
+++ b/server/generate-seo-templates.cjs
@@ -0,0 +1,220 @@
+/**
+ * SEO模板生成器
+ * 根据 useSEO.js 的页面配置自动生成静态 HTML 模板,供爬虫访问时返回
+ * 配置与 src/composables/useSEO.js 保持一致
+ *
+ * 多站点:通过环境变量 SEO_BASE_URL 指定 canonical/og:url 域名后生成
+ * 例:SEO_BASE_URL=https://www.tianyuandb.com node generate-seo-templates.cjs
+ */
+
+const fs = require('fs')
+const path = require('path')
+
+const BASE_URL = process.env.SEO_BASE_URL || 'https://www.tianyuancha.cn'
+
+// 页面 SEO 配置(与 src/composables/useSEO.js 的 routeConfigs 保持一致)
+const pageSEOConfigs = {
+ 'index.html': {
+ title: '天远查官网_企业与婚姻关联风险核验_综合履约背景核验',
+ description: '天远查官网(TianYuanCha)聚合官方公示数据,专注于商业安全与资产背调。提供企业工商画像、婚姻状态关联风险、司法涉诉筛查及配偶债务核验。数据实时同步,助您精准规避投资、交易及家庭结合中的经济与法律风险。',
+ keywords: '天远查,婚姻状态风险, 配偶背景核验,企业信用查询,司法诉讼记录,资产风险评估',
+ url: BASE_URL
+ },
+ 'inquire-category-lawsuit.html': {
+ title: '司法涉诉核验_个人及企业法律诉讼记录_履约风险评估_天远查',
+ description: '天远查司法风险检测中心,聚合全国法院公开公示数据。一键筛查开庭公告、裁判文书、立案信息及执行记录。帮助用户快速识别法律纠纷隐患,全方位扫除合作盲区。',
+ keywords: '司法案件核验,法律诉讼记录,个人涉诉详情,法院公告查询,案件执行状态',
+ url: `${BASE_URL}/inquire/category/lawsuit`
+ },
+ 'inquire-marriage.html': {
+ title: '婚前背景核验_婚姻关联司法风险筛查_情感综合保障_天远查',
+ description: '天远查婚恋风险报告为您提供深度的背景核实服务。基于合法公开数据,排查对象的重婚司法记录、家庭暴力涉诉历史、潜在债务风险及不良嗜好风险。拒绝盲目信任,用数据守护您的情感与财产安全。',
+ keywords: '婚前背景核实,婚恋对象评估,婚姻司法风险,个人情感风险,婚前背调工具',
+ url: `${BASE_URL}/inquire/marriage`
+ },
+ 'inquire-category-vehicle.html': {
+ title: '车辆档案报告_二手车车况与产权风险检测_机动车报告_天远查',
+ description: '天远查车辆数据中心,让车辆交易更透明。支持通过车牌号或VIN码,核验车辆的初次登记信息、抵押查封状态、事故维修记录及产权属性。数据同步权威行业系统,精准识别问题车。',
+ keywords: '车辆维修记录,二手车出险报告,车辆抵押报告,车况报告,机动车档案',
+ url: `${BASE_URL}/inquire/category/vehicle`
+ },
+ 'inquire-category-marriageStatus.html': {
+ title: '个人婚姻关联风险核验_家庭背景合规报告_天远查',
+ description: '天远查提供基于大数据的婚姻关联风险评估。通过分析司法文书及公开社会关系,辅助判断目标的真实家庭状况与情感履历。合法合规,保障知情权。',
+ keywords: '婚史风险排查,家庭背景核实,婚姻诚信评估,情感状态评估,涉婚法律记录',
+ url: `${BASE_URL}/inquire/category/marriageStatus`
+ },
+ 'agent.html': {
+ title: '天远查代理 - 免费开通代理权限 | 大数据风险报告代理',
+ description: '天远查代理平台,免费开通代理权限,享受大数据风险报告查询服务代理收益。专业的大数据风险报告、婚姻查询、个人信用评估等服务的代理合作。',
+ keywords: '天远查代理, 免费代理, 大数据风险报告代理, 代理权限, 代理收益',
+ url: `${BASE_URL}/agent`
+ },
+ 'help.html': {
+ title: '帮助中心 - 天远查使用指南 | 常见问题解答',
+ description: '天远查帮助中心,提供详细的使用指南、常见问题解答、操作教程等,帮助用户更好地使用大数据风险报告查询服务。',
+ keywords: '天远查帮助, 使用指南, 常见问题, 操作教程, 客服支持',
+ url: `${BASE_URL}/help`
+ },
+ 'help-guide.html': {
+ title: '使用指南 - 天远查操作教程 | 功能说明',
+ description: '天远查详细使用指南,包含各功能模块的操作教程、功能说明、注意事项等,让用户快速上手使用。',
+ keywords: '使用指南, 操作教程, 功能说明, 快速上手, 天远查教程',
+ url: `${BASE_URL}/help/guide`
+ },
+ 'example.html': {
+ title: '示例报告 - 天远查报告展示 | 大数据风险报告样例',
+ description: '天远查示例报告展示,包含大数据风险报告、婚姻状况查询、个人信用评估等服务的报告样例,让用户了解报告内容和格式。',
+ keywords: '示例报告, 报告展示, 报告样例, 大数据风险报告, 婚姻查询报告',
+ url: `${BASE_URL}/example`
+ },
+ 'service.html': {
+ title: '客服中心 - 天远查在线客服 | 技术支持',
+ description: '天远查客服中心,提供在线客服支持、技术咨询、问题反馈等服务,确保用户获得及时有效的帮助。',
+ keywords: '客服中心, 在线客服, 技术支持, 问题反馈, 天远查客服',
+ url: `${BASE_URL}/service`
+ },
+ 'inquire.html': {
+ title: '核验工具多场景数据核验服务天远查',
+ description: '提供车辆、企业、个人等多场景核验,包括状态、信用、身份等查询,权威高效,保护隐私。',
+ keywords: '核验工具,数据核验服务,车辆核验,企业核验,天远查',
+ url: `${BASE_URL}/inquire`
+ }
+}
+
+/**
+ * 规范化文案:统一为中文标点,避免乱码
+ */
+function normalizeText(str) {
+ if (typeof str !== 'string') return str
+ return str
+ .replace(/\uFFFD/g, '')
+ .replace(/。/g, '。')
+ .replace(/、/g, '、')
+}
+
+/**
+ * 转义 HTML 属性值
+ */
+function escapeAttr(str) {
+ if (typeof str !== 'string') return ''
+ return str
+ .replace(/&/g, '&')
+ .replace(/"/g, '"')
+ .replace(//g, '>')
+}
+
+/**
+ * 生成单页 HTML 模板
+ */
+function generateHTMLTemplate(config) {
+ const title = normalizeText(config.title)
+ const description = normalizeText(config.description)
+ const keywords = normalizeText(config.keywords)
+ const structuredData = {
+ '@context': 'https://schema.org',
+ '@type': 'WebPage',
+ name: title,
+ description: description,
+ url: config.url,
+ mainEntity: {
+ '@type': 'Organization',
+ name: '天远查',
+ url: 'https://www.tianyuancha.cn/',
+ description: '专业大数据风险报告查询与代理平台,支持个人和企业多场景风控应用'
+ }
+ }
+
+ return `
+
+
+
+
+
+
+ ${escapeAttr(title)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
${escapeAttr(title)}
+
+
正在跳转到完整版网站...
+
如果浏览器没有自动跳转,请 点击这里
+
+
${escapeAttr(description)}
+
+ 关于天远查
+ 天远查官网(TianYuanCha)聚合官方公示数据,专注于商业安全与资产背调。提供企业工商画像、婚姻状态关联风险、司法涉诉筛查及配偶债务核验。
+
+
+ 核心服务
+
+ - 司法涉诉核验与法律诉讼记录
+ - 婚前背景核验与婚姻关联风险筛查
+ - 车辆档案报告与二手车车况检测
+ - 个人婚姻关联风险核验
+ - 多场景数据核验服务
+
+
+
+
+`
+}
+
+function main() {
+ const outputDir = path.join(__dirname, '../public/seo-templates')
+
+ if (!fs.existsSync(outputDir)) {
+ fs.mkdirSync(outputDir, { recursive: true })
+ console.log(`✓ 创建模板目录: ${outputDir}`)
+ }
+
+ let successCount = 0
+ Object.entries(pageSEOConfigs).forEach(([filename, config]) => {
+ const htmlContent = generateHTMLTemplate(config)
+ const filePath = path.join(outputDir, filename)
+ fs.writeFileSync(filePath, htmlContent, 'utf-8')
+ console.log(`✓ 生成模板: ${filename}`)
+ successCount++
+ })
+
+ console.log(`\n✓ 成功生成 ${successCount} 个 SEO 模板文件`)
+ console.log(`📁 模板目录: ${outputDir}`)
+ console.log(`💡 配置与 useSEO.js 一致,当前域名: ${BASE_URL}`)
+}
+
+main()
diff --git a/server/middleware.js b/server/middleware.js
new file mode 100644
index 0000000..e284242
--- /dev/null
+++ b/server/middleware.js
@@ -0,0 +1,175 @@
+/**
+ * SEO中间件
+ * 用于在Node.js服务器中检测爬虫并返回静态HTML
+ */
+
+const fs = require('fs')
+const path = require('path')
+const CrawlerDetector = require('./crawler-detector')
+
+class SEOMiddleware {
+ constructor(options = {}) {
+ this.detector = new CrawlerDetector()
+ this.templateDir = options.templateDir || path.join(__dirname, '../public/seo-templates')
+ this.defaultTemplate = options.defaultTemplate || 'index.html'
+ this.fallbackToSPA = options.fallbackToSPA !== false
+ this.debug = options.debug || false
+
+ // 路由到模板的映射(与 useSEO.js 及 generate-seo-templates.cjs 保持一致;子路径放前面以优先精确匹配)
+ this.routeTemplateMap = {
+ '/': 'index.html',
+ '/inquire/category/lawsuit': 'inquire-category-lawsuit.html',
+ '/inquire/category/vehicle': 'inquire-category-vehicle.html',
+ '/inquire/category/marriageStatus': 'inquire-category-marriageStatus.html',
+ '/inquire/marriage': 'inquire-marriage.html',
+ '/inquire': 'inquire.html',
+ '/agent': 'agent.html',
+ '/help/guide': 'help-guide.html',
+ '/help': 'help.html',
+ '/example': 'example.html',
+ '/service': 'service.html'
+ }
+
+ // 初始化模板缓存
+ this.templateCache = new Map()
+ this.cacheTemplates()
+ }
+
+ /**
+ * 缓存所有模板文件
+ */
+ cacheTemplates() {
+ try {
+ if (!fs.existsSync(this.templateDir)) {
+ console.warn(`[SEOMiddleware] 模板目录不存在: ${this.templateDir}`)
+ return
+ }
+
+ const files = fs.readdirSync(this.templateDir)
+ files.forEach(file => {
+ const filePath = path.join(this.templateDir, file)
+ if (fs.statSync(filePath).isFile()) {
+ this.templateCache.set(file, fs.readFileSync(filePath, 'utf-8'))
+ if (this.debug) {
+ console.log(`[SEOMiddleware] 已缓存模板: ${file}`)
+ }
+ }
+ })
+
+ console.log(`[SEOMiddleware] 已缓存 ${this.templateCache.size} 个模板文件`)
+ } catch (error) {
+ console.error('[SEOMiddleware] 缓存模板失败:', error)
+ }
+ }
+
+ /**
+ * 获取对应的模板文件名
+ * @param {String} path - 请求路径
+ * @returns {String} 模板文件名
+ */
+ getTemplatePath(requestPath) {
+ // 完全匹配
+ if (this.routeTemplateMap[requestPath]) {
+ return this.routeTemplateMap[requestPath]
+ }
+
+ // 模糊匹配(处理动态路由)
+ const matchedKey = Object.keys(this.routeTemplateMap).find(route => {
+ return requestPath.startsWith(route)
+ })
+
+ return matchedKey ? this.routeTemplateMap[matchedKey] : this.defaultTemplate
+ }
+
+ /**
+ * 获取模板内容
+ * @param {String} templateName - 模板文件名
+ * @returns {String|null} 模板内容
+ */
+ getTemplate(templateName) {
+ // 首先尝试缓存
+ let content = this.templateCache.get(templateName)
+
+ // 如果缓存中没有,尝试从磁盘读取
+ if (!content) {
+ try {
+ const filePath = path.join(this.templateDir, templateName)
+ if (fs.existsSync(filePath)) {
+ content = fs.readFileSync(filePath, 'utf-8')
+ this.templateCache.set(templateName, content)
+ }
+ } catch (error) {
+ console.error(`[SEOMiddleware] 读取模板失败: ${templateName}`, error)
+ }
+ }
+
+ return content || null
+ }
+
+ /**
+ * Express中间件
+ */
+ express() {
+ return (req, res, next) => {
+ // 检测是否为爬虫
+ if (this.detector.isCrawler(req)) {
+ const templateName = this.getTemplatePath(req.path)
+ const template = this.getTemplate(templateName)
+
+ if (template) {
+ // 设置响应头
+ res.setHeader('Content-Type', 'text/html; charset=utf-8')
+ res.setHeader('X-SEOMiddleware', 'prerendered')
+
+ // 返回静态HTML
+ if (this.debug) {
+ console.log(`[SEOMiddleware] 返回SEO模板: ${templateName} for ${req.path}`)
+ }
+
+ return res.send(template)
+ }
+ }
+
+ // 不是爬虫或模板不存在,继续处理SPA
+ next()
+ }
+ }
+
+ /**
+ * Koa中间件
+ */
+ koa() {
+ return async (ctx, next) => {
+ // 检测是否为爬虫
+ if (this.detector.isCrawler(ctx.req)) {
+ const templateName = this.getTemplatePath(ctx.path)
+ const template = this.getTemplate(templateName)
+
+ if (template) {
+ ctx.type = 'text/html; charset=utf-8'
+ ctx.set('X-SEOMiddleware', 'prerendered')
+
+ if (this.debug) {
+ console.log(`[SEOMiddleware] 返回SEO模板: ${templateName} for ${ctx.path}`)
+ }
+
+ ctx.body = template
+ return
+ }
+ }
+
+ await next()
+ }
+ }
+
+ /**
+ * 重新加载模板缓存
+ */
+ reloadCache() {
+ this.templateCache.clear()
+ this.cacheTemplates()
+ console.log('[SEOMiddleware] 模板缓存已重新加载')
+ }
+}
+
+module.exports = SEOMiddleware
diff --git a/server/nginx-www.tianyuancha.cn.conf b/server/nginx-www.tianyuancha.cn.conf
new file mode 100644
index 0000000..18651ee
--- /dev/null
+++ b/server/nginx-www.tianyuancha.cn.conf
@@ -0,0 +1,316 @@
+# Nginx 配置 - www.tianyuancha.cn(天远查)
+# 含爬虫检测 + SEO 静态页回退,与 useSEO.js / generate-seo-templates.cjs 路由一致
+# 部署时将 public/seo-templates/ 下所有 .html 拷贝到 /www/sites/www.tianyuancha.cn/static-pages/
+
+server {
+ listen 80;
+ listen 443 ssl http2;
+ server_name www.tianyuancha.cn tianyuancha.cn;
+
+ # 网站根目录(SPA)
+ root /www/sites/www.tianyuancha.cn/index;
+
+ # SEO 静态页面目录(与 generate-seo-templates.cjs 输出一致)
+ 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;
+ }
+
+ # ========================================
+ # 首页(爬虫 → 静态页,用户 → SPA)
+ # ========================================
+ location = / {
+ if ($is_bot = 1) {
+ root /www/sites/www.tianyuancha.cn/static-pages;
+ rewrite ^ /index.html break;
+ }
+ try_files $uri $uri/ /index.html;
+ }
+
+ # ========================================
+ # SEO 关键页面(与 useSEO.js / middleware 一致;子路径在前)
+ # ========================================
+
+ # 司法涉诉核验
+ 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/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 = /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;
+ }
+
+ # 核验工具(/inquire 须在 /inquire/xxx 之后,由 location 精确匹配保证)
+ location = /inquire {
+ if ($is_bot = 1) {
+ root /www/sites/www.tianyuancha.cn/static-pages;
+ rewrite ^ /inquire.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;
+ }
+
+ # 使用指南(子路径须在 /help 之前)
+ location = /help/guide {
+ if ($is_bot = 1) {
+ root /www/sites/www.tianyuancha.cn/static-pages;
+ rewrite ^ /help-guide.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;
+ }
+
+ # ========================================
+ # 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;
+}
diff --git a/server/nginx-www.tianyuandb.com.conf b/server/nginx-www.tianyuandb.com.conf
new file mode 100644
index 0000000..adc20d3
--- /dev/null
+++ b/server/nginx-www.tianyuandb.com.conf
@@ -0,0 +1,141 @@
+# 天远数据 - www.tianyuandb.com 完整配置(含 SEO 爬虫检测)
+# 使用前请将 public/seo-templates 上传到服务器:/www/sites/www.tianyuandb.com/index/seo-templates/
+# 生成 tianyuandb 用模板:SEO_BASE_URL=https://www.tianyuandb.com node generate-seo-templates.cjs
+
+server {
+ listen 80;
+ listen 443 ssl http2;
+ server_name www.tianyuandb.com tianyuandb.com;
+ index index.php index.html index.htm default.php default.htm default.html;
+ root /www/sites/www.tianyuandb.com/index;
+
+ # ========== SEO 爬虫检测与模板映射(请勿删除) ==========
+ set $is_crawler 0;
+ if ($http_user_agent ~* "baiduspider|baiduspider-mobile|baiduspider-image|baiduspider-video|baiduspider-news|baiduboxapp") {
+ set $is_crawler 1;
+ }
+ if ($http_user_agent ~* "googlebot|googlebot-image|googlebot-news|googlebot-mobile|googlebot-video|google-web-snippet") {
+ set $is_crawler 1;
+ }
+ if ($http_user_agent ~* "bingbot|msnbot") {
+ set $is_crawler 1;
+ }
+ if ($http_user_agent ~* "360spider|soha-agent|haosouspider") {
+ set $is_crawler 1;
+ }
+ if ($http_user_agent ~* "sogou spider|sogou news spider|sogou orion spider|sogou-blog") {
+ set $is_crawler 1;
+ }
+ if ($http_user_agent ~* "slurp|sosospider|sosoimagespider|youdaobot|yodaobot") {
+ set $is_crawler 1;
+ }
+ if ($http_user_agent ~* "bytedance-spider|toutiaospider") {
+ set $is_crawler 1;
+ }
+ if ($http_user_agent ~* "facebookexternalhit|facebookcatalog|twitterbot|linkedinbot|whatsapp|telegrambot|viber|line") {
+ set $is_crawler 1;
+ }
+
+ set $seo_file index.html;
+ if ($uri = '/') { set $seo_file index.html; }
+ if ($uri = '/historyQuery') { set $seo_file historyQuery.html; }
+ if ($uri = '/agent') { set $seo_file agent.html; }
+ if ($uri = '/agent/promote') { set $seo_file agent-promote.html; }
+ if ($uri = '/agent/invitation') { set $seo_file agent-invitation.html; }
+ if ($uri = '/help') { set $seo_file help.html; }
+ if ($uri = '/help/guide') { set $seo_file help-guide.html; }
+ if ($uri = '/example') { set $seo_file example.html; }
+ if ($uri = '/service') { set $seo_file service.html; }
+ if ($uri = '/inquire/personalData') { set $seo_file inquire-personalData.html; }
+ if ($uri = '/inquire/companyinfo') { set $seo_file inquire-companyinfo.html; }
+ if ($uri = '/inquire/preloanbackgroundcheck') { set $seo_file inquire-preloanbackgroundcheck.html; }
+ if ($uri = '/inquire/marriage') { set $seo_file inquire-marriage.html; }
+ if ($uri = '/inquire/backgroundcheck') { set $seo_file inquire-backgroundcheck.html; }
+ if ($uri = '/inquire/homeservice') { set $seo_file inquire-homeservice.html; }
+ # ========== SEO 配置结束 ==========
+
+ 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.tianyuandb.com/log/access.log main;
+ error_log /www/sites/www.tianyuandb.com/log/error.log;
+
+ location ^~ /.well-known/acme-challenge {
+ allow all;
+ root /usr/share/nginx/html;
+ }
+
+ # SEO:爬虫访问时返回静态 HTML 模板
+ location /seo-templates/ {
+ internal;
+ add_header Content-Type "text/html; charset=utf-8";
+ add_header X-SEOMiddleware "nginx-prerendered";
+ }
+
+ location / {
+ if ($is_crawler = 1) {
+ rewrite ^ /seo-templates/$seo_file break;
+ }
+ try_files $uri $uri/ /index.html;
+ }
+
+ 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";
+ }
+
+ 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;
+ }
+
+ error_page 404 /404.html;
+ add_header Strict-Transport-Security "max-age=31536000";
+ include /www/sites/www.tianyuandb.com/redirect/*.conf;
+
+ if ($scheme = http) {
+ return 301 https://$host$request_uri;
+ }
+
+ ssl_certificate /www/sites/www.tianyuandb.com/ssl/fullchain.pem;
+ ssl_certificate_key /www/sites/www.tianyuandb.com/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;
+}
diff --git a/server/package.json b/server/package.json
new file mode 100644
index 0000000..dbb7c3e
--- /dev/null
+++ b/server/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "tydata-seo-server",
+ "version": "1.0.0",
+ "description": "SPA SEO 优化 - 爬虫检测与静态 HTML 回退,与 useSEO.js 同步",
+ "main": "server-example-express.js",
+ "scripts": {
+ "start": "node server-example-express.js",
+ "dev": "node server-example-express.js",
+ "generate": "node generate-seo-templates.cjs",
+ "test": "node test-seo.js",
+ "test:crawler": "node test-crawler-detection.js"
+ },
+ "keywords": [
+ "seo",
+ "crawler",
+ "spa",
+ "prerender"
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "express": "^4.18.2",
+ "compression": "^1.7.4"
+ },
+ "devDependencies": {
+ "nodemon": "^3.0.1"
+ }
+}
diff --git a/server/server-example-express.js b/server/server-example-express.js
new file mode 100644
index 0000000..811d63e
--- /dev/null
+++ b/server/server-example-express.js
@@ -0,0 +1,36 @@
+/**
+ * Express服务器示例
+ * 展示如何集成SEO中间件
+ */
+
+const express = require('express')
+const path = require('path')
+const SEOMiddleware = require('./middleware')
+
+const app = express()
+const port = process.env.PORT || 3000
+
+// 初始化SEO中间件
+const seoMiddleware = new SEOMiddleware({
+ templateDir: path.join(__dirname, '../public/seo-templates'),
+ debug: process.env.NODE_ENV === 'development'
+})
+
+// 应用SEO中间件(必须在静态文件服务之前)
+app.use(seoMiddleware.express())
+
+// 静态文件服务
+app.use(express.static(path.join(__dirname, '../dist')))
+
+// SPA路由处理
+app.get('*', (req, res) => {
+ res.sendFile(path.join(__dirname, '../dist/index.html'))
+})
+
+// 启动服务器
+app.listen(port, () => {
+ console.log(`🚀 服务器运行在 http://localhost:${port}`)
+ console.log(`🔍 SEO中间件已启用`)
+})
+
+module.exports = app
diff --git a/server/test-crawler-detection.js b/server/test-crawler-detection.js
new file mode 100644
index 0000000..d494d78
--- /dev/null
+++ b/server/test-crawler-detection.js
@@ -0,0 +1,112 @@
+/**
+ * 爬虫检测测试脚本
+ * 用于验证爬虫检测功能是否正常工作
+ */
+
+const CrawlerDetector = require('./crawler-detector')
+
+const detector = new CrawlerDetector()
+
+// 测试用例
+const testCases = [
+ // 爬虫User-Agent
+ { userAgent: 'Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)', expected: true, description: '百度爬虫' },
+ { userAgent: 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)', expected: true, description: 'Google爬虫' },
+ { userAgent: 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)', expected: true, description: '必应爬虫' },
+ { userAgent: 'Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)', expected: true, description: '搜狗爬虫' },
+ { userAgent: '360Spider', expected: true, description: '360爬虫' },
+ { userAgent: 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)', expected: true, description: 'Facebook爬虫' },
+ { userAgent: 'Twitterbot/1.0', expected: true, description: 'Twitter爬虫' },
+ { userAgent: 'LinkedInBot/1.0 (compatible; Mozilla/5.0; +https://www.linkedin.com/help/linkedin/answer/8665)', expected: true, description: 'LinkedIn爬虫' },
+
+ // 正常浏览器User-Agent
+ { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', expected: false, description: 'Chrome浏览器' },
+ { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0', expected: false, description: 'Firefox浏览器' },
+ { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15', expected: false, description: 'Safari浏览器' },
+ { userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1', expected: false, description: 'iPhone Safari' },
+ { userAgent: 'Mozilla/5.0 (Linux; Android 13; SM-S908B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36', expected: false, description: 'Android Chrome' },
+ { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', expected: false, description: 'Edge浏览器' },
+
+ // 边界情况
+ { userAgent: '', expected: false, description: '空User-Agent' },
+ { userAgent: 'Mozilla/5.0 (compatible; MyBot/1.0)', expected: true, description: '包含bot关键词' },
+ { userAgent: 'Mozilla/5.0 (compatible; Spider/1.0)', expected: true, description: '包含spider关键词' },
+ { userAgent: 'Mozilla/5.0 (compatible; Crawler/1.0)', expected: true, description: '包含crawler关键词' }
+]
+
+console.log('='.repeat(70))
+console.log('爬虫检测测试')
+console.log('='.repeat(70))
+console.log()
+
+let passed = 0
+let failed = 0
+
+testCases.forEach((testCase, index) => {
+ const req = {
+ headers: {
+ 'user-agent': testCase.userAgent
+ }
+ }
+
+ const result = detector.isCrawler(req)
+ const success = result === testCase.expected
+ const status = success ? '✓ 通过' : '✗ 失败'
+ const crawlerType = result ? detector.getCrawlerType(testCase.userAgent) : 'N/A'
+
+ if (success) {
+ passed++
+ console.log(`${status} 测试 ${index + 1}: ${testCase.description}`)
+ } else {
+ failed++
+ console.error(`${status} 测试 ${index + 1}: ${testCase.description}`)
+ console.error(` User-Agent: ${testCase.userAgent.substring(0, 80)}...`)
+ console.error(` 预期: ${testCase.expected}, 实际: ${result}`)
+ }
+
+ if (result) {
+ console.log(` 识别为: ${crawlerType} 爬虫`)
+ }
+})
+
+console.log()
+console.log('='.repeat(70))
+console.log(`测试结果: ${passed} 通过, ${failed} 失败, 共 ${testCases.length} 个测试`)
+console.log('='.repeat(70))
+console.log()
+
+// 测试爬虫类型识别
+console.log('爬虫类型识别测试:')
+console.log('-'.repeat(70))
+
+const crawlerTypes = [
+ { userAgent: 'Baiduspider', expected: 'baidu', description: '百度爬虫' },
+ { userAgent: 'Googlebot', expected: 'google', description: 'Google爬虫' },
+ { userAgent: 'bingbot', expected: 'bing', description: '必应爬虫' },
+ { userAgent: '360spider', expected: '360', description: '360爬虫' },
+ { userAgent: 'sogou spider', expected: 'sogou', description: '搜狗爬虫' },
+ { userAgent: 'facebookexternalhit', expected: 'facebook', description: 'Facebook爬虫' },
+ { userAgent: 'Twitterbot', expected: 'twitter', description: 'Twitter爬虫' },
+ { userAgent: 'linkedinbot', expected: 'linkedin', description: 'LinkedIn爬虫' }
+]
+
+let typePassed = 0
+crawlerTypes.forEach(test => {
+ const result = detector.getCrawlerType(test.userAgent)
+ const success = result === test.expected
+
+ if (success) {
+ typePassed++
+ console.log(`✓ ${test.description}: ${result}`)
+ } else {
+ console.error(`✗ ${test.description}: 预期 ${test.expected}, 实际 ${result}`)
+ }
+})
+
+console.log()
+console.log('='.repeat(70))
+console.log(`爬虫类型识别: ${typePassed}/${crawlerTypes.length} 正确`)
+console.log('='.repeat(70))
+
+// 退出码
+process.exit(failed === 0 ? 0 : 1)
diff --git a/server/test-seo.js b/server/test-seo.js
new file mode 100644
index 0000000..209c1d7
--- /dev/null
+++ b/server/test-seo.js
@@ -0,0 +1,178 @@
+/**
+ * SEO 端到端检测脚本
+ * 模拟爬虫与普通用户请求,验证是否返回正确的页面
+ *
+ * 使用前请先启动服务器: npm run start
+ * 然后运行: npm run test 或 node test-seo.js
+ */
+
+const http = require('http')
+const https = require('https')
+
+const BASE_URL = process.env.SEO_TEST_URL || 'http://localhost:3000'
+
+// 要检测的路由及期望的 SEO 标题关键词(与 useSEO.js 一致,天远数据)
+const ROUTES = [
+ { path: '/', titleKeyword: '天远数据' },
+ { path: '/agent', titleKeyword: '天远数据代理' },
+ { path: '/help', titleKeyword: '天远数据帮助中心' },
+ { path: '/inquire/personalData', titleKeyword: '个人综合风险报告' },
+ { path: '/agent/promote', titleKeyword: '推广码' },
+ { path: '/historyQuery', titleKeyword: '我的报告' }
+]
+
+function request(url, userAgent) {
+ return new Promise((resolve, reject) => {
+ const lib = url.startsWith('https') ? https : http
+ const req = lib.get(url, {
+ headers: { 'User-Agent': userAgent },
+ timeout: 10000
+ }, res => {
+ const chunks = []
+ res.on('data', chunk => chunks.push(chunk))
+ res.on('end', () => {
+ resolve({
+ statusCode: res.statusCode,
+ headers: res.headers,
+ body: Buffer.concat(chunks).toString('utf-8')
+ })
+ })
+ })
+ req.on('error', reject)
+ req.on('timeout', () => {
+ req.destroy()
+ reject(new Error('请求超时'))
+ })
+ })
+}
+
+function extractTitle(html) {
+ const match = html.match(/]*>([^<]+)<\/title>/i)
+ return match ? match[1].trim() : null
+}
+
+function hasMetaDescription(html) {
+ return / {
+ console.error('检测失败:', err)
+ process.exit(1)
+})
diff --git a/server/如何检测.md b/server/如何检测.md
new file mode 100644
index 0000000..dc6555e
--- /dev/null
+++ b/server/如何检测.md
@@ -0,0 +1,211 @@
+# SEO 检测指南
+
+## 一、本地快速检测
+
+### 1. 只测爬虫识别逻辑(不启动服务)
+
+```bash
+cd server
+node test-crawler-detection.js
+```
+
+会跑多组 User-Agent,看是否把百度/Google 等识别为爬虫、普通浏览器识别为非爬虫。
+
+### 2. 端到端检测(需先启动服务)
+
+**步骤 1:启动 SEO 服务器**
+
+```bash
+cd server
+npm install
+npm run start
+```
+
+**步骤 2:另开一个终端,运行检测**
+
+```bash
+cd server
+npm run test
+```
+
+或指定地址:
+
+```bash
+# Windows PowerShell
+$env:SEO_TEST_URL="http://localhost:3000"; node test-seo.js
+
+# 若部署在线上,可测线上
+$env:SEO_TEST_URL="https://www.xingfucha.cn"; node test-seo.js
+```
+
+脚本会:
+
+- 用 **百度爬虫 UA** 请求首页、代理页、帮助中心、个人查询等
+- 检查响应里是否有:``、``、``、``
+- 用 **普通浏览器 UA** 再请求一遍,确认仍是 200(SPA 正常)
+
+全部通过即说明:爬虫拿到的是 SEO 模板,普通用户拿到的是 SPA。
+
+---
+
+## 二、用 curl 手动检测
+
+在服务器已启动的前提下,在终端执行:
+
+### 爬虫应拿到“带 TDK 的 HTML”
+
+```bash
+# 模拟百度爬虫请求首页
+curl -s -A "Baiduspider/2.0" http://localhost:3000/ | findstr /i "title description keywords canonical"
+```
+
+应能看到包含「天远数据」的 title,以及 description、keywords、canonical 等标签。
+
+**Windows 下中文乱码说明**:服务器返回的是 UTF-8,CMD 默认是 GBK,直接 `curl … | findstr` 会看到乱码(如 `澶╄繙鏁版嵁`)或出现 “FINDSTR: 写入错误”。可任选一种方式解决:
+
+```cmd
+:: 方式 1:先切到 UTF-8 再执行(CMD)
+chcp 65001
+curl -s -A "Baiduspider/2.0" https://www.tianyuandb.com/ | findstr /i "title description"
+```
+
+```powershell
+# 方式 2:PowerShell 下指定输出编码
+[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
+curl -s -A "Baiduspider/2.0" https://www.tianyuandb.com/ | Select-String -Pattern "title|description"
+```
+
+```cmd
+:: 方式 3:保存到文件后用编辑器打开(任意编码都行)
+curl -s -A "Baiduspider/2.0" https://www.tianyuandb.com/ -o seo-test.html
+:: 用记事本/VSCode 打开 seo-test.html,选 UTF-8 即可看到正确中文
+```
+
+```bash
+# 看完整 HTML 前几行(含 )
+curl -s -A "Baiduspider/2.0" http://localhost:3000/ | more
+```
+
+### 普通用户应拿到 SPA(一般是带 script 的 index.html)
+
+```bash
+# 不带爬虫 UA,相当于普通浏览器
+curl -s http://localhost:3000/ | findstr /i "script root app"
+```
+
+通常会有 `id="app"` 或大量 `
diff --git a/vite.config.js b/vite.config.js
index 82fb402..077b78b 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -15,8 +15,8 @@ export default defineConfig({
strictPort: true, // 如果端口被占用则抛出错误而不是使用下一个可用端口
proxy: {
"/api/v1": {
- target: "http://127.0.0.1:8888", // 本地接口地址
- // target: "https://www.tianyuancha.cn", // 本地接口地址
+ // target: "http://127.0.0.1:8888", // 本地接口地址
+ target: "https://www.tianyuancha.cn", // 本地接口地址
changeOrigin: true,
},
},