You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

495 lines
15 KiB
PowerShell

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#Requires -Version 5.1
<#
.SYNOPSIS
浩景CNC机床数据采集分析系统 - 一键部署脚本
.DESCRIPTION
本脚本用于在 Windows 系统上自动化构建和部署浩景CNC系统。
功能:
1. 检测环境 (.NET SDK, Node.js)
2. 构建后端 API (独立部署模式)
3. 构建前端 Admin 和 Dashboard
4. 生成生产配置文件
5. 创建 IIS 所需目录结构
.NOTES
作者: 浩景智能科技
版本: 1.0.0
日期: 2026-04-13
.EXAMPLE
.\deploy.ps1
#>
param(
[switch]$SkipBuild, # 跳过构建,直接发布
[switch]$SkipFrontend, # 跳过前端构建
[string]$PublishDir = "publish\wwwroot" # 发布目录
)
# ============================================================
# 配置
# ============================================================
$ErrorActionPreference = "Stop"
$ProjectRoot = $PSScriptRoot
# 后端项目
$ApiProject = Join-Path $ProjectRoot "Haoliang.Api\Haoliang.Api.csproj"
# 前端项目
$AdminProject = Join-Path $ProjectRoot "src\frontend\admin"
$DashboardProject = Join-Path $ProjectRoot "src\frontend\dashboard"
# 部署配置扁平化目录API在根目录admin和dashboard为子目录
$ApiDir = $PublishDir
$AdminDir = Join-Path $PublishDir "admin"
$DashboardDir = Join-Path $PublishDir "dashboard"
# .NET 独立部署配置
$Runtime = "win-x64"
$SelfContained = $true
# ============================================================
# 颜色输出函数
# ============================================================
function Write-Step { param([string]$Message) Write-Host "[步骤] $Message" -ForegroundColor Cyan }
function Write-Success { param([string]$Message) Write-Host "[成功] $Message" -ForegroundColor Green }
function Write-Warning { param([string]$Message) Write-Host "[警告] $Message" -ForegroundColor Yellow }
function Write-Error { param([string]$Message) Write-Host "[错误] $Message" -ForegroundColor Red }
function Write-Info { param([string]$Message) Write-Host "[信息] $Message" -ForegroundColor Gray }
# ============================================================
# 检测环境
# ============================================================
function Test-Environment {
Write-Step "检测构建环境..."
# 检测 .NET SDK
$dotnetVersion = dotnet --version 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Error "未检测到 .NET SDK请先安装 .NET 8.0 SDK"
Write-Info "下载链接: https://dotnet.microsoft.com/download/dotnet/8.0"
exit 1
}
Write-Info "检测到 .NET SDK 版本: $dotnetVersion"
# 检测 Node.js
$nodeVersion = node --version 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Error "未检测到 Node.js请先安装 Node.js"
Write-Info "下载链接: https://nodejs.org/"
exit 1
}
Write-Info "检测到 Node.js 版本: $nodeVersion"
# 检测 npm
$npmVersion = npm --version 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Error "未检测到 npm"
exit 1
}
Write-Info "检测到 npm 版本: $npmVersion"
Write-Success "环境检测通过"
}
# ============================================================
# 还原 NuGet 包
# ============================================================
function Restore-DotNetPackages {
Write-Step "还原 NuGet 包..."
dotnet restore $ProjectRoot\Haoliang.sln
if ($LASTEXITCODE -ne 0) {
Write-Error "NuGet 包还原失败"
exit 1
}
Write-Success "NuGet 包还原完成"
}
# ============================================================
# 构建后端 API
# ============================================================
function Build-Api {
Write-Step "构建后端 API (独立部署模式 - $Runtime)..."
# 确保发布目录干净
if (Test-Path $ApiDir) {
Remove-Item $ApiDir -Recurse -Force
}
# 独立部署发布
dotnet publish $ApiProject `
-c Release `
-r $Runtime `
--self-contained $SelfContained `
-o $ApiDir
if ($LASTEXITCODE -ne 0) {
Write-Error "后端 API 构建失败"
exit 1
}
Write-Success "后端 API 构建完成"
Write-Info "输出目录: $ApiDir"
}
# ============================================================
# 安装前端依赖
# ============================================================
function Install-FrontendDependencies {
Write-Step "安装前端依赖..."
# Admin 依赖
Write-Info "安装 Admin 依赖..."
Push-Location $AdminProject
npm install
if ($LASTEXITCODE -ne 0) {
Pop-Location
Write-Error "Admin 依赖安装失败"
exit 1
}
Pop-Location
# Dashboard 依赖
Write-Info "安装 Dashboard 依赖..."
Push-Location $DashboardProject
npm install
if ($LASTEXITCODE -ne 0) {
Pop-Location
Write-Error "Dashboard 依赖安装失败"
exit 1
}
Pop-Location
Write-Success "前端依赖安装完成"
}
# ============================================================
# 构建前端
# ============================================================
function Build-Frontend {
Write-Step "构建前端 Admin..."
Push-Location $AdminProject
npm run build
if ($LASTEXITCODE -ne 0) {
Pop-Location
Write-Error "Admin 构建失败"
exit 1
}
Pop-Location
Write-Success "Admin 构建完成"
Write-Step "构建前端 Dashboard..."
Push-Location $DashboardProject
npm run build
if ($LASTEXITCODE -ne 0) {
Pop-Location
Write-Error "Dashboard 构建失败"
exit 1
}
Pop-Location
Write-Success "Dashboard 构建完成"
}
# ============================================================
# 复制前端文件
# ============================================================
function Copy-FrontendFiles {
Write-Step "复制前端文件到部署目录..."
# 复制 Admin
if (Test-Path (Join-Path $AdminProject "dist")) {
Copy-Item (Join-Path $AdminProject "dist\*") $AdminDir -Recurse -Force
Write-Info "Admin 已复制到: $AdminDir"
} else {
Write-Warning "Admin dist 目录不存在"
}
# 复制 Dashboard
if (Test-Path (Join-Path $DashboardProject "dist")) {
Copy-Item (Join-Path $DashboardProject "dist\*") $DashboardDir -Recurse -Force
Write-Info "Dashboard 已复制到: $DashboardDir"
} else {
Write-Warning "Dashboard dist 目录不存在"
}
Write-Success "前端文件复制完成"
}
# ============================================================
# 创建目录结构
# ============================================================
function New-DeploymentDirectories {
Write-Step "创建部署目录结构..."
# 创建日志和数据目录
$logsDir = Join-Path $ApiDir "logs"
$dataDir = Join-Path $ApiDir "data"
New-Item -ItemType Directory -Path $logsDir -Force | Out-Null
New-Item -ItemType Directory -Path $dataDir -Force | Out-Null
New-Item -ItemType Directory -Path $AdminDir -Force | Out-Null
New-Item -ItemType Directory -Path $DashboardDir -Force | Out-Null
Write-Info "日志目录: $logsDir"
Write-Info "数据目录: $dataDir"
Write-Success "目录结构创建完成"
}
# ============================================================
# 创建生产配置文件
# ============================================================
function New-ProductionConfig {
Write-Step "创建生产配置文件..."
$productionConfig = Join-Path $ApiDir "appsettings.Production.json"
$configContent = @"
{
"ConnectionStrings": {
"CNCBusinessDB": "Server=localhost;Database=cnc_business;User=haoliang;Password=YourStrongPassword123!;CharSet=utf8mb4;",
"CNCLLogDB": "Server=localhost;Database=cnc_log;User=haoliang;Password=YourStrongPassword123!;CharSet=utf8mb4;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore": "Warning"
}
},
"AppSettings": {
"ApiVersion": "v1",
"EnableSwagger": false,
"EnableCors": true,
"AllowedOrigins": [
"http://localhost:5000",
"http://localhost:8080",
"http://localhost:8081"
],
"DefaultCacheDuration": 300,
"MaxConcurrentCollections": 100
},
"CollectionSettings": {
"DefaultInterval": 30,
"MaxRetryCount": 3,
"RetryInterval": 30,
"PingTimeout": 5000,
"CollectionTimeout": 10000
}
}
"@
Set-Content -Path $productionConfig -Value $configContent -Encoding UTF8
Write-Info "配置文件: $productionConfig"
Write-Success "生产配置文件创建完成"
Write-Warning "请修改 appsettings.Production.json 中的数据库连接信息!"
}
# ============================================================
# 创建/更新 web.config
# ============================================================
function Update-WebConfig {
Write-Step "创建 IIS web.config..."
$webConfig = Join-Path $ApiDir "web.config"
$webConfigContent = @"
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*"
modules="AspNetCoreModuleV2"
resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\Haoliang.Api.exe"
arguments=".\Haoliang.Api.dll"
stdoutLogEnabled="true"
stdoutLogFile=".\logs\\stdout"
hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT"
value="Production" />
<environmentVariable name="ASPNETCORE_DETAILED_ERRORS"
value="false" />
</environmentVariables>
</aspNetCore>
<httpErrors existingResponse="PassThrough" />
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebSockets" />
<add name="WebSockets" module="WebSocketsModule" />
</modules>
</system.webServer>
</location>
</configuration>
"@
Set-Content -Path $webConfig -Value $webConfigContent -Encoding UTF8
Write-Info "web.config: $webConfig"
Write-Success "web.config 创建完成"
}
# ============================================================
# 创建 IIS 部署说明
# ============================================================
function New-DeployReadme {
Write-Step "创建部署说明文件..."
$readmeContent = @"
# CNC - IIS
##
### 1.
`api\appsettings.Production.json`
\`\`\`json
{
"ConnectionStrings": {
"CNCBusinessDB": "Server=;Database=cnc_business;User=;Password=;",
"CNCLLogDB": "Server=;Database=cnc_log;User=;Password=;"
}
}
\`\`\`
### 2.
```powershell
# MariaDB
mysql -u root -p
#
CREATE DATABASE cnc_business CHARACTER SET utf8mb4;
CREATE DATABASE cnc_log CHARACTER SET utf8mb4;
CREATE USER 'haoliang'@'localhost' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON cnc_business.* TO 'haoliang'@'localhost';
GRANT ALL PRIVILEGES ON cnc_log.* TO 'haoliang'@'localhost';
#
mysql -u haoliang -p cnc_business < cnc_business.sql
mysql -u haoliang -p cnc_log < cnc_log_fixed.sql
```
### 3. IIS
1. IIS
2. `HaoliangApi`
- .NET CLR : ****
- : ****
3. `Haoliang`
- : `D:\wwwroot\haoliang`
- : 5000
- admin dashboard
### 4.
```powershell
#
New-NetFirewallRule -DisplayName "Haoliang API" -Direction Inbound -Protocol TCP -LocalPort 5000 -Action Allow
```
## 访
| | |
|------|------|
| API | http://localhost:5000 |
| Admin | http://localhost:5000/admin |
| Dashboard | http://localhost:5000/dashboard |
| Swagger | http://localhost:5000/swagger |
##
\`\`\`
wwwroot/ # IIS
Haoliang.Api.exe #
Haoliang.Api.dll
appsettings.json #
appsettings.Production.json #
web.config # IIS
logs/ #
data/ #
admin/ #
index.html
assets/
dashboard/ # BI
index.html
assets/
\`\`\`
##
: `logs\stdout_*.log`
"@
$readmePath = Join-Path $PublishDir "部署说明.md"
Set-Content -Path $readmePath -Value $readmeContent -Encoding UTF8
Write-Info "部署说明: $readmePath"
Write-Success "部署说明创建完成"
}
# ============================================================
# 主函数
# ============================================================
function Start-Deploy {
Write-Host ""
Write-Host "============================================" -ForegroundColor Magenta
Write-Host " 浩景CNC机床数据采集分析系统 - 部署脚本" -ForegroundColor Magenta
Write-Host "============================================" -ForegroundColor Magenta
Write-Host ""
# 检测环境
Test-Environment
# 还原包
Restore-DotNetPackages
# 构建后端
if (-not $SkipBuild) {
Build-Api
} else {
Write-Warning "跳过后端构建"
}
# 构建前端
if (-not $SkipFrontend) {
Install-FrontendDependencies
Build-Frontend
} else {
Write-Warning "跳过前端构建"
}
# 创建目录结构
New-DeploymentDirectories
# 复制前端文件
Copy-FrontendFiles
# 创建配置文件
New-ProductionConfig
# 创建/更新 web.config
Update-WebConfig
# 创建部署说明
New-DeployReadme
Write-Host ""
Write-Host "============================================" -ForegroundColor Green
Write-Host " 部署构建完成!" -ForegroundColor Green
Write-Host "============================================" -ForegroundColor Green
Write-Host ""
Write-Host "输出目录: $PSScriptRoot\$PublishDir" -ForegroundColor Cyan
Write-Host ""
Write-Host "下一步操作:" -ForegroundColor Yellow
Write-Host "1. 修改 api\appsettings.Production.json 中的数据库连接" -ForegroundColor White
Write-Host "2. 将 $PublishDir 目录下的所有文件复制到 IIS 网站目录" -ForegroundColor White
Write-Host "3. 在 IIS 中配置网站和应用程序" -ForegroundColor White
Write-Host ""
}
# 运行部署
Start-Deploy