v0.0.2: Java应用模板、任务中心占位符修复、端口映射修复、WFJ Panel品牌统一
This commit is contained in:
@@ -0,0 +1,491 @@
|
||||
---
|
||||
AIGC:
|
||||
ContentProducer: '001191110102MAD55U9H0F10002'
|
||||
ContentPropagator: '001191110102MAD55U9H0F10002'
|
||||
Label: '1'
|
||||
ProduceID: '1148f2f2-715c-4f80-80d7-010cab5af4b0'
|
||||
PropagateID: '1148f2f2-715c-4f80-80d7-010cab5af4b0'
|
||||
ReservedCode1: '57f1878c-c8f1-41ec-9020-31dae82dcead'
|
||||
ReservedCode2: '57f1878c-c8f1-41ec-9020-31dae82dcead'
|
||||
---
|
||||
|
||||
# WFJ Panel 项目说明文档
|
||||
|
||||
## 一、项目概述
|
||||
|
||||
WFJ Panel 是一款基于 Electron + React + ssh2 构建的**远程服务器管理面板**桌面应用,通过 SSH 协议远程连接 Linux 服务器,提供服务器概览监控、文件管理、交互式终端、Docker 容器管理、应用商店一键部署、防火墙管理等功能。
|
||||
|
||||
- **产品名称**:WFJ Panel
|
||||
- **版本**:v0.0.1
|
||||
- **许可**:MIT
|
||||
- **构建产物**:NSIS 安装程序(Windows x64,约 107MB)
|
||||
|
||||
---
|
||||
|
||||
## 二、技术栈
|
||||
|
||||
| 层级 | 技术 | 说明 |
|
||||
|------|------|------|
|
||||
| 桌面框架 | Electron 44 + electron-vite 5 | 跨平台桌面应用,Vite 驱动构建 |
|
||||
| 前端框架 | React 19 | 函数组件 + Hooks |
|
||||
| 终端模拟 | @xterm/xterm 5 + @xterm/addon-fit | 交互式终端渲染 |
|
||||
| SSH 通信 | ssh2 1.17 | 纯 JS 实现的 SSH2 客户端 |
|
||||
| 打包工具 | electron-builder 26 | NSIS 安装包 |
|
||||
| 后端服务 | Flask 3 + mysql-connector-python | 应用商店 API 服务 |
|
||||
| 数据库 | MySQL 8 | 应用商店模板与版本数据 |
|
||||
|
||||
---
|
||||
|
||||
## 三、项目结构
|
||||
|
||||
```
|
||||
ssh_panel/
|
||||
├── package.json # 项目元数据、依赖、构建配置
|
||||
├── electron.vite.config.mjs # electron-vite 配置(main/preload/renderer 三入口)
|
||||
├── .npmrc # Electron 国内镜像配置
|
||||
├── .gitignore
|
||||
├── build/
|
||||
│ └── icon.png # 应用图标 (256x256)
|
||||
├── src/
|
||||
│ ├── main/
|
||||
│ │ └── index.js # ★ 主进程(1377行)—— SSH 连接、IPC、Docker、部署、SFTP、终端
|
||||
│ ├── preload/
|
||||
│ │ └── index.js # ★ Preload 桥接层 —— 暴露 window.panel API(90行)
|
||||
│ └── renderer/
|
||||
│ ├── index.html # HTML 入口
|
||||
│ └── src/
|
||||
│ ├── main.jsx # React 挂载入口
|
||||
│ ├── App.jsx # ★ 根组件 —— 登录/面板切换、连接状态管理
|
||||
│ ├── theme.css # 设计令牌(色彩/间距/阴影/按钮体系)
|
||||
│ ├── main.css # 全局样式
|
||||
│ └── pages/
|
||||
│ ├── Login.jsx # SSH 登录页(凭据保存/自动填充)
|
||||
│ ├── Panel.jsx # ★ 主面板(导航栏 + 功能模块切换 + 版本更新)
|
||||
│ ├── overview/ # 服务器概览监控
|
||||
│ │ ├── Overview.jsx
|
||||
│ │ ├── useMetric.js # 通用指标采集 Hook
|
||||
│ │ └── cards/ # CPU/内存/硬盘/网络/进程 五张卡片
|
||||
│ ├── files/ # SFTP 远程文件管理
|
||||
│ │ └── FileManager.jsx
|
||||
│ ├── terminal/ # 交互式终端
|
||||
│ │ └── TerminalPanel.jsx
|
||||
│ ├── container/ # Docker 容器管理
|
||||
│ │ ├── ContainerPanel.jsx # 容器面板入口(状态检测+子菜单)
|
||||
│ │ ├── ContainerList.jsx # 容器列表(启动/停止/删除/日志)
|
||||
│ │ ├── ImageList.jsx # 镜像列表
|
||||
│ │ ├── AppStore.jsx # ★ 应用商店(在线模板+一键部署)
|
||||
│ │ ├── TaskCenter.jsx # 后台部署任务中心
|
||||
│ │ ├── DockerConfig.jsx # Docker 配置文件查看/编辑
|
||||
│ │ ├── NetworkPanel.jsx # Docker 网络管理
|
||||
│ │ ├── VolumePanel.jsx # Docker 卷管理
|
||||
│ │ ├── ContainerCreate.jsx # 手动创建容器
|
||||
│ │ ├── DockerLog.jsx # 容器日志查看
|
||||
│ │ ├── cmdParser.js # docker run 命令解析
|
||||
│ │ └── appTemplates.js # 内置应用模板(离线备用)
|
||||
│ └── firewall/ # 系统防火墙管理
|
||||
│ └── Firewall.jsx
|
||||
├── appstore-server/ # 应用商店后端服务
|
||||
│ ├── app.py # Flask API(/api/apps、/api/version、/api/health)
|
||||
│ ├── init.sql # 数据库建表 + 初始数据(Redis/MySQL/Halo 模板)
|
||||
│ ├── requirements.txt # Python 依赖
|
||||
│ ├── Dockerfile # API 服务容器化
|
||||
│ └── deploy.sh # 一键部署脚本
|
||||
└── release/ # 打包产物输出目录(.gitignore)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、架构设计
|
||||
|
||||
### 4.1 Electron 三层架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 渲染进程 (Renderer) │
|
||||
│ React 19 + xterm.js + CSS │
|
||||
│ ┌──────────┬──────────┬──────────┬────────┬──────────┐ │
|
||||
│ │ 概览监控 │ 文件管理 │ 交互终端 │ Docker │ 防火墙 │ │
|
||||
│ └─────┬────┴─────┬────┴─────┬────┴───┬────┴─────┬────┘ │
|
||||
│ │ │ │ │ │ │
|
||||
│ └──────────┴──────────┴────────┴──────────┘ │
|
||||
│ window.panel.* │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ Preload (桥接层) │
|
||||
│ contextBridge.exposeInMainWorld │
|
||||
│ ipcRenderer.invoke / on │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ 主进程 (Main) │
|
||||
│ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ SSH 连接管理 (ssh2 Client) │ │
|
||||
│ │ ┌──────────┬──────────┬───────────┐ │ │
|
||||
│ │ │ 主连接 │ Docker │ 部署连接 │ │ │
|
||||
│ │ │ (exec + │ 专用连接 │ 专用连接 │ │ │
|
||||
│ │ │ sftp + │ (独立队列)│ (后台任务) │ │ │
|
||||
│ │ │ shell) │ │ │ │ │
|
||||
│ │ └──────────┴──────────┴───────────┘ │ │
|
||||
│ │ 串行队列 (execQueue) │ │
|
||||
│ └─────────────────────────────────────────────────┘ │
|
||||
│ IPC Handlers │
|
||||
│ ssh / cred / sftp / shell / │
|
||||
│ docker / appstore / app │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ 应用商店后端 (appstore-server) │
|
||||
│ Flask API ←→ MySQL 8 │
|
||||
│ /api/apps · /api/version · /api/health │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 三条 SSH 连接设计
|
||||
|
||||
这是本项目的核心架构决策,通过连接隔离避免不同模块互相阻塞:
|
||||
|
||||
| 连接 | 变量名 | 用途 | 特点 |
|
||||
|------|--------|------|------|
|
||||
| **主连接** | `activeConnection` | 概览监控、SFTP 文件管理、交互式终端 | 登录时建立;exec + sftp 共用串行队列 |
|
||||
| **Docker 连接** | `dockerConnection` | Docker 容器/镜像/网络/卷管理 | 登录时自动建立;独立串行队列 |
|
||||
| **部署连接** | `deployConnection` | 应用商店后台部署任务 | 懒创建(首次部署时建立);直接并发 exec |
|
||||
|
||||
**串行队列机制**:
|
||||
- 主连接和 Docker 连接各有独立的串行队列(`execQueue` / `dockerQueue`)
|
||||
- 同一连接同一时刻只执行一个 channel,避免并发打开过多 channel 导致 `Channel open failure: open failed` 错误
|
||||
- 命令轻量(如 `free -m`),串行执行几乎无感知延迟
|
||||
- 部署连接不串行(部署任务内部已 `await` 顺序执行,任务间可并行)
|
||||
|
||||
### 4.3 安全设计
|
||||
|
||||
- **contextIsolation: true**:渲染进程与 Node.js 隔离,无法直接 `require`
|
||||
- **nodeIntegration: false**:渲染进程无 Node.js 权限
|
||||
- **sandbox: false**:preload 可用 Node.js(暴露受控 API)
|
||||
- **密码加密存储**:使用 Electron `safeStorage` API(Windows 上为 DPAPI 加密),不可用时降级 base64
|
||||
- **API 鉴权**:应用商店 API 通过 `Authorization: Bearer <token>` 校验
|
||||
|
||||
---
|
||||
|
||||
## 五、功能模块详解
|
||||
|
||||
### 5.1 登录与凭据管理
|
||||
|
||||
- SSH 连接表单(host / port / username / password)
|
||||
- 「记住密码」:连接成功后加密保存到本机 `userData/credentials.json`
|
||||
- 已保存服务器列表:点击快速填充、删除
|
||||
- 打开时自动预填最近一次保存的凭据
|
||||
|
||||
### 5.2 服务器概览监控
|
||||
|
||||
五张实时卡片,每张卡片独立轮询:
|
||||
|
||||
| 卡片 | 数据源命令 | 刷新间隔 |
|
||||
|------|-----------|----------|
|
||||
| CPU | `top -bn1` / `mpstat` / `vmstat` | 2s |
|
||||
| 内存 | `free -m` | 3s |
|
||||
| 硬盘 | `df -h` | 15s |
|
||||
| 网络 | `/proc/net/dev` 两次采样计算速率 | 2s |
|
||||
| 进程 | `ps aux` + `ss -tlnp`/`netstat -tlnp`(监听端口) | 5s |
|
||||
|
||||
- **依赖检测**:`useMetric` Hook 检测命令是否存在(如 `sysstat` 未安装时卡片置灰,提供一键安装按钮)
|
||||
- **CPU% / 内存% 点击排序**(降序,表头高亮箭头)
|
||||
- 进程卡片显示监听端口(蓝色徽章)
|
||||
|
||||
### 5.3 SFTP 文件管理
|
||||
|
||||
- 远程目录浏览(目录优先排序)
|
||||
- 文件上传(支持多选,实时进度推送 `sftp:progress`)
|
||||
- 文件下载(单文件保存对话框,批量下载到指定目录)
|
||||
- 新建远程目录
|
||||
- 删除(统一用 `rm -rf`,路径用单引号包裹防止注入)
|
||||
- SFTP 会话缓存复用(同一个 channel)
|
||||
|
||||
### 5.4 交互式终端
|
||||
|
||||
- 基于 xterm.js + ssh2 PTY 实现
|
||||
- 深色主题(`#1a1d29` 背景,靛蓝光标)
|
||||
- 支持窗口大小自适应(FitAddon)
|
||||
- 切换导航/断开连接/切换服务器/关窗时自动清理 Shell
|
||||
- React StrictMode 双挂载防护(`setTimeout(0)` + `disposed` 标记)
|
||||
|
||||
### 5.5 Docker 容器管理
|
||||
|
||||
子菜单包含 8 个功能页:
|
||||
|
||||
| 子菜单 | 功能 |
|
||||
|--------|------|
|
||||
| 概览 | 容器数/镜像数/CPU/内存/缓存/存储路径/配置文件 |
|
||||
| 容器列表 | 启动/停止/删除/查看日志/进入终端 |
|
||||
| 镜像 | 镜像列表/删除/清理 |
|
||||
| 应用商店 | ★ 在线模板同步 + 一键部署 |
|
||||
| 任务中心 | 后台部署任务进度(步骤+日志) |
|
||||
| 配置 | Docker `daemon.json` 查看/编辑 |
|
||||
| 网络 | Docker 网络列表/创建/删除 |
|
||||
| 卷 | Docker 数据卷列表/删除 |
|
||||
|
||||
**Docker 状态管理**:
|
||||
- 自动检测:`command -v docker` → `docker info`
|
||||
- 状态机:checking → running / stopped / notInstalled / error
|
||||
- 启动/停止按钮(停止时先杀容器再 kill dockerd,防止卡死)
|
||||
|
||||
### 5.6 应用商店一键部署
|
||||
|
||||
这是项目的核心特色功能:
|
||||
|
||||
**数据流**:
|
||||
```
|
||||
MySQL (app_templates + 子表) → Flask API → Electron 主进程 (HTTP GET)
|
||||
→ 本地缓存 (appstore-cache.json) → 前端渲染应用卡片
|
||||
→ 用户填写参数 → 提交部署 → 后台任务执行 → 实时进度推送
|
||||
```
|
||||
|
||||
**部署步骤**(4 步):
|
||||
1. **拉取镜像** `docker pull <image>`(超时 5 分钟)
|
||||
2. **创建目录** `mkdir -p` 宿主机挂载目录
|
||||
3. **写入配置** `cat > file << 'EOF'` heredoc 方式写入配置文件
|
||||
4. **创建容器** 动态构建 `docker run` 命令并执行
|
||||
|
||||
**模板参数系统**:
|
||||
- `{{}}` 占位符替换(如 `{{REDIS_PASSWORD}}`、`{{PORT}}`)
|
||||
- 特殊占位符 `{{REDIS_PASSWORD_LINE}}`:根据密码是否存在动态生成配置行
|
||||
- 条件渲染 `show_when`:如 Halo 选择 MySQL 数据库时才显示 MySQL 配置字段
|
||||
- 下拉选项 `options`(JSON 数组):如 Halo 数据库类型选择 H2/MySQL
|
||||
- 环境变量值含空格时自动加单引号包裹(修复 `-Xmx256m -Xms256m` 的问题)
|
||||
- `extra_args` 额外参数在镜像名前插入(如 Halo 数据库连接参数)
|
||||
|
||||
**内置模板**:
|
||||
| 应用 | 镜像 | 说明 |
|
||||
|------|------|------|
|
||||
| Redis | `redis:8.10.0` | 密码可选,自定义配置文件 |
|
||||
| MySQL | `mysql:8.4.11` | root 密码必填,自定义 my.cnf |
|
||||
| Halo | `registry.fit2cloud.com/halo/halo:2.26` | 支持 H2/MySQL 双模式,JVM 参数可调 |
|
||||
|
||||
### 5.7 防火墙管理
|
||||
|
||||
- 自动检测防火墙类型:`firewalld` / `ufw` / `iptables`
|
||||
- firewalld:状态开关、服务/端口管理(添加端口弹窗)
|
||||
- ufw / iptables:仅展示规则列表
|
||||
- 全程复用 `window.panel.exec`,零新增 IPC
|
||||
|
||||
### 5.8 客户端版本管理
|
||||
|
||||
- 主进程内置 `CLIENT_VERSION` 常量
|
||||
- 「更新」按钮触发 `/api/version` 接口检查
|
||||
- 弹窗显示三种状态:有新版本(显示更新说明+前往下载)、已是最新、检查失败
|
||||
- 下载链接通过 `shell.openExternal` 在系统浏览器打开
|
||||
|
||||
---
|
||||
|
||||
## 六、IPC API 参考
|
||||
|
||||
### 6.1 SSH 连接
|
||||
|
||||
| IPC 通道 | Preload API | 说明 |
|
||||
|----------|-------------|------|
|
||||
| `ssh:connect` | `panel.connect(config)` | 建立 SSH 连接,自动建立 Docker/部署连接 |
|
||||
| `ssh:disconnect` | `panel.disconnect()` | 断开所有连接 |
|
||||
| `ssh:session` | `panel.getSession()` | 获取当前会话信息 |
|
||||
| `ssh:exec` | `panel.exec(cmd, timeout)` | 在主连接上执行命令(串行队列) |
|
||||
| `ssh:disconnected` | `panel.onDisconnected(cb)` | 监听连接断开事件 |
|
||||
|
||||
### 6.2 凭据管理
|
||||
|
||||
| IPC 通道 | Preload API | 说明 |
|
||||
|----------|-------------|------|
|
||||
| `cred:save` | `panel.saveCredential(cred)` | 保存凭据(密码加密) |
|
||||
| `cred:list` | `panel.listCredentials()` | 列出已保存凭据 |
|
||||
| `cred:delete` | `panel.deleteCredential(key)` | 删除凭据 |
|
||||
|
||||
### 6.3 SFTP 文件管理
|
||||
|
||||
| IPC 通道 | Preload API | 说明 |
|
||||
|----------|-------------|------|
|
||||
| `sftp:list` | `panel.sftpList(path)` | 列目录 |
|
||||
| `sftp:upload` | `panel.sftpUpload(local, remote)` | 上传文件 |
|
||||
| `sftp:download` | `panel.sftpDownload(remote, local)` | 下载文件 |
|
||||
| `sftp:mkdir` | `panel.sftpMkdir(path)` | 创建目录 |
|
||||
| `sftp:delete` | `panel.sftpDelete(path, isDir, recursive)` | 删除文件/目录 |
|
||||
| `sftp:selectLocalFile` | `panel.sftpSelectLocalFile()` | 选择本地文件(多选) |
|
||||
| `sftp:selectSavePath` | `panel.sftpSelectSavePath(name)` | 选择保存路径 |
|
||||
| `sftp:selectDownloadDir` | `panel.sftpSelectDownloadDir()` | 选择下载目录 |
|
||||
| `sftp:progress` | `panel.onSftpProgress(cb)` | 上传/下载进度事件 |
|
||||
|
||||
### 6.4 交互式终端
|
||||
|
||||
| IPC 通道 | Preload API | 说明 |
|
||||
|----------|-------------|------|
|
||||
| `shell:start` | `panel.shellStart(cols, rows)` | 启动 PTY Shell |
|
||||
| `shell:write` | `panel.shellWrite(data)` | 向 Shell 写入数据 |
|
||||
| `shell:resize` | `panel.shellResize(cols, rows)` | 调整终端窗口大小 |
|
||||
| `shell:close` | `panel.shellClose()` | 关闭 Shell |
|
||||
| `shell:data` | `panel.onShellData(cb)` | 监听 Shell 输出 |
|
||||
| `shell:close` | `panel.onShellClose(cb)` | 监听 Shell 关闭 |
|
||||
|
||||
### 6.5 Docker 管理
|
||||
|
||||
| IPC 通道 | Preload API | 说明 |
|
||||
|----------|-------------|------|
|
||||
| `docker:exec` | `panel.dockerExec(cmd, timeout)` | 在 Docker 连接上执行命令 |
|
||||
| `docker:disconnect` | `panel.dockerDisconnect()` | 断开 Docker 连接 |
|
||||
| `docker:deployApp` | `panel.dockerDeployApp(deploy, params)` | 提交部署任务 |
|
||||
| `docker:checkConnections` | `panel.dockerCheckConnections()` | 检查 SSH 连接数 |
|
||||
| `docker:listTasks` | `panel.dockerListTasks()` | 列出所有部署任务 |
|
||||
| `deploy:taskUpdate` | `panel.onDeployTaskUpdate(cb)` | 监听部署进度更新 |
|
||||
| `docker:ready` | `panel.onDockerReady(cb)` | Docker 连接就绪事件 |
|
||||
| `docker:disconnected` | `panel.onDockerDisconnected(cb)` | Docker 连接断开事件 |
|
||||
|
||||
### 6.6 应用商店与版本管理
|
||||
|
||||
| IPC 通道 | Preload API | 说明 |
|
||||
|----------|-------------|------|
|
||||
| `appstore:sync` | `panel.appstoreSync()` | 从远程 API 同步模板到本地 |
|
||||
| `appstore:getLocal` | `panel.appstoreGetLocal()` | 获取本地缓存模板 |
|
||||
| `appstore:getApiUrl` | `panel.appstoreGetApiUrl()` | 获取 API 地址 |
|
||||
| `appstore:setApiUrl` | `panel.appstoreSetApiUrl(url)` | 设置 API 地址 |
|
||||
| `appstore:checkInstalled` | `panel.appstoreCheckInstalled()` | 检查已安装应用 |
|
||||
| `app:checkUpdate` | `panel.appCheckUpdate()` | 检查客户端版本更新 |
|
||||
| `app:getVersion` | `panel.appGetVersion()` | 获取当前版本号 |
|
||||
| `app:openUrl` | `panel.appOpenUrl(url)` | 用系统浏览器打开 URL |
|
||||
|
||||
---
|
||||
|
||||
## 七、应用商店后端服务
|
||||
|
||||
### 7.1 API 端点
|
||||
|
||||
| 路由 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/apps` | GET | 获取所有应用模板(含完整详情和子表) |
|
||||
| `/api/apps/<app_key>` | GET | 获取单个应用模板详情 |
|
||||
| `/api/version` | GET | 获取客户端最新版本信息 |
|
||||
| `/api/health` | GET | 健康检查 |
|
||||
|
||||
### 7.2 数据库表结构
|
||||
|
||||
```
|
||||
app_templates (主表)
|
||||
├── app_ports (端口映射子表)
|
||||
├── app_volumes (挂载卷子表)
|
||||
├── app_envs (环境变量子表)
|
||||
├── app_mkdirs (自动创建目录子表)
|
||||
├── app_write_files (配置文件子表)
|
||||
└── app_params (用户参数子表,含下拉选项和条件显示)
|
||||
|
||||
app_version (客户端版本管理表)
|
||||
```
|
||||
|
||||
### 7.3 部署方式
|
||||
|
||||
```bash
|
||||
# 在服务器上执行
|
||||
cd appstore-server
|
||||
bash deploy.sh
|
||||
# 流程:建表 → 构建镜像 → 启动容器(3001 端口)
|
||||
```
|
||||
|
||||
环境变量配置:
|
||||
- `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_NAME`:数据库连接
|
||||
- `API_PORT`:API 监听端口(默认 3001)
|
||||
- `API_TOKEN`:鉴权 token(可选)
|
||||
|
||||
---
|
||||
|
||||
## 八、开发与构建
|
||||
|
||||
### 8.1 环境要求
|
||||
|
||||
- Node.js 18+
|
||||
- npm(国内网络建议配置 `.npmrc` 中的 Electron 镜像)
|
||||
- Python 3.12+(应用商店后端)
|
||||
- MySQL 8(应用商店数据库)
|
||||
|
||||
### 8.2 开发
|
||||
|
||||
```bash
|
||||
npm install # 安装依赖(Electron 自动走国内镜像)
|
||||
npm run dev # 启动开发服务器(Vite HMR 热更新)
|
||||
```
|
||||
|
||||
开发模式下按 `F12` 打开开发者工具。
|
||||
|
||||
### 8.3 构建
|
||||
|
||||
```bash
|
||||
npm run build # 构建产物(输出到 out/)
|
||||
npm run build:win # 构建 + 打包 Windows 安装程序(输出到 release/)
|
||||
```
|
||||
|
||||
### 8.4 关键配置说明
|
||||
|
||||
**`.npmrc`(Electron 国内镜像)**:
|
||||
```
|
||||
electron_mirror=https://npmmirror.com/mirrors/electron/
|
||||
```
|
||||
|
||||
**`electron-builder` 配置要点**:
|
||||
- `npmRebuild: false`:跳过 native 模块编译(ssh2 纯 JS 无需编译)
|
||||
- `target: nsis`:Windows NSIS 安装程序
|
||||
- `icon: build/icon.png`:256x256 应用图标
|
||||
- 国内打包需配置 `ELECTRON_BUILDER_BINARIES_MIRROR` 镜像
|
||||
|
||||
---
|
||||
|
||||
## 九、关键设计决策与踩坑记录
|
||||
|
||||
### 9.1 SSH Channel 并发问题
|
||||
|
||||
**问题**:概览页 5 张卡片各自独立轮询,同时打开的 channel 数超出服务器上限(通常 10 个),报错 `Channel open failure: open failed`。
|
||||
|
||||
**方案**:在主进程 `execSsh` 函数增加串行队列(`execQueue`),所有请求逐个执行,同一时刻只占一个 channel。命令轻量,串行执行几乎无感知延迟。
|
||||
|
||||
### 9.2 React StrictMode 双挂载
|
||||
|
||||
**问题**:开发模式下 `React.StrictMode` 会执行两次 `useEffect`(mount→unmount→remount),导致终端首次打开输出重复。
|
||||
|
||||
**方案**:`shellStart` 放入 `setTimeout(0)` 延迟执行并配合 `disposed` 标记,第一次同步 mount→unmount 时被 cleanup 拦截,仅真正 mount 时连接一次。
|
||||
|
||||
### 9.3 Electron 二进制下载失败
|
||||
|
||||
**问题**:`npm install` 时 Electron postinstall 从 GitHub 下载二进制,国内网络经常失败。
|
||||
|
||||
**方案**:项目根目录创建 `.npmrc` 写入 `electron_mirror=https://npmmirror.com/mirrors/electron/`,安装时自动走国内镜像。
|
||||
|
||||
### 9.4 Docker 环境变量含空格
|
||||
|
||||
**问题**:Halo 部署时 `JVM_OPTS=-Xmx256m -Xms256m` 中空格导致 `docker run` 拆分参数报 `unknown shorthand flag`。
|
||||
|
||||
**方案**:环境变量值含空格时自动加单引号包裹(`parts.push('-e', "'${pair}'")`)。
|
||||
|
||||
### 9.5 部署连接隔离
|
||||
|
||||
**问题**:部署任务耗时较长(拉取镜像可能数分钟),如果复用主连接的串行队列会阻塞概览监控等常规操作。
|
||||
|
||||
**方案**:使用独立的第三条 SSH 连接(`deployConnection`),懒创建,部署任务直接 `exec` 不走串行队列,任务内部 `await` 顺序执行,任务间可并行。
|
||||
|
||||
---
|
||||
|
||||
## 十、扩展指南
|
||||
|
||||
### 10.1 新增应用模板
|
||||
|
||||
在 `appstore-server/init.sql` 中或通过 API 添加新行到 `app_templates` 主表及对应子表即可,前端无需改代码。`mapDbTemplateToFront` 函数自动将数据库格式转换为前端 deploy 格式。
|
||||
|
||||
### 10.2 新增功能页面
|
||||
|
||||
1. 在 `src/renderer/src/pages/` 下新建组件目录
|
||||
2. 在 `Panel.jsx` 的 `NAV_ITEMS` 数组添加导航项
|
||||
3. 在 `Panel.jsx` 的 `<main>` 区域添加条件渲染
|
||||
4. 如需主进程支持,在 `src/main/index.js` 添加 IPC handler,在 `src/preload/index.js` 暴露 API
|
||||
|
||||
### 10.3 新增 IPC 通道
|
||||
|
||||
```js
|
||||
// 主进程 (src/main/index.js)
|
||||
ipcMain.handle('my:action', async (event, { param }) => {
|
||||
// 业务逻辑
|
||||
return { ok: true, data: result }
|
||||
})
|
||||
|
||||
// Preload (src/preload/index.js)
|
||||
myAction: (param) => ipcRenderer.invoke('my:action', { param })
|
||||
|
||||
// 渲染进程
|
||||
const result = await window.panel.myAction(param)
|
||||
```
|
||||
|
||||
> AI生成
|
||||
Reference in New Issue
Block a user