fix: 修复托盘菜单语法错误与激活页缺失,完善 Windows 打包流程
- electron/main.cjs: 修复托盘菜单损坏的合并代码(SyntaxError),托盘 3D 意识空间与 ipc 路由改用正确的 backendPort 变量 - 新增 activation.html 激活页(对接 /activate 接口,支持自动识别/8 个服务商) - scripts/package-win.ps1: 打包前切换 better-sqlite3 到 Electron ABI、打包后还原 Node ABI,避免 dev 后端崩溃;内置 npmmirror 工具链镜像 - scripts/gen-icons.ps1 + build/icon.ico: 生成安装包图标(electron-builder 必需) - package.json: build 脚本改用 package-win.ps1(不再依赖 VS 工具链) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
85
scripts/gen-icons.ps1
Normal file
85
scripts/gen-icons.ps1
Normal file
@@ -0,0 +1,85 @@
|
||||
# gen-icons.ps1 — Generate build/icon.ico from an existing logo PNG.
|
||||
# Produces a multi-size PNG-compressed ICO (16/24/32/48/64/128/256), usable by
|
||||
# electron-builder (win.icon / installerHeaderIcon) and NSIS on Win10+.
|
||||
param(
|
||||
[string]$Source = "images/bailongma-logo.png",
|
||||
[string]$OutDir = "build"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
$srcPath = Join-Path (Split-Path $PSScriptRoot) $Source
|
||||
$outPath = Join-Path (Split-Path $PSScriptRoot) "$OutDir\icon.ico"
|
||||
|
||||
if (-not (Test-Path $srcPath)) { Write-Error "Source image not found: $srcPath" }
|
||||
|
||||
$src = [System.Drawing.Image]::FromFile((Resolve-Path $srcPath))
|
||||
try {
|
||||
# Square crop to the shorter side so the icon is not distorted.
|
||||
$side = [Math]::Min($src.Width, $src.Height)
|
||||
$cropX = [int](($src.Width - $side) / 2)
|
||||
$cropY = [int](($src.Height - $side) / 2)
|
||||
$square = New-Object System.Drawing.Bitmap($side, $side)
|
||||
$g0 = [System.Drawing.Graphics]::FromImage($square)
|
||||
try {
|
||||
$g0.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
|
||||
$g0.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
|
||||
$g0.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
|
||||
$g0.DrawImage($src, (New-Object System.Drawing.Rectangle(0, 0, $side, $side)),
|
||||
(New-Object System.Drawing.Rectangle($cropX, $cropY, $side, $side)),
|
||||
[System.Drawing.GraphicsUnit]::Pixel)
|
||||
} finally { $g0.Dispose() }
|
||||
|
||||
$sizes = @(16, 24, 32, 48, 64, 128, 256)
|
||||
$pngBlobs = @()
|
||||
foreach ($s in $sizes) {
|
||||
$bmp = New-Object System.Drawing.Bitmap($s, $s, [System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
|
||||
$g = [System.Drawing.Graphics]::FromImage($bmp)
|
||||
try {
|
||||
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
|
||||
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
|
||||
$g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
|
||||
$g.Clear([System.Drawing.Color]::Transparent)
|
||||
$g.DrawImage($square, 0, 0, $s, $s)
|
||||
} finally { $g.Dispose() }
|
||||
|
||||
$ms = New-Object System.IO.MemoryStream
|
||||
$bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
|
||||
$pngBlobs += , $ms.ToArray()
|
||||
$ms.Dispose()
|
||||
$bmp.Dispose()
|
||||
}
|
||||
$square.Dispose()
|
||||
|
||||
# Assemble ICO: ICONDIR + ICONDIRENTRY per image + PNG blobs.
|
||||
$fs = [System.IO.File]::Create($outPath)
|
||||
$w = New-Object System.IO.BinaryWriter($fs)
|
||||
try {
|
||||
$w.Write([UInt16]0) # reserved
|
||||
$w.Write([UInt16]1) # type: icon
|
||||
$w.Write([UInt16]$pngBlobs.Count) # image count
|
||||
$offset = 6 + 16 * $pngBlobs.Count
|
||||
foreach ($i in 0..($pngBlobs.Count - 1)) {
|
||||
$blob = $pngBlobs[$i]
|
||||
$size = $sizes[$i]
|
||||
$w.Write([Byte]($(if ($size -ge 256) { 0 } else { $size }))) # width (0 = 256)
|
||||
$w.Write([Byte]($(if ($size -ge 256) { 0 } else { $size }))) # height (0 = 256)
|
||||
$w.Write([Byte]0) # color count
|
||||
$w.Write([Byte]0) # reserved
|
||||
$w.Write([UInt16]1) # planes
|
||||
$w.Write([UInt16]32) # bit count
|
||||
$w.Write([UInt32]$blob.Length) # bytes in resource
|
||||
$w.Write([UInt32]$offset) # image offset
|
||||
$offset += $blob.Length
|
||||
}
|
||||
foreach ($blob in $pngBlobs) { $w.Write($blob) }
|
||||
$w.Flush()
|
||||
} finally {
|
||||
$w.Dispose()
|
||||
$fs.Dispose()
|
||||
}
|
||||
Write-Host "[gen-icons] wrote $outPath ($((Get-Item $outPath).Length) bytes, $($pngBlobs.Count) sizes)"
|
||||
} finally {
|
||||
$src.Dispose()
|
||||
}
|
||||
56
scripts/package-win.ps1
Normal file
56
scripts/package-win.ps1
Normal file
@@ -0,0 +1,56 @@
|
||||
# package-win.ps1 — Build the Windows NSIS installer.
|
||||
#
|
||||
# better-sqlite3 is a native module and its binary must match the runtime ABI:
|
||||
# - packaged app / `npm start` → Electron ABI (v130 for Electron 33)
|
||||
# - `npm run start:backend` → Node ABI
|
||||
# This script swaps the prebuilt binary to Electron ABI before packaging and
|
||||
# restores the Node ABI afterwards, so dev backend mode keeps working.
|
||||
#
|
||||
# No compiler needed: prebuild-install downloads prebuilt binaries (uses the
|
||||
# npm prebuild cache when GitHub is unreachable).
|
||||
#
|
||||
# Usage: powershell -ExecutionPolicy Bypass -File scripts/package-win.ps1
|
||||
|
||||
param([string]$ElectronVersion = "33.4.11")
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$root = Split-Path $PSScriptRoot
|
||||
Set-Location $root
|
||||
|
||||
function Invoke-PrebuildInstall {
|
||||
param([string]$Runtime, [string]$Target)
|
||||
Push-Location "node_modules\better-sqlite3"
|
||||
try {
|
||||
if ($Runtime -eq "electron") {
|
||||
npx prebuild-install --runtime=electron --target=$Target
|
||||
} else {
|
||||
npx prebuild-install
|
||||
}
|
||||
if ($LASTEXITCODE -ne 0) { throw "prebuild-install ($Runtime) failed with exit code $LASTEXITCODE" }
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
|
||||
# 1) Swap better-sqlite3 to the Electron-ABI prebuilt binary.
|
||||
Invoke-PrebuildInstall -Runtime electron -Target $ElectronVersion
|
||||
|
||||
try {
|
||||
# 2) Package. Point electron-builder at the local electron dist to skip the
|
||||
# GitHub download, and mirror NSIS/winCodeSign through npmmirror (GitHub
|
||||
# is unreachable on CN networks).
|
||||
$env:ELECTRON_BUILDER_BINARIES_MIRROR = "https://cdn.npmmirror.com/binaries/electron-builder-binaries/"
|
||||
$dist = Join-Path $root "node_modules\electron\dist"
|
||||
npx electron-builder --win "-c.electronDist=$dist"
|
||||
if ($LASTEXITCODE -ne 0) { throw "electron-builder failed with exit code $LASTEXITCODE" }
|
||||
Write-Host "[package] NSIS installer built:" -ForegroundColor Green
|
||||
Get-ChildItem "$root\dist\*.exe" | ForEach-Object { Write-Host " $_" -ForegroundColor Green }
|
||||
} finally {
|
||||
# 3) Restore the Node-ABI binary so `npm run start:backend` / `npm run dev` keep working.
|
||||
try {
|
||||
Invoke-PrebuildInstall -Runtime node
|
||||
Write-Host "[package] better-sqlite3 restored to Node ABI" -ForegroundColor Cyan
|
||||
} catch {
|
||||
Write-Host "[package] WARN: failed to restore Node prebuild: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user