From 59722d731164d7414dfb9955e960664dc7af7890 Mon Sep 17 00:00:00 2001 From: WrBug Date: Wed, 3 Dec 2025 02:48:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=E7=9A=84=E9=83=A8=E7=BD=B2=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端多环境配置(dev, prod) - Docker 部署支持(Dockerfile, docker-compose.yml) - Java 部署脚本(deploy.sh) - 前端构建脚本(build.sh,支持自定义后端地址) - 健康检查接口(/api/health) - 完整的部署文档(docs/DEPLOYMENT.md) - 前端环境变量支持(VITE_API_URL, VITE_WS_URL) --- README.md | 63 +-- backend/.dockerignore | 33 ++ backend/Dockerfile | 48 +++ backend/deploy.sh | 203 +++++++++ backend/docker-compose.yml | 54 +++ .../controller/HealthController.kt | 26 ++ .../src/main/resources/application.properties | 8 +- docs/DEPLOYMENT.md | 399 ++++++++++++++++++ frontend/.dockerignore | 34 ++ frontend/build.sh | 137 ++++++ frontend/src/services/api.ts | 15 +- frontend/src/services/websocket.ts | 20 +- frontend/src/vite-env.d.ts | 11 + frontend/vite.config.ts | 43 +- 14 files changed, 1047 insertions(+), 47 deletions(-) create mode 100644 backend/.dockerignore create mode 100644 backend/Dockerfile create mode 100755 backend/deploy.sh create mode 100644 backend/docker-compose.yml create mode 100644 backend/src/main/kotlin/com/wrbug/polymarketbot/controller/HealthController.kt create mode 100644 docs/DEPLOYMENT.md create mode 100644 frontend/.dockerignore create mode 100755 frontend/build.sh create mode 100644 frontend/src/vite-env.d.ts diff --git a/README.md b/README.md index c6d0b59..55ab1ff 100644 --- a/README.md +++ b/README.md @@ -80,9 +80,9 @@ polymarket-bot/ - JDK 17+ - Node.js 18+ - MySQL 8.0+ -- Gradle 7.5+ +- Gradle 7.5+(或使用 Gradle Wrapper) -### 安装步骤 +### 开发环境 1. **克隆仓库** @@ -99,33 +99,16 @@ cd PolyHermes CREATE DATABASE polymarket_bot CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` -3. **配置后端** - -编辑 `backend/src/main/resources/application.properties`: - -```properties -# 数据库配置 -spring.datasource.url=jdbc:mysql://localhost:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8mb4 -spring.datasource.username=${DB_USERNAME:root} -spring.datasource.password=${DB_PASSWORD:your_password} - -# 服务器端口 -server.port=${SERVER_PORT:8000} - -# Polygon RPC(用于查询链上余额) -polygon.rpc.url=${POLYGON_RPC_URL:https://polygon-rpc.com} -``` - -4. **启动后端** +3. **启动后端** ```bash cd backend ./gradlew bootRun ``` -后端服务将在 `http://localhost:8000` 启动。 +后端服务将在 `http://localhost:8000` 启动(开发环境)。 -5. **启动前端** +4. **启动前端** ```bash cd frontend @@ -135,6 +118,34 @@ npm run dev 前端应用将在 `http://localhost:3000` 启动。 +### 生产部署 + +详细的部署文档请参考:[部署文档](docs/DEPLOYMENT.md) + +#### 快速部署 + +**后端(Java 方式)**: +```bash +cd backend +./deploy.sh java +``` + +**后端(Docker 方式)**: +```bash +cd backend +./deploy.sh docker +``` + +**前端**: +```bash +cd frontend +# 使用默认后端地址 +./build.sh + +# 或指定自定义后端地址 +./build.sh --api-url http://your-backend-server.com:8000 +``` + ## 📖 使用指南 ### 账户管理 @@ -180,11 +191,11 @@ npm run dev 3. 启用代理并测试连接 4. 配置实时生效,无需重启服务 -## 📚 API 文档 +## 📚 文档 -详细的 API 文档请参考: -- [跟单系统需求文档](docs/copy-trading-requirements.md) -- [前端需求文档](docs/copy-trading-frontend-requirements.md) +- [部署文档](docs/DEPLOYMENT.md) - 详细的部署指南(Java/Docker) +- [跟单系统需求文档](docs/copy-trading-requirements.md) - 后端 API 接口文档 +- [前端需求文档](docs/copy-trading-frontend-requirements.md) - 前端功能文档 ## 🤝 贡献 diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..240f6c0 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,33 @@ +# Gradle +.gradle/ +build/ +out/ +bin/ +*.log + +# IDE +.idea/ +*.iml +*.iws +*.ipr +.vscode/ +*.swp +*.swo +*~ +.DS_Store + +# 部署相关 +deploy/ +*.jar +!build/libs/*.jar + +# 环境配置 +.env +.env.local +.env.*.local + +# 其他 +*.bak +*.backup +*.old + diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..1091424 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,48 @@ +# 多阶段构建 Dockerfile +# 阶段1:构建应用 +FROM gradle:8.5-jdk17 AS build + +WORKDIR /app + +# 复制 Gradle 配置文件 +COPY build.gradle.kts settings.gradle.kts ./ +COPY gradle ./gradle + +# 下载依赖(利用 Docker 缓存) +RUN gradle dependencies --no-daemon || true + +# 复制源代码 +COPY src ./src + +# 构建应用 +RUN gradle bootJar --no-daemon + +# 阶段2:运行应用 +FROM openjdk:17-jre-slim + +WORKDIR /app + +# 安装必要的工具 +RUN apt-get update && \ + apt-get install -y curl && \ + rm -rf /var/lib/apt/lists/* + +# 从构建阶段复制 JAR 文件 +COPY --from=build /app/build/libs/*.jar app.jar + +# 创建非 root 用户 +RUN useradd -m -u 1000 appuser && \ + chown -R appuser:appuser /app + +USER appuser + +# 暴露端口 +EXPOSE 8000 + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ + CMD curl -f http://localhost:8000/api/health || exit 1 + +# 启动应用 +ENTRYPOINT ["java", "-jar", "app.jar"] + diff --git a/backend/deploy.sh b/backend/deploy.sh new file mode 100755 index 0000000..69f6488 --- /dev/null +++ b/backend/deploy.sh @@ -0,0 +1,203 @@ +#!/bin/bash + +# PolyHermes 后端部署脚本 +# 支持 Java 直接部署和 Docker 部署 + +set -e + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# 配置 +APP_NAME="polymarket-bot-backend" +JAR_NAME="polymarket-bot-backend-1.0.0.jar" +DEPLOY_DIR="./deploy" +PROFILE="${SPRING_PROFILES_ACTIVE:-prod}" + +# 打印信息 +info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 检查 Java 环境 +check_java() { + if ! command -v java &> /dev/null; then + error "Java 未安装,请先安装 Java 17+" + exit 1 + fi + + JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | cut -d'.' -f1) + if [ "$JAVA_VERSION" -lt 17 ]; then + error "Java 版本过低,需要 Java 17+,当前版本: $JAVA_VERSION" + exit 1 + fi + + info "Java 环境检查通过: $(java -version 2>&1 | head -n 1)" +} + +# 构建应用 +build_app() { + info "开始构建应用..." + + if ! command -v gradle &> /dev/null; then + error "Gradle 未安装,请先安装 Gradle 或使用 Gradle Wrapper" + exit 1 + fi + + ./gradlew clean bootJar + + if [ ! -f "build/libs/$JAR_NAME" ]; then + error "构建失败,JAR 文件不存在" + exit 1 + fi + + info "构建完成: build/libs/$JAR_NAME" +} + +# Java 部署 +deploy_java() { + info "使用 Java 方式部署..." + + # 创建部署目录 + mkdir -p "$DEPLOY_DIR" + + # 复制 JAR 文件 + cp "build/libs/$JAR_NAME" "$DEPLOY_DIR/" + + # 创建启动脚本 + cat > "$DEPLOY_DIR/start.sh" < "$DEPLOY_DIR/${APP_NAME}.service" < /dev/null; then + error "Docker 未安装,请先安装 Docker" + exit 1 + fi + + if ! command -v docker-compose &> /dev/null; then + error "Docker Compose 未安装,请先安装 Docker Compose" + exit 1 + fi + + # 创建 .env 文件(如果不存在) + if [ ! -f ".env" ]; then + warn ".env 文件不存在,创建示例文件..." + cat > .env <> { + return ResponseEntity.ok(mapOf( + "status" to "UP", + "timestamp" to System.currentTimeMillis(), + "service" to "polymarket-bot-backend" + )) + } +} + diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 631a8b6..c87e26c 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,8 +1,8 @@ # 应用配置 spring.application.name=polymarket-bot-backend -# 数据源配置 -spring.datasource.url=jdbc:mysql://localhost:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8&allowPublicKeyRetrieval=true +# 数据源配置(默认配置,可通过环境变量覆盖) +spring.datasource.url=${DB_URL:jdbc:mysql://localhost:3306/polymarket_bot?useSSL=false&serverTimezone=UTC&characterEncoding=utf8&allowPublicKeyRetrieval=true} spring.datasource.username=${DB_USERNAME:root} spring.datasource.password=${DB_PASSWORD:11111111} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver @@ -25,6 +25,10 @@ spring.flyway.baseline-on-migrate=true # 服务器配置 server.port=${SERVER_PORT:8000} +# Spring Profile 配置 +# 默认使用 dev 环境,可通过 --spring.profiles.active=prod 切换 +spring.profiles.active=${SPRING_PROFILES_ACTIVE:dev} + # 日志配置 logging.level.root=INFO logging.level.com.wrbug.polymarketbot=DEBUG diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 0000000..fe579b6 --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,399 @@ +# PolyHermes 部署文档 + +本文档介绍如何部署 PolyHermes 项目,包括后端和前端的不同部署方式。 + +## 目录 + +- [后端部署](#后端部署) + - [Java 直接部署](#java-直接部署) + - [Docker 部署](#docker-部署) +- [前端部署](#前端部署) +- [环境配置](#环境配置) +- [常见问题](#常见问题) + +## 后端部署 + +### Java 直接部署 + +#### 前置要求 + +- JDK 17+ +- MySQL 8.0+ +- Gradle 7.5+(或使用 Gradle Wrapper) + +#### 部署步骤 + +1. **构建应用** + +```bash +cd backend +./gradlew clean bootJar +``` + +构建产物位于 `build/libs/polymarket-bot-backend-1.0.0.jar` + +2. **使用部署脚本(推荐)** + +```bash +# 构建并创建部署文件 +./deploy.sh java + +# 或仅构建 +./deploy.sh build +``` + +脚本会自动: +- 检查 Java 环境 +- 构建应用 +- 创建部署目录和启动脚本 +- 生成 systemd 服务文件(可选) + +3. **手动启动** + +```bash +# 开发环境 +java -jar build/libs/polymarket-bot-backend-1.0.0.jar --spring.profiles.active=dev + +# 生产环境 +java -jar build/libs/polymarket-bot-backend-1.0.0.jar --spring.profiles.active=prod +``` + +4. **使用 systemd 管理(Linux)** + +```bash +# 复制服务文件 +sudo cp deploy/polymarket-bot-backend.service /etc/systemd/system/ + +# 编辑服务文件,修改路径和用户 +sudo nano /etc/systemd/system/polymarket-bot-backend.service + +# 启动服务 +sudo systemctl daemon-reload +sudo systemctl enable polymarket-bot-backend +sudo systemctl start polymarket-bot-backend + +# 查看日志 +sudo journalctl -u polymarket-bot-backend -f +``` + +### Docker 部署 + +#### 前置要求 + +- Docker 20.10+ +- Docker Compose 2.0+ + +#### 部署步骤 + +1. **使用部署脚本(推荐)** + +```bash +cd backend +./deploy.sh docker +``` + +脚本会自动: +- 检查 Docker 环境 +- 创建 `.env` 配置文件(如果不存在) +- 构建 Docker 镜像 +- 启动服务 + +2. **手动部署** + +```bash +# 创建 .env 文件 +cat > .env < .env.production < + ServerName your-domain.com + DocumentRoot /path/to/frontend/dist + + # API 代理 + ProxyPass /api http://localhost:8000/api + ProxyPassReverse /api http://localhost:8000/api + + # WebSocket 代理 + ProxyPass /ws ws://localhost:8000/ws + ProxyPassReverse /ws ws://localhost:8000/ws + + # 前端路由(SPA) + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + RewriteEngine On + RewriteBase / + RewriteRule ^index\.html$ - [L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . /index.html [L] + + +``` + +#### 方式3:使用 serve(开发/测试) + +```bash +# 安装 serve +npm install -g serve + +# 启动服务 +serve -s dist -l 3000 +``` + +## 环境配置 + +### 后端环境变量 + +| 变量名 | 说明 | 默认值 | 必需 | +|--------|------|--------|------| +| `SPRING_PROFILES_ACTIVE` | Spring Profile | `dev` | 否 | +| `DB_URL` | 数据库连接 URL | - | 是(生产) | +| `DB_USERNAME` | 数据库用户名 | `root` | 是(生产) | +| `DB_PASSWORD` | 数据库密码 | - | 是(生产) | +| `SERVER_PORT` | 服务器端口 | `8000` | 否 | +| `POLYGON_RPC_URL` | Polygon RPC 地址 | `https://polygon-rpc.com` | 否 | +| `JWT_SECRET` | JWT 密钥 | - | 是(生产) | +| `ADMIN_RESET_PASSWORD_KEY` | 管理员密码重置密钥 | - | 是(生产) | + +### 前端环境变量 + +| 变量名 | 说明 | 默认值 | +|--------|------|--------| +| `VITE_API_URL` | 后端 API 地址 | `http://127.0.0.1:8000` | +| `VITE_WS_URL` | WebSocket 地址 | `ws://127.0.0.1:8000` | + +### 配置文件说明 + +#### 后端配置文件 + +- `application.properties` - 基础配置(所有环境共享) +- `application-dev.properties` - 开发环境配置 +- `application-prod.properties` - 生产环境配置 + +通过 `--spring.profiles.active=prod` 或环境变量 `SPRING_PROFILES_ACTIVE=prod` 切换环境。 + +#### 前端环境变量 + +Vite 使用 `.env.production` 文件在构建时注入环境变量。构建脚本会自动创建此文件。 + +## 常见问题 + +### 1. 数据库连接失败 + +**问题**: 后端无法连接数据库 + +**解决方案**: +- 检查数据库服务是否运行 +- 检查数据库连接 URL、用户名、密码是否正确 +- 检查防火墙是否允许连接 +- 对于 Docker 部署,确保使用正确的数据库地址(`mysql` 而非 `localhost`) + +### 2. 前端无法连接后端 + +**问题**: 前端请求后端 API 失败 + +**解决方案**: +- 检查后端服务是否运行 +- 检查 `VITE_API_URL` 配置是否正确 +- 检查 CORS 配置(如果跨域) +- 检查网络连接和防火墙 + +### 3. WebSocket 连接失败 + +**问题**: WebSocket 无法建立连接 + +**解决方案**: +- 检查 `VITE_WS_URL` 配置是否正确 +- 检查 WebSocket 代理配置(Nginx/Apache) +- 检查防火墙是否允许 WebSocket 连接 +- 检查后端 WebSocket 服务是否正常 + +### 4. Docker 容器无法访问数据库 + +**问题**: Docker 容器中的后端无法连接宿主机数据库 + +**解决方案**: +- 使用 `host.docker.internal` 作为数据库地址(Mac/Windows) +- 使用 Docker 网络连接(推荐使用 docker-compose) +- 检查数据库是否允许远程连接 + +### 5. 构建失败 + +**问题**: 前端或后端构建失败 + +**解决方案**: +- 检查 Node.js 版本(需要 18+) +- 检查 Java 版本(需要 17+) +- 清理缓存后重新构建: + ```bash + # 前端 + rm -rf node_modules dist + npm install + npm run build + + # 后端 + ./gradlew clean build + ``` + +## 生产环境检查清单 + +- [ ] 修改所有默认密码和密钥(JWT_SECRET、ADMIN_RESET_PASSWORD_KEY、数据库密码) +- [ ] 配置正确的数据库连接(使用 SSL) +- [ ] 设置正确的 Spring Profile(`prod`) +- [ ] 配置正确的后端 API 地址(前端) +- [ ] 配置反向代理(Nginx/Apache) +- [ ] 配置 HTTPS(生产环境推荐) +- [ ] 配置防火墙规则 +- [ ] 设置日志轮转 +- [ ] 配置监控和告警 +- [ ] 定期备份数据库 + +## 性能优化建议 + +### 后端 + +- 调整 JVM 参数(堆内存、GC 策略) +- 配置数据库连接池大小 +- 启用 HTTP 压缩 +- 配置缓存策略 + +### 前端 + +- 启用 Gzip 压缩(Nginx) +- 配置静态资源缓存 +- 使用 CDN 加速 +- 启用 HTTP/2 + +## 安全建议 + +- 使用 HTTPS(生产环境必须) +- 配置 CORS 白名单 +- 定期更新依赖包 +- 使用强密码和密钥 +- 限制数据库访问权限 +- 配置防火墙规则 +- 定期备份数据 +- 监控异常访问 + +## 技术支持 + +如有问题,请提交 Issue 到 [GitHub](https://github.com/WrBug/PolyHermes) 或联系 [Twitter](https://x.com/quant_tr)。 + diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..24c5a75 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,34 @@ +# 依赖 +node_modules/ +.pnpm-store/ + +# 构建产物 +dist/ +build/ +out/ + +# 环境配置 +.env +.env.local +.env.*.local + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store + +# 日志 +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# 其他 +*.bak +*.backup +*.old + diff --git a/frontend/build.sh b/frontend/build.sh new file mode 100755 index 0000000..7bc0b69 --- /dev/null +++ b/frontend/build.sh @@ -0,0 +1,137 @@ +#!/bin/bash + +# PolyHermes 前端构建脚本 +# 支持自定义后端 API 地址 + +set -e + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# 默认配置 +DEFAULT_API_URL="http://127.0.0.1:8000" +API_URL="${VITE_API_URL:-$DEFAULT_API_URL}" + +# 打印信息 +info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 检查 Node.js 环境 +check_node() { + if ! command -v node &> /dev/null; then + error "Node.js 未安装,请先安装 Node.js 18+" + exit 1 + fi + + NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) + if [ "$NODE_VERSION" -lt 18 ]; then + error "Node.js 版本过低,需要 Node.js 18+,当前版本: $(node -v)" + exit 1 + fi + + info "Node.js 环境检查通过: $(node -v)" +} + +# 创建环境配置文件 +create_env_file() { + info "创建环境配置文件..." + + # 解析 API URL,提取协议、主机和端口 + if [[ $API_URL == http* ]]; then + # 提取协议和主机 + PROTOCOL=$(echo $API_URL | sed -E 's|^([^:]+)://.*|\1|') + HOST_PORT=$(echo $API_URL | sed -E 's|^[^:]+://([^/]+).*|\1|') + HOST=$(echo $HOST_PORT | cut -d':' -f1) + PORT=$(echo $HOST_PORT | cut -d':' -f2) + + # 构建 WebSocket URL + if [ "$PROTOCOL" = "https" ]; then + WS_PROTOCOL="wss" + else + WS_PROTOCOL="ws" + fi + WS_URL="${WS_PROTOCOL}://${HOST}:${PORT}" + else + error "API URL 格式错误,应为 http://host:port 或 https://host:port" + exit 1 + fi + + # 创建 .env.production 文件 + cat > .env.production < { + const envApiUrl = import.meta.env.VITE_API_URL + if (envApiUrl) { + // 如果设置了环境变量,使用完整 URL + return `${envApiUrl}/api` + } + // 否则使用相对路径(适用于开发环境代理或同域部署) + return '/api' +} + const apiClient: AxiosInstance = axios.create({ - baseURL: '/api', + baseURL: getBaseURL(), timeout: 30000, headers: { 'Content-Type': 'application/json' diff --git a/frontend/src/services/websocket.ts b/frontend/src/services/websocket.ts index 80fb520..d79a476 100644 --- a/frontend/src/services/websocket.ts +++ b/frontend/src/services/websocket.ts @@ -325,16 +325,28 @@ class WebSocketManager { /** * 获取 WebSocket URL(带token认证) + * 支持通过环境变量 VITE_WS_URL 配置 WebSocket 地址 */ private getWebSocketUrl(): string { - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:' - const host = window.location.host + const envWsUrl = import.meta.env.VITE_WS_URL + let wsBaseUrl: string + + if (envWsUrl) { + // 如果设置了环境变量,使用完整 URL + wsBaseUrl = envWsUrl + } else { + // 否则使用相对路径(适用于开发环境代理或同域部署) + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:' + const host = window.location.host + wsBaseUrl = `${protocol}//${host}` + } + const token = this.getToken() if (token) { // 通过查询参数传递token - return `${protocol}//${host}/ws?token=${encodeURIComponent(token)}` + return `${wsBaseUrl}/ws?token=${encodeURIComponent(token)}` } - return `${protocol}//${host}/ws` + return `${wsBaseUrl}/ws` } /** diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..fd00d2d --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1,11 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_URL?: string + readonly VITE_WS_URL?: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} + diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index f9c6211..9faaf41 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,21 +1,36 @@ -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], - server: { - port: 3000, - proxy: { - '/api': { - target: 'http://localhost:8000', - changeOrigin: true - }, - '/ws': { - target: 'ws://localhost:8000', - ws: true, - changeOrigin: true +export default defineConfig(({ mode }) => { + // 加载环境变量 + const env = loadEnv(mode, process.cwd(), '') + + // 从环境变量获取 API 地址,默认使用 localhost:8000 + const API_URL = env.VITE_API_URL || 'http://localhost:8000' + const WS_URL = env.VITE_WS_URL || 'ws://localhost:8000' + + return { + plugins: [react()], + server: { + port: 3000, + proxy: { + '/api': { + target: API_URL, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, '/api') + }, + '/ws': { + target: WS_URL, + ws: true, + changeOrigin: true + } } + }, + // 定义环境变量,在构建时注入 + define: { + 'import.meta.env.VITE_API_URL': JSON.stringify(API_URL), + 'import.meta.env.VITE_WS_URL': JSON.stringify(WS_URL) } } })