一、写在前面

欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态:鸿蒙PC开发者社区:https://harmonypc.csdn.net/

项目开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_pgAdmin4

欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

这次鸿蒙 PC 适配没有直接把 Python 运行时、Python 三方依赖、PostgreSQL 客户端工具和 pgAdmin Web 服务全部塞进 HAP,而是采用了更稳的第一阶段方案:

HarmonyOS PC Electron HAP
  -> 加载 pgAdmin Electron runtime
  -> 访问 Mac 上已经启动的 pgAdmin4 Web 服务
  -> 通过 pgAdmin4 连接 PostgreSQL 测试库

也就是说,鸿蒙 PC 侧运行的是 Electron HAP 壳和 pgAdmin 页面;Mac 侧负责启动 pgAdmin4 的 Python Flask 服务。两端通过网络访问,最终验证到可以登录 pgAdmin、展开服务器、连接 PostgreSQL、查看对象树和仪表盘。

在这里插入图片描述

二、项目原始结构和适配判断

pgAdmin4 的桌面版并不是“一个窗口加载一个静态页面”这么简单。它的主要结构可以拆成三层:

pgadmin4-master/
├── web/              # pgAdmin4 Web 服务,Python Flask 后端和 React/Webpack 前端资源
├── runtime/          # Electron 桌面运行时,负责启动服务、创建窗口、菜单、下载等桌面能力
├── pkg/              # 打包相关逻辑
├── pkg/ohos/         # 本次新增的鸿蒙资源同步和 HAP 构建脚本
└── ohos_hap/         # 本次新增的 OpenHarmony Electron HAP 工程

传统桌面环境中,pgAdmin runtime 会尝试在本机启动 Python 服务,然后 Electron 窗口加载本机端口,例如:

http://127.0.0.1:5050

但是放到 HarmonyOS PC 的 Electron HAP 里,这条链路会遇到几个问题:

  • HAP 内没有现成的 Python 解释器
  • pgAdmin Web 服务依赖 Python 包和部分 native 能力
  • pgAdmin 还可能依赖 PostgreSQL 客户端工具,例如 psqlpg_dumppg_restore
  • Electron 主进程中的部分桌面能力在 OpenHarmony runtime 中表现不同
  • HAP 资源路径和普通桌面 Electron 的资源路径不同

因此这次没有一上来做“完全离线桌面版”。如果直接硬攻本地 Python,工作量会变成另一类问题:要验证 child_process.spawn、Python runtime、Python native extension、libpq、数据库工具链和 HAP 签名资源的组合可行性。这个目标可以后续继续做,但不是最快让用户在鸿蒙 PC 上用起来的路线。

本次第一阶段目标更明确:

让 pgAdmin4 在 HarmonyOS PC 上先完整打开、登录、连接数据库并完成基本管理操作。

为此选择外部服务模式:

Mac 启动 pgAdmin4 Server
HarmonyOS PC 安装 Electron HAP
HAP 访问 Mac 上的 pgAdmin4 Server
pgAdmin4 Server 再连接 PostgreSQL 测试库

这种方式的好处是适配风险更可控。Electron HAP 只负责承载 pgAdmin runtime 和页面访问能力,不需要在鸿蒙包里立刻解决完整 Python 生态。

三、建立 OpenHarmony Electron HAP 工程

适配后新增了 ohos_hap/ 目录,核心结构如下:

ohos_hap/
├── AppScope/
├── electron/
│   ├── build-profile.json5
│   ├── hvigorfile.ts
│   ├── libs/arm64-v8a/
│   └── src/main/module.json5
├── web_engine/
│   ├── build-profile.json5
│   ├── hvigorfile.ts
│   └── src/main/resources/resfile/
└── build-profile.json5

pgAdmin runtime 最终会被同步到 HAP 的资源目录:

ohos_hap/web_engine/src/main/resources/resfile/resources/app

这个目录就是 OpenHarmony Electron runtime 加载 Node/Electron 应用的位置。构建时会把 pgAdmin 的 Electron runtime 入口、HTML、JS、CSS、assets 和生产依赖同步进去。

本次新增了两个 pgAdmin 自己的鸿蒙构建脚本:

pkg/ohos/build-package.mjs
pkg/ohos/build-hap.mjs

build-package.mjs 负责生成 resources/app,主要做这些事:

  • 清理输出目录
  • 拷贝 runtime/assets
  • 拷贝 runtime/src
  • 写入 OpenHarmony 专用入口 main.cjs
  • 写入生产依赖版 package.json
  • 安装 runtime 生产依赖
  • 根据环境变量注入外部 pgAdmin Server 地址

生成的 main.cjs 会设置关键环境变量:

PGADMIN_OPENHARMONY=1
PGADMIN_DISABLE_GPU=1
PGADMIN_EXTERNAL_SERVER_URL=<外部 pgAdmin Server 地址>

build-hap.mjs 负责把 pgAdmin 资源同步到 ohos_hap,然后调用 Hvigor 构建 HAP。项目根目录 Makefile 中增加了两个入口:

ohos-package:
	node pkg/ohos/build-package.mjs

ohos-hap:
	node pkg/ohos/build-hap.mjs

这样后续构建时只需要执行:

PGADMIN_OHOS_EXTERNAL_SERVER_URL=http://127.0.0.1:5050 make ohos-hap

这里使用 127.0.0.1:5050 不是因为 pgAdmin 服务真的跑在鸿蒙设备内部,而是后面会通过 hdc rport 做 USB 端口反向映射,让鸿蒙 PC 访问自己的 127.0.0.1:5050 时实际连到 Mac 上的 pgAdmin 服务。

在这里插入图片描述

四、给 HAP 补权限和入口

pgAdmin HAP 要访问外部服务,必须允许网络访问。鸿蒙模块配置中补了网络相关权限:

ohos_hap/electron/src/main/module.json5

关键权限包括:

ohos.permission.INTERNET
ohos.permission.GET_NETWORK_INFO

如果缺少 INTERNET,HAP 里的 Electron 页面即使启动了,也无法稳定访问外部 pgAdmin Server。表现出来可能不是很直观,有时看起来只是白屏、等待中或者加载失败。

同时,pgAdmin runtime 增加了 OpenHarmony 平台识别逻辑:

runtime/src/js/platform.js

核心判断包括:

const OPENHARMONY_PLATFORMS = new Set(['ohos', 'openharmony', 'harmony']);

并且通过环境变量读取外部服务地址:

export function getExternalServerUrl() {
  const serverUrl = process.env.PGADMIN_EXTERNAL_SERVER_URL ||
    process.env.PGADMIN_SERVER_URL ||
    process.env.PGADMIN_DEV_SERVER_URL;

  return normalizeServerUrl(serverUrl);
}

这样 HAP 包可以在构建时写死一个默认 pgAdmin Server URL,也可以在没有 URL 时弹出配置页让用户手动输入。

五、Mac 侧启动 pgAdmin4 Server

鸿蒙 PC 侧暂时不内置 Python,所以 Mac 侧需要先把 pgAdmin4 Web 服务启动起来。

本次测试使用的 pgAdmin 配置文件是:

~/XM/pgadmin4-master/web/config_local.py

内容如下:

import os

SERVER_MODE = True
DEFAULT_SERVER = '0.0.0.0'
DEFAULT_SERVER_PORT = 5050
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '.pgadmin-test-data'))
MASTER_PASSWORD_REQUIRED = False
ENHANCED_COOKIE_PROTECTION = False
UPGRADE_CHECK_ENABLED = False

这里有几个关键点:

  • SERVER_MODE = True:按服务模式启动 pgAdmin
  • DEFAULT_SERVER = '0.0.0.0':允许外部设备访问
  • DEFAULT_SERVER_PORT = 5050:固定测试端口
  • DATA_DIR:把测试数据目录放到项目内,方便隔离
  • MASTER_PASSWORD_REQUIRED = False:测试时减少主密码弹窗干扰
  • ENHANCED_COOKIE_PROTECTION = False:降低跨设备测试时 cookie 保护导致的干扰
  • UPGRADE_CHECK_ENABLED = False:避免启动后访问外部版本检查接口造成日志超时

pgAdmin 前端资源需要提前构建。之前页面一直显示等待中,其中一个关键原因就是服务端返回的页面引用了:

/static/js/generated/...

但是这些 generated 静态资源没有构建出来,导致浏览器不断请求 404。

修复方式是在 web/ 目录下重新安装并构建前端资源:

cd ~/XM/pgadmin4-master/web
corepack yarn install
NODE_ENV=production NODE_OPTIONS=--max-old-space-size=3072 corepack yarn run webpacker

然后回到项目根目录启动 pgAdmin 服务:

cd ~/XM/pgadmin4-master
.pgadmin-test-venv/bin/python web/pgAdmin4.py

本次测试账号:

test@example.com
testpass

服务启动后,Mac 本机可访问:

http://127.0.0.1:5050

如果使用同一局域网测试,也可以让鸿蒙 PC 访问:

http://<Mac 局域网 IP>:5050

但本次最终采用的是 USB reverse 方式,稳定性更好,不依赖 Wi-Fi IP 是否变化。

六、构建、安装和 USB reverse

构建 HAP 的命令:

cd ~/XM/pgadmin4-master
PGADMIN_OHOS_EXTERNAL_SERVER_URL=http://127.0.0.1:5050 make ohos-hap

构建成功后会输出 HAP 文件,本次最终安装的是:

ohos_hap/electron/build/default/outputs/default/electron-default-signed.hap

安装到 HarmonyOS PC 设备:

/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc \
  -t 3QC0124C20001268 \
  install -r ohos_hap/electron/build/default/outputs/default/electron-default-signed.hap

建立 USB reverse:

/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc \
  -t 3QC0124C20001268 \
  rport tcp:5050 tcp:5050

如果看到类似下面的提示:

[Fail]TCP Port listen failed at 5050

不一定是失败,也可能是映射已经存在。可以直接在鸿蒙设备侧验证:

/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc \
  -t 3QC0124C20001268 \
  shell wget -O - http://127.0.0.1:5050/login

只要能返回 pgAdmin 登录页 HTML,就说明鸿蒙设备访问 127.0.0.1:5050 已经能打到 Mac 侧服务。

在这里插入图片描述

七、白屏问题定位和修复

最开始 HAP 装到鸿蒙 PC 后,出现过白屏和启动异常。这里的问题不是单一原因,而是几处 Electron runtime 差异叠加出来的。

7.1 GPU 禁用时机导致主进程异常

pgAdmin runtime 原来会调用:

app.disableHardwareAcceleration()

在 OpenHarmony Electron runtime 中,应用可能已经进入 ready 状态后才执行到这段逻辑。如果此时继续调用,就可能触发异常,导致主进程启动链路中断。

修复后改成先追加命令行开关:

app.commandLine.appendSwitch('disable-gpu');
app.commandLine.appendSwitch('disable-gpu-compositing');

如果 app.isReady() 已经为 true,就只打印信息,不再强行调用 app.disableHardwareAcceleration()

console.info('Skipping app.disableHardwareAcceleration(); Electron app is already ready.');

7.2 菜单数据未到导致 map 报错

日志里还出现过:

TypeError: Cannot read properties of undefined (reading 'map')

问题点在:

runtime/src/js/menu.js

pgAdmin 的菜单数据来自 renderer 侧。如果 refreshMenus() 执行时 renderer 还没有发送完整菜单数据,原逻辑直接对空值执行 map,就会让主进程报错。

修复思路是对菜单数据做空保护:

if (!Array.isArray(cachedMenus)) {
  return;
}

同时 bindMenuClicks() 里也对 submenu 做数组判断,菜单为空时退回最小可用菜单。这样即使 renderer 菜单数据还没到,主窗口也不会因为菜单刷新而崩。

7.3 外部服务加载失败时没有稳定兜底

pgAdmin 在普通桌面环境下默认自己拉起 Python 服务。但在 OpenHarmony 模式下,我们希望优先加载外部 pgAdmin Server。

因此 runtime/src/js/pgadmin.js 做了几处调整:

  • OpenHarmony 下默认进入 external server mode
  • 优先复用主窗口,不再依赖额外小窗口承载配置页
  • 加入 did-fail-load 监听
  • 加入 15 秒加载超时
  • 加载失败时回到 Server URL 配置页
  • 配置页通过 window.pgadminSetExternalServerStatus 显示具体失败原因

对应配置页在:

runtime/src/html/external_server.html

其中暴露了状态更新函数:

window.pgadminSetExternalServerStatus = setStatus;

这样一来,如果 HAP 里配置了错误的旧 IP,例如:

http://192.168.0.76:5050/

页面不会一直白屏,而是能退回 URL 配置页面,让用户重新填写可访问地址。

八、一直显示等待中的问题

白屏修完之后,又遇到过页面一直显示“等待中”的问题。

这次的核心不是 HAP 没启动,而是 pgAdmin Web 页面加载后,前端静态资源没有完整返回。服务端页面里引用了 generated bundle:

/static/js/generated/...

但本地 web 目录没有构建出对应产物,导致 HarmonyOS PC 上的页面一直等不到完整前端资源。这个问题在 Mac 浏览器里直接打开 http://127.0.0.1:5050 也能发现,只是放到 HAP 里表现为一直等待。

处理方式就是重新构建 pgAdmin Web 前端:

cd ~/XM/pgadmin4-master/web
corepack yarn install
NODE_ENV=production NODE_OPTIONS=--max-old-space-size=3072 corepack yarn run webpacker

构建完成后,重启 Mac 侧 pgAdmin Server,再重新打开鸿蒙 PC 上的 HAP。此时页面就可以进入 pgAdmin 登录页。

这个问题也说明,适配 Electron HAP 时不要只盯鸿蒙侧。如果页面卡在等待中,要同时看三边:

  • HAP 主进程日志
  • HarmonyOS PC 到服务端的网络连通性
  • Mac 上 pgAdmin Server 自己是否能完整返回前端资源

九、鸿蒙 PC 上登录 pgAdmin

在 Mac 侧服务启动、USB reverse 建立、HAP 安装完成后,打开 HarmonyOS PC 上的 pgAdmin 应用。

如果 HAP 构建时已经写入:

PGADMIN_OHOS_EXTERNAL_SERVER_URL=http://127.0.0.1:5050

应用启动后会直接加载:

http://127.0.0.1:5050

因为 USB reverse 已经建立,这个地址实际会访问 Mac 上的 pgAdmin Server。

登录信息:

Email: test@example.com
Password: testpass

登录成功后,可以看到 pgAdmin 的 Browser 树、Dashboard、菜单和主体页面正常显示。

在这里插入图片描述

十、连接 PostgreSQL 测试库

为了确认不是“只打开了页面”,还需要真的连一次 PostgreSQL。

本次使用了一个本地 Docker PostgreSQL 测试容器:

容器名:nexent-postgresql
端口:5434 -> 5432
数据库:nexent
用户名:root
密码:nexent@4321

pgAdmin 中导入的测试服务器配置文件:

~/XM/pgadmin4-master/.ohos_build/pgadmin-test-servers.json

导入命令:

cd ~/XM/pgadmin4-master
.pgadmin-test-venv/bin/python web/setup.py load-servers \
  ~/XM/pgadmin4-master/.ohos_build/pgadmin-test-servers.json \
  --user test@example.com \
  --sqlite-path ~/XM/pgadmin4-master/.pgadmin-test-data/pgadmin4.db

导入后 pgAdmin 左侧对象树中可以看到:

local-test-nexent

连接成功后,可以展开:

Databases
Login/Group Roles
Tablespaces

也可以执行测试 SQL:

select * from codex_pgadmin_ohos_test;

测试数据中包含:

ohos-pgadmin-test

到这一步,说明 HarmonyOS PC 上运行的 pgAdmin HAP 已经不只是“能打开”,而是可以通过 Mac 侧 pgAdmin Server 实际完成数据库管理链路。

在这里插入图片描述

十一、这次适配涉及的关键文件

本次适配核心修改和新增文件可以按作用分成几类。

第一类是 OpenHarmony 平台识别:

runtime/src/js/platform.js

它负责判断当前是否是 OpenHarmony 环境、是否禁用 GPU、是否读取外部服务地址,以及是否显式启用本地 Python 模式。

第二类是 pgAdmin Electron 主进程:

runtime/src/js/pgadmin.js

主要改动包括:

  • OpenHarmony 下默认进入 external server mode
  • 支持通过 PGADMIN_EXTERNAL_SERVER_URL 加载外部 pgAdmin Server
  • 加载失败时回退到 URL 配置页
  • 复用主窗口承载配置页和 pgAdmin 页面
  • 避免 ready 后继续调用 app.disableHardwareAcceleration()
  • OpenHarmony 下不启动自动更新流程

第三类是菜单兼容:

runtime/src/js/menu.js

主要修复菜单数据为空时的崩溃问题。renderer 侧菜单还没发过来时,主进程不再对 undefined 调用 map,并提供最小菜单兜底。

第四类是外部服务配置页:

runtime/src/html/external_server.html

这个页面用于在没有内置 Python 服务时,让用户输入已有 pgAdmin Server 地址。加载失败时也可以把错误原因显示到页面底部。

第五类是 HAP 构建脚本:

pkg/ohos/build-package.mjs
pkg/ohos/build-hap.mjs

它们把 pgAdmin runtime 同步到 HAP 的 resources/app,再调用 Hvigor 生成 HAP。

第六类是 OpenHarmony HAP 工程:

ohos_hap/

这里包含 Electron 模块、web_engine 模块、OpenHarmony 配置、权限、native runtime 库和最终构建产物。

十二、最终验证结果

最终验证结果如下:

  • HAP 可以成功构建
  • HAP 可以安装到 HarmonyOS PC
  • 应用启动后不再白屏
  • 旧 IP 或服务不可达时可以回到 Server URL 配置页
  • USB reverse 到 127.0.0.1:5050 可用
  • pgAdmin 登录页正常显示
  • test@example.com / testpass 可以登录
  • 可以展开 local-test-nexent
  • 可以查看 DatabasesLogin/Group RolesTablespaces
  • Dashboard 页面和图表可以正常显示
  • PostgreSQL 测试表 codex_pgadmin_ohos_test 可以查询

这说明本次适配已经达到“用户可以使用”的第一阶段目标。

十三、总结

pgAdmin4 的鸿蒙 PC 适配和普通 Electron 应用不太一样。普通 Electron 应用通常只需要处理主进程、renderer、资源路径和少量 API 兼容。但 pgAdmin4 背后还有 Python Flask 服务、前端构建产物、SQLite 用户数据、PostgreSQL 连接配置和数据库客户端生态。

所以这次没有直接把问题扩大成“在鸿蒙 HAP 中完整内置 Python 桌面版 pgAdmin”,而是先做了一个可运行、可登录、可连接数据库的 OpenHarmony Electron HAP 版本。

这条路径的关键是:

  • Electron HAP 负责承载 pgAdmin runtime
  • Mac 负责启动 pgAdmin Web 服务
  • 通过 USB reverse 或局域网让鸿蒙 PC 访问服务
  • pgAdmin Server 再连接真实 PostgreSQL

在这个基础上,下一阶段如果继续做完全离线版,就可以再攻本地 Python runtime、Python 依赖、libpq 和 PostgreSQL 工具链。但从用户可用角度看,目前这个版本已经完成了从启动、登录到数据库连接验证的完整闭环。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐