Electron for HarmonyOS_PC Swifty 密码管理器适配开源鸿蒙PC开发实践

📋 项目概述

本文档基于一个完整的 Swifty 密码管理器 适配项目,详细介绍了如何在 HarmonyOS PC 平台上使用 Electron for HarmonyOS 框架,将成熟的 Electron 应用(Swifty)成功运行在鸿蒙 PC 设备上。项目实现了完整的应用集成、资源文件管理、多语言支持等功能,展示了 Electron 应用在 HarmonyOS 平台上的实际适配经验。

项目功能
  • ✅ 完整的 Swifty 密码管理器功能(登录/密码存储、信用卡信息、安全笔记)
  • ✅ 强密码生成器(一键生成)
  • ✅ 基于时间的一次性密码支持(TOTP)
  • ✅ Google Drive 同步(可选)
  • ✅ 本地加密存储(AES-256-GCM)
  • ✅ 多语言支持(i18n)
  • ✅ 完整的 Electron 主进程和渲染进程集成
  • ✅ 响应式布局,适配鸿蒙 PC 屏幕
原始项目对比

原始项目(Swifty Electron)

  • 使用 Electron 27.x + React 18 + Redux Toolkit
  • 使用 Webpack 打包构建
  • 支持 macOS、Windows、Linux 多平台
  • 使用 bozon 作为构建工具
  • 标准的 Electron 应用结构(main、renderer、preload)

HarmonyOS 适配版本(Electron for HarmonyOS)

  • 使用 Electron for HarmonyOS 框架
  • 集成到 HarmonyOS HAP 包中
  • 适配鸿蒙 PC 平台的文件系统和资源管理
  • 修改主进程入口以适配 HarmonyOS 生命周期
  • 调整文件路径和资源加载方式
  • 配置 Content-Security-Policy 以允许本地资源加载

📸 效果展示

以下是 Swifty 密码管理器在 HarmonyOS PC 平台上的运行效果:

演示示例 1

Swifty 应用主界面在 HarmonyOS PC 上的显示效果

演示示例 2

Swifty 密码管理功能在鸿蒙PC上的实际运行效果

从效果图可以看出,Swifty 应用已成功适配到 HarmonyOS PC 平台,界面显示正常,功能完整可用。


🎯 核心技术要点

1. HarmonyOS Electron 主进程入口:main.js

⚠️ 关键要点 :必须在 app.whenReady() 之前加载 Swifty 主进程代码!

javascript 复制代码
// ✅ 正确写法
const { app, BrowserWindow } = require('electron');
const path = require('path');

// 设置 swifty 需要的 CONFIG 变量
global.CONFIG = {
    appId: 'fcae8dc8cd68b98ad0aa7da1b8479a94edde0eb698acb7e537a94a185b5b1425',
    width: 460,
    height: 500,
    analytics: null,
    reload: true,
    devTools: true,
    apiHost: 'https://getswifty.pro',
    autoUpdate: false,
    googleOauth: {
        scope: 'https://www.googleapis.com/auth/drive.file'
    }
};

// ⚠️ 关键:在 app ready 之前加载 swifty 主进程
const swiftyMainPath = path.join(__dirname, 'swifty', 'main', 'index.js');
try {
    require(swiftyMainPath);
    // swifty 主进程会自己注册 app.on('ready') 事件并创建窗口
} catch (error) {
    console.error('Error loading swifty main process:', error);
    // 如果加载失败,使用备用窗口创建方式
    app.whenReady().then(() => {
        createWindow();
    });
}

// ❌ 错误写法(会导致 ready 事件丢失)
app.whenReady().then(() => {
    require(swiftyMainPath);  // Swifty 的 app.on('ready') 可能不会被调用
});

原因说明

  • Swifty 主进程代码内部注册了 app.on('ready') 事件处理器
  • 如果在 app.whenReady() 之后加载,Swifty 的 ready 处理器可能无法正确注册
  • 必须在应用启动早期加载,确保事件监听器正确绑定

2. 硬件加速禁用配置

⚠️ 关键要点:HarmonyOS PC 上需要禁用硬件加速以避免渲染问题!

javascript 复制代码
// Step 1: 在 Electron 层面禁用硬件加速
app.disableHardwareAcceleration();

// Step 2: 在 Chromium 层面追加命令行开关,彻底禁用 GPU
app.commandLine.appendSwitch('disable-gpu');

配置说明

  • app.disableHardwareAcceleration():禁用 Electron 的硬件加速
  • disable-gpu 开关:在 Chromium 层面禁用 GPU 渲染
  • 这两个配置必须同时使用,确保在 HarmonyOS PC 上稳定运行

3. 文件路径和资源管理
3.1 资源文件路径配置
javascript 复制代码
function createWindow() {
    // ⚠️ 关键:使用 path.join 构建正确的资源路径
    const swiftyRendererPath = path.join(__dirname, 'swifty', 'renderer', 'index.html');
    const swiftyPreloadPath = path.join(__dirname, 'swifty', 'preload', 'index.js');
  
    const win = new BrowserWindow({
        width: 460,
        height: 500,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
            preload: swiftyPreloadPath,
            webSecurity: false  // ⚠️ 允许加载本地资源
        }
    });
  
    win.loadFile(swiftyRendererPath);
}

路径结构

复制代码
web_engine/src/main/resources/resfile/resources/app/
├── main.js                    # Electron 主进程入口
├── swifty/                    # Swifty 应用目录
│   ├── main/                  # 主进程代码
│   │   └── locales/           # 多语言文件
│   ├── preload/               # Preload 脚本
│   │   └── index.js
│   └── renderer/              # 渲染进程代码
│       ├── index.html
│       └── index.js
3.2 多语言文件路径

⚠️ 关键要点 :locales 文件必须放在 main/locales/ 目录下!

javascript 复制代码
// Swifty 的 i18n 模块会查找以下路径:
// app.getAppPath() + 'main/locales/'

// ✅ 正确位置
web_engine/src/main/resources/resfile/resources/app/main/locales/
├── en-US.json
├── zh-CN.json
└── ...

// ❌ 错误位置(会导致 ENOENT 错误)
web_engine/src/main/resources/resfile/resources/app/swifty/main/locales/

解决方法

bash 复制代码
# 复制 locales 文件到正确位置
mkdir -p web_engine/src/main/resources/resfile/resources/app/main/locales
cp -r swifty/builds/development/main/locales/* \
  web_engine/src/main/resources/resfile/resources/app/main/locales/

4. Content-Security-Policy 配置

⚠️ 关键要点:必须放宽 CSP 策略以允许本地资源加载!

html 复制代码
<!-- ✅ 正确配置 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Swifty</title>
    <meta
        http-equiv="Content-Security-Policy"
        content="default-src 'self' 'unsafe-inline' 'unsafe-eval'; 
                 img-src 'self' data:; 
                 script-src 'self' 'unsafe-inline' 'unsafe-eval'; 
                 style-src 'self' 'unsafe-inline';"
    />
    <script src="index.js" type="text/javascript"></script>
</head>
<body>
    <div id="root"></div>
</body>
</html>

配置说明

  • 'unsafe-inline':允许内联脚本和样式(React 需要)
  • 'unsafe-eval' :允许 eval() 函数(Webpack 开发模式需要)
  • data::允许 data URI 图片(Base64 图片)
  • 这些配置对于 Electron 应用在 HarmonyOS 上运行是必需的

5. 应用图标和名称配置
5.1 应用图标
bash 复制代码
# 复制 Swifty 图标到鸿蒙项目
cp swifty/build/icon.png \
  ElectronForHarmony_swifty/AppScope/resources/base/media/app_icon.png
cp swifty/build/icon.png \
  ElectronForHarmony_swifty/AppScope/resources/base/media/product_logo_32.png
cp swifty/build/icon.png \
  ElectronForHarmony_swifty/AppScope/resources/base/media/startIcon.png
5.2 应用名称
json 复制代码
// AppScope/resources/base/element/string.json
{
    "string": [
        {
            "name": "app_name",
            "value": "Swifty"
        }
    ]
}

💡 完整代码示例

主进程入口文件 (main.js)
javascript 复制代码
const { app, BrowserWindow } = require('electron');
const path = require('path');

// 1. 禁用硬件加速(HarmonyOS PC 必需)
app.disableHardwareAcceleration();
app.commandLine.appendSwitch('disable-gpu');

// 2. 设置 Swifty 需要的全局配置
global.CONFIG = {
    appId: 'fcae8dc8cd68b98ad0aa7da1b8479a94edde0eb698acb7e537a94a185b5b1425',
    width: 460,
    height: 500,
    analytics: null,
    reload: true,
    devTools: true,
    apiHost: 'https://getswifty.pro',
    autoUpdate: false,
    googleOauth: {
        scope: 'https://www.googleapis.com/auth/drive.file'
    }
};

// 3. 备用窗口创建函数
function createWindow() {
    const swiftyRendererPath = path.join(__dirname, 'swifty', 'renderer', 'index.html');
    const swiftyPreloadPath = path.join(__dirname, 'swifty', 'preload', 'index.js');
  
    console.log('Creating window...');
    console.log('Renderer path:', swiftyRendererPath);
    console.log('Preload path:', swiftyPreloadPath);
  
    const win = new BrowserWindow({
        width: 460,
        height: 500,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
            preload: swiftyPreloadPath,
            webSecurity: false  // 允许加载本地资源
        }
    });

    // 打开开发者工具以便调试
    win.webContents.openDevTools();
  
    // 加载 Swifty 渲染进程页面
    win.loadFile(swiftyRendererPath).then(() => {
        console.log('Window loaded successfully');
    }).catch((error) => {
        console.error('Error loading window:', error);
    });
}

// 4. ⚠️ 关键:在 app ready 之前加载 Swifty 主进程
const swiftyMainPath = path.join(__dirname, 'swifty', 'main', 'index.js');
console.log('Attempting to load swifty main process from:', swiftyMainPath);

try {
    require(swiftyMainPath);
    console.log('Swifty main process loaded successfully - it will manage window creation');
    // Swifty 主进程会自己注册 app.on('ready') 事件并创建窗口
} catch (error) {
    console.error('Error loading swifty main process:', error.message);
    console.error('Error stack:', error.stack);
    // 如果加载失败,使用备用窗口创建方式
    app.whenReady().then(() => {
        console.log('App is ready, falling back to simple window creation');
        createWindow();
    });
}

// 5. 窗口关闭处理
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit();
    }
});

🚀 构建和部署流程

Step 1: 安装 Swifty 依赖
bash 复制代码
cd swifty
npm install

# ⚠️ 注意:需要 GitHub Personal Access Token
# 配置 .npmrc 文件:
# @swiftyapp:registry=https://npm.pkg.github.com
# always-auth=true
# //npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
Step 2: 构建 Swifty 应用
bash 复制代码
# 使用 bozon 构建(开发模式)
npm start

# 构建产物位于:swifty/builds/development/
Step 3: 复制文件到鸿蒙项目
bash 复制代码
cd ../ElectronForHarmony_swifty

# 复制 Swifty 构建文件
cp -r ../swifty/builds/development \
  web_engine/src/main/resources/resfile/resources/app/swifty

# 复制多语言文件(⚠️ 关键:必须放在 main/locales/)
mkdir -p web_engine/src/main/resources/resfile/resources/app/main/locales
cp -r ../swifty/builds/development/main/locales/* \
  web_engine/src/main/resources/resfile/resources/app/main/locales/

# 复制 preload 脚本
mkdir -p web_engine/src/main/resources/resfile/resources/app/preload
cp ../swifty/builds/development/preload/index.js \
  web_engine/src/main/resources/resfile/resources/app/preload/

# 复制 renderer 文件
mkdir -p web_engine/src/main/resources/resfile/resources/app/renderer
cp -r ../swifty/builds/development/renderer/* \
  web_engine/src/main/resources/resfile/resources/app/renderer/
Step 4: 配置应用图标和名称
bash 复制代码
# 复制应用图标
cp ../swifty/build/icon.png \
  AppScope/resources/base/media/app_icon.png

# 修改应用名称(编辑 string.json)
# AppScope/resources/base/element/string.json
Step 5: 在 DevEco Studio 中构建
  1. 打开 ElectronForHarmony_swifty 项目
  2. 点击 Build → Build Hap(s)/APP(s) → Build Hap(s)
  3. 等待构建完成
Step 6: 安装到鸿蒙 PC
bash 复制代码
# 使用 hdc 工具安装
hdc install electron/build/default/outputs/default/electron-default-signed.hap

# 或者在 DevEco Studio 中点击 Run 按钮

🐛 常见问题与解决方案

问题 1:白屏(应用无法显示)

错误现象

  • 应用启动后显示空白窗口
  • 控制台没有错误信息

可能原因

  1. Swifty 主进程加载失败
  2. Renderer 进程的 JavaScript 未执行
  3. Preload 脚本未正确加载
  4. Content-Security-Policy 过于严格

解决方法

javascript 复制代码
// 1. 检查主进程加载顺序
// ✅ 确保在 app.whenReady() 之前加载
require(swiftyMainPath);

// 2. 检查文件路径
console.log('Renderer path:', swiftyRendererPath);
console.log('Preload path:', swiftyPreloadPath);

// 3. 放宽 CSP 策略
// 在 index.html 中修改 Content-Security-Policy

// 4. 打开 DevTools 查看错误
win.webContents.openDevTools();

问题 2:找不到 locales 文件

错误信息

复制代码
ENOENT: no such file or directory, open '.../main/locales/en-US.json'

原因

  • Swifty 的 i18n 模块查找路径为:app.getAppPath() + 'main/locales/'
  • 文件被放在了错误的位置

解决方法

bash 复制代码
# ✅ 正确位置
web_engine/src/main/resources/resfile/resources/app/main/locales/

# ❌ 错误位置
web_engine/src/main/resources/resfile/resources/app/swifty/main/locales/

# 复制文件到正确位置
mkdir -p web_engine/src/main/resources/resfile/resources/app/main/locales
cp -r swifty/builds/development/main/locales/* \
  web_engine/src/main/resources/resfile/resources/app/main/locales/

问题 3:GitHub Token 认证失败

错误信息

复制代码
npm error 401 Unauthorized - GET https://npm.pkg.github.com/download/@swiftyapp/cryptor/...

原因

  • Swifty 依赖私有包 @swiftyapp/cryptor
  • 需要 GitHub Personal Access Token 才能下载

解决方法

bash 复制代码
# 1. 创建 GitHub Personal Access Token
# Settings → Developer settings → Personal access tokens → Tokens (classic)
# 权限:read:packages

# 2. 配置环境变量
export NODE_AUTH_TOKEN=your_token_here

# 3. 配置 .npmrc
cat > swifty/.npmrc << EOF
@swiftyapp:registry=https://npm.pkg.github.com
always-auth=true
//npm.pkg.github.com/:_authToken=\${NODE_AUTH_TOKEN}
EOF

# 4. 永久设置(MacOS)
echo 'export NODE_AUTH_TOKEN=your_token_here' >> ~/.zshrc
source ~/.zshrc

问题 4:应用图标未更新

现象

  • 构建后应用图标仍然是默认图标
  • 应用名称未更改

解决方法

bash 复制代码
# 1. 确认图标文件已更新
ls -lh AppScope/resources/base/media/app_icon.png

# 2. 确认应用名称配置
cat AppScope/resources/base/element/string.json

# 3. 清理构建缓存
# 在 DevEco Studio 中:Build → Clean Project

# 4. 重新构建
# Build → Build Hap(s)/APP(s) → Build Hap(s)

📁 项目结构说明

复制代码
ElectronForHarmony_swifty/
├── AppScope/                          # 应用配置
│   ├── app.json5                     # 应用配置(应用名称:Swifty)
│   └── resources/
│       └── base/
│           ├── media/
│           │   └── app_icon.png      # Swifty 应用图标
│           └── element/
│               └── string.json       # 应用名称配置
├── electron/                          # Electron 模块
│   └── src/main/
│       └── ets/                      # 鸿蒙原生代码
├── web_engine/                       # Web 引擎模块
│   └── src/main/
│       └── resources/
│           └── resfile/
│               └── resources/
│                   └── app/
│                       ├── main.js   # Electron 主进程入口 ⚠️ 关键文件
│                       ├── main/     # Swifty 主进程代码
│                       │   └── locales/  # 多语言文件 ⚠️ 关键目录
│                       ├── preload/  # Preload 脚本
│                       └── renderer/ # Swifty 渲染进程代码
└── build-profile.json5               # 构建配置

⚠️ 重要注意事项

  1. 主进程加载顺序 :必须在 app.whenReady() 之前加载 Swifty 主进程代码,否则 ready 事件监听器无法正确注册。

  2. 硬件加速:HarmonyOS PC 上必须禁用硬件加速,否则可能导致渲染问题。

  3. 文件路径:确保所有文件路径正确,特别是:

    • main/locales/ - 多语言文件必须放在这个位置
    • preload/index.js - Preload 脚本路径
    • renderer/index.html - 渲染进程入口
  4. Content-Security-Policy:必须放宽 CSP 策略以允许本地资源加载和 React 运行。

  5. GitHub Token:Swifty 依赖私有包,需要配置 GitHub Personal Access Token。

  6. 应用图标和名称:修改后需要清理构建缓存并重新构建。


📦 构建产物

构建完成后,HAP 包位于:

复制代码
electron/build/default/outputs/default/electron-default-signed.hap

可以使用 hdc 工具安装到鸿蒙 PC:

bash 复制代码
hdc install electron/build/default/outputs/default/electron-default-signed.hap

🔗 相关资源


📄 许可证

本项目基于 Swifty 项目(GNU/GPL Version 3)和 Electron for HarmonyOS 框架。

相关推荐
少卿2 小时前
React Compiler 完全指南:自动化性能优化的未来
前端·javascript
爱隐身的官人2 小时前
beef-xss hook.js访问失败500错误
javascript·xss
军军3603 小时前
从图片到点阵:用JavaScript重现复古数码点阵艺术图
前端·javascript
znhy@1233 小时前
Vue基础知识(一)
前端·javascript·vue.js
肖邦不歌唱3 小时前
electron 图片缩放后无法拖动
前端·electron
学习吖4 小时前
vue中封装的函数常用方法(持续更新)
大数据·javascript·vue.js·ajax·前端框架
范特东南西北风4 小时前
Wappalyzer 原型链漏洞问题完整解决过程
前端·javascript
fruge4 小时前
自制浏览器插件:实现网页内容高亮、自动整理收藏夹功能
开发语言·前端·javascript
爱笑的眼睛114 小时前
ArkTS接口与泛型在HarmonyOS应用开发中的深度应用
华为·harmonyos
英俊潇洒的码农5 小时前
Array.isArray()性能测试
前端·javascript