feat: 修复Mac打包编译

This commit is contained in:
duanshuwen
2026-04-11 17:22:29 +08:00
parent b1ca06bb07
commit 37ed157e4a
10 changed files with 191 additions and 1780 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1,99 +1 @@
"use strict"; "use strict";const n=require("electron");var i=(e=>(e.EXTERNAL_OPEN="external-open",e.WINDOW_MINIMIZE="window-minimize",e.WINDOW_MAXIMIZE="window-maximize",e.WINDOW_CLOSE="window-close",e.IS_WINDOW_MAXIMIZED="is-window-maximized",e.APP_SET_FRAMELESS="app:set-frameless",e.APP_LOAD_PAGE="app:load-page",e.TAB_CREATE="tab:create",e.TAB_LIST="tab:list",e.TAB_NAVIGATE="tab:navigate",e.TAB_RELOAD="tab:reload",e.TAB_BACK="tab:back",e.TAB_FORWARD="tab:forward",e.TAB_SWITCH="tab:switch",e.TAB_CLOSE="tab:close",e.LOG_TO_MAIN="log-to-main",e.READ_FILE="read-file",e.INVOKE="ipc:invoke",e.INVOKE_ASYNC="ipc:invokeAsync",e.APP_MINIMIZE="app:minimize",e.APP_MAXIMIZE="app:maximize",e.APP_QUIT="app:quit",e.FILE_READ="file:read",e.FILE_WRITE="file:write",e.GET_WINDOW_ID="get-window-id",e.CUSTOM_EVENT="custom:event",e.TIME_UPDATE="time:update",e.RENDERER_IS_READY="renderer-ready",e.SHOW_CONTEXT_MENU="show-context-menu",e.START_A_DIALOGUE="start-a-dialogue",e.OPEN_WINDOW="open-window",e.LOG_DEBUG="log-debug",e.LOG_INFO="log-info",e.LOG_WARN="log-warn",e.LOG_ERROR="log-error",e.CONFIG_UPDATED="config-updated",e.SET_CONFIG="set-config",e.GET_CONFIG="get-config",e.UPDATE_CONFIG="update-config",e.SET_THEME_MODE="set-theme-mode",e.GET_THEME_MODE="get-theme-mode",e.IS_DARK_THEME="is-dark-theme",e.THEME_MODE_UPDATED="theme-mode-updated",e.EXECUTE_SCRIPT="execute-script",e.OPEN_CHANNEL="open-channel",e.UPDATE_CHECK="update:check",e.UPDATE_DOWNLOAD="update:download",e.UPDATE_INSTALL="update:install",e.UPDATE_VERSION="update:version",e.UPDATE_STATUS_CHANGED="update:status-changed",e))(i||{});const a={versions:process.versions,external:{open:e=>n.ipcRenderer.invoke("external-open",e)},closeWindow:()=>n.ipcRenderer.send(i.WINDOW_CLOSE),minimizeWindow:()=>n.ipcRenderer.send(i.WINDOW_MINIMIZE),maximizeWindow:()=>n.ipcRenderer.send(i.WINDOW_MAXIMIZE),onWindowMaximized:e=>n.ipcRenderer.on(i.WINDOW_MAXIMIZE+"back",(r,d)=>e(d)),isWindowMaximized:()=>n.ipcRenderer.invoke(i.IS_WINDOW_MAXIMIZED),viewIsReady:()=>n.ipcRenderer.send(i.RENDERER_IS_READY),app:{setFrameless:e=>n.ipcRenderer.invoke(i.APP_SET_FRAMELESS,e),loadPage:e=>n.ipcRenderer.invoke(i.APP_LOAD_PAGE,e)},readFile:e=>n.ipcRenderer.invoke(i.READ_FILE,e),invoke:(e,...r)=>n.ipcRenderer.invoke(e,...r),invokeAsync:(e,...r)=>n.ipcRenderer.invoke(e,...r),on:(e,r)=>{const d=(t,...o)=>r(...o);return n.ipcRenderer.on(e,d),()=>n.ipcRenderer.removeListener(e,d)},send:(e,...r)=>n.ipcRenderer.send(e,...r),getCurrentWindowId:()=>n.ipcRenderer.sendSync(i.GET_WINDOW_ID),logger:{debug:(e,...r)=>n.ipcRenderer.send(i.LOG_DEBUG,e,...r),info:(e,...r)=>n.ipcRenderer.send(i.LOG_INFO,e,...r),warn:(e,...r)=>n.ipcRenderer.send(i.LOG_WARN,e,...r),error:(e,...r)=>n.ipcRenderer.send(i.LOG_ERROR,e,...r)},executeScript:e=>n.ipcRenderer.invoke(i.EXECUTE_SCRIPT,e),openChannel:e=>n.ipcRenderer.invoke(i.OPEN_CHANNEL,e)};n.contextBridge.exposeInMainWorld("api",a);
const electron = require("electron");
var IPC_EVENTS = /* @__PURE__ */ ((IPC_EVENTS2) => {
IPC_EVENTS2["EXTERNAL_OPEN"] = "external-open";
IPC_EVENTS2["WINDOW_MINIMIZE"] = "window-minimize";
IPC_EVENTS2["WINDOW_MAXIMIZE"] = "window-maximize";
IPC_EVENTS2["WINDOW_CLOSE"] = "window-close";
IPC_EVENTS2["IS_WINDOW_MAXIMIZED"] = "is-window-maximized";
IPC_EVENTS2["APP_SET_FRAMELESS"] = "app:set-frameless";
IPC_EVENTS2["APP_LOAD_PAGE"] = "app:load-page";
IPC_EVENTS2["TAB_CREATE"] = "tab:create";
IPC_EVENTS2["TAB_LIST"] = "tab:list";
IPC_EVENTS2["TAB_NAVIGATE"] = "tab:navigate";
IPC_EVENTS2["TAB_RELOAD"] = "tab:reload";
IPC_EVENTS2["TAB_BACK"] = "tab:back";
IPC_EVENTS2["TAB_FORWARD"] = "tab:forward";
IPC_EVENTS2["TAB_SWITCH"] = "tab:switch";
IPC_EVENTS2["TAB_CLOSE"] = "tab:close";
IPC_EVENTS2["LOG_TO_MAIN"] = "log-to-main";
IPC_EVENTS2["READ_FILE"] = "read-file";
IPC_EVENTS2["INVOKE"] = "ipc:invoke";
IPC_EVENTS2["INVOKE_ASYNC"] = "ipc:invokeAsync";
IPC_EVENTS2["APP_MINIMIZE"] = "app:minimize";
IPC_EVENTS2["APP_MAXIMIZE"] = "app:maximize";
IPC_EVENTS2["APP_QUIT"] = "app:quit";
IPC_EVENTS2["FILE_READ"] = "file:read";
IPC_EVENTS2["FILE_WRITE"] = "file:write";
IPC_EVENTS2["GET_WINDOW_ID"] = "get-window-id";
IPC_EVENTS2["CUSTOM_EVENT"] = "custom:event";
IPC_EVENTS2["TIME_UPDATE"] = "time:update";
IPC_EVENTS2["RENDERER_IS_READY"] = "renderer-ready";
IPC_EVENTS2["SHOW_CONTEXT_MENU"] = "show-context-menu";
IPC_EVENTS2["START_A_DIALOGUE"] = "start-a-dialogue";
IPC_EVENTS2["OPEN_WINDOW"] = "open-window";
IPC_EVENTS2["LOG_DEBUG"] = "log-debug";
IPC_EVENTS2["LOG_INFO"] = "log-info";
IPC_EVENTS2["LOG_WARN"] = "log-warn";
IPC_EVENTS2["LOG_ERROR"] = "log-error";
IPC_EVENTS2["CONFIG_UPDATED"] = "config-updated";
IPC_EVENTS2["SET_CONFIG"] = "set-config";
IPC_EVENTS2["GET_CONFIG"] = "get-config";
IPC_EVENTS2["UPDATE_CONFIG"] = "update-config";
IPC_EVENTS2["SET_THEME_MODE"] = "set-theme-mode";
IPC_EVENTS2["GET_THEME_MODE"] = "get-theme-mode";
IPC_EVENTS2["IS_DARK_THEME"] = "is-dark-theme";
IPC_EVENTS2["THEME_MODE_UPDATED"] = "theme-mode-updated";
IPC_EVENTS2["EXECUTE_SCRIPT"] = "execute-script";
IPC_EVENTS2["OPEN_CHANNEL"] = "open-channel";
IPC_EVENTS2["UPDATE_CHECK"] = "update:check";
IPC_EVENTS2["UPDATE_DOWNLOAD"] = "update:download";
IPC_EVENTS2["UPDATE_INSTALL"] = "update:install";
IPC_EVENTS2["UPDATE_VERSION"] = "update:version";
IPC_EVENTS2["UPDATE_STATUS_CHANGED"] = "update:status-changed";
return IPC_EVENTS2;
})(IPC_EVENTS || {});
const api = {
versions: process.versions,
external: {
open: (url) => electron.ipcRenderer.invoke("external-open", url)
},
closeWindow: () => electron.ipcRenderer.send(IPC_EVENTS.WINDOW_CLOSE),
minimizeWindow: () => electron.ipcRenderer.send(IPC_EVENTS.WINDOW_MINIMIZE),
maximizeWindow: () => electron.ipcRenderer.send(IPC_EVENTS.WINDOW_MAXIMIZE),
onWindowMaximized: (callback) => electron.ipcRenderer.on(IPC_EVENTS.WINDOW_MAXIMIZE + "back", (_, isMaximized) => callback(isMaximized)),
isWindowMaximized: () => electron.ipcRenderer.invoke(IPC_EVENTS.IS_WINDOW_MAXIMIZED),
viewIsReady: () => electron.ipcRenderer.send(IPC_EVENTS.RENDERER_IS_READY),
app: {
setFrameless: (route) => electron.ipcRenderer.invoke(IPC_EVENTS.APP_SET_FRAMELESS, route),
loadPage: (page) => electron.ipcRenderer.invoke(IPC_EVENTS.APP_LOAD_PAGE, page)
},
// 通过 IPC 调用主进程
readFile: (filePath) => electron.ipcRenderer.invoke(IPC_EVENTS.READ_FILE, filePath),
// 异步调用(映射为 electron 的 invoke)
invoke: (channel, ...args) => electron.ipcRenderer.invoke(channel, ...args),
// 异步调用(为了兼容老代码)
invokeAsync: (channel, ...args) => electron.ipcRenderer.invoke(channel, ...args),
// 监听主进程消息
on: (event, callback) => {
const subscription = (_event, ...args) => callback(...args);
electron.ipcRenderer.on(event, subscription);
return () => electron.ipcRenderer.removeListener(event, subscription);
},
// 发送消息到主进程
send: (channel, ...args) => electron.ipcRenderer.send(channel, ...args),
// 获取窗口ID
getCurrentWindowId: () => electron.ipcRenderer.sendSync(IPC_EVENTS.GET_WINDOW_ID),
// 发送日志
logger: {
debug: (message, ...meta) => electron.ipcRenderer.send(IPC_EVENTS.LOG_DEBUG, message, ...meta),
info: (message, ...meta) => electron.ipcRenderer.send(IPC_EVENTS.LOG_INFO, message, ...meta),
warn: (message, ...meta) => electron.ipcRenderer.send(IPC_EVENTS.LOG_WARN, message, ...meta),
error: (message, ...meta) => electron.ipcRenderer.send(IPC_EVENTS.LOG_ERROR, message, ...meta)
},
// 执行脚本
executeScript: (params) => electron.ipcRenderer.invoke(IPC_EVENTS.EXECUTE_SCRIPT, params),
// 打开渠道
openChannel: (channels) => electron.ipcRenderer.invoke(IPC_EVENTS.OPEN_CHANNEL, channels)
};
electron.contextBridge.exposeInMainWorld("api", api);

View File

@@ -1 +0,0 @@
[data-v-eceb1c86] .el-steps--simple{background:0 0}[data-v-eceb1c86] .el-step.is-simple .el-step__arrow:before{background:#525866;width:2px}[data-v-eceb1c86] .el-step.is-simple .el-step__arrow:after{background:#525866;width:2px}[data-v-eceb1c86] .el-step__head.is-process .el-step__icon.is-text{border-color:#2b7fff}[data-v-eceb1c86] .el-step__head.is-success{color:#1fc16b}[data-v-eceb1c86] .el-step__head.is-success .el-step__icon.is-text{background:#1fc16b}[data-v-eceb1c86] .el-step__head.is-success .el-step__icon.is-text{color:#fff;border-color:#1fc16b}[data-v-eceb1c86] .el-step__title.is-success{color:#525866;font-size:14px;font-weight:500}[data-v-eceb1c86] .el-textarea .el-input__count.is-outside{top:auto;bottom:10px;right:15px}[data-v-6ab79709] .el-button.button{background:linear-gradient(#4a8ff9,#0000),#2b7fff;border:1px solid #1447e6;border-radius:8px;padding-top:18px;padding-bottom:18px;box-shadow:0 1px 1px #0000000d,inset 0 0 0 1px #ffffff3d}[data-v-84bf9ea3] .el-table tr td:nth-of-type(1){background:#eff6ff!important}[data-v-84bf9ea3] .el-tag{color:#525866;background:#fff!important;border:1px solid #e5e8ee!important;border-radius:6px!important}[data-v-4c31200f] .el-tabs__item{color:#99a0ae}[data-v-4c31200f] .el-tabs__item.is-active{color:#2b7fff}[data-v-4c31200f] .el-tabs__active-bar{background-color:#2b7fff}

View File

@@ -1 +0,0 @@
.task[data-v-74ff89ed]{z-index:1;transition:all .2s linear;position:relative}.task .success[data-v-74ff89ed]{color:#1fc16b;background-color:#e0faec}.task .error[data-v-74ff89ed]{color:#fb3748;background-color:#ffebec}.task .warning[data-v-74ff89ed]{color:#fa7319;background-color:#fff3eb}.task[data-v-74ff89ed]:hover{z-index:2;transform:translateY(-2px);box-shadow:0 10px 20px #0000001a}.task-tab .text[data-v-be5e193a]{color:#525866;cursor:pointer;font-size:14px}.task-tab .active[data-v-be5e193a]{color:#2b7fff;background:#fff;border-radius:8px;position:relative}.task-tab .active[data-v-be5e193a]:after{content:"";border:1px solid #2b7fff;border-radius:8px;width:100%;height:100%;position:absolute;top:0;left:0}.task-tab .text[data-v-33324fcc]{color:#525866;cursor:pointer;font-size:14px}.task-tab .active[data-v-33324fcc]{color:#2b7fff;background:#fff;border-radius:8px;position:relative}.task-tab .active[data-v-33324fcc]:after{content:"";border:1px solid #2b7fff;border-radius:8px;width:100%;height:100%;position:absolute;top:0;left:0}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}.wave[data-v-5b734189]{text-align:center;width:30px;position:relative}.dot[data-v-5b734189]{background:#333;border-radius:50%;width:3px;height:3px;margin-right:3px;animation:1.3s linear infinite wave-5b734189;display:inline-block}.dot[data-v-5b734189]:nth-child(2){animation-delay:-1.1s}.dot[data-v-5b734189]:nth-child(3){animation-delay:-.9s}@keyframes wave-5b734189{0%,60%,to{transform:initial}30%{transform:translateY(-5px)}}

34
dist/index.html vendored
View File

@@ -1,17 +1,17 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>NIANXX</title> <title>NIANXX</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' http://8.138.234.141 https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com; connect-src 'self' http://8.138.234.141 https://api.iconify.design wss://onefeel.brother7.cn" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' http://8.138.234.141 https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com; connect-src 'self' http://8.138.234.141 https://api.iconify.design wss://onefeel.brother7.cn"
/> />
<script type="module" crossorigin src="./assets/index-C4Gb4VF1.js"></script> <script type="module" crossorigin src="./assets/index-BmjJNchE.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-CZoyThnd.css"> <link rel="stylesheet" crossorigin href="./assets/index-BjlT3-UA.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
</body>
</body> </html>

View File

@@ -9,7 +9,7 @@
"start": "vite", "start": "vite",
"build": "vite build && electron-builder", "build": "vite build && electron-builder",
"build:vite": "vite build", "build:vite": "vite build",
"package": "electron-builder", "package": "vite build",
"icons": "zx scripts/generate-icons.mjs", "icons": "zx scripts/generate-icons.mjs",
"uv:download": "zx scripts/download-bundled-uv.mjs", "uv:download": "zx scripts/download-bundled-uv.mjs",
"uv:download:mac": "zx scripts/download-bundled-uv.mjs --platform=mac", "uv:download:mac": "zx scripts/download-bundled-uv.mjs --platform=mac",
@@ -18,10 +18,14 @@
"uv:download:all": "zx scripts/download-bundled-uv.mjs --all", "uv:download:all": "zx scripts/download-bundled-uv.mjs --all",
"node:download:win": "zx scripts/download-bundled-node.mjs --platform=win", "node:download:win": "zx scripts/download-bundled-node.mjs --platform=win",
"prep:win-binaries": "pnpm run uv:download:win && pnpm run node:download:win", "prep:win-binaries": "pnpm run uv:download:win && pnpm run node:download:win",
"package:win": "pnpm run prep:win-binaries && vite build && electron-builder --win --publish never", "package:win": "pnpm run prep:win-binaries && pnpm run package && electron-builder --win --publish never",
"package:mac": "vite build && electron-builder --mac --publish never", "package:mac": "pnpm run package && electron-builder --mac --publish never",
"package:linux": "vite build && electron-builder --linux --publish never", "package:mac:local": "SKIP_AFTERPACK_CLEANUP=1 pnpm run package && electron-builder --mac --publish never",
"release": "vite build && electron-builder --publish always", "package:mac:x64": "pnpm run package && electron-builder --mac --x64 --publish never",
"package:mac:arm64": "pnpm run package && electron-builder --mac --arm64 --publish never",
"package:mac:fast": "pnpm run package && electron-builder --mac --publish never --config.compression=normal",
"package:linux": "pnpm run package && electron-builder --linux --publish never",
"release": "pnpm run package && electron-builder --publish always",
"lint": "eslint --ext .ts,.tsx .", "lint": "eslint --ext .ts,.tsx .",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"openapi": "dotenv -e .env -- openapi-ts", "openapi": "dotenv -e .env -- openapi-ts",

View File

@@ -0,0 +1,145 @@
# package:mac 打包诊断报告
**诊断时间**: 2026-04-11
**项目路径**: `/Users/duanshuwen/Documents/workspace/electron/zn-ai`
**执行命令**: `pnpm run package:mac`
---
## 1. 结论摘要
**本次打包失败不是因为项目源码缺少文件或 `electron-builder.yml` 配置项缺失,而是因为**
1. **网络下载中断**`electron-builder` 在构建 DMG 时需要下载 `dmgbuild-bundle-x86_64`,该请求被服务器中断(`ReadError: The server aborted pending request`)。
2. **并发锁竞争**`mac.target` 同时配置了 `x64``arm64` 两种架构,`electron-builder` 并行打包时两个进程争抢 `proper-lockfile` 的缓存锁,导致下载失败后的清理阶段抛出 `Lock file is already being held` 错误。
3. **(非致命)代码签名证书已过期**:本地唯一的 `Apple Development` 证书状态为 `CSSMERR_TP_CERT_EXPIRED`,因此 `electron-builder` 跳过了正式签名,仅做了 ad-hoc 签名。这不会导致打包中断,但会影响最终 app 在 macOS Gatekeeper 下的可运行性。
---
## 2. 关键错误日志
```text
• downloading release=dmg-builder@1.2.0 file=dmgbuild-bundle-x86_64-75c8a6c.tar.gz
...
ReadError: The server aborted pending request
...
Error: Lock file is already being held
at /Users/duanshuwen/Documents/workspace/electron/zn-ai/node_modules/proper-lockfile/lib/lockfile.js:68:47
...
ELIFECYCLE Command failed with exit code 1.
```
---
## 3. 配置与文件检查结果
| 检查项 | 状态 | 说明 |
|--------|------|------|
| `package.json` | 正常 | 存在且 `package:mac` 脚本定义正确 |
| `electron-builder.yml` | 正常 | 配置完整,`mac` / `dmg` / `win` / `linux` 分平台配置齐全 |
| `resources/icons/icon.icns` | 正常 | `mac.icon` 指向的文件存在 |
| `entitlements.mac.plist` | 正常 | 文件存在并已配置 |
| `dist` / `dist-electron` | 正常 | `vite build` 阶段成功通过,产物已生成 |
| 发布产物 | 部分生成 | `zip`x64 / arm64已成功生成但 DMGx64 / arm64因下载失败未完成 |
---
## 4. 详细原因分析
### 4.1 网络问题导致 dmg-builder 下载中断
`electron-builder` 在首次构建 DMG 时需要拉取预编译的 `dmg-builder` bundle`dmgbuild-bundle-x86_64-75c8a6c.tar.gz`)。由于该资源托管在 GitHub / AWS CDN 上,在国内网络环境下极易出现连接被重置或请求被服务器中断的情况。
### 4.2 并发构建加剧锁竞争
`electron-builder.yml` 中配置了同时打包两种架构:
```yaml
mac:
target:
- target: dmg
arch:
- x64
- arm64
- target: zip
arch:
- x64
- arm64
```
这导致 `electron-builder` 会并行启动多个打包任务。当它们同时尝试下载/解压同一个 `dmg-builder` 缓存时,`proper-lockfile` 产生竞争;一旦其中一个下载失败,另一个在清理阶段也会因无法获取锁而报错,最终整体构建失败。
### 4.3 代码签名证书过期(仅提示,不中断构建)
日志中出现的:
```text
skipped macOS application code signing reason=cannot find valid "Developer ID Application" identity ...
"Apple Development: 562304744@qq.com (Z27TQS657B)" (CSSMERR_TP_CERT_EXPIRED)
```
这说明本地证书已过期,不会影响打包流程本身,但生成的 `.app` 没有有效的开发者签名,分发后用户打开时会遇到 "已损坏,无法打开" 的 Gatekeeper 提示。
---
## 5. 解决方案与建议
### 方案 A分架构单独打包推荐最稳定
先避免并发锁竞争,同时降低单次构建对网络的敏感度:
```bash
# 仅打包 arm64Apple Silicon
cd zn-ai
npx electron-builder --mac --arm64 --publish never
# 仅打包 x64Intel
npx electron-builder --mac --x64 --publish never
```
若网络仍不稳定,可配置代理或手动下载缓存(见方案 B
### 方案 B配置 electron-builder 缓存
如果网络受限,可预先设置缓存目录并手动下载所需 bundle
```bash
export ELECTRON_BUILDER_CACHE="$HOME/.electron-builder-cache"
```
然后手动将 `dmgbuild-bundle-x86_64-75c8a6c.tar.gz` 放置到缓存目录的 `cache/dmg-builder` 子目录下,再执行打包。
### 方案 C修改 `electron-builder.yml` 降低并发
`mac.target` 里先只保留当前常用架构(如 `arm64`),需要时再切换:
```yaml
mac:
target:
- target: dmg
arch:
- arm64
- target: zip
arch:
- arm64
```
### 方案 D修复代码签名分发前必须
若计划将应用分发给其他用户,需要:
1. 在 Apple Developer 后台续期或重新申请 **Developer ID Application** 证书;
2.`notarize` 改为 `true` 并配置正确的 `teamId`
3. 在构建机器上安装新证书后重新打包。
---
## 6. 附录:构建产物现状
截至诊断时,`release/` 目录下已生成:
- `NIANXX-1.0.0-mac-x64.zip` (133 MB)
- `NIANXX-1.0.0-mac-arm64.zip` (129 MB)
- 对应的 `.blockmap` 文件
**未生成**
- `NIANXX-1.0.0-mac-x64.dmg`
- `NIANXX-1.0.0-mac-arm64.dmg`
原因即上述网络下载中断 + 并发锁竞争。
---
*报告结束*

View File

@@ -142,19 +142,23 @@ module.exports = async function afterPack(context) {
await ensureDependency(dep); await ensureDependency(dep);
} }
// 3. Clean up unnecessary development files from node_modules // 3. Clean up unnecessary development files from node_modules (skip if SKIP_AFTERPACK_CLEANUP is set)
const nodeModulesDest = path.join(appOutDir, 'node_modules'); if (!process.env.SKIP_AFTERPACK_CLEANUP) {
if (await fs.pathExists(nodeModulesDest)) { const nodeModulesDest = path.join(appOutDir, 'node_modules');
console.log('Cleaning up development files in node_modules...'); if (await fs.pathExists(nodeModulesDest)) {
const removed = cleanupUnnecessaryFiles(nodeModulesDest); console.log('Cleaning up development files in node_modules...');
console.log(`Removed ${removed} unnecessary files/directories from node_modules.`); const removed = cleanupUnnecessaryFiles(nodeModulesDest);
} console.log(`Removed ${removed} unnecessary files/directories from node_modules.`);
}
// 4. Clean up unnecessary files in scripts directory // 4. Clean up unnecessary files in scripts directory
if (await fs.pathExists(scriptsDest)) { if (await fs.pathExists(scriptsDest)) {
console.log('Cleaning up development files in scripts directory...'); console.log('Cleaning up development files in scripts directory...');
const removedScripts = cleanupUnnecessaryFiles(scriptsDest); const removedScripts = cleanupUnnecessaryFiles(scriptsDest);
console.log(`Removed ${removedScripts} unnecessary files/directories from scripts.`); console.log(`Removed ${removedScripts} unnecessary files/directories from scripts.`);
}
} else {
console.log('Skipping afterPack cleanup (SKIP_AFTERPACK_CLEANUP is set)');
} }
// 5. Optional: platform-specific native package cleanup // 5. Optional: platform-specific native package cleanup