# EPEEKit 内网穿透启动脚本 # 使用 Cloudflare Quick Tunnel(无需账号,免费) # 用法:在 PowerShell 中执行 .\start-tunnel.ps1 param( [int]$BackendPort = 8000, [int]$FrontendPort = 3000 ) $ErrorActionPreference = "Stop" # 检查 cloudflared 是否可用 try { $null = Get-Command cloudflared -ErrorAction Stop } catch { Write-Host "[错误] 未找到 cloudflared,请先安装:winget install Cloudflare.cloudflared" -ForegroundColor Red exit 1 } Write-Host "" Write-Host " ╔═══════════════════════════════════════════╗" -ForegroundColor Cyan Write-Host " ║ EPEEKit 内网穿透 ║" -ForegroundColor Cyan Write-Host " ╚═══════════════════════════════════════════╝" -ForegroundColor Cyan Write-Host "" # 启动后端穿透 Write-Host "[1/2] 启动后端穿透隧道 (localhost:$BackendPort)..." -ForegroundColor Yellow $backendTunnel = Start-Process cloudflared -ArgumentList "tunnel", "--url", "http://localhost:$BackendPort" ` -PassThru -RedirectStandardError "$env:TEMP\epeekit-tunnel-backend.log" -WindowStyle Hidden Start-Sleep -Seconds 3 # 从日志中提取后端公网 URL $backendUrl = "" for ($i = 0; $i -lt 10; $i++) { if (Test-Path "$env:TEMP\epeekit-tunnel-backend.log") { $logContent = Get-Content "$env:TEMP\epeekit-tunnel-backend.log" -Raw -ErrorAction SilentlyContinue if ($logContent -match '(https://[a-z0-9-]+\.trycloudflare\.com)') { $backendUrl = $Matches[1] break } } Start-Sleep -Seconds 2 } if (-not $backendUrl) { Write-Host "[错误] 无法获取后端穿透地址,请检查 cloudflared 日志" -ForegroundColor Red Write-Host " 日志路径: $env:TEMP\epeekit-tunnel-backend.log" Stop-Process -Id $backendTunnel.Id -Force -ErrorAction SilentlyContinue exit 1 } Write-Host " 后端穿透地址: $backendUrl" -ForegroundColor Green # 更新前端环境变量 $envFile = Join-Path $PSScriptRoot "frontend\.env.local" @" # 后端 API 地址(由 start-tunnel.ps1 自动更新) NEXT_PUBLIC_API_URL=$backendUrl "@ | Set-Content $envFile -Encoding UTF8 Write-Host " 已更新 frontend\.env.local" -ForegroundColor Green Write-Host "" # 启动前端穿透 Write-Host "[2/2] 启动前端穿透隧道 (localhost:$FrontendPort)..." -ForegroundColor Yellow $frontendTunnel = Start-Process cloudflared -ArgumentList "tunnel", "--url", "http://localhost:$FrontendPort" ` -PassThru -RedirectStandardError "$env:TEMP\epeekit-tunnel-frontend.log" -WindowStyle Hidden Start-Sleep -Seconds 3 $frontendUrl = "" for ($i = 0; $i -lt 10; $i++) { if (Test-Path "$env:TEMP\epeekit-tunnel-frontend.log") { $logContent = Get-Content "$env:TEMP\epeekit-tunnel-frontend.log" -Raw -ErrorAction SilentlyContinue if ($logContent -match '(https://[a-z0-9-]+\.trycloudflare\.com)') { $frontendUrl = $Matches[1] break } } Start-Sleep -Seconds 2 } if (-not $frontendUrl) { Write-Host "[错误] 无法获取前端穿透地址" -ForegroundColor Red Stop-Process -Id $backendTunnel.Id -Force -ErrorAction SilentlyContinue Stop-Process -Id $frontendTunnel.Id -Force -ErrorAction SilentlyContinue exit 1 } Write-Host " 前端穿透地址: $frontendUrl" -ForegroundColor Green Write-Host "" Write-Host " ╔═══════════════════════════════════════════╗" -ForegroundColor Green Write-Host " ║ 穿透隧道已就绪! ║" -ForegroundColor Green Write-Host " ╚═══════════════════════════════════════════╝" -ForegroundColor Green Write-Host "" Write-Host " 手机浏览器访问: $frontendUrl" -ForegroundColor Cyan Write-Host " 后端 API: $backendUrl" -ForegroundColor Cyan Write-Host "" Write-Host " [重要] 前端需要重启才能读取新的 .env.local" -ForegroundColor Yellow Write-Host " [提示] 按 Ctrl+C 或关闭此窗口停止穿透" -ForegroundColor DarkGray Write-Host "" # 等待用户中断 try { Write-Host "隧道运行中... (按 Ctrl+C 停止)" -ForegroundColor DarkGray while ($true) { Start-Sleep -Seconds 5 # 检查进程是否还活着 if ($backendTunnel.HasExited) { Write-Host "[警告] 后端隧道已断开" -ForegroundColor Red break } if ($frontendTunnel.HasExited) { Write-Host "[警告] 前端隧道已断开" -ForegroundColor Red break } } } finally { Write-Host "" Write-Host "正在关闭隧道..." -ForegroundColor Yellow Stop-Process -Id $backendTunnel.Id -Force -ErrorAction SilentlyContinue Stop-Process -Id $frontendTunnel.Id -Force -ErrorAction SilentlyContinue # 恢复 .env.local 为 localhost @" # 后端 API 地址 NEXT_PUBLIC_API_URL=http://localhost:8000 "@ | Set-Content $envFile -Encoding UTF8 Write-Host "已恢复 .env.local 为 localhost" -ForegroundColor Green Write-Host "隧道已关闭" -ForegroundColor Green }