diff --git a/.env.example b/.env.example index ebee828..0a6ad2d 100644 --- a/.env.example +++ b/.env.example @@ -43,16 +43,33 @@ COS_BUCKET=your-bucket-name COS_REGION=ap-guangzhou # Application Configuration +# 端口配置说明: +# - 如需并行运行多个项目实例,请修改以下端口配置 +# - 建议使用不同的端口范围,例如: +# - 实例1: FRONTEND_PORT=8001, BACKEND_PORT=8002 +# - 实例2: FRONTEND_PORT=8011, BACKEND_PORT=8012 +# - 实例3: FRONTEND_PORT=8021, BACKEND_PORT=8022 +# +# 注意:修改端口后,需要同时更新以下配置: +# - NEXT_PUBLIC_API_URL (前端调用后端的地址) +# - CORS_ORIGIN (后端允许的前端地址) +# - AUTH_BASE_URL (认证基础 URL) BACKEND_PORT=8002 FRONTEND_PORT=8001 NODE_ENV=development # CORS -# Cors (production example: https://novel.daerai.com) +# 后端允许的前端地址列表,多个地址用逗号分隔 +# 开发环境示例: http://localhost:8001 +# 生产环境示例: https://novel.daerai.com +# 如需并行运行多个项目,需要添加对应前端地址 CORS_ORIGIN=http://localhost:8001,https://novel.daerai.com # Authentication Base URL (MUST be set in production) -# Example: https://novel.daerai.com/api/auth +# 认证服务的基础 URL,用于 OAuth 回调等 +# 开发环境示例: http://localhost:8002/api/auth +# 生产环境示例: https://novel.daerai.com/api/auth +# 如需并行运行多个项目,需要修改为对应后端端口 AUTH_BASE_URL=http://localhost:8002/api/auth # LinuxDo OAuth diff --git a/apps/backend/src/index.ts b/apps/backend/src/index.ts index 5857dc6..0e69a41 100644 --- a/apps/backend/src/index.ts +++ b/apps/backend/src/index.ts @@ -30,9 +30,11 @@ import sandboxRoutes from './routes/sandbox.routes'; const app: Application = express(); const httpServer = createServer(app); // CORS configuration +const frontendPort = process.env.FRONTEND_PORT || 8001; +const defaultFrontendUrl = `http://localhost:${frontendPort}`; const allowedOrigins = process.env.CORS_ORIGIN ? process.env.CORS_ORIGIN.split(',').map(origin => origin.trim()) - : ['http://localhost:8001', 'tauri://localhost', 'http://tauri.localhost']; + : [defaultFrontendUrl, 'tauri://localhost', 'http://tauri.localhost']; const corsOptions = { origin: (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => { diff --git a/apps/frontend/.env.local.example b/apps/frontend/.env.local.example index a41d8c6..ec76412 100644 --- a/apps/frontend/.env.local.example +++ b/apps/frontend/.env.local.example @@ -1 +1,10 @@ +# 前端调用后端 API 的地址 +# 开发环境示例: http://localhost:8002 +# 生产环境示例: https://novel.daerai.com +# +# 如需并行运行多个项目实例,需要修改为对应后端端口 +# 例如: +# - 实例1: NEXT_PUBLIC_API_URL=http://localhost:8002 +# - 实例2: NEXT_PUBLIC_API_URL=http://localhost:8012 +# - 实例3: NEXT_PUBLIC_API_URL=http://localhost:8022 NEXT_PUBLIC_API_URL=http://localhost:8002 diff --git a/apps/frontend/package.json b/apps/frontend/package.json index abe9fad..fa17ad9 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "scripts": { - "dev": "next dev -p 8001", + "dev": "next dev -p ${FRONTEND_PORT:-8001}", "build": "next build", "start": "next start", "lint": "next lint", diff --git a/start.sh b/start.sh index 79f9e92..4f5bfb3 100755 --- a/start.sh +++ b/start.sh @@ -6,6 +6,36 @@ ulimit -n 65536 2>/dev/null || ulimit -n 10240 echo "🔧 System File Limit: $(ulimit -n)" echo "================================" +# 检查端口是否可用的函数 +is_port_available() { + local port=$1 + # 使用 lsof 检查端口是否被占用 + if lsof -ti :$port > /dev/null 2>&1; then + return 1 # 端口被占用 + else + return 0 # 端口可用 + fi +} + +# 查找可用端口对的函数 +find_available_ports() { + local base_port=$1 + local max_attempts=100 + + for ((i=0; i /dev/null; then echo "❌ 错误: 未安装 Docker" @@ -24,24 +54,160 @@ if [ ! -f .env ]; then read -p "按 Enter 继续..." fi -# 检查并清理端口 +# 从 .env 读取端口配置(如果存在) +if [ -f .env ]; then + FRONTEND_PORT=$(grep -E "^FRONTEND_PORT=" .env | cut -d'=' -f2) + BACKEND_PORT=$(grep -E "^BACKEND_PORT=" .env | cut -d'=' -f2) +fi + +# 如果 .env 中没有配置,使用默认值 +FRONTEND_PORT=${FRONTEND_PORT:-8001} +BACKEND_PORT=${BACKEND_PORT:-8002} + +# 检查端口占用 echo "" echo "🔍 检查端口占用..." -# 清理端口 8001 (前端) -PID_FE=$(lsof -ti :8001) +# 检查前端端口 +PID_FE=$(lsof -ti :$FRONTEND_PORT 2>/dev/null) +# 检查后端端口 +PID_BE=$(lsof -ti :$BACKEND_PORT 2>/dev/null) + +# 标记是否有端口被占用 +PORT_CONFLICT=false + if [ ! -z "$PID_FE" ]; then - echo "⚠️ 端口 8001 被占用 (PID: $PID_FE),正在终止..." - kill -9 $PID_FE - echo "✅ 端口 8001 已释放" + echo "⚠️ 前端端口 $FRONTEND_PORT 被占用 (PID: $PID_FE)" + PORT_CONFLICT=true fi -# 清理端口 8002 (后端) -PID_BE=$(lsof -ti :8002) if [ ! -z "$PID_BE" ]; then - echo "⚠️ 端口 8002 被占用 (PID: $PID_BE),正在终止..." - kill -9 $PID_BE - echo "✅ 端口 8002 已释放" + echo "⚠️ 后端端口 $BACKEND_PORT 被占用 (PID: $PID_BE)" + PORT_CONFLICT=true +fi + +# 如果有端口冲突,询问用户如何处理 +if [ "$PORT_CONFLICT" = true ]; then + echo "" + echo "⚠️ 检测到端口冲突!" + echo "================================" + echo "请选择处理方式:" + echo "1) 终止占用进程并继续 (可能影响其他项目)" + echo "2) 自动选择新端口并启动 (推荐,一键并行运行)" + echo "3) 修改端口后继续" + echo "4) 取消启动" + echo "================================" + read -p "请输入选项 (1/2/3/4): " PORT_CHOICE + + case $PORT_CHOICE in + 1) + # 终止占用进程 + if [ ! -z "$PID_FE" ]; then + echo "🔨 终止前端端口 $FRONTEND_PORT 的进程 (PID: $PID_FE)..." + kill -9 $PID_FE 2>/dev/null + echo "✅ 前端端口 $FRONTEND_PORT 已释放" + fi + if [ ! -z "$PID_BE" ]; then + echo "🔨 终止后端端口 $BACKEND_PORT 的进程 (PID: $PID_BE)..." + kill -9 $PID_BE 2>/dev/null + echo "✅ 后端端口 $BACKEND_PORT 已释放" + fi + ;; + 2) + # 自动选择新端口并启动 + echo "" + echo "🔍 正在查找可用端口..." + + # 从当前端口开始查找 + PORTS=$(find_available_ports $FRONTEND_PORT) + + if [ -z "$PORTS" ]; then + echo "❌ 未找到可用端口,请尝试手动修改配置" + exit 1 + fi + + # 解析找到的端口 + NEW_FE_PORT=$(echo $PORTS | cut -d' ' -f1) + NEW_BE_PORT=$(echo $PORTS | cut -d' ' -f2) + + echo "✅ 找到可用端口:" + echo " 前端端口: $NEW_FE_PORT" + echo " 后端端口: $NEW_BE_PORT" + echo "" + echo "🔧 正在配置环境变量..." + + # 设置环境变量,这些变量将在启动时被使用 + export FRONTEND_PORT=$NEW_FE_PORT + export BACKEND_PORT=$NEW_BE_PORT + export NEXT_PUBLIC_API_URL="http://localhost:$NEW_BE_PORT" + export CORS_ORIGIN="http://localhost:$NEW_FE_PORT" + export AUTH_BASE_URL="http://localhost:$NEW_BE_PORT/api/auth" + + echo "✅ 环境变量已配置:" + echo " FRONTEND_PORT=$FRONTEND_PORT" + echo " BACKEND_PORT=$BACKEND_PORT" + echo " NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL" + echo " CORS_ORIGIN=$CORS_ORIGIN" + echo " AUTH_BASE_URL=$AUTH_BASE_URL" + echo "" + echo "💡 提示: 这些环境变量仅对本次启动有效,不会修改配置文件" + echo " 前端将在: http://localhost:$NEW_FE_PORT" + echo " 后端将在: http://localhost:$NEW_BE_PORT" + ;; + 3) + # 修改端口 + echo "" + echo "💡 提示: 请修改 .env 文件中的端口配置" + echo " - FRONTEND_PORT: 前端端口 (当前: $FRONTEND_PORT)" + echo " - BACKEND_PORT: 后端端口 (当前: $BACKEND_PORT)" + echo " - NEXT_PUBLIC_API_URL: 前端调用后端的地址" + echo " - CORS_ORIGIN: 后端允许的前端地址" + echo " - AUTH_BASE_URL: 认证基础 URL" + echo "" + echo "📝 示例配置(使用新端口):" + echo " FRONTEND_PORT=8011" + echo " BACKEND_PORT=8012" + echo " NEXT_PUBLIC_API_URL=http://localhost:8012" + echo " CORS_ORIGIN=http://localhost:8011,https://novel.daerai.com" + echo " AUTH_BASE_URL=http://localhost:8012/api/auth" + echo "" + + # 检查是否有 .env 文件 + if [ -f .env ]; then + read -p "是否现在打开 .env 文件进行编辑? (y/n): " EDIT_NOW + if [ "$EDIT_NOW" == "y" ] || [ "$EDIT_NOW" == "Y" ]; then + # 尝试使用用户的默认编辑器 + if [ ! -z "$EDITOR" ]; then + $EDITOR .env + elif command -v nano &> /dev/null; then + nano .env + elif command -v vim &> /dev/null; then + vim .env + elif command -v code &> /dev/null; then + code .env + else + echo "⚠️ 未找到编辑器,请手动编辑 .env 文件" + fi + echo "" + echo "📝 请重新运行 start.sh 以使用新的端口配置" + exit 0 + fi + else + echo "⚠️ 未找到 .env 文件,请先运行脚本创建" + exit 1 + fi + ;; + 4) + # 取消启动 + echo "❌ 已取消启动" + exit 0 + ;; + *) + # 默认选项:取消 + echo "⚠️ 无效选项,已取消启动" + exit 1 + ;; + esac fi # 安装依赖