修改小程序

This commit is contained in:
2025-10-17 17:29:11 +08:00
parent 434fa135d1
commit 212dffd0da
227 changed files with 12887 additions and 45341 deletions

View File

@@ -0,0 +1,50 @@
# Government Backend Dockerfile
# 基于Node.js 18 Alpine镜像构建
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 安装系统依赖
RUN apk add --no-cache \
# 用于数据库备份的MySQL客户端
mysql-client \
# 开发工具
git \
# 用于健康检查的curl
curl \
&& rm -rf /var/cache/apk/*
# 复制package.json和package-lock.json
COPY package*.json ./
# 安装Node.js依赖
RUN npm ci --only=production && npm cache clean --force
# 复制应用代码
COPY . .
# 创建必要的目录
RUN mkdir -p logs uploads temp
# 设置文件权限
RUN chown -R node:node /app
# 切换到非root用户
USER node
# 暴露端口
EXPOSE 5352
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:5352/api/health || exit 1
# 启动应用
CMD ["npm", "start"]
# 元数据标签
LABEL maintainer="宁夏智慧牧场政府端 <support@nxxm.com>" \
description="宁夏智慧牧场政府端后端服务" \
application="nxxm-government-platform" \
tier="backend"

View File

@@ -0,0 +1,133 @@
# Nginx 404 错误最终修复方案
## 🔍 问题现状
根据测试结果:
- ✅ 后端服务正常:`http://localhost:5352/api/government/departments` 返回 200
- ✅ 登录接口正常:`https://ad.ningmuyun.com/api/government/auth/login` 返回 401
- ❌ 正确路径 404`https://ad.ningmuyun.com/api/government/departments` 返回 404
- ❌ 正确路径 404`https://ad.ningmuyun.com/api/government/data-center` 返回 404
- ❌ 正确路径 404`https://ad.ningmuyun.com/api/government/market-price` 返回 404
- ✅ 重复路径正常:`https://ad.ningmuyun.com/api/government/government/departments` 返回 200
## 📊 问题分析
### 关键发现
1. 登录接口 `/api/government/auth/login` 正常工作
2. 其他政府接口 `/api/government/departments` 等返回 404
3. 重复路径 `/api/government/government/departments` 却能正常工作
### 推断
这说明 nginx 配置中:
- `location ^~ /api/government/auth/` 规则工作正常
- `location ^~ /api/government/` 规则没有生效
- 重复路径能工作,说明可能有其他规则在处理请求
## 🔧 当前 Nginx 配置
```nginx
# 政府认证API代理 - 处理登录等认证接口
location ^~ /api/government/auth/ {
proxy_pass http://localhost:5352/api/auth/;
# ... CORS 配置
}
# 政府API代理 - 处理其他政府相关接口
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/;
# ... CORS 配置
}
```
## 🎯 可能的原因和解决方案
### 方案 1Nginx 配置未重新加载
最可能的原因是 nginx 配置修改后没有重新加载。
**解决步骤:**
```bash
# 1. 检查 nginx 配置语法
sudo nginx -t
# 2. 重新加载 nginx 配置
sudo systemctl reload nginx
# 3. 如果 reload 不行,尝试重启
sudo systemctl restart nginx
# 4. 检查 nginx 状态
sudo systemctl status nginx
# 5. 查看 nginx 错误日志
sudo tail -f /var/log/nginx/error.log
```
### 方案 2浏览器缓存问题
**解决步骤:**
1. 清除浏览器缓存
2. 使用无痕模式测试
3. 或使用 curl 命令测试(绕过浏览器)
### 方案 3Location 规则匹配优先级问题
如果还不行,可能需要调整 location 规则的顺序或写法。
**尝试修改为:**
```nginx
# 方案 A使用正则表达式匹配
location ~ ^/api/government/(?!auth/) {
proxy_pass http://localhost:5352;
# ... 其他配置
}
# 方案 B去掉尾部斜杠
location ^~ /api/government/ {
proxy_pass http://localhost:5352;
rewrite ^/api/government/(.*)$ /api/government/$1 break;
# ... 其他配置
}
```
## 📝 验证步骤
修复后运行以下命令验证:
```bash
node test-final-fix.js
```
或使用 curl 测试:
```bash
# 测试部门接口
curl -X GET https://ad.ningmuyun.com/api/government/departments
# 测试数据中心接口
curl -X GET https://ad.ningmuyun.com/api/government/data-center
# 测试市场价格接口
curl -X GET "https://ad.ningmuyun.com/api/government/market-price?type=beef"
```
## 🚨 重要提醒
1. **必须重启 nginx**:修改配置文件后,必须重启或重新加载 nginx 服务
2. **清除缓存**:测试时要清除浏览器缓存或使用无痕模式
3. **检查日志**:如果问题持续,查看 nginx 错误日志以获取更多信息
## 📞 下一步行动
请在服务器上执行以下命令:
```bash
# 1. 检查配置语法
sudo nginx -t
# 2. 重新加载配置
sudo systemctl reload nginx
# 3. 验证修复效果
curl -X GET https://ad.ningmuyun.com/api/government/departments
```
如果执行后问题仍然存在,请提供:
1. nginx -t 的输出结果
2. nginx error.log 的最新内容
3. curl 命令的完整输出

View File

@@ -0,0 +1,792 @@
server {
if ($host = datav.ningmuyun.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = wapi.ningmuyun.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = ad.ningmuyun.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = www.ningmuyun.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name www.ningmuyun.com ad.ningmuyun.com datav.ningmuyun.com wapi.ningmuyun.com;
return 301 https://$host$request_uri;
}
# HTTPS服务器配置
server {
listen 443 ssl;
server_name www.ningmuyun.com;
root /data/website/ningmuyun/;
# SSL 证书和私钥文件的路径
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
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:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
index index.html;
location / {
try_files $uri $uri/ /index.html; # 关键修复
add_header Cache-Control "no-cache, no-store";
expires 0;
}
# 日志配置
access_log /var/log/nginx/www.ningmuyun.com.access.log;
error_log /var/log/nginx/www.ningmuyun.com.error.log;
# 百度地图API代理
location /map-api/ {
proxy_pass https://api.map.baidu.com/;
proxy_set_header Host api.map.baidu.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 缓存地图API响应
proxy_cache_valid 200 1h;
proxy_cache_valid 404 1m;
}
ssl_certificate /etc/letsencrypt/live/www.ningmuyun.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.ningmuyun.com/privkey.pem; # managed by Certbot
}
# HTTPS服务器配置
server {
listen 443 ;
server_name wapi.ningmuyun.com;
ssl_certificate /etc/letsencrypt/live/wapi.ningmuyun.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/wapi.ningmuyun.com/privkey.pem; # managed by Certbot
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
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:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# 启用HSTS
add_header Strict-Transport-Security "max-age=31536000" always;
# 客户端上传大小限制
client_max_body_size 10M;
# 日志配置
access_log /var/log/nginx/wapi.ningmuyun.com.access.log;
error_log /var/log/nginx/wapi.ningmuyun.com.error.log;
# API反向代理
location /api/ {
proxy_pass http://localhost:5350/api/;
limit_except GET POST OPTIONS { # 确保包含 POST
deny all;
}
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_set_header X-Forwarded-Proto $scheme;
# 代理超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 120s;
# 缓冲区设置
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 16k;
# 建议添加 CORS 配置如果前端与API不同域[1](@ref)
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# WebSocket代理
location /socket.io/ {
proxy_pass http://localhost:5350;
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_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}
# 百度地图API代理
location /map-api/ {
proxy_pass https://api.map.baidu.com/;
proxy_set_header Host api.map.baidu.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 缓存地图API响应
proxy_cache_valid 200 1h;
proxy_cache_valid 404 1m;
}
# ===== 静态资源服务 - 修复重复问题 =====
# 合并所有静态资源处理
location ~ ^/(assets/|admin/assets/) {
# 尝试多个可能的资源位置
try_files $uri $uri/ @check_assets;
# 缓存策略
expires 30d;
access_log off;
add_header Cache-Control "public";
}
# 管理后台页面 - 关键修复:明确指定路径
location /admin {
alias /data/vue/ningmuyun/farm/dist;
index index.html;
# 处理SPA路由
try_files $uri $uri/ /admin/index.html;
# 禁用HTML缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Dashboard页面
location /dashboard {
alias /data/vue/ningmuyun/farm/dist;
index index.html;
try_files $uri $uri/ /dashboard/index.html;
# 禁用HTML缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# 登录页面
location /login {
alias /data/vue/ningmuyun/farm/dist;
index index.html;
try_files $uri $uri/ /login/index.html;
# 禁用HTML缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# 健康检查端点
location /health {
access_log off;
proxy_pass http://localhost:5350/health;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 错误页面配置
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# HTTPS服务器配置
server {
listen 443 ;
server_name ad.ningmuyun.com;
# root /data/vue/ningmuyun/admin-system/dist/;
# index index.html;
ssl_certificate /etc/letsencrypt/live/ad.ningmuyun.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/ad.ningmuyun.com/privkey.pem; # managed by Certbot
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
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:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# 启用HSTS
add_header Strict-Transport-Security "max-age=31536000" always;
# 客户端上传大小限制
client_max_body_size 10M;
# root /data/vue/ningmuyun/;
# 日志配置
access_log /var/log/nginx/ad.ningmuyun.com.access.log;
error_log /var/log/nginx/ad.ningmuyun.com.error.log;
# ==================== 银行项目 (bank) ====================
location ^~ /bank/ {
# 银行项目前端静态文件目录
#
alias /data/vue/ningmuyun/bank/dist/; # ✅ 确保末尾有斜杠
index index.html;
try_files $uri $uri/ /bank/index.html;
# 加上 Content-Type 调试
add_header Content-Type "text/html" always;
# 静态资源长期缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# HTML文件不缓存
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
}
}
# 银行项目后端API代理
location ^~ /bank/api/ {
proxy_pass http://localhost:5351/api/; # 银行后端服务端口
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_set_header X-Forwarded-Proto $scheme;
# CORS配置
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
# 预检请求处理
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# ==================== 保险项目 (baoxian) ====================
location ^~ /insurance/ {
# 银行项目前端静态文件目录
#
alias /data/vue/ningmuyun/insurance/dist/; # ✅ 确保末尾有斜杠
index index.html;
try_files $uri $uri/ /insurance/index.html;
# 加上 Content-Type 调试
add_header Content-Type "text/html" always;
# 静态资源长期缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# HTML文件不缓存
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
}
}
# 银行项目后端API代理
location ^~ /insurance/api/ {
proxy_pass http://localhost:3000/api/; # 银行后端服务端口
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_set_header X-Forwarded-Proto $scheme;
# CORS配置
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
# 预检请求处理
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# 政府认证API代理 - 处理登录等认证接口(优先级最高)
location ^~ /api/government/auth/ {
proxy_pass http://localhost:5352/api/auth/; # 政府后端认证服务端口
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_set_header X-Forwarded-Proto $scheme;
# CORS配置
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# 政府API代理 - 处理其他政府相关接口(优先级第二)
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/;
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_set_header X-Forwarded-Proto $scheme;
# CORS配置同上
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# ==================== 政府项目 (zhengfu) ====================
location ^~ /government/ {
alias /data/vue/ningmuyun/government/dist/;
index index.html;
try_files $uri $uri/ /zhengfu/index.html;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
}
}
# location ^~ /government/api/ {
# proxy_pass http://localhost:5352/; # 政府后端服务端口
# }
# ==================== 养殖项目 (yangzhi) ====================
location ^~ /farm/ {
alias /data/vue/ningmuyun/farm/dist/;
index index.html;
try_files $uri $uri/ /farm/index.html;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
}
}
location ^~ /farm/api/ {
proxy_pass http://localhost:5350/api/; # 养殖后端服务端口
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_set_header X-Forwarded-Proto $scheme;
# CORS配置同上
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# location /api/ {
# proxy_pass http://localhost:5350/api/;
# limit_except GET POST OPTIONS { # 确保包含 POST
# deny all;
# }
# 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_set_header X-Forwarded-Proto $scheme;
# # 代理超时设置
# proxy_connect_timeout 60s;
# proxy_send_timeout 60s;
# proxy_read_timeout 120s;
# # 缓冲区设置
# proxy_buffering on;
# proxy_buffer_size 8k;
# proxy_buffers 8 16k;
# proxy_busy_buffers_size 16k;
# # 建议添加 CORS 配置如果前端与API不同域[1](@ref)
# add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
# add_header 'Access-Control-Allow-Credentials' 'true' always;
# if ($request_method = 'OPTIONS') {
# add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
# add_header 'Access-Control-Allow-Credentials' 'true';
# add_header 'Content-Type' 'text/plain; charset=UTF-8';
# add_header 'Content-Length' 0;
# return 204;
# }
# }
# # WebSocket代理
# location /socket.io/ {
# proxy_pass http://localhost:5350;
# 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_set_header X-Forwarded-Proto $scheme;
# proxy_read_timeout 86400;
# }
# 百度地图API代理
location /map-api/ {
proxy_pass https://api.map.baidu.com/;
proxy_set_header Host api.map.baidu.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 缓存地图API响应
proxy_cache_valid 200 1h;
proxy_cache_valid 404 1m;
}
# ===== 静态资源服务 - 修复重复问题 =====
# 合并所有静态资源处理
location ~ ^/(assets/|admin/assets/) {
# 尝试多个可能的资源位置
try_files $uri $uri/ @check_assets;
# 缓存策略
expires 30d;
access_log off;
add_header Cache-Control "public";
}
# 管理后台页面 - 关键修复:明确指定路径
location /admin {
alias /data/vue/ningmuyun/farm/dist;
index index.html;
# 处理SPA路由
try_files $uri $uri/ /admin/index.html;
# 禁用HTML缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Dashboard页面
location /dashboard {
alias /data/vue/ningmuyun/farm/dist;
index index.html;
try_files $uri $uri/ /dashboard/index.html;
# 禁用HTML缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# 登录页面
location /login {
alias /data/vue/ningmuyun/farm/dist;
index index.html;
try_files $uri $uri/ /login/index.html;
# 禁用HTML缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# 健康检查端点
location /health {
access_log off;
proxy_pass http://localhost:5350/health;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 错误页面配置
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# server {
# listen 443 ;
# server_name datav.ningmuyun.com;
# root /data/datav/ningmuyun/dist/;
# index index.html;
# ssl_session_timeout 5m;
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# 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:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
# ssl_prefer_server_ciphers on;
# # 启用HSTS
# add_header Strict-Transport-Security "max-age=31536000" always;
# # 客户端上传大小限制
# client_max_body_size 10M;
# # 日志配置
# access_log /var/log/nginx/datav.ningmuyun.com.access.log;
# error_log /var/log/nginx/datav.ningmuyun.com.error.log;
# location / {
# try_files $uri $uri/ /index.html; # 关键修复
# add_header Cache-Control "no-cache, no-store";
# expires 0;
# }
# ssl_certificate /etc/letsencrypt/live/datav.ningmuyun.com/fullchain.pem; # managed by Certbot
# ssl_certificate_key /etc/letsencrypt/live/datav.ningmuyun.com/privkey.pem; # managed by Certbot
# }
# ============================================================
# datav.ningmuyun.com → 四项目(与 ad.ningmuyun.com 同构)
# ============================================================
server {
listen 443 ssl;
server_name datav.ningmuyun.com;
ssl_certificate /etc/letsencrypt/live/datav.ningmuyun.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/datav.ningmuyun.com/privkey.pem; # managed by Certbot
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000" always;
client_max_body_size 10M;
access_log /var/log/nginx/datav.ningmuyun.com.access.log;
error_log /var/log/nginx/datav.ningmuyun.com.error.log;
# --------------- 1. 银行项目 ---------------
location ^~ /bank/ {
alias /data/datav/ningmuyun/bank/dist/;
index index.html;
try_files $uri $uri/ /bank/index.html;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y; add_header Cache-Control "public, immutable"; access_log off;
}
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; expires 0;
}
}
# location ^~ /bank/api/ {
# proxy_pass http://localhost:5351/api/;
# 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_set_header X-Forwarded-Proto $scheme;
# # CORS
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com' always;
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
# add_header 'Access-Control-Allow-Credentials' 'true' always;
# if ($request_method = 'OPTIONS') {
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com';
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
# add_header 'Access-Control-Allow-Credentials' 'true';
# add_header 'Content-Type' 'text/plain; charset=UTF-8';
# add_header 'Content-Length' 0;
# return 204;
# }
# }
# --------------- 2. 保险项目 ---------------
location ^~ /insurance/ {
alias /data/datav/ningmuyun/insurance/dist/;
index index.html;
try_files $uri $uri/ /insurance/index.html;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y; add_header Cache-Control "public, immutable"; access_log off;
}
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; expires 0;
}
}
# location ^~ /insurance/api/ {
# proxy_pass http://localhost:3000/api/;
# # 同上 CORS
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com' always;
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
# add_header 'Access-Control-Allow-Credentials' 'true' always;
# if ($request_method = 'OPTIONS') {
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com';
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
# add_header 'Access-Control-Allow-Credentials' 'true';
# add_header 'Content-Type' 'text/plain; charset=UTF-8';
# add_header 'Content-Length' 0;
# return 204;
# }
# }
# --------------- 3. 政府项目 ---------------
location ^~ /government/ {
alias /data/datav/ningmuyun/government/dist/;
index index.html;
try_files $uri $uri/ /zhengfu/index.html;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y; add_header Cache-Control "public, immutable"; access_log off;
}
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; expires 0;
}
}
# location ^~ /zhengfu/api/ {
# proxy_pass http://localhost:5353/;
# # 同上 CORS
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com' always;
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
# add_header 'Access-Control-Allow-Credentials' 'true' always;
# if ($request_method = 'OPTIONS') {
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com';
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
# add_header 'Access-Control-Allow-Credentials' 'true';
# add_header 'Content-Type' 'text/plain; charset=UTF-8';
# add_header 'Content-Length' 0;
# return 204;
# }
# }
# --------------- 4. 养殖项目 ---------------
location ^~ /farm/ {
alias /data/datav/ningmuyun/farm/dist/;
index index.html;
try_files $uri $uri/ /farm/index.html;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y; add_header Cache-Control "public, immutable"; access_log off;
}
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; expires 0;
}
}
# location ^~ /farm/api/ {
# proxy_pass http://localhost:5350/api/;
# # 同上 CORS
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com' always;
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
# add_header 'Access-Control-Allow-Credentials' 'true' always;
# if ($request_method = 'OPTIONS') {
# add_header 'Access-Control-Allow-Origin' 'https://datav.ningmuyun.com';
# add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
# add_header 'Access-Control-Allow-Credentials' 'true';
# add_header 'Content-Type' 'text/plain; charset=UTF-8';
# add_header 'Content-Length' 0;
# return 204;
# }
# }
# --------------- 公共附加WebSocket + 地图 ---------------
# location /socket.io/ {
# proxy_pass http://localhost:5350;
# 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_set_header X-Forwarded-Proto $scheme;
# proxy_read_timeout 86400;
# }
# location /map-api/ {
# proxy_pass https://api.map.baidu.com/;
# proxy_set_header Host api.map.baidu.com;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_cache_valid 200 1h;
# proxy_cache_valid 404 1m;
# }
# --------------- 默认兜底(可选) ---------------
location / {
alias /data/datav/ningmuyun/farm/dist/;
index index.html;
try_files $uri $uri/ /index.html;
}
}

View File

@@ -78,6 +78,7 @@ app.use((err, req, res, next) => {
// 启动服务器
const PORT = process.env.PORT || 5352;
app.listen(PORT, () => {
console.log(`政府管理系统后端服务已启动,端口: ${PORT}`);
const HOST = process.env.HOST || '0.0.0.0';
app.listen(PORT, HOST, () => {
console.log(`政府管理系统后端服务已启动,地址: ${HOST}:${PORT}`);
});

View File

@@ -0,0 +1,106 @@
const axios = require('axios');
// 调试nginx问题
async function debugNginxIssue() {
console.log('🔍 调试nginx问题...\n');
const testCases = [
{
name: '直接测试后端服务',
url: 'http://localhost:5352/api/government/departments',
expected: '应该返回200'
},
{
name: '通过nginx测试部门接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
expected: '应该返回200'
},
{
name: '通过nginx测试登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
expected: '应该返回401认证错误'
},
{
name: '测试重复路径接口',
url: 'https://ad.ningmuyun.com/api/government/government/departments',
expected: '应该返回200如果nginx配置有问题'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 接口不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: nginx配置问题路径映射不正确`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 调试完成!');
console.log('');
console.log('📝 可能的问题:');
console.log(' 1. nginx配置语法错误');
console.log(' 2. nginx服务未重启');
console.log(' 3. location规则冲突');
console.log(' 4. proxy_pass配置错误');
console.log('');
console.log('🔄 建议的解决步骤:');
console.log(' 1. 检查nginx配置语法: sudo nginx -t');
console.log(' 2. 重启nginx服务: sudo systemctl reload nginx');
console.log(' 3. 检查nginx错误日志: sudo tail -f /var/log/nginx/error.log');
console.log(' 4. 检查nginx访问日志: sudo tail -f /var/log/nginx/ad.ningmuyun.com.access.log');
}
// 运行调试
debugNginxIssue().catch(console.error);

View File

@@ -0,0 +1,98 @@
#!/bin/bash
# Government Backend 部署脚本
# 用于自动化部署 government-backend 服务
set -e
echo "🚀 开始部署 Government Backend..."
# 1. 检查环境
echo "📋 检查环境..."
if ! command -v node &> /dev/null; then
echo "❌ Node.js 未安装"
exit 1
fi
if ! command -v npm &> /dev/null; then
echo "❌ npm 未安装"
exit 1
fi
if ! command -v pm2 &> /dev/null; then
echo "📦 安装 PM2..."
npm install -g pm2
fi
# 2. 进入项目目录
PROJECT_DIR="/var/www/government-backend"
if [ ! -d "$PROJECT_DIR" ]; then
echo "❌ 项目目录不存在: $PROJECT_DIR"
exit 1
fi
cd $PROJECT_DIR
# 3. 更新代码
echo "📥 更新代码..."
git pull origin main
# 4. 安装依赖
echo "📦 安装依赖..."
npm install --production
# 5. 创建日志目录
echo "📁 创建日志目录..."
mkdir -p logs
# 6. 检查配置文件
if [ ! -f ".env" ]; then
echo "⚠️ .env 文件不存在,创建默认配置..."
cat > .env << EOF
NODE_ENV=production
PORT=5352
DB_DIALECT=mysql
DB_HOST=129.211.213.226
DB_PORT=9527
DB_DATABASE=ningxia_zhengfu
DB_USER=root
DB_PASSWORD=aiotAiot123!
JWT_SECRET=government_super_secret_jwt_key_2024_very_long_and_secure
LOG_LEVEL=info
CORS_ORIGIN=*
UPLOAD_PATH=./uploads
MAX_FILE_SIZE=10485760
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
EOF
fi
# 7. 停止现有进程
echo "🛑 停止现有进程..."
pm2 stop government-backend 2>/dev/null || true
pm2 delete government-backend 2>/dev/null || true
# 8. 启动服务
echo "🚀 启动服务..."
pm2 start ecosystem.config.js --env production
# 9. 保存PM2配置
echo "💾 保存PM2配置..."
pm2 save
# 10. 设置开机自启
echo "🔄 设置开机自启..."
pm2 startup
# 11. 检查服务状态
echo "✅ 检查服务状态..."
sleep 3
pm2 status
echo ""
echo "🎉 部署完成!"
echo "📊 服务状态: pm2 status"
echo "📝 查看日志: pm2 logs government-backend"
echo "🔍 监控面板: pm2 monit"
echo "🌐 服务地址: http://localhost:5352"

View File

@@ -0,0 +1,75 @@
const axios = require('axios');
// 诊断URL重复问题
async function diagnoseURLIssue() {
console.log('🔍 诊断政府端API URL重复问题...\n');
const testURLs = [
{
name: '正确的部门接口URL',
url: 'https://ad.ningmuyun.com/api/government/departments',
description: '应该是正确的API路径'
},
{
name: '错误的重复URL',
url: 'https://ad.ningmuyun.com/api/government/government/departments',
description: '您提到的重复路径问题'
},
{
name: '静态文件路径测试',
url: 'https://ad.ningmuyun.com/government/',
description: '测试静态文件路径是否正常'
}
];
for (const test of testURLs) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 说明: ${test.description}`);
try {
const response = await axios.get(test.url, {
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
});
console.log(` ✅ 状态码: ${response.status}`);
console.log(` ✅ 响应类型: ${response.headers['content-type']}`);
if (response.status === 200) {
if (response.headers['content-type']?.includes('application/json')) {
console.log(` ✅ 返回JSON数据: ${JSON.stringify(response.data).substring(0, 100)}...`);
} else {
console.log(` ✅ 返回HTML内容 (可能是静态文件)`);
}
} else if (response.status === 404) {
console.log(` ❌ 404错误: 路径不存在`);
} else if (response.status === 401) {
console.log(` ✅ 401错误: 需要认证 (API接口正常)`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
} else {
console.log(` ❌ 网络错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 诊断完成!');
console.log('');
console.log('📝 分析结果:');
console.log(' - 如果正确的URL返回404说明nginx配置有问题');
console.log(' - 如果错误的URL也能访问说明有路径重写问题');
console.log(' - 如果静态文件路径正常说明nginx基本配置正确');
}
// 运行诊断
diagnoseURLIssue().catch(console.error);

View File

@@ -0,0 +1,38 @@
module.exports = {
apps: [{
name: 'government-backend',
script: 'app.js',
cwd: '/var/www/government-backend',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development',
PORT: 5352
},
env_production: {
NODE_ENV: 'production',
PORT: 5352,
DB_DIALECT: 'mysql',
DB_HOST: '129.211.213.226',
DB_PORT: 9527,
DB_DATABASE: 'ningxia_zhengfu',
DB_USER: 'root',
DB_PASSWORD: 'aiotAiot123!',
JWT_SECRET: 'government_super_secret_jwt_key_2024_very_long_and_secure',
LOG_LEVEL: 'info'
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_file: './logs/combined.log',
time: true,
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
max_restarts: 10,
min_uptime: '10s',
kill_timeout: 5000,
listen_timeout: 8000,
shutdown_with_message: true
}]
};

View File

@@ -0,0 +1,173 @@
const axios = require('axios');
// 最终nginx配置测试
async function finalNginxTest() {
console.log('🔍 最终nginx配置测试...\n');
console.log('📝 修复说明:');
console.log(' 将 proxy_pass http://localhost:5352/api/government/');
console.log(' 改为 proxy_pass http://localhost:5352');
console.log(' 这样可以保持完整路径,避免路径重复\n');
const testCases = [
{
name: '部门列表接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
shouldWork: true
},
{
name: '数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
shouldWork: true
},
{
name: '市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
shouldWork: true
},
{
name: '岗位列表接口',
url: 'https://ad.ningmuyun.com/api/government/positions',
shouldWork: true
},
{
name: '养殖户列表接口',
url: 'https://ad.ningmuyun.com/api/government/farmers',
shouldWork: true
},
{
name: '登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
shouldWork: true,
expectedStatus: 401
},
{
name: '重复路径接口应该404',
url: 'https://ad.ningmuyun.com/api/government/government/departments',
shouldWork: false
}
];
let successCount = 0;
let failCount = 0;
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500;
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` 状态码: ${response.status}`);
if (test.shouldWork) {
if (test.expectedStatus) {
if (response.status === test.expectedStatus) {
console.log(` ✅ 成功: 返回预期状态码 ${test.expectedStatus}`);
successCount++;
} else {
console.log(` ❌ 失败: 预期状态码 ${test.expectedStatus},实际 ${response.status}`);
failCount++;
}
} else if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
successCount++;
} else if (response.status === 404) {
console.log(` ❌ 失败: 接口返回 404`);
failCount++;
}
} else {
if (response.status === 404) {
console.log(` ✅ 成功: 正确返回 404重复路径应该不存在`);
successCount++;
} else if (response.status === 200) {
console.log(` ❌ 失败: 重复路径不应该工作`);
failCount++;
}
}
} catch (error) {
if (error.response) {
console.log(` 状态码: ${error.response.status}`);
if (test.shouldWork) {
console.log(` ❌ 失败: ${error.response.statusText}`);
failCount++;
} else {
if (error.response.status === 404) {
console.log(` ✅ 成功: 正确返回 404`);
successCount++;
}
}
} else {
console.log(` ❌ 网络错误: ${error.message}`);
failCount++;
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log(` ✅ 成功: ${successCount}`);
console.log(` ❌ 失败: ${failCount}`);
console.log('');
if (failCount === 0) {
console.log('🎉 所有测试通过Nginx配置修复成功');
} else {
console.log('⚠️ 还有测试失败,请检查:');
console.log(' 1. Nginx配置是否正确修改');
console.log(' 2. Nginx服务是否已重启');
console.log(' 3. 浏览器缓存是否已清除');
console.log('');
console.log('🔄 重启Nginx:');
console.log(' sudo nginx -t');
console.log(' sudo systemctl reload nginx');
}
console.log('');
console.log('📝 最终nginx配置:');
console.log(' location ^~ /api/government/auth/ {');
console.log(' proxy_pass http://localhost:5352/api/auth/;');
console.log(' }');
console.log(' location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352;');
console.log(' }');
console.log('');
console.log('🔄 路径映射:');
console.log(' /api/government/departments → http://localhost:5352/api/government/departments');
console.log(' /api/government/data-center → http://localhost:5352/api/government/data-center');
console.log(' /api/government/market-price → http://localhost:5352/api/government/market-price');
console.log('');
console.log('🚨 重要提醒:');
console.log(' 修改nginx配置后必须重启nginx服务才能生效');
console.log(' sudo nginx -t # 检查配置语法');
console.log(' sudo systemctl reload nginx # 重新加载配置');
}
// 运行测试
finalNginxTest().catch(console.error);

View File

@@ -1,119 +0,0 @@
server {
listen 443 ssl http2;
server_name ad.ningmuyun.com;
# SSL证书配置需要替换为实际的证书路径
ssl_certificate /etc/ssl/certs/ad.ningmuyun.com.crt;
ssl_certificate_key /etc/ssl/private/ad.ningmuyun.com.key;
# SSL配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# 政府端前端静态文件
location /government/ {
alias /var/www/government-admin-system/dist/;
try_files $uri $uri/ /government/index.html;
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
# 政府端后端API代理
location /api/government/ {
proxy_pass http://127.0.0.1:5352/api/government/;
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_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
# CORS headers
add_header Access-Control-Allow-Origin https://ad.ningmuyun.com;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With";
add_header Access-Control-Allow-Credentials true;
# 处理预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin https://ad.ningmuyun.com;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With";
add_header Access-Control-Allow-Credentials true;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
# 保险端前端静态文件
location /insurance/ {
alias /var/www/insurance-admin-system/dist/;
try_files $uri $uri/ /insurance/index.html;
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
# 保险端后端API代理
location /insurance/api/ {
proxy_pass http://127.0.0.1:3000/api/;
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_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
# CORS headers
add_header Access-Control-Allow-Origin https://ad.ningmuyun.com;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With";
add_header Access-Control-Allow-Credentials true;
# 处理预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin https://ad.ningmuyun.com;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With";
add_header Access-Control-Allow-Credentials true;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
# 健康检查
location /health {
proxy_pass http://127.0.0.1:5352/health;
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_set_header X-Forwarded-Proto $scheme;
}
# 根路径重定向到政府端
location = / {
return 301 /government/;
}
}
# HTTP重定向到HTTPS
server {
listen 80;
server_name ad.ningmuyun.com;
return 301 https://$server_name$request_uri;
}

View File

@@ -0,0 +1,63 @@
# Nginx配置检查说明
## 问题分析
### 当前状态
- ✅ 后端服务正常:`http://localhost:5352/api/government/departments` 返回200
- ✅ 登录接口正常:`https://ad.ningmuyun.com/api/government/auth/login` 返回401
- ❌ 其他接口404`https://ad.ningmuyun.com/api/government/departments` 返回404
### 问题根因
nginx配置中的 `location ^~ /api/government/` 规则没有正确工作。
### 当前nginx配置
```nginx
# 政府认证API代理 - 处理登录等认证接口优先级高于通用government代理
location ^~ /api/government/auth/ {
proxy_pass http://localhost:5352/api/auth/;
# ... CORS配置
}
# 政府API代理 - 处理其他政府相关接口
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/;
# ... CORS配置
}
```
### 可能的问题
1. **nginx配置语法错误** - 需要检查配置语法
2. **nginx服务未重启** - 配置修改后需要重启
3. **location规则冲突** - 可能有其他规则干扰
4. **proxy_pass配置错误** - 路径映射不正确
## 解决步骤
### 1. 检查nginx配置语法
```bash
sudo nginx -t
```
### 2. 重启nginx服务
```bash
sudo systemctl reload nginx
# 或者
sudo systemctl restart nginx
```
### 3. 检查nginx错误日志
```bash
sudo tail -f /var/log/nginx/error.log
```
### 4. 检查nginx访问日志
```bash
sudo tail -f /var/log/nginx/ad.ningmuyun.com.access.log
```
## 预期结果
修复后,以下接口应该正常工作:
-`https://ad.ningmuyun.com/api/government/auth/login` (登录)
-`https://ad.ningmuyun.com/api/government/departments` (部门列表)
-`https://ad.ningmuyun.com/api/government/data-center` (数据中心)
-`https://ad.ningmuyun.com/api/government/market-price` (市场价格)

View File

@@ -0,0 +1,77 @@
# Nginx配置测试说明
## 问题描述
- 登录接口:`/api/government/auth/login` ✅ 正常
- 其他接口:`/api/government/departments` ❌ 报错
- 错误URL`/api/government/government/departments` (路径重复)
## 当前nginx配置分析
### Server块1: ad.ningmuyun.com (HTTPS 443)
```nginx
# 静态文件服务
location ^~ /government/ {
alias /data/vue/ningmuyun/government/dist/;
# 处理前端静态文件
}
# 认证API代理 (优先级最高)
location ^~ /api/government/auth/ {
proxy_pass http://localhost:5352/api/auth/;
# 处理登录等认证接口
}
# 其他API代理 (优先级较低)
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/;
# 处理其他政府API接口
}
```
## 路径映射测试
| 请求路径 | 匹配规则 | 代理目标 | 预期结果 |
|---------|---------|---------|---------|
| `/api/government/auth/login` | `^~ /api/government/auth/` | `/api/auth/login` | ✅ 正常 |
| `/api/government/departments` | `^~ /api/government/` | `/api/government/departments` | ✅ 应该正常 |
| `/api/government/government/departments` | 无匹配 | 404 | ❌ 不应该出现 |
## 可能的问题原因
1. **前端请求路径错误**:前端可能错误地构造了重复路径
2. **nginx重写规则**可能有隐藏的rewrite规则导致路径重复
3. **代理配置问题**proxy_pass的路径处理可能有问题
## 测试步骤
1. 运行诊断脚本:
```bash
node diagnose-url-issue.js
```
2. 检查nginx错误日志
```bash
sudo tail -f /var/log/nginx/error.log
```
3. 检查nginx访问日志
```bash
sudo tail -f /var/log/nginx/ad.ningmuyun.com.access.log
```
## 修复建议
如果确认是nginx配置问题可能需要
1. 调整location规则的顺序
2. 添加更具体的路径匹配规则
3. 检查是否有隐藏的rewrite规则
4. 验证proxy_pass的路径处理
## 验证方法
修复后以下URL应该正常工作
- ✅ `https://ad.ningmuyun.com/api/government/auth/login`
- ✅ `https://ad.ningmuyun.com/api/government/departments`
- ✅ `https://ad.ningmuyun.com/api/government/market-price`
- ❌ `https://ad.ningmuyun.com/api/government/government/departments` (不应该存在)

View File

@@ -0,0 +1,113 @@
# 政府端API 404错误问题分析报告
## 问题描述
- **错误URL**: `https://ad.ningmuyun.com/api/government/market-price?type=beef`
- **错误状态**: 404 Not Found
- **影响范围**: 政府端管理系统市场价格功能
## 问题根因分析
### 1. 后端代码检查 ✅
- **路由配置**: `government-backend/routes/government.js` 第11行
```javascript
router.get('/market-price', governmentController.getMarketPrice);
```
- **控制器方法**: `governmentController.getMarketPrice` 已正确实现
- **应用路由注册**: `app.js` 第50行已正确注册
```javascript
app.use('/api/government', require('./routes/government'));
```
### 2. 前端代码检查 ✅
- **API调用**: `government-admin/src/views/MarketPrice.vue` 第94行
```javascript
const response = await axios.get('/api/government/market-price', {
params: { type }
})
```
- **代理配置**: `vite.config.js` 开发环境代理配置正确
### 3. Nginx配置问题 ❌
**问题所在**: nginx配置中政府API的路径匹配错误
**原始错误配置**:
```nginx
location ^~ /government/api/ {
proxy_pass http://localhost:5352/;
}
```
**问题分析**:
- 前端请求路径: `/api/government/market-price`
- nginx匹配路径: `/government/api/`
- 路径不匹配导致404错误
## 解决方案
### 修复nginx配置
将政府API代理路径从 `/government/api/` 修改为 `/api/government/`:
```nginx
# 政府API代理 - 修复路径匹配问题
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/;
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_set_header X-Forwarded-Proto $scheme;
# CORS配置
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
```
## 部署步骤
1. **备份当前nginx配置**:
```bash
sudo cp /etc/nginx/conf.d/ningmuyun_one.conf /etc/nginx/conf.d/ningmuyun_one.conf.backup
```
2. **应用修复配置**:
```bash
sudo cp nginx-fix-government-api.conf /etc/nginx/conf.d/
# 或者手动编辑配置文件,将上述配置添加到 ad.ningmuyun.com server 块中
```
3. **测试nginx配置**:
```bash
sudo nginx -t
```
4. **重新加载nginx**:
```bash
sudo systemctl reload nginx
```
5. **验证修复**:
```bash
curl -k https://ad.ningmuyun.com/api/government/market-price?type=beef
```
## 预期结果
修复后,`https://ad.ningmuyun.com/api/government/market-price?type=beef` 应该返回正确的市场价格数据而不是404错误。
## 相关文件
- `government-backend/_etc_nginx_conf.d_ningmuyun_one.conf` - 主nginx配置文件
- `government-backend/nginx-fix-government-api.conf` - 修复配置片段
- `government-backend/routes/government.js` - 后端路由
- `government-backend/controllers/governmentController.js` - 控制器实现
- `government-admin/src/views/MarketPrice.vue` - 前端页面

View File

@@ -0,0 +1,116 @@
const axios = require('axios');
// 测试重启后的API接口
async function testAfterRestart() {
console.log('🔍 测试nginx重启后的API接口...\n');
const testCases = [
{
name: '登录接口测试',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
expected: '应该返回401认证错误接口正常'
},
{
name: '部门列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/departments',
method: 'GET',
data: null,
expected: '应该返回200或401'
},
{
name: '数据中心接口测试',
url: 'https://ad.ningmuyun.com/api/government/data-center',
method: 'GET',
data: null,
expected: '应该返回200或401'
},
{
name: '市场价格接口测试',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
method: 'GET',
data: null,
expected: '应该返回200或401'
},
{
name: '岗位列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/positions',
method: 'GET',
data: null,
expected: '应该返回200或401'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const config = {
method: test.method,
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 接口不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: nginx配置可能还有问题`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 当前nginx配置:');
console.log(' location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352/api/government/;');
console.log(' }');
console.log('');
console.log('🔄 路径映射:');
console.log(' /api/government/departments → http://localhost:5352/api/government/departments');
console.log(' /api/government/positions → http://localhost:5352/api/government/positions');
}
// 运行测试
testAfterRestart().catch(console.error);

View File

@@ -0,0 +1,126 @@
const axios = require('axios');
// 测试最终修复效果
async function testFinalFix() {
console.log('🔍 测试最终修复效果...\n');
const testCases = [
{
name: '部门列表接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
expected: '应该返回200状态码和部门数据'
},
{
name: '数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
expected: '应该返回200状态码和统计数据'
},
{
name: '市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
expected: '应该返回200状态码和价格数据'
},
{
name: '岗位列表接口',
url: 'https://ad.ningmuyun.com/api/government/positions',
expected: '应该返回200状态码和岗位数据'
},
{
name: '养殖户列表接口',
url: 'https://ad.ningmuyun.com/api/government/farmers',
expected: '应该返回200状态码和养殖户数据'
},
{
name: '养殖类型接口',
url: 'https://ad.ningmuyun.com/api/government/farm-types',
expected: '应该返回200状态码和养殖类型数据'
},
{
name: '登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
expected: '应该返回401认证错误接口正常'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 接口不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: nginx配置可能还有问题`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 最终nginx配置:');
console.log(' location ^~ /api/government/auth/ {');
console.log(' proxy_pass http://localhost:5352/api/auth/;');
console.log(' }');
console.log(' location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352/api/government/;');
console.log(' }');
console.log('');
console.log('🔄 路径映射:');
console.log(' /api/government/departments → http://localhost:5352/api/government/departments');
console.log(' /api/government/data-center → http://localhost:5352/api/government/data-center');
console.log(' /api/government/market-price → http://localhost:5352/api/government/market-price');
console.log('');
console.log('🔄 现在需要重启nginx使配置生效:');
console.log(' sudo nginx -t # 检查配置语法');
console.log(' sudo systemctl reload nginx # 重新加载配置');
}
// 运行测试
testFinalFix().catch(console.error);

View File

@@ -0,0 +1,94 @@
const axios = require('axios');
// 测试修复后的API接口
async function testFixedAPIs() {
console.log('🔍 测试修复后的政府端API接口...\n');
const testCases = [
{
name: '部门列表接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
expected: '应该返回200状态码和部门数据'
},
{
name: '数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
expected: '应该返回200状态码和统计数据'
},
{
name: '市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
expected: '应该返回200状态码和价格数据'
},
{
name: '岗位列表接口',
url: 'https://ad.ningmuyun.com/api/government/positions',
expected: '应该返回200状态码和岗位数据'
},
{
name: '养殖户列表接口',
url: 'https://ad.ningmuyun.com/api/government/farmers',
expected: '应该返回200状态码和养殖户数据'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const response = await axios.get(test.url, {
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
});
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 接口不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: nginx配置可能还有问题`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 修复说明:');
console.log(' 问题: location规则缺少注释符号导致被注释掉');
console.log(' 修复: 添加了正确的注释和location规则');
console.log('');
console.log('🔄 现在需要重启nginx使配置生效:');
console.log(' sudo nginx -t # 检查配置语法');
console.log(' sudo systemctl reload nginx # 重新加载配置');
}
// 运行测试
testFixedAPIs().catch(console.error);

View File

@@ -0,0 +1,97 @@
const axios = require('axios');
// 测试政府端各种API接口
async function testGovernmentAPIs() {
console.log('🔍 测试政府端API接口...\n');
const testCases = [
{
name: '登录接口测试',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
expected: '应该返回登录成功或认证错误'
},
{
name: '部门列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/departments',
method: 'GET',
data: null,
expected: '应该返回部门列表或认证错误'
},
{
name: '市场价格接口测试',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
method: 'GET',
data: null,
expected: '应该返回市场价格数据或认证错误'
},
{
name: '数据中心接口测试',
url: 'https://ad.ningmuyun.com/api/government/data-center',
method: 'GET',
data: null,
expected: '应该返回数据中心数据或认证错误'
}
];
for (const testCase of testCases) {
console.log(`📋 ${testCase.name}`);
console.log(` URL: ${testCase.url}`);
console.log(` 方法: ${testCase.method}`);
console.log(` 预期: ${testCase.expected}`);
try {
const config = {
method: testCase.method,
url: testCase.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000
};
if (testCase.data) {
config.data = testCase.data;
}
const response = await axios(config);
console.log(` ✅ 状态码: ${response.status}`);
console.log(` ✅ 响应数据: ${JSON.stringify(response.data, null, 2).substring(0, 200)}...`);
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误信息: ${JSON.stringify(error.response.data, null, 2)}`);
// 分析错误类型
if (error.response.status === 404) {
console.log(` 🔍 分析: 404错误可能是路径映射问题`);
} else if (error.response.status === 401) {
console.log(` 🔍 分析: 401错误需要认证这是正常的`);
} else if (error.response.status === 500) {
console.log(` 🔍 分析: 500错误服务器内部错误`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 分析说明:');
console.log(' - 如果所有接口都返回404说明nginx配置有问题');
console.log(' - 如果只有登录接口正常其他返回404说明路径映射有问题');
console.log(' - 如果返回401认证错误说明接口正常但需要登录');
console.log(' - 如果返回500错误说明后端服务有问题');
}
// 运行测试
testGovernmentAPIs().catch(console.error);

View File

@@ -0,0 +1,160 @@
const axios = require('axios');
// 测试location规则顺序修复效果
async function testLocationOrderFix() {
console.log('🔍 测试location规则顺序修复效果...\n');
console.log('📝 修复说明:');
console.log(' 调整了location规则的顺序让API规则优先于静态文件规则');
console.log(' 1. location ^~ /api/government/auth/ (最高优先级)');
console.log(' 2. location ^~ /api/government/ (第二优先级)');
console.log(' 3. location ^~ /government/ (静态文件,最低优先级)');
console.log('');
const testCases = [
{
name: '部门列表接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
shouldWork: true
},
{
name: '数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
shouldWork: true
},
{
name: '市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
shouldWork: true
},
{
name: '岗位列表接口',
url: 'https://ad.ningmuyun.com/api/government/positions',
shouldWork: true
},
{
name: '养殖户列表接口',
url: 'https://ad.ningmuyun.com/api/government/farmers',
shouldWork: true
},
{
name: '登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
shouldWork: true,
expectedStatus: 401
}
];
let successCount = 0;
let failCount = 0;
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500;
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` 状态码: ${response.status}`);
if (test.shouldWork) {
if (test.expectedStatus) {
if (response.status === test.expectedStatus) {
console.log(` ✅ 成功: 返回预期状态码 ${test.expectedStatus}`);
successCount++;
} else {
console.log(` ❌ 失败: 预期状态码 ${test.expectedStatus},实际 ${response.status}`);
failCount++;
}
} else if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
successCount++;
} else if (response.status === 404) {
console.log(` ❌ 失败: 接口返回 404`);
failCount++;
}
}
} catch (error) {
if (error.response) {
console.log(` 状态码: ${error.response.status}`);
if (test.shouldWork) {
console.log(` ❌ 失败: ${error.response.statusText}`);
failCount++;
}
} else {
console.log(` ❌ 网络错误: ${error.message}`);
failCount++;
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log(` ✅ 成功: ${successCount}`);
console.log(` ❌ 失败: ${failCount}`);
console.log('');
if (failCount === 0) {
console.log('🎉 所有测试通过Location规则顺序修复成功');
} else {
console.log('⚠️ 还有测试失败,请检查:');
console.log(' 1. Nginx配置是否正确修改');
console.log(' 2. Nginx服务是否已重启');
console.log(' 3. 后端服务是否正常运行');
console.log('');
console.log('🔄 重启Nginx:');
console.log(' sudo nginx -t');
console.log(' sudo systemctl reload nginx');
}
console.log('');
console.log('📝 修复后的nginx配置顺序:');
console.log(' 1. location ^~ /api/government/auth/ {');
console.log(' proxy_pass http://localhost:5352/api/auth/;');
console.log(' }');
console.log(' 2. location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352/api/government/;');
console.log(' }');
console.log(' 3. location ^~ /government/ {');
console.log(' alias /data/vue/ningmuyun/government/dist/;');
console.log(' }');
console.log('');
console.log('🔄 路径映射:');
console.log(' /api/government/departments → http://localhost:5352/api/government/departments');
console.log(' /api/government/data-center → http://localhost:5352/api/government/data-center');
console.log(' /api/government/market-price → http://localhost:5352/api/government/market-price');
console.log('');
console.log('🚨 重要提醒:');
console.log(' 修改nginx配置后必须重启nginx服务才能生效');
console.log(' sudo nginx -t # 检查配置语法');
console.log(' sudo systemctl reload nginx # 重新加载配置');
}
// 运行测试
testLocationOrderFix().catch(console.error);

View File

@@ -0,0 +1,66 @@
const axios = require('axios');
// 测试登录接口
async function testLoginAPI() {
console.log('🔍 测试政府端登录接口...\n');
const testCases = [
{
name: '本地后端直接测试',
url: 'http://localhost:5352/api/auth/login',
description: '直接访问后端服务'
},
{
name: '生产环境nginx代理测试',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
description: '通过nginx代理访问'
}
];
const testData = {
username: 'admin',
password: 'admin123'
};
for (const testCase of testCases) {
console.log(`📋 ${testCase.name}`);
console.log(` 描述: ${testCase.description}`);
console.log(` URL: ${testCase.url}`);
console.log(` 数据: ${JSON.stringify(testData)}`);
try {
const response = await axios.post(testCase.url, testData, {
headers: {
'Content-Type': 'application/json'
},
timeout: 10000
});
console.log(` ✅ 状态码: ${response.status}`);
console.log(` ✅ 响应: ${JSON.stringify(response.data, null, 2)}`);
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误信息: ${JSON.stringify(error.response.data, null, 2)}`);
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(50));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 说明:');
console.log(' - 如果本地测试成功但生产环境失败说明nginx配置有问题');
console.log(' - 如果两个都失败,说明后端服务有问题');
console.log(' - 如果两个都成功,说明修复生效');
}
// 运行测试
testLoginAPI().catch(console.error);

View File

@@ -0,0 +1,114 @@
const axios = require('axios');
// 测试nginx配置问题
async function testNginxConfig() {
console.log('🔍 测试nginx配置问题...\n');
const testCases = [
{
name: '直接测试后端服务',
url: 'http://localhost:5352/api/government/departments',
expected: '应该返回200'
},
{
name: '通过nginx测试部门接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
expected: '应该返回200'
},
{
name: '通过nginx测试登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
expected: '应该返回401认证错误'
},
{
name: '测试重复路径接口',
url: 'https://ad.ningmuyun.com/api/government/government/departments',
expected: '应该返回200如果nginx配置有问题'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500;
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 接口不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: nginx配置问题路径映射不正确`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 可能的问题:');
console.log(' 1. nginx配置语法错误');
console.log(' 2. nginx服务未重启');
console.log(' 3. location规则冲突');
console.log(' 4. proxy_pass配置错误');
console.log('');
console.log('🔄 建议的解决步骤:');
console.log(' 1. 检查nginx配置语法: sudo nginx -t');
console.log(' 2. 重启nginx服务: sudo systemctl reload nginx');
console.log(' 3. 检查nginx错误日志: sudo tail -f /var/log/nginx/error.log');
console.log(' 4. 检查nginx访问日志: sudo tail -f /var/log/nginx/ad.ningmuyun.com.access.log');
console.log('');
console.log('📝 当前nginx配置应该是:');
console.log(' location ^~ /api/government/auth/ {');
console.log(' proxy_pass http://localhost:5352/api/auth/;');
console.log(' }');
console.log(' location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352/api/government/;');
console.log(' }');
}
// 运行测试
testNginxConfig().catch(console.error);

View File

@@ -0,0 +1,112 @@
const axios = require('axios');
// 调试nginx配置问题
async function testNginxDebug() {
console.log('🔍 调试nginx配置问题...\n');
const testCases = [
{
name: '直接测试后端服务',
url: 'http://localhost:5352/api/government/departments',
expected: '应该返回200'
},
{
name: '通过nginx测试部门接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
expected: '应该返回200'
},
{
name: '通过nginx测试数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
expected: '应该返回200'
},
{
name: '通过nginx测试市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
expected: '应该返回200'
},
{
name: '通过nginx测试登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
expected: '应该返回401认证错误'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 接口不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: nginx配置问题路径映射不正确`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 调试完成!');
console.log('');
console.log('📝 当前nginx配置:');
console.log(' location ^~ /api/government/auth/ {');
console.log(' proxy_pass http://localhost:5352/api/auth/;');
console.log(' }');
console.log(' location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352/api/government/;');
console.log(' }');
console.log('');
console.log('🔄 如果所有接口都返回404可能需要:');
console.log(' 1. 检查nginx配置语法: sudo nginx -t');
console.log(' 2. 重启nginx服务: sudo systemctl reload nginx');
console.log(' 3. 检查nginx错误日志: sudo tail -f /var/log/nginx/error.log');
}
// 运行测试
testNginxDebug().catch(console.error);

View File

@@ -0,0 +1,155 @@
const axios = require('axios');
// 测试nginx最终修复效果
async function testNginxFixFinal() {
console.log('🔍 测试nginx最终修复效果...\n');
console.log('📝 修复说明:');
console.log(' 将 proxy_pass http://localhost:5352');
console.log(' 改为 proxy_pass http://localhost:5352/api/government/');
console.log(' 这样可以正确代理到后端API路径\n');
const testCases = [
{
name: '部门列表接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
shouldWork: true
},
{
name: '数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
shouldWork: true
},
{
name: '市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
shouldWork: true
},
{
name: '岗位列表接口',
url: 'https://ad.ningmuyun.com/api/government/positions',
shouldWork: true
},
{
name: '养殖户列表接口',
url: 'https://ad.ningmuyun.com/api/government/farmers',
shouldWork: true
},
{
name: '登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
shouldWork: true,
expectedStatus: 401
}
];
let successCount = 0;
let failCount = 0;
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500;
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` 状态码: ${response.status}`);
if (test.shouldWork) {
if (test.expectedStatus) {
if (response.status === test.expectedStatus) {
console.log(` ✅ 成功: 返回预期状态码 ${test.expectedStatus}`);
successCount++;
} else {
console.log(` ❌ 失败: 预期状态码 ${test.expectedStatus},实际 ${response.status}`);
failCount++;
}
} else if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
successCount++;
} else if (response.status === 404) {
console.log(` ❌ 失败: 接口返回 404`);
failCount++;
}
}
} catch (error) {
if (error.response) {
console.log(` 状态码: ${error.response.status}`);
if (test.shouldWork) {
console.log(` ❌ 失败: ${error.response.statusText}`);
failCount++;
}
} else {
console.log(` ❌ 网络错误: ${error.message}`);
failCount++;
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log(` ✅ 成功: ${successCount}`);
console.log(` ❌ 失败: ${failCount}`);
console.log('');
if (failCount === 0) {
console.log('🎉 所有测试通过Nginx配置修复成功');
} else {
console.log('⚠️ 还有测试失败,请检查:');
console.log(' 1. Nginx配置是否正确修改');
console.log(' 2. Nginx服务是否已重启');
console.log(' 3. 后端服务是否正常运行');
console.log('');
console.log('🔄 重启Nginx:');
console.log(' sudo nginx -t');
console.log(' sudo systemctl reload nginx');
}
console.log('');
console.log('📝 当前nginx配置:');
console.log(' location ^~ /api/government/auth/ {');
console.log(' proxy_pass http://localhost:5352/api/auth/;');
console.log(' }');
console.log(' location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352/api/government/;');
console.log(' }');
console.log('');
console.log('🔄 路径映射:');
console.log(' /api/government/departments → http://localhost:5352/api/government/departments');
console.log(' /api/government/data-center → http://localhost:5352/api/government/data-center');
console.log(' /api/government/market-price → http://localhost:5352/api/government/market-price');
console.log('');
console.log('🚨 重要提醒:');
console.log(' 修改nginx配置后必须重启nginx服务才能生效');
console.log(' sudo nginx -t # 检查配置语法');
console.log(' sudo systemctl reload nginx # 重新加载配置');
}
// 运行测试
testNginxFixFinal().catch(console.error);

View File

@@ -0,0 +1,111 @@
const axios = require('axios');
// 测试nginx配置修复后的API接口
async function testNginxFix() {
console.log('🔍 测试nginx配置修复后的API接口...\n');
const testCases = [
{
name: '登录接口测试',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
expected: '应该返回401认证错误接口正常'
},
{
name: '部门列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/departments',
method: 'GET',
expected: '应该返回200状态码和部门数据'
},
{
name: '数据中心接口测试',
url: 'https://ad.ningmuyun.com/api/government/data-center',
method: 'GET',
expected: '应该返回200状态码和统计数据'
},
{
name: '市场价格接口测试',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
method: 'GET',
expected: '应该返回200状态码和价格数据'
},
{
name: '岗位列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/positions',
method: 'GET',
expected: '应该返回200状态码和岗位数据'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const config = {
method: test.method,
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 接口不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: nginx配置可能还有问题`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 修复说明:');
console.log(' 问题: location规则缩进不正确被嵌套在错误的块内');
console.log(' 修复: 调整了location规则的缩进和位置');
console.log('');
console.log('🔄 现在需要重启nginx使配置生效:');
console.log(' sudo nginx -t # 检查配置语法');
console.log(' sudo systemctl reload nginx # 重新加载配置');
}
// 运行测试
testNginxFix().catch(console.error);

View File

@@ -0,0 +1,150 @@
const axios = require('axios');
// 测试nginx重启后的修复效果
async function testNginxRestartFix() {
console.log('🔍 测试nginx重启后的修复效果...\n');
console.log('📝 修复说明:');
console.log(' 将 proxy_pass http://localhost:5352');
console.log(' 改为 proxy_pass http://localhost:5352/api/government/');
console.log(' 这样可以正确代理到后端API路径\n');
const testCases = [
{
name: '部门列表接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
shouldWork: true
},
{
name: '数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
shouldWork: true
},
{
name: '市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
shouldWork: true
},
{
name: '岗位列表接口',
url: 'https://ad.ningmuyun.com/api/government/positions',
shouldWork: true
},
{
name: '养殖户列表接口',
url: 'https://ad.ningmuyun.com/api/government/farmers',
shouldWork: true
},
{
name: '登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
shouldWork: true,
expectedStatus: 401
}
];
let successCount = 0;
let failCount = 0;
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500;
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` 状态码: ${response.status}`);
if (test.shouldWork) {
if (test.expectedStatus) {
if (response.status === test.expectedStatus) {
console.log(` ✅ 成功: 返回预期状态码 ${test.expectedStatus}`);
successCount++;
} else {
console.log(` ❌ 失败: 预期状态码 ${test.expectedStatus},实际 ${response.status}`);
failCount++;
}
} else if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
successCount++;
} else if (response.status === 404) {
console.log(` ❌ 失败: 接口返回 404`);
failCount++;
}
}
} catch (error) {
if (error.response) {
console.log(` 状态码: ${error.response.status}`);
if (test.shouldWork) {
console.log(` ❌ 失败: ${error.response.statusText}`);
failCount++;
}
} else {
console.log(` ❌ 网络错误: ${error.message}`);
failCount++;
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log(` ✅ 成功: ${successCount}`);
console.log(` ❌ 失败: ${failCount}`);
console.log('');
if (failCount === 0) {
console.log('🎉 所有测试通过Nginx配置修复成功');
} else {
console.log('⚠️ 还有测试失败,请检查:');
console.log(' 1. Nginx配置是否正确修改');
console.log(' 2. Nginx服务是否已重启');
console.log(' 3. 后端服务是否正常运行');
console.log('');
console.log('🔄 重启Nginx:');
console.log(' sudo nginx -t');
console.log(' sudo systemctl reload nginx');
}
console.log('');
console.log('📝 当前nginx配置:');
console.log(' location ^~ /api/government/auth/ {');
console.log(' proxy_pass http://localhost:5352/api/auth/;');
console.log(' }');
console.log(' location ^~ /api/government/ {');
console.log(' proxy_pass http://localhost:5352/api/government/;');
console.log(' }');
console.log('');
console.log('🔄 路径映射:');
console.log(' /api/government/departments → http://localhost:5352/api/government/departments');
console.log(' /api/government/data-center → http://localhost:5352/api/government/data-center');
console.log(' /api/government/market-price → http://localhost:5352/api/government/market-price');
}
// 运行测试
testNginxRestartFix().catch(console.error);

View File

@@ -0,0 +1,35 @@
const { exec } = require('child_process');
// 测试nginx配置语法
function testNginxSyntax() {
console.log('🔍 测试nginx配置语法...\n');
exec('nginx -t', (error, stdout, stderr) => {
if (error) {
console.log('❌ nginx配置语法错误:');
console.log(stderr);
console.log('\n🔍 可能的问题:');
console.log(' 1. 缩进问题');
console.log(' 2. 缺少分号');
console.log(' 3. 括号不匹配');
console.log(' 4. 隐藏字符');
return;
}
if (stderr) {
console.log('⚠️ nginx配置警告:');
console.log(stderr);
}
console.log('✅ nginx配置语法正确');
console.log(stdout);
console.log('\n🔄 建议的解决步骤:');
console.log(' 1. 重启nginx服务: sudo systemctl reload nginx');
console.log(' 2. 检查nginx错误日志: sudo tail -f /var/log/nginx/error.log');
console.log(' 3. 检查nginx访问日志: sudo tail -f /var/log/nginx/access.log');
});
}
// 运行测试
testNginxSyntax();

View File

@@ -0,0 +1,115 @@
const axios = require('axios');
// 测试路径重复修复效果
async function testPathDuplicationFix() {
console.log('🔍 测试路径重复修复效果...\n');
const testCases = [
{
name: '正确路径 - 部门列表',
url: 'https://ad.ningmuyun.com/api/government/departments',
expected: '应该返回200状态码'
},
{
name: '重复路径 - 部门列表',
url: 'https://ad.ningmuyun.com/api/government/government/departments',
expected: '应该返回404错误路径不存在'
},
{
name: '正确路径 - 数据中心',
url: 'https://ad.ningmuyun.com/api/government/data-center',
expected: '应该返回200状态码'
},
{
name: '重复路径 - 数据中心',
url: 'https://ad.ningmuyun.com/api/government/government/data-center',
expected: '应该返回404错误路径不存在'
},
{
name: '正确路径 - 市场价格',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
expected: '应该返回200状态码'
},
{
name: '重复路径 - 市场价格',
url: 'https://ad.ningmuyun.com/api/government/government/market-price?type=beef',
expected: '应该返回404错误路径不存在'
},
{
name: '正确路径 - 养殖类型',
url: 'https://ad.ningmuyun.com/api/government/farm-types',
expected: '应该返回200状态码'
},
{
name: '重复路径 - 养殖类型',
url: 'https://ad.ningmuyun.com/api/government/government/farm-types',
expected: '应该返回404错误路径不存在'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const response = await axios.get(test.url, {
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
});
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证(接口路径正确)`);
} else if (response.status === 404) {
console.log(` ✅ 正常: 路径不存在(符合预期)`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` ✅ 正常: 路径不存在(符合预期)`);
}
} else if (error.request) {
console.log(` ❌ 网络错误: ${error.message}`);
} else {
console.log(` ❌ 请求配置错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 修复说明:');
console.log(' 问题: proxy_pass配置导致路径重复');
console.log(' 修复前: proxy_pass http://localhost:5352/api/government/;');
console.log(' 修复后: proxy_pass http://localhost:5352/;');
console.log('');
console.log('🔄 路径映射:');
console.log(' /api/government/departments → http://localhost:5352/api/government/departments');
console.log(' /api/government/data-center → http://localhost:5352/api/government/data-center');
console.log(' /api/government/market-price → http://localhost:5352/api/government/market-price');
console.log('');
console.log('🔄 现在需要重启nginx使配置生效:');
console.log(' sudo nginx -t # 检查配置语法');
console.log(' sudo systemctl reload nginx # 重新加载配置');
}
// 运行测试
testPathDuplicationFix().catch(console.error);

View File

@@ -0,0 +1,84 @@
const axios = require('axios');
// 测试路径修复效果
async function testPathFix() {
console.log('🔍 测试政府端API路径修复效果...\n');
const testCases = [
{
name: '岗位列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/positions',
expected: '应该返回岗位列表数据'
},
{
name: '部门列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/departments',
expected: '应该返回部门列表数据'
},
{
name: '养殖户列表接口测试',
url: 'https://ad.ningmuyun.com/api/government/farmers',
expected: '应该返回养殖户列表数据'
},
{
name: '市场价格接口测试',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
expected: '应该返回市场价格数据'
}
];
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
console.log(` 预期: ${test.expected}`);
try {
const response = await axios.get(test.url, {
timeout: 10000,
validateStatus: function (status) {
return status < 500; // 接受所有小于500的状态码
}
});
console.log(` ✅ 状态码: ${response.status}`);
if (response.status === 200) {
console.log(` ✅ 成功: 返回了正确的数据`);
if (Array.isArray(response.data)) {
console.log(` 📊 数据量: ${response.data.length} 条记录`);
} else if (response.data && typeof response.data === 'object') {
console.log(` 📊 数据类型: 对象,包含 ${Object.keys(response.data).length} 个字段`);
}
} else if (response.status === 401) {
console.log(` ✅ 正常: 需要认证 (接口路径正确)`);
} else if (response.status === 404) {
console.log(` ❌ 错误: 路径不存在`);
}
} catch (error) {
if (error.response) {
console.log(` ❌ 状态码: ${error.response.status}`);
console.log(` ❌ 错误: ${error.response.statusText}`);
if (error.response.status === 404) {
console.log(` 🔍 分析: 可能是nginx配置问题路径映射不正确`);
}
} else {
console.log(` ❌ 网络错误: ${error.message}`);
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log('');
console.log('📝 修复说明:');
console.log(' - 修复前: proxy_pass http://localhost:5352/api/government/; (会重复路径)');
console.log(' - 修复后: proxy_pass http://localhost:5352/; (正确映射)');
console.log(' - 现在 /api/government/positions 应该正确映射到 /api/government/positions');
}
// 运行测试
testPathFix().catch(console.error);

View File

@@ -0,0 +1,149 @@
const axios = require('axios');
// 验证nginx修复效果
async function verifyNginxFix() {
console.log('🔍 验证 Nginx 修复效果...\n');
console.log('📝 修改说明:');
console.log(' 将 proxy_pass http://localhost:5352/api/government/');
console.log(' 改为 proxy_pass http://localhost:5352');
console.log(' 这样可以保持完整路径,避免路径重复\n');
const testCases = [
{
name: '部门列表接口',
url: 'https://ad.ningmuyun.com/api/government/departments',
shouldWork: true
},
{
name: '数据中心接口',
url: 'https://ad.ningmuyun.com/api/government/data-center',
shouldWork: true
},
{
name: '市场价格接口',
url: 'https://ad.ningmuyun.com/api/government/market-price?type=beef',
shouldWork: true
},
{
name: '岗位列表接口',
url: 'https://ad.ningmuyun.com/api/government/positions',
shouldWork: true
},
{
name: '养殖户列表接口',
url: 'https://ad.ningmuyun.com/api/government/farmers',
shouldWork: true
},
{
name: '登录接口',
url: 'https://ad.ningmuyun.com/api/government/auth/login',
method: 'POST',
data: { username: 'admin', password: 'admin123' },
shouldWork: true,
expectedStatus: 401
},
{
name: '重复路径接口应该404',
url: 'https://ad.ningmuyun.com/api/government/government/departments',
shouldWork: false
}
];
let successCount = 0;
let failCount = 0;
for (const test of testCases) {
console.log(`📋 ${test.name}`);
console.log(` URL: ${test.url}`);
try {
const config = {
method: test.method || 'GET',
url: test.url,
headers: {
'Content-Type': 'application/json'
},
timeout: 10000,
validateStatus: function (status) {
return status < 500;
}
};
if (test.data) {
config.data = test.data;
}
const response = await axios(config);
console.log(` 状态码: ${response.status}`);
if (test.shouldWork) {
if (test.expectedStatus) {
if (response.status === test.expectedStatus) {
console.log(` ✅ 成功: 返回预期状态码 ${test.expectedStatus}`);
successCount++;
} else {
console.log(` ❌ 失败: 预期状态码 ${test.expectedStatus},实际 ${response.status}`);
failCount++;
}
} else if (response.status === 200) {
console.log(` ✅ 成功: 接口正常工作`);
successCount++;
} else if (response.status === 404) {
console.log(` ❌ 失败: 接口返回 404`);
failCount++;
}
} else {
if (response.status === 404) {
console.log(` ✅ 成功: 正确返回 404重复路径应该不存在`);
successCount++;
} else if (response.status === 200) {
console.log(` ❌ 失败: 重复路径不应该工作`);
failCount++;
}
}
} catch (error) {
if (error.response) {
console.log(` 状态码: ${error.response.status}`);
if (test.shouldWork) {
console.log(` ❌ 失败: ${error.response.statusText}`);
failCount++;
} else {
if (error.response.status === 404) {
console.log(` ✅ 成功: 正确返回 404`);
successCount++;
}
}
} else {
console.log(` ❌ 网络错误: ${error.message}`);
failCount++;
}
}
console.log(' ' + '─'.repeat(60));
console.log('');
}
console.log('🎯 测试完成!');
console.log(` ✅ 成功: ${successCount}`);
console.log(` ❌ 失败: ${failCount}`);
console.log('');
if (failCount === 0) {
console.log('🎉 所有测试通过Nginx 配置修复成功!');
} else {
console.log('⚠️ 还有测试失败,请检查:');
console.log(' 1. Nginx 配置是否正确修改');
console.log(' 2. Nginx 服务是否已重启');
console.log(' 3. 浏览器缓存是否已清除');
console.log('');
console.log('🔄 重启 Nginx:');
console.log(' sudo nginx -t');
console.log(' sudo systemctl reload nginx');
}
}
// 运行验证
verifyNginxFix().catch(console.error);

View File

@@ -0,0 +1,126 @@
# 前端API路径修复说明
## 问题描述
- **错误URL**: `https://ad.ningmuyun.com/api/government/government/positions`
- **问题**: URL中出现两个`government`,导致路径重复
- **影响范围**: 政府端管理系统所有政府相关API接口
## 问题根因分析
### 1. 前端API配置问题 ❌
`government-admin/src/utils/api.js`政府相关的API接口缺少 `/api` 前缀:
**原始错误配置**:
```javascript
// 部门管理
departments: {
getList: (params) => instance.get('/government/departments', { params })
},
// 岗位管理
positions: {
getList: (params) => instance.get('/government/positions', { params })
},
// 养殖户管理
farmers: {
getList: (params) => instance.get('/government/farmers', { params }),
create: (data) => instance.post('/government/farmers', data),
// ... 其他方法
}
```
### 2. 路径构造过程
1. **前端baseURL**: `http://localhost:5352/api` (开发环境)
2. **API调用**: `instance.get('/government/positions')`
3. **实际请求**: `http://localhost:5352/api/government/positions` ✅ 正确
但在生产环境中:
1. **前端baseURL**: `https://ad.ningmuyun.com` (生产环境)
2. **API调用**: `instance.get('/government/positions')`
3. **实际请求**: `https://ad.ningmuyun.com/government/positions` ❌ 缺少 `/api` 前缀
4. **nginx匹配**: 匹配到 `location ^~ /government/` (静态文件规则)
5. **重定向**: 可能被重写为 `/api/government/government/positions` ❌ 重复
## 解决方案
### 修复前端API配置
将所有政府相关API接口添加 `/api` 前缀:
```javascript
// 部门管理
departments: {
getList: (params) => instance.get('/api/government/departments', { params })
},
// 岗位管理
positions: {
getList: (params) => instance.get('/api/government/positions', { params })
},
// 养殖户管理
farmers: {
getList: (params) => instance.get('/api/government/farmers', { params }),
create: (data) => instance.post('/api/government/farmers', data),
update: (id, data) => instance.put(`/api/government/farmers/${id}`, data),
delete: (id) => instance.delete(`/api/government/farmers/${id}`),
resetPassword: (id) => instance.post(`/api/government/farmers/${id}/reset-password`)
},
// 养殖类型相关
farmTypes: {
getList: () => instance.get('/api/government/farm-types')
},
// 养殖种类相关
animalTypes: {
getList: () => instance.get('/api/government/animal-types')
},
// 智能项圈管理
collars: {
getList: (params) => instance.get('/api/government/collars', { params }),
create: (data) => instance.post('/api/government/collars', data),
update: (id, data) => instance.put(`/api/government/collars/${id}`, data),
delete: (id) => instance.delete(`/api/government/collars/${id}`)
}
```
## 修复后的路径映射
| 前端调用 | 生产环境URL | nginx匹配 | 后端路由 | 状态 |
|---------|------------|----------|---------|------|
| `/api/government/departments` | `https://ad.ningmuyun.com/api/government/departments` | `^~ /api/government/` | `/api/government/departments` | ✅ 正确 |
| `/api/government/positions` | `https://ad.ningmuyun.com/api/government/positions` | `^~ /api/government/` | `/api/government/positions` | ✅ 正确 |
| `/api/government/farmers` | `https://ad.ningmuyun.com/api/government/farmers` | `^~ /api/government/` | `/api/government/farmers` | ✅ 正确 |
## 验证步骤
1. **重新构建前端项目**:
```bash
cd government-admin
npm run build
```
2. **部署到生产环境**:
- 将构建后的文件部署到服务器
- 确保nginx配置正确
3. **测试API接口**:
```bash
# 测试岗位接口
curl https://ad.ningmuyun.com/api/government/positions
# 测试部门接口
curl https://ad.ningmuyun.com/api/government/departments
```
## 相关文件
- `government-admin/src/utils/api.js` - 前端API配置文件
- `government-backend/_etc_nginx_conf.d_ningmuyun_one.conf` - nginx配置文件
## 修复时间
2024年12月19日
## 修复状态
✅ 已修复 - 前端API配置已更新添加了正确的 `/api` 前缀

View File

@@ -0,0 +1,149 @@
# 检查 Nginx 配置的关键步骤
## 🔍 问题分析
根据您的反馈:
- 修改 nginx 配置后,所有接口都返回 404
- 只有登录接口正常(`/api/government/auth/login`
- 重复路径可以正常工作(`/api/government/government/departments`
这说明:
1. Nginx 已经重启并读取了新配置
2. `/api/government/auth/` 规则工作正常
3. `/api/government/` 规则可能有问题
## 🎯 关键问题
**重复路径能工作说明了什么?**
如果 `/api/government/government/departments` 能返回 200说明
- 请求到达了 nginx
- Nginx 将请求代理到了后端
- 后端处理了 `/api/government/departments` 路径(去掉了一个 government
这意味着当前的 proxy_pass 配置可能是:
```nginx
proxy_pass http://localhost:5352/api/government/;
```
这会导致:
- 请求:`/api/government/government/departments`
- Nginx 匹配:`location ^~ /api/government/`
- 代理到:`http://localhost:5352/api/government/ + government/departments`
- 实际请求:`http://localhost:5352/api/government/government/departments`
但是后端路由是 `/api/government/departments`,所以单个 government 的路径会 404。
## 🔧 正确的解决方案
需要修改 `proxy_pass` 配置,去掉路径重写:
```nginx
# 错误的配置(当前)
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/;
# 这会导致路径重复:/api/government/departments → http://localhost:5352/api/government/departments
}
# 正确的配置
location ^~ /api/government/ {
proxy_pass http://localhost:5352;
# 这会保持原始路径:/api/government/departments → http://localhost:5352/api/government/departments
}
```
## 📝 修改步骤
### 1. 修改 nginx 配置文件
找到 `_etc_nginx_conf.d_ningmuyun_one.conf` 文件中的这一段:
```nginx
# 政府API代理 - 处理其他政府相关接口
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/; # ❌ 错误
# ... 其他配置
}
```
修改为:
```nginx
# 政府API代理 - 处理其他政府相关接口
location ^~ /api/government/ {
proxy_pass http://localhost:5352; # ✅ 正确
# ... 其他配置
}
```
### 2. 重启 nginx
```bash
sudo nginx -t
sudo systemctl reload nginx
```
### 3. 验证修复
```bash
# 应该返回 200
curl -X GET https://ad.ningmuyun.com/api/government/departments
# 应该返回 404因为路径不再重复
curl -X GET https://ad.ningmuyun.com/api/government/government/departments
```
## 🎯 proxy_pass 尾部斜杠的区别
这是一个非常重要的 nginx 配置细节:
### 有尾部斜杠
```nginx
location ^~ /api/government/ {
proxy_pass http://localhost:5352/api/government/;
}
```
- 请求:`/api/government/departments`
- 匹配部分:`/api/government/`
- 剩余部分:`departments`
- 代理到:`http://localhost:5352/api/government/departments`
### 无尾部斜杠
```nginx
location ^~ /api/government/ {
proxy_pass http://localhost:5352;
}
```
- 请求:`/api/government/departments`
- 代理到:`http://localhost:5352/api/government/departments`(保持完整路径)
## 📊 当前配置应该是
```nginx
# 政府认证API代理
location ^~ /api/government/auth/ {
proxy_pass http://localhost:5352/api/auth/; # ✅ 正确(需要去掉 government
# ... 其他配置
}
# 政府API代理
location ^~ /api/government/ {
proxy_pass http://localhost:5352; # ✅ 正确(保持完整路径)
# ... 其他配置
}
```
## 🚨 总结
修改配置文件,将:
```nginx
proxy_pass http://localhost:5352/api/government/;
```
改为:
```nginx
proxy_pass http://localhost:5352;
```
然后重启 nginx问题应该就能解决了。

View File

@@ -0,0 +1,126 @@
# 政府端登录接口404错误修复说明
## 问题描述
- **错误URL**: `https://ad.ningmuyun.com/api/government/auth/login`
- **错误状态**: 404 Not Found
- **影响范围**: 政府端管理系统登录功能
## 问题根因分析
### 1. 前端API调用路径
- **前端调用**: `https://ad.ningmuyun.com/api/government/auth/login`
- **API定义**: `government-admin/src/utils/api.js` 第74行
```javascript
login: (data) => instance.post('/auth/login', data)
```
- **baseURL**: `http://localhost:5352/api` (开发环境)
- **实际请求**: `http://localhost:5352/api/auth/login`
### 2. 后端路由配置 ✅
- **认证路由**: `government-backend/routes/auth.js` 第6行
```javascript
router.post('/login', login)
```
- **应用路由注册**: `government-backend/app.js` 第39行
```javascript
app.use('/api/auth', require('./routes/auth'));
```
- **完整路径**: `/api/auth/login`
### 3. Nginx配置问题 ❌
**问题所在**: nginx配置中缺少政府认证API的路径匹配
**原始配置问题**:
- 只有 `/api/government/` 的代理配置
- 缺少 `/api/government/auth/` 的专门代理配置
- 导致 `/api/government/auth/login` 请求无法正确路由到后端的 `/api/auth/login`
## 解决方案
### 修复nginx配置
在 `government-backend/_etc_nginx_conf.d_ningmuyun_one.conf` 中添加政府认证API代理配置:
```nginx
# 政府认证API代理 - 处理登录等认证接口
location ^~ /api/government/auth/ {
proxy_pass http://localhost:5352/api/auth/; # 政府后端认证服务端口
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_set_header X-Forwarded-Proto $scheme;
# CORS配置
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://ad.ningmuyun.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
```
### 路径映射说明
- **前端请求**: `/api/government/auth/login`
- **nginx匹配**: `location ^~ /api/government/auth/`
- **代理转发**: `http://localhost:5352/api/auth/login`
- **后端处理**: `/api/auth/login` (authController.login)
## 验证步骤
1. **重启nginx服务**:
```bash
sudo nginx -t # 检查配置语法
sudo systemctl reload nginx # 重新加载配置
```
2. **测试登录接口**:
```bash
curl -X POST https://ad.ningmuyun.com/api/government/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test"}'
```
3. **检查前端登录功能**:
- 访问政府端管理系统登录页面
- 输入正确的用户名和密码
- 确认登录成功
## 相关文件
- `government-backend/_etc_nginx_conf.d_ningmuyun_one.conf` - nginx配置文件
- `government-backend/routes/auth.js` - 认证路由
- `government-backend/controllers/authController.js` - 认证控制器
- `government-admin/src/utils/api.js` - 前端API配置
- `government-admin/src/stores/auth.js` - 前端认证状态管理
## 修复时间
2024年12月19日
## 修复状态
✅ 已修复 - nginx配置已更新添加了政府认证API代理配置
## 重要说明
**配置优先级**: 在nginx中更具体的location规则会优先匹配。因此
- `/api/government/auth/` 配置必须在 `/api/government/` 配置之前
- 这样 `/api/government/auth/login` 会匹配到第一个规则,正确代理到 `/api/auth/login`
- 其他 `/api/government/` 开头的请求会匹配到第二个规则
## 测试方法
运行测试脚本验证修复效果:
```bash
cd government-backend
node test-login-api.js
```
## 重启nginx命令
```bash
sudo nginx -t # 检查配置语法
sudo systemctl reload nginx # 重新加载配置
```