# ============================================================ # 文传易 一键发布脚本 # 1. dotnet publish 后端 (Release, net8.0) # 2. npm run build 前端 (Vite, dist) # 3. FTP 上传合并产物至 IIS 站点根目录 # # 用法: # powershell -ExecutionPolicy Bypass -File deploy/publish.ps1 # # 前置: 本机已安装 .NET 8 SDK / Node.js >=18; FTP 凭据见下方变量 # ============================================================ param( [string]$FtpHost = "116.198.221.125", [int] $FtpPort = 21, [string]$FtpUser = "wenchuanyi", [string]$FtpPass = "r7P^f*v7rFts", [string]$RemoteRoot = "/", # FTP 远端目标目录 (IIS 站点根目录) [switch]$SkipBuild # 跳过构建, 仅上传已有产物 ) $ErrorActionPreference = "Stop" $Root = Split-Path -Parent $PSScriptRoot $BackendDir = Join-Path $Root "backend\WenChuanyi.Api" $FrontendDir = Join-Path $Root "frontend" $PublishDir = Join-Path $BackendDir "bin\Release\net8.0\publish" $DistDir = Join-Path $FrontendDir "dist" $StagingDir = Join-Path $env:TEMP "wcy_publish_staging" # ---------------- 1. 构建 ---------------- if (-not $SkipBuild) { Write-Host "==> [1/3] 构建后端..." -ForegroundColor Cyan Push-Location $BackendDir try { dotnet publish -c Release --nologo -v q } finally { Pop-Location } Write-Host "==> [2/3] 构建前端..." -ForegroundColor Cyan if (-not (Test-Path (Join-Path $FrontendDir "node_modules"))) { Write-Host " 首次构建, 安装 npm 依赖..." -ForegroundColor Yellow Push-Location $FrontendDir try { npm install --no-audit --no-fund } finally { Pop-Location } } Push-Location $FrontendDir try { npm run build } finally { Pop-Location } } else { Write-Host "==> [1-2/3] 跳过构建 (SkipBuild)..." -ForegroundColor Yellow } if (-not (Test-Path $PublishDir)) { throw "后端发布目录不存在: $PublishDir (请先 dotnet publish)" } if (-not (Test-Path $DistDir)) { throw "前端产物目录不存在: $DistDir (请先 npm run build)" } # ---------------- 2. 合并产物到临时目录 ---------------- Write-Host "==> [3/3] 合并产物并 FTP 上传..." -ForegroundColor Cyan if (Test-Path $StagingDir) { Remove-Item $StagingDir -Recurse -Force } New-Item -ItemType Directory -Path $StagingDir -Force | Out-Null Copy-Item "$DistDir\*" $StagingDir -Recurse -Force Copy-Item "$PublishDir\*" $StagingDir -Recurse -Force Write-Host " 产物合计: $((Get-ChildItem $StagingDir -File -Recurse | Measure-Object).Count) 个文件" -ForegroundColor Gray # ---------------- FTP 工具函数 ---------------- function New-FtpRequest([string]$path, [string]$method) { $uri = "ftp://${FtpHost}:${FtpPort}/" + $path.TrimStart('/') $req = [System.Net.FtpWebRequest]::Create($uri) $req.Method = $method $req.Credentials = New-Object System.Net.NetworkCredential($FtpUser, $FtpPass) $req.UsePassive = $true $req.UseBinary = $true $req.KeepAlive = $false return $req } function New-FtpDirectory([string]$remotePath) { $req = New-FtpRequest $remotePath ([System.Net.WebRequestMethods+Ftp]::MakeDirectory) try { $null = $req.GetResponse() } catch { } # 目录已存在时报错, 忽略 } function Send-FtpFile([string]$localPath, [string]$remotePath) { $req = New-FtpRequest $remotePath ([System.Net.WebRequestMethods+Ftp]::UploadFile) $bytes = [System.IO.File]::ReadAllBytes($localPath) $req.ContentLength = $bytes.Length $stream = $req.GetRequestStream() try { $stream.Write($bytes, 0, $bytes.Length) } finally { $stream.Close() } $resp = $req.GetResponse() try { $resp.Close() } catch { } } function Send-FtpDirectory([string]$localDir, [string]$remoteDir) { foreach ($dir in Get-ChildItem $localDir -Directory) { $child = "$remoteDir/$($dir.Name)" New-FtpDirectory $child Send-FtpDirectory $dir.FullName $child } foreach ($file in Get-ChildItem $localDir -File) { $remoteFile = "$remoteDir/$($file.Name)" Send-FtpFile $file.FullName $remoteFile Write-Host " UP $remoteFile" -ForegroundColor Gray } } # ---------------- 上传 ---------------- New-FtpDirectory $RemoteRoot Send-FtpDirectory $StagingDir $RemoteRoot Remove-Item $StagingDir -Recurse -Force Write-Host "" Write-Host "============================================================" -ForegroundColor Green Write-Host " 发布完成! 请手动回收 IIS 应用程序池使新版本生效:" -ForegroundColor Green Write-Host " IIS 管理器 -> 应用程序池 -> wenchuanyi -> 右键回收" -ForegroundColor Green Write-Host " 或: appcmd recycle apppool /apppool.name:wenchuanyi" -ForegroundColor Green Write-Host "============================================================" -ForegroundColor Green