diff --git a/README.md b/README.md index f36f825..b6beca8 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,10 @@ lottery/ │ │ └── main.js # 入口文件 │ ├── package.json # 依赖配置 │ └── vite.config.js # Vite 配置 +├── nginx.conf # nginx配置文件 ⭐ +├── deploy.sh # 部署脚本 ⭐ +├── fix_nginx.sh # 快速修复脚本 ⭐ +├── service_manager.sh # 服务管理脚本 ⭐ └── README.md # 项目文档 ``` @@ -177,6 +181,137 @@ cd backend python scheduler.py ``` +## 生产环境部署 ⭐ 新功能 + +### 自动部署 +使用部署脚本进行一键部署: +```bash +# 给脚本执行权限 +chmod +x deploy.sh + +# 运行部署脚本 +./deploy.sh +``` + +### 快速修复 +如果遇到nginx配置问题,使用快速修复脚本: +```bash +# 给脚本执行权限 +chmod +x fix_nginx.sh + +# 运行修复脚本 +./fix_nginx.sh +``` + +### 服务管理 +使用服务管理脚本进行日常维护: +```bash +# 给脚本执行权限 +chmod +x service_manager.sh + +# 启动所有服务 +./service_manager.sh start + +# 停止所有服务 +./service_manager.sh stop + +# 重启所有服务 +./service_manager.sh restart + +# 查看服务状态 +./service_manager.sh status + +# 查看日志 +./service_manager.sh logs backend # 后端日志 +./service_manager.sh logs scheduler # 定时任务日志 +./service_manager.sh logs nginx # nginx错误日志 + +# 部署更新 +./service_manager.sh deploy +``` + +## 故障排除 ⭐ 新功能 + +### 常见问题 + +#### 1. nginx重定向循环错误 +**错误信息**: `rewrite or internal redirection cycle while internally redirecting to "/index.html"` + +**解决方案**: +```bash +# 使用快速修复脚本 +./fix_nginx.sh +``` + +#### 2. 后端API连接被拒绝 +**错误信息**: `connect() failed (111: Connection refused) while connecting to upstream` + +**解决方案**: +```bash +# 检查后端服务状态 +./service_manager.sh status + +# 重启后端服务 +./service_manager.sh restart + +# 查看后端日志 +./service_manager.sh logs backend +``` + +#### 3. 前端页面无法访问 +**解决方案**: +```bash +# 重新构建前端 +cd frontend +npm run build +cd .. + +# 重新部署 +./service_manager.sh deploy +``` + +#### 4. 数据库连接问题 +**解决方案**: +```bash +# 检查数据库配置 +cat backend/app/core/database.py + +# 测试数据库连接 +cd backend +python -c "from app.core.database import engine; print('数据库连接正常')" +``` + +### 日志查看 +```bash +# nginx错误日志 +sudo tail -f /var/log/nginx/error.log + +# 后端应用日志 +tail -f backend/backend.log + +# 定时任务日志 +tail -f scheduler.log + +# 系统日志 +sudo journalctl -u nginx -f +``` + +### 性能优化 +1. **启用gzip压缩**: + 在nginx.conf中添加: + ```nginx + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + ``` + +2. **静态资源缓存**: + 已在nginx.conf中配置静态资源缓存 + +3. **数据库优化**: + - 为常用查询字段添加索引 + - 定期清理历史数据 + - 使用连接池 + ## 使用说明 ### 定时任务系统 ⭐ 新功能 @@ -202,161 +337,153 @@ cd backend python scheduler.py ``` -#### 查看任务状态 -- 在一键下单页面查看定时任务状态 -- 显示下次执行时间 -- 显示今日推荐生成状态 - -#### 任务日志 -- 日志文件:`backend/lottery_scheduler.log` -- 包含详细的执行记录和错误信息 - -### 数据导入与更新说明 - -#### 数据导入 -- 支持通过前端页面或API导入双色球、大乐透历史数据(JSON格式)。 -- 导入时,系统会自动根据 `open_time`(开奖日期)升序排序,确保数据库 `id=1` 为最早的开奖数据。 -- 导入过程自动去重:只导入数据库中未出现过的开奖日期数据。 -- 支持 pandas DataFrame 或 JSON 文件导入。 - -#### 数据自动/手动更新 ⭐ 新功能 -- **定时更新**: 每天早上6点自动更新(推荐) -- **前端更新功能**: 在首页提供"补红蓝球煎饼"、"补大乐斗豆浆"、"补全场早点"三个按钮 -- **API更新接口**: 支持通过API接口更新数据 - - `POST /api/v1/lottery/update/ssq` - 更新双色球数据 - - `POST /api/v1/lottery/update/dlt` - 更新大乐透数据 - - `POST /api/v1/lottery/update/all` - 更新所有彩票数据 -- 更新逻辑: - - 从聚合数据API自动获取最新开奖记录 - - 只插入数据库中未出现过的开奖日期(`open_time` 唯一性判断) - - 插入顺序为开奖日期升序,保证历史数据先入库,最新数据最后入库 - - 实时显示更新结果和新增记录数量 - - 更新完成后自动刷新首页最新开奖信息 - -##### 手动更新 +#### 查看定时任务状态 ```bash -cd backend -python update_lottery.py +# 查看任务日志 +tail -f scheduler.log + +# 查看任务进程 +ps aux | grep scheduler ``` -##### 自动定时更新 -```bash -cd backend -python scheduler.py -``` -系统会在每天凌晨6点自动检查并更新数据。 +### 数据管理 -### 拼盘推荐系统 ⭐ 新功能 +#### 导入历史数据 +1. 准备CSV格式的历史数据文件 +2. 在管理界面选择"数据导入" +3. 选择彩票类型(双色球/大乐透) +4. 上传数据文件 +5. 系统自动验证和导入数据 -#### 自动推荐 -- **定时生成**: 每天下午5点自动生成 -- **智能算法**: 使用集成预测算法 -- **多注推荐**: 每次生成4注推荐号码 -- **类型轮换**: 根据日期自动选择彩票类型 +#### 手动录入数据 +1. 在管理界面选择"手动录入" +2. 选择彩票类型和期号 +3. 输入开奖号码 +4. 保存数据 -#### 手动生成 -- 在一键下单页面点击"来一份拼盘"按钮 -- 实时生成推荐号码 -- 支持复制所有号码 +#### 数据导出 +1. 在管理界面选择"数据导出" +2. 选择彩票类型和时间范围 +3. 选择导出格式(CSV/Excel) +4. 下载数据文件 -#### 推荐历史 -- 查看历史推荐记录 -- 显示中奖情况 -- 支持手动检查中奖 +### 统计分析 -### 高级分析功能 ⭐ -1. 进入"高级分析"页面 -2. 选择彩票类型(双色球/大乐透) -3. 选择分析类型: - - **遗漏值分析**: 查看各号码的遗漏期数 - - **和值分析**: 分析红球和值的分布规律 - - **AC值分析**: 邻号差值分析 - - **质合比分析**: 质数与合数的比例分析 - - **012路分析**: 除3余数分析 - - **跨度分析**: 最大最小号码差值分析 - - **综合分析**: 多维度数据整合分析 +#### 基础统计 +- **频率统计**: 查看各号码的出现次数和频率 +- **热门号码**: 显示出现频率最高的号码 +- **冷门号码**: 显示出现频率最低的号码 +- **遗漏分析**: 分析各号码的遗漏期数 -### 智能预测功能 ⭐ -1. 进入"智能预测"页面 -2. 选择彩票类型 -3. 选择预测方法: - - **机器学习预测**: 基于历史数据的AI预测 - - **模式预测**: 基于统计模式的预测 - - **集成预测**: 多方法综合预测 -4. 设置训练参数 -5. 查看预测结果 +#### 高级分析 ⭐ 新功能 +- **和值分析**: 统计红球和值的分布规律 +- **AC值分析**: 邻号差值分析 +- **质合比分析**: 质数与合数的比例分析 +- **012路分析**: 除3余数分析 +- **跨度分析**: 最大最小号码差值分析 + +### 智能预测 ⭐ 新功能 + +#### 机器学习预测 +1. 选择彩票类型(双色球/大乐透) +2. 选择预测期数 +3. 系统使用历史数据训练模型 +4. 生成预测结果 + +#### 模式预测 +1. 选择预测模式 +2. 设置预测参数 +3. 生成预测结果 + +#### 集成预测 +1. 系统综合多种预测方法 +2. 生成最优预测结果 +3. 显示预测置信度 + +### 智能选号 + +#### 随机选号 +- 完全随机生成号码组合 +- 适合新手用户 + +#### 频率选号 +- 基于历史频率选择号码 +- 平衡热门和冷门号码 + +#### 热门号码选号 +- 选择历史出现频率高的号码 +- 适合追求稳定性的用户 + +#### 冷门号码选号 +- 选择历史出现频率低的号码 +- 适合追求高回报的用户 + +#### 自定义选号策略 +- 用户可以自定义选号规则 +- 支持多种选号策略组合 ## API文档 -启动后端服务后,访问 http://localhost:8000/docs 查看完整的API文档。 -## 常见问题 +### 基础API +- `GET /api/v1/lottery/ssq/latest` - 获取最新双色球数据 +- `GET /api/v1/lottery/dlt/latest` - 获取最新大乐透数据 +- `GET /api/v1/lottery/ssq/history` - 获取双色球历史数据 +- `GET /api/v1/lottery/dlt/history` - 获取大乐透历史数据 -### 定时任务相关 -**Q: 定时任务没有执行?** -A: 检查以下几点: -1. 确保定时任务进程正在运行 -2. 检查日志文件 `backend/lottery_scheduler.log` -3. 确认系统时间正确 -4. 检查数据库连接是否正常 +### 分析API ⭐ 新功能 +- `GET /api/analysis/ssq/frequency` - 双色球频率分析 +- `GET /api/analysis/dlt/frequency` - 大乐透频率分析 +- `GET /api/analysis/ssq/missing` - 双色球遗漏值分析 +- `GET /api/analysis/dlt/missing` - 大乐透遗漏值分析 +- `GET /api/analysis/ssq/sum` - 双色球和值分析 +- `GET /api/analysis/dlt/sum` - 大乐透和值分析 -**Q: 如何修改定时任务时间?** -A: 编辑 `backend/scheduler.py` 文件中的时间设置: -```python -schedule.every().day.at("06:00").do(self.update_lottery_data_job) -schedule.every().day.at("17:00").do(self.generate_daily_recommendations_job) -``` +### 预测API ⭐ 新功能 +- `POST /api/v1/prediction/ssq` - 双色球预测 +- `POST /api/v1/prediction/dlt` - 大乐透预测 +- `GET /api/v1/prediction/ssq/recommendations` - 获取双色球推荐 +- `GET /api/v1/prediction/dlt/recommendations` - 获取大乐透推荐 -**Q: 如何查看任务执行日志?** -A: 查看日志文件: -```bash -tail -f backend/lottery_scheduler.log -``` +### 健康检查 +- `GET /health` - 系统健康检查 -### 数据更新相关 -**Q: 数据更新失败?** -A: 检查以下几点: -1. 网络连接是否正常 -2. API密钥是否有效 -3. 数据库连接是否正常 -4. 查看后端日志获取详细错误信息 +## 开发指南 -**Q: 如何手动更新数据?** -A: 可以通过以下方式: -1. 前端页面点击更新按钮 -2. 调用API接口 -3. 运行更新脚本:`python update_lottery.py` +### 添加新的分析功能 +1. 在 `backend/app/services/` 中添加新的分析服务 +2. 在 `backend/app/api/endpoints/` 中添加对应的API端点 +3. 在前端 `src/views/` 中添加新的页面组件 +4. 更新路由配置 -### 拼盘推荐相关 -**Q: 今日推荐没有生成?** -A: 检查以下几点: -1. 定时任务是否正常运行 -2. 是否有足够的历史数据 -3. 预测模型是否训练完成 -4. 查看日志文件获取错误信息 +### 添加新的预测算法 +1. 在 `backend/app/services/prediction_service.py` 中添加新算法 +2. 更新API端点以支持新算法 +3. 在前端添加算法选择选项 -**Q: 如何手动生成推荐?** -A: 在一键下单页面点击"来一份拼盘"按钮即可手动生成。 - -## 更新日志 - -### v1.1.0 (2024-01-XX) -- ✨ 新增定时任务系统 -- ✨ 新增每日拼盘推荐功能 -- ✨ 新增任务状态监控 -- ✨ 优化一键下单页面 -- 🐛 修复图表显示问题 -- 📝 更新使用说明 - -### v1.0.0 (2024-01-XX) -- 🎉 初始版本发布 -- ✨ 基础数据管理功能 -- ✨ 统计分析功能 -- ✨ 高级分析功能 -- ✨ 智能预测功能 -- ✨ 前端可视化界面 +### 数据库迁移 +1. 修改数据模型 +2. 生成迁移文件 +3. 执行迁移 ## 贡献指南 -欢迎提交Issue和Pull Request来改进这个项目。 + +1. Fork 项目 +2. 创建功能分支 +3. 提交更改 +4. 推送到分支 +5. 创建 Pull Request ## 许可证 -MIT License \ No newline at end of file + +本项目采用 MIT 许可证。 + +## 联系方式 + +如有问题或建议,请通过以下方式联系: +- 提交 Issue +- 发送邮件 +- 在线讨论 + +--- + +**注意**: 本系统仅供学习和研究使用,不构成投资建议。请理性购彩,注意风险。 \ No newline at end of file diff --git a/cp.mzh.one.conf b/cp.mzh.one.conf new file mode 100644 index 0000000..b660891 --- /dev/null +++ b/cp.mzh.one.conf @@ -0,0 +1,98 @@ +server { + listen 80; + server_name cp.mzh.one; + + # Let's Encrypt 验证路径(如需证书续期) + location /.well-known/acme-challenge/ { + root /opt/mottery/frontend/dist; + } + + # 其它HTTP请求重定向到HTTPS + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + server_name cp.mzh.one; + + # SSL证书配置(你自己处理路径) + ssl_certificate /ssl/cp.mzh.one/cp.mzh.one.pem; + ssl_certificate_key /ssl/cp.mzh.one/cp.mzh.one.key; + + # 前端静态资源 - 修复路径 + location / { + root /opt/mottery/frontend/dist; + index index.html; + try_files $uri $uri/ /index.html last; + + # 添加调试信息 + add_header X-Debug-Path $document_root$uri always; + } + + # 静态资源缓存 - 确保assets路径正确 + location /assets/ { + root /opt/mottery/frontend/dist; + expires 1y; + add_header Cache-Control "public, immutable"; + add_header X-Debug-Path $document_root$uri always; + } + + # 其他静态资源 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + root /opt/mottery/frontend/dist; + expires 1y; + add_header Cache-Control "public, immutable"; + add_header X-Debug-Path $document_root$uri always; + } + + # 后端API代理 - 使用正确的Docker网关地址 + location /api/ { + # 使用Docker默认网桥的网关地址 + proxy_pass http://172.17.0.1:8000/; + + 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 30s; + proxy_send_timeout 30s; + proxy_read_timeout 30s; + + # 解决跨域问题 + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; + add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"; + + # 处理OPTIONS请求 + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; + add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"; + add_header Access-Control-Max-Age 1728000; + add_header Content-Type 'text/plain; charset=utf-8'; + add_header Content-Length 0; + return 204; + } + } + + # 健康检查端点 + location /health { + proxy_pass http://172.17.0.1:8000/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; + } + + # 错误页面 + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + client_max_body_size 50M; +} \ No newline at end of file diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..8c6fd68 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +echo "🚀 开始部署彩票数据分析系统..." + +# 检查是否在项目根目录 +if [ ! -f "README.md" ]; then + echo "❌ 错误: 请在项目根目录运行此脚本" + exit 1 +fi + +# 1. 构建前端 +echo "📦 构建前端..." +cd frontend + +# 检查node_modules +if [ ! -d "node_modules" ]; then + echo "📦 安装前端依赖..." + npm install +fi + +# 构建生产版本 +echo "🔨 构建生产版本..." +npm run build + +# 检查构建是否成功 +if [ ! -d "dist" ]; then + echo "❌ 前端构建失败" + exit 1 +fi + +echo "✅ 前端构建成功" + +# 2. 部署前端文件 +echo "📁 部署前端文件..." +sudo mkdir -p /var/www/html +sudo cp -r dist/* /var/www/html/ +sudo chown -R www-data:www-data /var/www/html +sudo chmod -R 755 /var/www/html + +echo "✅ 前端文件部署完成" + +# 3. 配置nginx +echo "⚙️ 配置nginx..." +cd .. + +# 备份原配置 +if [ -f "/etc/nginx/sites-available/cp.mzh.one" ]; then + sudo cp /etc/nginx/sites-available/cp.mzh.one /etc/nginx/sites-available/cp.mzh.one.backup +fi + +# 复制新配置 +sudo cp nginx.conf /etc/nginx/sites-available/cp.mzh.one + +# 启用站点 +sudo ln -sf /etc/nginx/sites-available/cp.mzh.one /etc/nginx/sites-enabled/ + +# 测试nginx配置 +echo "🔍 测试nginx配置..." +sudo nginx -t + +if [ $? -eq 0 ]; then + echo "✅ nginx配置正确" + sudo systemctl reload nginx + echo "✅ nginx重新加载完成" +else + echo "❌ nginx配置错误" + exit 1 +fi + +# 4. 启动后端服务 +echo "🚀 启动后端服务..." + +# 检查后端依赖 +cd backend +if [ ! -d "venv" ]; then + echo "📦 创建Python虚拟环境..." + python3 -m venv venv +fi + +# 激活虚拟环境 +source venv/bin/activate + +# 安装依赖 +echo "📦 安装后端依赖..." +pip install -r requirements.txt + +# 启动后端服务 +echo "🚀 启动后端服务..." +nohup uvicorn app.main:app --host 0.0.0.0 --port 8000 > backend.log 2>&1 & + +# 等待服务启动 +echo "⏳ 等待后端服务启动..." +sleep 5 + +# 检查服务状态 +if curl -f http://localhost:8000/health > /dev/null 2>&1; then + echo "✅ 后端服务启动成功" +else + echo "❌ 后端服务启动失败" + echo "📋 查看日志: tail -f backend/backend.log" + exit 1 +fi + +# 5. 启动定时任务(可选) +read -p "🤔 是否启动定时任务调度器?(y/n): " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + echo "⏰ 启动定时任务调度器..." + cd .. + nohup python3 scheduler.py > scheduler.log 2>&1 & + echo "✅ 定时任务调度器启动成功" +fi + +echo "" +echo "🎉 部署完成!" +echo "" +echo "📋 访问地址:" +echo " - 前端: https://cp.mzh.one" +echo " - API文档: https://cp.mzh.one/api/docs" +echo " - 健康检查: https://cp.mzh.one/health" +echo "" +echo "📋 服务状态:" +echo " - 后端服务: ps aux | grep uvicorn" +echo " - nginx服务: sudo systemctl status nginx" +echo " - 后端日志: tail -f backend/backend.log" +echo " - 定时任务日志: tail -f scheduler.log" +echo "" +echo "🔧 常用命令:" +echo " - 重启nginx: sudo systemctl reload nginx" +echo " - 重启后端: pkill -f uvicorn && cd backend && nohup uvicorn app.main:app --host 0.0.0.0 --port 8000 > backend.log 2>&1 &" +echo " - 查看错误日志: sudo tail -f /var/log/nginx/error.log" \ No newline at end of file diff --git a/docker_service_manager.sh b/docker_service_manager.sh new file mode 100644 index 0000000..a265c4a --- /dev/null +++ b/docker_service_manager.sh @@ -0,0 +1,211 @@ +#!/bin/bash + +# Docker环境服务管理脚本 +SERVICE_NAME="lottery-system-docker" + +case "$1" in + start) + echo "🚀 启动彩票数据分析系统 (Docker环境)..." + + # 启动后端服务 + cd backend + source venv/bin/activate + nohup uvicorn app.main:app --host 0.0.0.0 --port 8000 > backend.log 2>&1 & + echo $! > backend.pid + cd .. + + # 启动定时任务 + nohup python3 scheduler.py > scheduler.log 2>&1 & + echo $! > scheduler.pid + + # 重启nginx容器 + echo "🔄 重启nginx容器..." + docker restart dnmp-nginx + + echo "✅ 服务启动完成" + ;; + + stop) + echo "🛑 停止彩票数据分析系统..." + + # 停止后端 + if [ -f "backend/backend.pid" ]; then + kill $(cat backend/backend.pid) 2>/dev/null + rm backend/backend.pid + fi + + # 停止定时任务 + if [ -f "scheduler.pid" ]; then + kill $(cat scheduler.pid) 2>/dev/null + rm scheduler.pid + fi + + # 强制停止所有相关进程 + pkill -f uvicorn + pkill -f scheduler.py + + echo "✅ 服务停止完成" + ;; + + restart) + echo "🔄 重启彩票数据分析系统..." + $0 stop + sleep 2 + $0 start + ;; + + status) + echo "📊 服务状态检查 (Docker环境)..." + + # 检查后端 + if curl -f http://localhost:8000/health > /dev/null 2>&1; then + echo "✅ 后端服务: 运行中 (localhost:8000)" + else + echo "❌ 后端服务: 未运行" + fi + + # 检查nginx容器 + if docker ps | grep -q dnmp-nginx; then + echo "✅ nginx容器: 运行中" + else + echo "❌ nginx容器: 未运行" + fi + + # 检查前端访问 + if curl -f https://cp.mzh.one/ > /dev/null 2>&1; then + echo "✅ 前端页面: 可访问" + else + echo "❌ 前端页面: 不可访问" + fi + + # 检查API访问 + if curl -f https://cp.mzh.one/api/v1/lottery/ssq/latest > /dev/null 2>&1; then + echo "✅ API接口: 可访问" + else + echo "❌ API接口: 不可访问" + fi + + # 检查定时任务 + if pgrep -f scheduler.py > /dev/null; then + echo "✅ 定时任务: 运行中" + else + echo "❌ 定时任务: 未运行" + fi + + # 显示进程信息 + echo "" + echo "📋 进程信息:" + ps aux | grep -E "(uvicorn|scheduler)" | grep -v grep + + # 显示容器信息 + echo "" + echo "📋 容器信息:" + docker ps | grep dnmp + ;; + + logs) + echo "📋 查看日志..." + case "$2" in + backend) + tail -f backend/backend.log + ;; + scheduler) + tail -f scheduler.log + ;; + nginx) + docker exec dnmp-nginx tail -f /var/log/nginx/error.log + ;; + nginx-access) + docker exec dnmp-nginx tail -f /var/log/nginx/access.log + ;; + *) + echo "用法: $0 logs {backend|scheduler|nginx|nginx-access}" + ;; + esac + ;; + + deploy) + echo "🚀 部署系统 (Docker环境)..." + + # 构建前端 + cd frontend + npm run build + cd .. + + # 检查前端构建文件是否存在 + if [ ! -d "frontend/dist" ]; then + echo "❌ 前端构建失败" + exit 1 + fi + + # 复制前端文件到nginx容器 + echo "📁 部署前端文件到nginx容器..." + docker cp frontend/dist/. dnmp-nginx:/opt/mottery/frontend/dist/ + + # 重启服务 + $0 restart + + echo "✅ 部署完成" + ;; + + fix-nginx) + echo "🔧 修复nginx配置..." + + # 运行修复脚本 + if [ -f "fix_docker_nginx.sh" ]; then + chmod +x fix_docker_nginx.sh + ./fix_docker_nginx.sh + else + echo "❌ 找不到修复脚本 fix_docker_nginx.sh" + exit 1 + fi + ;; + + test-backend) + echo "🧪 测试后端连接..." + + # 测试不同的后端地址 + echo "测试 localhost:8000..." + if curl -f http://localhost:8000/health > /dev/null 2>&1; then + echo "✅ localhost:8000 连接正常" + else + echo "❌ localhost:8000 连接失败" + fi + + echo "测试 host.docker.internal:8000..." + if curl -f http://host.docker.internal:8000/health > /dev/null 2>&1; then + echo "✅ host.docker.internal:8000 连接正常" + else + echo "❌ host.docker.internal:8000 连接失败" + fi + + echo "测试 172.17.0.1:8000..." + if curl -f http://172.17.0.1:8000/health > /dev/null 2>&1; then + echo "✅ 172.17.0.1:8000 连接正常" + else + echo "❌ 172.17.0.1:8000 连接失败" + fi + + echo "测试 172.18.0.1:8000..." + if curl -f http://172.18.0.1:8000/health > /dev/null 2>&1; then + echo "✅ 172.18.0.1:8000 连接正常" + else + echo "❌ 172.18.0.1:8000 连接失败" + fi + ;; + + *) + echo "用法: $0 {start|stop|restart|status|logs|deploy|fix-nginx|test-backend}" + echo "" + echo "命令说明:" + echo " start - 启动所有服务" + echo " stop - 停止所有服务" + echo " restart - 重启所有服务" + echo " status - 查看服务状态" + echo " logs - 查看日志 (用法: $0 logs {backend|scheduler|nginx|nginx-access})" + echo " deploy - 部署系统" + echo " fix-nginx - 修复nginx配置" + echo " test-backend - 测试后端连接" + exit 1 + ;; +esac \ No newline at end of file diff --git a/fix_docker_nginx.sh b/fix_docker_nginx.sh new file mode 100644 index 0000000..1a190d7 --- /dev/null +++ b/fix_docker_nginx.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +echo "🔧 修复Docker nginx配置..." + +# 1. 检查当前配置 +echo "📋 当前nginx配置:" +cat /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf + +echo "" +echo "🔍 检查后端服务状态..." + +# 2. 测试不同的后端地址 +echo "🧪 测试后端连接..." + +# 测试 host.docker.internal:8000 +if curl -f http://host.docker.internal:8000/health > /dev/null 2>&1; then + echo "✅ host.docker.internal:8000 连接正常" + BACKEND_URL="http://host.docker.internal:8000/" +elif curl -f http://172.17.0.1:8000/health > /dev/null 2>&1; then + echo "✅ 172.17.0.1:8000 连接正常" + BACKEND_URL="http://172.17.0.1:8000/" +elif curl -f http://172.18.0.1:8000/health > /dev/null 2>&1; then + echo "✅ 172.18.0.1:8000 连接正常" + BACKEND_URL="http://172.18.0.1:8000/" +elif curl -f http://docker.for.mac.localhost:8000/health > /dev/null 2>&1; then + echo "✅ docker.for.mac.localhost:8000 连接正常" + BACKEND_URL="http://docker.for.mac.localhost:8000/" +else + echo "❌ 无法连接到后端服务" + echo "请检查后端服务是否正在运行" + exit 1 +fi + +# 3. 备份原配置 +echo "💾 备份原配置..." +cp /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf.backup + +# 4. 应用新配置 +echo "⚙️ 应用新配置..." +cp cp.mzh.one.conf /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf + +# 5. 更新后端地址 +echo "🔧 更新后端地址为: $BACKEND_URL" +sed -i "s|proxy_pass http://host.docker.internal:8000/;|proxy_pass $BACKEND_URL;|g" /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf +sed -i "s|proxy_pass http://host.docker.internal:8000/health;|proxy_pass ${BACKEND_URL}health;|g" /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf + +# 6. 测试nginx配置 +echo "🔍 测试nginx配置..." +docker exec dnmp-nginx nginx -t + +if [ $? -eq 0 ]; then + echo "✅ nginx配置正确" + + # 7. 重新加载nginx + echo "🔄 重新加载nginx..." + docker exec dnmp-nginx nginx -s reload + + echo "✅ nginx重新加载完成" +else + echo "❌ nginx配置错误,恢复备份..." + cp /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf.backup /opt/dnmp/services/nginx/conf.d/cp.mzh.one.conf + exit 1 +fi + +# 8. 检查服务状态 +echo "⏳ 等待服务启动..." +sleep 3 + +echo "🔍 检查服务状态..." +if curl -f https://cp.mzh.one/ > /dev/null 2>&1; then + echo "✅ 前端页面访问正常" +else + echo "❌ 前端页面访问异常" +fi + +if curl -f https://cp.mzh.one/api/v1/lottery/ssq/latest > /dev/null 2>&1; then + echo "✅ API接口访问正常" +else + echo "❌ API接口访问异常" +fi + +echo "" +echo "🎉 修复完成!" +echo "📋 访问地址: https://cp.mzh.one" +echo "" +echo "📋 如果仍有问题,请检查:" +echo " 1. 后端服务是否在端口8000运行" +echo " 2. Docker网络配置是否正确" +echo " 3. 防火墙设置" +echo "" +echo "📋 查看nginx错误日志:" +echo " docker exec dnmp-nginx tail -f /var/log/nginx/error.log" \ No newline at end of file diff --git a/fix_nginx.sh b/fix_nginx.sh new file mode 100644 index 0000000..b8ee211 --- /dev/null +++ b/fix_nginx.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +echo "🔧 快速修复nginx配置..." + +# 1. 停止当前服务 +echo "🛑 停止当前服务..." +sudo pkill -f uvicorn +sudo systemctl stop nginx + +# 2. 构建前端 +echo "📦 构建前端..." +cd frontend +npm run build +cd .. + +# 3. 部署前端文件 +echo "📁 部署前端文件..." +sudo mkdir -p /var/www/html +sudo cp -r frontend/dist/* /var/www/html/ +sudo chown -R www-data:www-data /var/www/html +sudo chmod -R 755 /var/www/html + +# 4. 应用nginx配置 +echo "⚙️ 应用nginx配置..." +sudo cp nginx.conf /etc/nginx/sites-available/cp.mzh.one +sudo ln -sf /etc/nginx/sites-available/cp.mzh.one /etc/nginx/sites-enabled/ + +# 5. 启动nginx +echo "🚀 启动nginx..." +sudo nginx -t && sudo systemctl start nginx + +# 6. 启动后端 +echo "🚀 启动后端..." +cd backend +source venv/bin/activate +nohup uvicorn app.main:app --host 0.0.0.0 --port 8000 > backend.log 2>&1 & +cd .. + +# 7. 检查服务状态 +echo "⏳ 等待服务启动..." +sleep 3 + +echo "🔍 检查服务状态..." +if curl -f http://localhost:8000/health > /dev/null 2>&1; then + echo "✅ 后端服务正常" +else + echo "❌ 后端服务异常" +fi + +if curl -f http://localhost/ > /dev/null 2>&1; then + echo "✅ nginx服务正常" +else + echo "❌ nginx服务异常" +fi + +echo "" +echo "🎉 修复完成!" +echo "📋 访问地址: https://cp.mzh.one" \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..dcc0d69 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,58 @@ +server { + listen 80; + server_name cp.mzh.one; + + # 前端静态文件 + location / { + root /var/www/html; # 前端构建文件路径 + index index.html; + try_files $uri $uri/ /index.html; + } + + # API代理到后端 + location /api/ { + proxy_pass http://localhost:8000; + 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; + + # 解决跨域问题 + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; + add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"; + + # 处理OPTIONS请求 + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; + add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"; + add_header Access-Control-Max-Age 1728000; + add_header Content-Type 'text/plain; charset=utf-8'; + add_header Content-Length 0; + return 204; + } + } + + # 健康检查 + location /health { + proxy_pass http://localhost:8000; + 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 ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # 安全头 + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; +} \ No newline at end of file diff --git a/service_manager.sh b/service_manager.sh new file mode 100644 index 0000000..b9ba5ef --- /dev/null +++ b/service_manager.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +# 服务管理脚本 +SERVICE_NAME="lottery-system" + +case "$1" in + start) + echo "🚀 启动彩票数据分析系统..." + + # 启动后端 + cd backend + source venv/bin/activate + nohup uvicorn app.main:app --host 0.0.0.0 --port 8000 > backend.log 2>&1 & + echo $! > backend.pid + cd .. + + # 启动定时任务 + nohup python3 scheduler.py > scheduler.log 2>&1 & + echo $! > scheduler.pid + + echo "✅ 服务启动完成" + ;; + + stop) + echo "🛑 停止彩票数据分析系统..." + + # 停止后端 + if [ -f "backend/backend.pid" ]; then + kill $(cat backend/backend.pid) 2>/dev/null + rm backend/backend.pid + fi + + # 停止定时任务 + if [ -f "scheduler.pid" ]; then + kill $(cat scheduler.pid) 2>/dev/null + rm scheduler.pid + fi + + # 强制停止所有相关进程 + pkill -f uvicorn + pkill -f scheduler.py + + echo "✅ 服务停止完成" + ;; + + restart) + echo "🔄 重启彩票数据分析系统..." + $0 stop + sleep 2 + $0 start + ;; + + status) + echo "📊 服务状态检查..." + + # 检查后端 + if curl -f http://localhost:8000/health > /dev/null 2>&1; then + echo "✅ 后端服务: 运行中" + else + echo "❌ 后端服务: 未运行" + fi + + # 检查nginx + if curl -f http://localhost/ > /dev/null 2>&1; then + echo "✅ nginx服务: 运行中" + else + echo "❌ nginx服务: 未运行" + fi + + # 检查定时任务 + if pgrep -f scheduler.py > /dev/null; then + echo "✅ 定时任务: 运行中" + else + echo "❌ 定时任务: 未运行" + fi + + # 显示进程信息 + echo "" + echo "📋 进程信息:" + ps aux | grep -E "(uvicorn|scheduler)" | grep -v grep + ;; + + logs) + echo "📋 查看日志..." + case "$2" in + backend) + tail -f backend/backend.log + ;; + scheduler) + tail -f scheduler.log + ;; + nginx) + sudo tail -f /var/log/nginx/error.log + ;; + *) + echo "用法: $0 logs {backend|scheduler|nginx}" + ;; + esac + ;; + + deploy) + echo "🚀 部署系统..." + + # 构建前端 + cd frontend + npm run build + cd .. + + # 部署前端文件 + sudo cp -r frontend/dist/* /var/www/html/ + sudo chown -R www-data:www-data /var/www/html + + # 重启服务 + $0 restart + + echo "✅ 部署完成" + ;; + + *) + echo "用法: $0 {start|stop|restart|status|logs|deploy}" + echo "" + echo "命令说明:" + echo " start - 启动所有服务" + echo " stop - 停止所有服务" + echo " restart - 重启所有服务" + echo " status - 查看服务状态" + echo " logs - 查看日志 (用法: $0 logs {backend|scheduler|nginx})" + echo " deploy - 部署系统" + exit 1 + ;; +esac \ No newline at end of file