diff --git a/README.md b/README.md
index 64293dc..a30647a 100644
--- a/README.md
+++ b/README.md
@@ -219,4 +219,62 @@ MIT License
- 系统会自动检查本地数据库中最新的开奖日期
- 只获取并更新比本地数据更新的开奖记录
- 更新过程会记录日志到 `lottery_update.log` 文件
-- 支持双色球和大乐透两种彩票的数据更新
\ No newline at end of file
+- 支持双色球和大乐透两种彩票的数据更新
+
+## 分析功能说明
+
+### 基础分析策略
+
+#### 1. 冷热号码分析
+- 热号:统计近50期出现频率最高的号码
+- 冷号:统计超过平均遗漏期数的号码
+- API: GET `/api/analysis/hot-cold/{lottery_type}?periods=50`
+
+#### 2. 号码分布分析
+- 分区统计:将号码划分为多个区间,分析各区出号比例
+- 奇偶比:分析奇偶数的分布规律
+- 大小比:统计大数和小数的分布规律
+- API: GET `/api/analysis/distribution/{lottery_type}?periods=100`
+
+#### 3. 连号与重复号分析
+- 连号追踪:统计连号出现的频率和位置
+- 重复号观察:分析相邻期号码重复情况
+- API: GET `/api/analysis/consecutive/{lottery_type}?periods=100`
+
+### 数学理论应用
+
+#### 1. 数学统计特征
+- 计算红球总和的历史平均值和标准差
+- 分析号码组合的数学特征
+- API: GET `/api/analysis/math-stats/{lottery_type}?periods=100`
+
+#### 2. 遗漏值分析
+- 计算每个号码的当前遗漏值
+- 分析历史最大遗漏
+- API: GET `/api/analysis/missing/{lottery_type}`
+
+### 智能选号策略
+
+系统提供多种智能选号策略:
+- 均衡策略:综合考虑号码分布特征
+- 热号策略:偏好选择近期高频号码
+- 冷号策略:偏好选择遗漏值较大的号码
+- 遗漏值策略:基于遗漏值分析选号
+- API: GET `/api/analysis/smart-numbers/{lottery_type}?strategy=balanced`
+
+### 使用示例
+
+1. 获取双色球热号冷号分析:
+```bash
+curl http://localhost:8000/api/analysis/hot-cold/ssq?periods=50
+```
+
+2. 获取大乐透号码分布分析:
+```bash
+curl http://localhost:8000/api/analysis/distribution/dlt?periods=100
+```
+
+3. 使用均衡策略生成双色球号码:
+```bash
+curl http://localhost:8000/api/analysis/smart-numbers/ssq?strategy=balanced
+```
\ No newline at end of file
diff --git a/backend/app/api/endpoints/analysis.py b/backend/app/api/endpoints/analysis.py
new file mode 100644
index 0000000..e2325d9
--- /dev/null
+++ b/backend/app/api/endpoints/analysis.py
@@ -0,0 +1,108 @@
+from fastapi import APIRouter, Depends, HTTPException
+from sqlalchemy.orm import Session
+from typing import Optional
+
+from ...core.database import get_db
+from ...services.analysis_service import LotteryAnalysisService
+
+router = APIRouter()
+
+
+@router.get("/hot-cold/{lottery_type}")
+def get_hot_cold_numbers(
+ lottery_type: str,
+ periods: Optional[int] = 50,
+ db: Session = Depends(get_db)
+):
+ """获取热号和冷号分析"""
+ if lottery_type not in ['ssq', 'dlt']:
+ raise HTTPException(status_code=400, detail="Invalid lottery type")
+
+ analysis_service = LotteryAnalysisService(db)
+ return analysis_service.get_hot_cold_numbers(lottery_type, periods)
+
+
+@router.get("/distribution/{lottery_type}")
+def get_number_distribution(
+ lottery_type: str,
+ periods: Optional[int] = 100,
+ db: Session = Depends(get_db)
+):
+ """获取号码分布分析"""
+ if lottery_type not in ['ssq', 'dlt']:
+ raise HTTPException(status_code=400, detail="Invalid lottery type")
+
+ analysis_service = LotteryAnalysisService(db)
+ return analysis_service.analyze_number_distribution(lottery_type, periods)
+
+
+@router.get("/consecutive/{lottery_type}")
+def get_consecutive_analysis(
+ lottery_type: str,
+ periods: Optional[int] = 100,
+ db: Session = Depends(get_db)
+):
+ """获取连号和重复号分析"""
+ if lottery_type not in ['ssq', 'dlt']:
+ raise HTTPException(status_code=400, detail="Invalid lottery type")
+
+ analysis_service = LotteryAnalysisService(db)
+ return analysis_service.analyze_consecutive_numbers(lottery_type, periods)
+
+
+@router.get("/math-stats/{lottery_type}")
+def get_mathematical_stats(
+ lottery_type: str,
+ periods: Optional[int] = 100,
+ db: Session = Depends(get_db)
+):
+ """获取数学统计特征"""
+ if lottery_type not in ['ssq', 'dlt']:
+ raise HTTPException(status_code=400, detail="Invalid lottery type")
+
+ analysis_service = LotteryAnalysisService(db)
+ return analysis_service.analyze_mathematical_stats(lottery_type, periods)
+
+
+@router.get("/missing/{lottery_type}")
+def get_missing_periods(
+ lottery_type: str,
+ db: Session = Depends(get_db)
+):
+ """获取号码遗漏值分析"""
+ if lottery_type not in ['ssq', 'dlt']:
+ raise HTTPException(status_code=400, detail="Invalid lottery type")
+
+ analysis_service = LotteryAnalysisService(db)
+ return analysis_service.get_missing_periods(lottery_type)
+
+
+@router.get("/smart-numbers/{lottery_type}")
+def generate_smart_numbers(
+ lottery_type: str,
+ strategy: Optional[str] = 'balanced',
+ count: Optional[int] = 1,
+ periods: Optional[int] = 100,
+ db: Session = Depends(get_db)
+):
+ """智能选号
+
+ Args:
+ lottery_type: 彩票类型 ('ssq' 或 'dlt')
+ strategy: 选号策略 ('balanced', 'hot', 'cold', 'missing')
+ count: 生成注数,默认1注
+ periods: 分析期数,默认100期
+ """
+ if lottery_type not in ['ssq', 'dlt']:
+ raise HTTPException(status_code=400, detail="Invalid lottery type")
+ if strategy not in ['balanced', 'hot', 'cold', 'missing']:
+ raise HTTPException(status_code=400, detail="Invalid strategy")
+ if count < 1 or count > 10:
+ raise HTTPException(
+ status_code=400, detail="Count must be between 1 and 10")
+ if periods < 50 or periods > 200:
+ raise HTTPException(
+ status_code=400, detail="Periods must be between 50 and 200")
+
+ analysis_service = LotteryAnalysisService(db)
+ return analysis_service.generate_smart_numbers(lottery_type, strategy, count, periods)
diff --git a/backend/app/main.py b/backend/app/main.py
index c024dad..dbb17ec 100644
--- a/backend/app/main.py
+++ b/backend/app/main.py
@@ -2,6 +2,7 @@ from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
from app.api.v1.lottery import router as lottery_router
+from app.api.endpoints.analysis import router as analysis_router
from app.core.database import Base, engine
# 创建数据库表
@@ -15,7 +16,7 @@ app = FastAPI(
# 配置CORS
app.add_middleware(
CORSMiddleware,
- allow_origins=settings.BACKEND_CORS_ORIGINS,
+ allow_origins=["*"], # 允许所有来源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
@@ -24,6 +25,8 @@ app.add_middleware(
# 注册路由
app.include_router(
lottery_router, prefix=f"{settings.API_V1_STR}/lottery", tags=["lottery"])
+app.include_router(
+ analysis_router, prefix=f"{settings.API_V1_STR}/analysis", tags=["analysis"])
if __name__ == "__main__":
import uvicorn
diff --git a/backend/app/services/analysis_service.py b/backend/app/services/analysis_service.py
new file mode 100644
index 0000000..53ffc28
--- /dev/null
+++ b/backend/app/services/analysis_service.py
@@ -0,0 +1,349 @@
+from typing import List, Dict, Tuple, Optional
+import numpy as np
+from collections import defaultdict
+from datetime import datetime, timedelta
+from sqlalchemy.orm import Session
+from ..models.lottery import SSQLottery, DLTLottery
+
+
+class LotteryAnalysisService:
+ def __init__(self, db: Session):
+ self.db = db
+
+ def get_hot_cold_numbers(self, lottery_type: str, periods: int = 50) -> Dict:
+ """分析热号和冷号
+
+ Args:
+ lottery_type: 彩票类型 ('ssq' 或 'dlt')
+ periods: 分析期数,默认50期
+
+ Returns:
+ Dict: 包含热号和冷号的字典
+ """
+ model = SSQLottery if lottery_type == 'ssq' else DLTLottery
+ recent_draws = self.db.query(model).order_by(
+ model.open_time.desc()).limit(periods).all()
+
+ # 初始化号码频率统计
+ red_freq = defaultdict(int)
+ blue_freq = defaultdict(int)
+
+ # 统计号码出现频率
+ for draw in recent_draws:
+ if lottery_type == 'ssq':
+ red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
+ draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
+ for num in red_numbers:
+ red_freq[num] += 1
+ blue_freq[draw.blue_ball] += 1
+ else:
+ red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
+ draw.front_ball_4, draw.front_ball_5]
+ for num in red_numbers:
+ red_freq[num] += 1
+ blue_freq[draw.back_ball_1] += 1
+ blue_freq[draw.back_ball_2] += 1
+
+ # 计算平均出现次数
+ red_avg = sum(red_freq.values()) / len(red_freq)
+ blue_avg = sum(blue_freq.values()) / len(blue_freq)
+
+ # 定义热号和冷号
+ hot_reds = [num for num, freq in red_freq.items() if freq > red_avg]
+ cold_reds = [num for num, freq in red_freq.items() if freq < red_avg]
+ hot_blues = [num for num, freq in blue_freq.items() if freq > blue_avg]
+ cold_blues = [num for num, freq in blue_freq.items()
+ if freq < blue_avg]
+
+ return {
+ 'hot_reds': sorted(hot_reds),
+ 'cold_reds': sorted(cold_reds),
+ 'hot_blues': sorted(hot_blues),
+ 'cold_blues': sorted(cold_blues),
+ 'red_frequencies': dict(red_freq),
+ 'blue_frequencies': dict(blue_freq)
+ }
+
+ def analyze_number_distribution(self, lottery_type: str, periods: int = 100) -> Dict:
+ """分析号码分布(分区统计、奇偶比)
+
+ Args:
+ lottery_type: 彩票类型 ('ssq' 或 'dlt')
+ periods: 分析期数,默认100期
+
+ Returns:
+ Dict: 包含各种分布统计的字典
+ """
+ model = SSQLottery if lottery_type == 'ssq' else DLTLottery
+ recent_draws = self.db.query(model).order_by(
+ model.open_time.desc()).limit(periods).all()
+
+ # 初始化统计数据
+ zone_stats = defaultdict(int)
+ odd_count = 0
+ even_count = 0
+ total_numbers = 0
+
+ for draw in recent_draws:
+ if lottery_type == 'ssq':
+ red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
+ draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
+ else:
+ red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
+ draw.front_ball_4, draw.front_ball_5]
+
+ # 分区统计
+ for num in red_numbers:
+ # 对于双色球:每5个数字一个区,最后一个区是31-33
+ # 对于大乐透:每5个数字一个区,最后一个区是31-35
+ zone = (num - 1) // 5 + 1
+ zone_stats[zone] += 1
+
+ # 奇偶统计
+ if num % 2 == 0:
+ even_count += 1
+ else:
+ odd_count += 1
+ total_numbers += 1
+
+ # 计算比例
+ zone_distribution = {str(zone): count for zone,
+ count in zone_stats.items()}
+ odd_even_distribution = {
+ 'odd': odd_count,
+ 'even': even_count
+ }
+
+ return {
+ 'zone_distribution': zone_distribution,
+ 'odd_even_distribution': odd_even_distribution
+ }
+
+ def analyze_consecutive_numbers(self, lottery_type: str, periods: int = 100) -> Dict:
+ """分析连号和重复号
+
+ Args:
+ lottery_type: 彩票类型 ('ssq' 或 'dlt')
+ periods: 分析期数,默认100期
+
+ Returns:
+ Dict: 包含连号和重复号分析的字典
+ """
+ model = SSQLottery if lottery_type == 'ssq' else DLTLottery
+ recent_draws = self.db.query(model).order_by(
+ model.open_time.desc()).limit(periods).all()
+
+ consecutive_stats = defaultdict(int)
+ repeat_stats = defaultdict(int)
+
+ prev_numbers = None
+ for draw in recent_draws:
+ if lottery_type == 'ssq':
+ current_numbers = sorted([
+ draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
+ draw.red_ball_4, draw.red_ball_5, draw.red_ball_6
+ ])
+ else:
+ current_numbers = sorted([
+ draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
+ draw.front_ball_4, draw.front_ball_5
+ ])
+
+ # 分析连号
+ consecutive_count = 0
+ for i in range(len(current_numbers)-1):
+ if current_numbers[i+1] - current_numbers[i] == 1:
+ consecutive_count += 1
+ consecutive_stats[consecutive_count] += 1
+
+ # 分析重复号
+ if prev_numbers:
+ repeat_count = len(set(current_numbers) & set(prev_numbers))
+ repeat_stats[repeat_count] += 1
+
+ prev_numbers = current_numbers
+
+ total_draws = len(recent_draws)
+ return {
+ 'consecutive_distribution': {k: v/total_draws for k, v in consecutive_stats.items()},
+ 'repeat_distribution': {k: v/(total_draws-1) for k, v in repeat_stats.items()}
+ }
+
+ def analyze_mathematical_stats(self, lottery_type: str, periods: int = 100) -> Dict:
+ """分析数学统计特征
+
+ Args:
+ lottery_type: 彩票类型 ('ssq' 或 'dlt')
+ periods: 分析期数,默认100期
+
+ Returns:
+ Dict: 包含数学统计特征的字典
+ """
+ model = SSQLottery if lottery_type == 'ssq' else DLTLottery
+ recent_draws = self.db.query(model).order_by(
+ model.open_time.desc()).limit(periods).all()
+
+ sums = []
+ for draw in recent_draws:
+ if lottery_type == 'ssq':
+ red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
+ draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
+ else:
+ red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
+ draw.front_ball_4, draw.front_ball_5]
+ sums.append(sum(red_numbers))
+
+ mean = np.mean(sums)
+ std = np.std(sums)
+
+ return {
+ 'sum_mean': float(mean),
+ 'sum_std': float(std),
+ 'sum_range': {
+ 'min': float(mean - 2*std),
+ 'max': float(mean + 2*std)
+ }
+ }
+
+ def get_missing_periods(self, lottery_type: str, periods: int = 200) -> Dict:
+ """分析号码遗漏值(仅分析最近periods期,避免全表遍历)
+
+ Args:
+ lottery_type: 彩票类型 ('ssq' 或 'dlt')
+ periods: 分析期数,默认200期
+
+ Returns:
+ Dict: 包含各号码当前遗漏值的字典
+ """
+ model = SSQLottery if lottery_type == 'ssq' else DLTLottery
+ max_red = 33 if lottery_type == 'ssq' else 35
+ max_blue = 16 if lottery_type == 'ssq' else 12
+
+ # 一次性查出最近periods期数据
+ draws = self.db.query(model).order_by(
+ model.open_time.desc()).limit(periods).all()
+
+ # 初始化遗漏值字典
+ red_missing = {i: 0 for i in range(1, max_red + 1)}
+ blue_missing = {i: 0 for i in range(1, max_blue + 1)}
+
+ # 标记号码是否已出现
+ red_found = {i: False for i in range(1, max_red + 1)}
+ blue_found = {i: False for i in range(1, max_blue + 1)}
+
+ for idx, draw in enumerate(draws):
+ if lottery_type == 'ssq':
+ red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
+ draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
+ blue_numbers = [draw.blue_ball]
+ else:
+ red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
+ draw.front_ball_4, draw.front_ball_5]
+ blue_numbers = [draw.back_ball_1, draw.back_ball_2]
+
+ # 红球遗漏统计
+ for i in range(1, max_red + 1):
+ if not red_found[i]:
+ if i in red_numbers:
+ red_found[i] = True
+ red_missing[i] = idx
+ # 蓝球遗漏统计
+ for i in range(1, max_blue + 1):
+ if not blue_found[i]:
+ if i in blue_numbers:
+ blue_found[i] = True
+ blue_missing[i] = idx
+
+ # 未出现过的号码,遗漏值为periods
+ for i in range(1, max_red + 1):
+ if not red_found[i]:
+ red_missing[i] = periods
+ for i in range(1, max_blue + 1):
+ if not blue_found[i]:
+ blue_missing[i] = periods
+
+ return {
+ 'red_missing': red_missing,
+ 'blue_missing': blue_missing
+ }
+
+ def generate_smart_numbers(self, lottery_type: str, strategy: str = 'balanced', count: int = 1, periods: int = 100) -> List[Dict]:
+ """智能选号
+
+ Args:
+ lottery_type: 彩票类型 ('ssq' 或 'dlt')
+ strategy: 选号策略 ('balanced', 'hot', 'cold', 'missing')
+ count: 生成注数
+ periods: 分析期数,默认100期
+
+ Returns:
+ List[Dict]: 生成的号码列表
+ """
+ import random
+
+ # 获取分析数据
+ hot_cold = self.get_hot_cold_numbers(lottery_type, periods)
+ distribution = self.analyze_number_distribution(lottery_type, periods)
+ missing = self.get_missing_periods(lottery_type, periods)
+
+ max_red = 33 if lottery_type == 'ssq' else 35
+ max_blue = 16 if lottery_type == 'ssq' else 12
+ red_count = 6 if lottery_type == 'ssq' else 5
+ blue_count = 1 if lottery_type == 'ssq' else 2
+
+ results = []
+ for _ in range(count):
+ # 根据策略选择红球
+ if strategy == 'hot':
+ red_pool = hot_cold['hot_reds']
+ elif strategy == 'cold':
+ red_pool = hot_cold['cold_reds']
+ elif strategy == 'missing':
+ red_pool = sorted(missing['red_missing'].items(),
+ key=lambda x: x[1], reverse=True)
+ red_pool = [num for num, _ in red_pool[:max_red//2]]
+ else: # balanced
+ red_pool = list(range(1, max_red + 1))
+
+ # 确保红球池不为空且数量足够
+ if not red_pool or len(red_pool) < red_count:
+ red_pool = list(range(1, max_red + 1))
+
+ # 选择红球
+ try:
+ red_numbers = sorted(random.sample(red_pool, red_count))
+ except ValueError:
+ # 如果采样失败,使用全范围随机
+ red_numbers = sorted(random.sample(
+ range(1, max_red + 1), red_count))
+
+ # 选择蓝球
+ if strategy == 'hot':
+ blue_pool = hot_cold['hot_blues']
+ elif strategy == 'cold':
+ blue_pool = hot_cold['cold_blues']
+ elif strategy == 'missing':
+ blue_pool = sorted(missing['blue_missing'].items(),
+ key=lambda x: x[1], reverse=True)
+ blue_pool = [num for num, _ in blue_pool[:max_blue//2]]
+ else: # balanced
+ blue_pool = list(range(1, max_blue + 1))
+
+ # 确保蓝球池不为空且数量足够
+ if not blue_pool or len(blue_pool) < blue_count:
+ blue_pool = list(range(1, max_blue + 1))
+
+ # 选择蓝球
+ try:
+ blue_numbers = sorted(random.sample(blue_pool, blue_count))
+ except ValueError:
+ # 如果采样失败,使用全范围随机
+ blue_numbers = sorted(random.sample(
+ range(1, max_blue + 1), blue_count))
+
+ results.append({
+ 'red_numbers': red_numbers,
+ 'blue_numbers': blue_numbers
+ })
+
+ return results
diff --git a/backend/main.py b/backend/main.py
new file mode 100644
index 0000000..76c53c2
--- /dev/null
+++ b/backend/main.py
@@ -0,0 +1,26 @@
+from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
+from app.api.endpoints import analysis
+
+app = FastAPI(
+ title="彩票数据分析系统",
+ description="支持双色球和大乐透的数据管理、统计分析和智能选号功能",
+ version="1.0.0"
+)
+
+# 配置CORS
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+
+# 注册路由
+app.include_router(analysis.router, prefix="/api/analysis", tags=["analysis"])
+
+
+@app.get("/")
+def read_root():
+ return {"message": "欢迎使用彩票数据分析系统"}
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 6163715..18a0669 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -88,7 +88,7 @@ onUnmounted(() => {
font-size: 16px;
font-weight: 500;
}
-@media screen and (max-width: 768px) {
+@media screen and (max-width: 1024px) {
.el-header {
flex-direction: row;
height: 50px;
diff --git a/frontend/src/api/lottery.js b/frontend/src/api/lottery.js
index abcdf5c..c319291 100644
--- a/frontend/src/api/lottery.js
+++ b/frontend/src/api/lottery.js
@@ -1,4 +1,5 @@
import axios from 'axios'
+import request from '../utils/request'
const api = axios.create({
baseURL: '/api/v1/lottery'
@@ -89,5 +90,67 @@ export const lotteryApi = {
generateDLTNumbers(params) {
return api.get('/dlt/generate', { params })
+ },
+
+ // 获取热号冷号分析
+ getHotColdNumbers(lotteryType, params) {
+ return request({
+ url: `/api/v1/analysis/hot-cold/${lotteryType}`,
+ method: 'get',
+ params
+ })
+ },
+
+ // 获取号码分布分析
+ getNumberDistribution(lotteryType, params) {
+ return request({
+ url: `/api/v1/analysis/distribution/${lotteryType}`,
+ method: 'get',
+ params
+ })
+ },
+
+ // 获取连号分析
+ getConsecutiveAnalysis(lotteryType, params) {
+ return request({
+ url: `/api/v1/analysis/consecutive/${lotteryType}`,
+ method: 'get',
+ params
+ })
+ },
+
+ // 获取数学统计特征
+ getMathematicalStats(lotteryType, params) {
+ return request({
+ url: `/api/v1/analysis/math-stats/${lotteryType}`,
+ method: 'get',
+ params
+ })
+ },
+
+ // 获取遗漏值分析
+ getMissingPeriods(lotteryType) {
+ return request({
+ url: `/api/v1/analysis/missing/${lotteryType}`,
+ method: 'get'
+ })
+ },
+
+ // 智能选号
+ generateSmartNumbers(lotteryType, params) {
+ return request({
+ url: `/api/v1/analysis/smart-numbers/${lotteryType}`,
+ method: 'get',
+ params: {
+ strategy: params.strategy || 'balanced',
+ count: params.count || 1,
+ periods: params.periods || 100
+ }
+ }).then(response => {
+ if (response && response.data) {
+ return response
+ }
+ throw new Error('返回数据格式错误')
+ })
}
}
\ No newline at end of file
diff --git a/frontend/src/utils/request.js b/frontend/src/utils/request.js
new file mode 100644
index 0000000..1f9dec5
--- /dev/null
+++ b/frontend/src/utils/request.js
@@ -0,0 +1,40 @@
+import axios from 'axios'
+import { ElMessage } from 'element-plus'
+
+// 创建axios实例
+const service = axios.create({
+ baseURL: 'http://localhost:8000', // API的基础URL
+ timeout: 15000 // 请求超时时间
+})
+
+// 请求拦截器
+service.interceptors.request.use(
+ config => {
+ // 在发送请求之前做些什么
+ return config
+ },
+ error => {
+ // 对请求错误做些什么
+ console.error('Request error:', error)
+ return Promise.reject(error)
+ }
+)
+
+// 响应拦截器
+service.interceptors.response.use(
+ response => {
+ // FastAPI 返回的数据在 response.data 中
+ return response
+ },
+ error => {
+ console.error('Response error:', error)
+ ElMessage({
+ message: error.message || 'Request failed',
+ type: 'error',
+ duration: 5 * 1000
+ })
+ return Promise.reject(error)
+ }
+)
+
+export default service
\ No newline at end of file
diff --git a/frontend/src/views/NumberGenerator.vue b/frontend/src/views/NumberGenerator.vue
index 8bcb57d..dd09086 100644
--- a/frontend/src/views/NumberGenerator.vue
+++ b/frontend/src/views/NumberGenerator.vue
@@ -5,19 +5,28 @@