前言

随着鸿蒙生态(HarmonyOS)的持续扩张,其分布式能力已成为核心竞争力之一 —— 打破设备壁垒,实现手机、PC、平板、智能穿戴等多终端的无缝协同,正是鸿蒙 “万物互联” 理念的核心落地。而 Electron 作为跨平台桌面应用开发框架,凭借 “一次开发、多端运行” 的特性,在桌面端开发中占据重要地位。

当 Electron 桌面应用接入鸿蒙生态,如何利用鸿蒙的分布式数据管理(Distributed Data Management, DDM) 能力实现跨设备通信与数据同步?这一需求在办公协同、智能家居控制、跨端文件传输等场景中尤为迫切。

本文将从基础概念解析→环境搭建→实战开发→进阶优化→问题排查,全方位拆解鸿蒙 + Electron 跨设备通信的实现方案,提供可直接运行的代码示例和完整项目结构,帮助开发者快速掌握多端协同核心技术,适配鸿蒙生态的跨设备场景开发。

本文配套代码已开源至 GitHub:harmonyos-electron-ddm-demo(注:实际发布时替换为真实仓库链接),建议结合代码阅读本文,效果更佳。适配环境:HarmonyOS 4.0+、Electron 28.0+、CANN 7.0+、Node.js 18.x

一、核心概念铺垫

在进入实战前,需先理清鸿蒙分布式数据管理与 Electron 跨设备通信的核心技术点,避免开发中 “知其然不知其所以然”。

1.1 鸿蒙分布式数据管理(DDM)核心能力

鸿蒙 DDM 是鸿蒙分布式技术栈的核心模块,旨在解决多设备间数据一致、实时同步、权限管控等问题,核心特性包括:

  • 分布式数据对象:支持将普通数据结构(如 UserInfo、DeviceStatus)封装为分布式对象,通过注解(如 @DistributedData)标记后,自动实现跨设备同步。
  • 数据同步模式:提供两种核心同步策略:
    • 主动同步:通过 DataSyncManager 调用 sync() 方法触发即时同步;
    • 被动同步:数据变更时通过观察者模式(DataObserver)自动通知所有关联设备。
  • 设备发现与组网:依赖鸿蒙分布式软总线(Distributed Soft Bus),自动发现同一局域网内的鸿蒙设备,无需手动配置 IP。
  • 权限管控:通过 distributed_permission 模块申请跨设备数据访问权限,确保数据安全。

官方文档参考:鸿蒙分布式数据管理开发指南

1.2 Electron 与鸿蒙的适配逻辑

Electron 基于 Chromium 和 Node.js,本质是 “桌面端 Web 应用容器”。要让 Electron 接入鸿蒙分布式能力,核心是通过 鸿蒙 Node.js 原生模块(@ohos/node-api) 实现桥接,逻辑如下:

  • Electron 主进程(Node.js 环境)通过鸿蒙提供的 Node.js SDK 调用 DDM 相关 API;
  • 渲染进程(Web 环境)通过 IPC 通信(Electron 的 ipcMain/ipcRenderer)与主进程交互,间接操作分布式数据;
  • 跨设备通信时,Electron 端作为 “鸿蒙分布式网络中的一个节点”,与其他鸿蒙设备(如手机、平板)通过软总线进行数据传输。

1.3 跨设备通信的核心流程

基于 DDM 的多端协同方案,核心流程可概括为 5 步:

  1. 设备组网:Electron 端与其他鸿蒙设备通过软总线自动发现并建立连接;
  2. 数据建模:定义分布式数据对象(如跨端共享的任务列表、设备状态);
  3. 权限申请:Electron 端向系统申请跨设备数据访问权限;
  4. 数据操作:Electron 端或其他设备对分布式数据进行增删改查;
  5. 同步回调:所有关联设备通过观察者监听数据变更,触发 UI 刷新或业务逻辑执行。

二、开发环境搭建(详细步骤)

环境搭建是实战的基础,需同时配置鸿蒙开发环境和 Electron 开发环境,确保两者兼容。

2.1 前提条件

  • 硬件要求:
    • 开发机:Windows 10/11 64 位(推荐)或 macOS 12+;
    • 测试设备:至少 2 台支持鸿蒙 4.0+ 的设备(如华为手机、鸿蒙平板),或 1 台设备 + 1 个鸿蒙模拟器;
    • 网络:所有设备处于同一局域网(Wi-Fi 或有线)。
  • 软件要求:
    • 鸿蒙开发工具:DevEco Studio 4.0+(下载链接);
    • Node.js:18.x LTS(下载链接);
    • Electron:28.0+(通过 npm 安装);
    • 鸿蒙 Node.js SDK:@ohos/hvigor 3.0+、@ohos/distributed-data 1.0+(通过 npm 安装);
    • 依赖工具:CMake 3.20+(用于编译鸿蒙原生模块)、Python 3.8+。

2.2 鸿蒙环境配置(关键步骤)

  1. 安装 DevEco Studio 后,在 SDK Manager 中下载:
    • HarmonyOS SDK(API Version 10+);
    • Node.js SDK for HarmonyOS(确保版本与 Node.js 18.x 兼容);
    • 分布式能力相关模块(Distributed Data Management、Distributed Soft Bus)。
  2. 配置环境变量:

    bash

    运行

    # Windows 系统(cmd 命令行)
    set HARMONYOS_SDK_PATH=D:\DevEcoStudio\sdk\harmonyos
    set NODE_PATH=%HARMONYOS_SDK_PATH%\nodejs\lib\node_modules
    # macOS/Linux 系统(终端)
    export HARMONYOS_SDK_PATH=/Users/xxx/DevEcoStudio/sdk/harmonyos
    export NODE_PATH=$HARMONYOS_SDK_PATH/nodejs/lib/node_modules
    
  3. 验证鸿蒙环境:

    bash

    运行

    hdc shell "hilog | grep distributed_data"  # 查看分布式数据服务日志
    

2.3 Electron 项目初始化与依赖安装

  1. 创建 Electron 项目并初始化:

    bash

    运行

    mkdir harmonyos-electron-ddm-demo
    cd harmonyos-electron-ddm-demo
    npm init -y
    # 安装核心依赖
    npm install electron@28.0.0 --save-dev
    npm install @ohos/distributed-data@1.0.0 --save  # 鸿蒙分布式数据管理 SDK
    npm install @ohos/distributed_permission@1.0.0 --save  # 鸿蒙分布式权限 SDK
    npm install electron-rebuild --save-dev  # 重建原生模块依赖
    
  2. 配置 package.json:

    json

    {
      "name": "harmonyos-electron-ddm-demo",
      "version": "1.0.0",
      "main": "main.js",
      "scripts": {
        "start": "electron .",
        "rebuild": "electron-rebuild -f -w @ohos/distributed-data"
      },
      "dependencies": {
        "@ohos/distributed-data": "^1.0.0",
        "@ohos/distributed_permission": "^1.0.0"
      },
      "devDependencies": {
        "electron": "^28.0.0",
        "electron-rebuild": "^3.2.9"
      },
      "engines": {
        "node": ">=18.x"
      }
    }
    
  3. 重建原生模块(关键步骤,避免鸿蒙 SDK 与 Electron 不兼容):

    bash

    运行

    npm run rebuild
    

2.4 环境验证

创建简单的测试文件 test-env.js,验证鸿蒙 SDK 是否正常加载:

javascript

运行

// test-env.js
const { DistributedDataManager } = require('@ohos/distributed-data');

try {
  const dataManager = new DistributedDataManager();
  console.log('鸿蒙分布式数据管理模块加载成功!');
  console.log('当前支持的同步模式:', dataManager.getSupportedSyncModes());
} catch (error) {
  console.error('环境配置失败:', error.message);
}

运行测试脚本:

bash

运行

node test-env.js

若输出 “鸿蒙分布式数据管理模块加载成功!”,则环境配置完成;若报错,需检查鸿蒙 SDK 版本与 Node.js 版本是否兼容,或重新执行 npm run rebuild

三、实战开发:跨设备通信核心功能实现

本章节将基于 “跨设备任务列表同步” 场景,实现核心功能:设备发现、分布式数据建模、数据同步、多端交互。项目结构如下:

plaintext

harmonyos-electron-ddm-demo/
├── main.js          # Electron 主进程(核心逻辑:DDM 调用、设备管理)
├── renderer/        # 渲染进程(UI 界面:任务列表、设备列表)
│   ├── index.html   # 前端页面
│   ├── renderer.js  # 渲染进程逻辑(IPC 通信、UI 刷新)
│   └── style.css    # 样式文件
├── src/             # 核心模块
│   ├── ddm-manager.js  # 分布式数据管理封装
│   ├── device-manager.js  # 设备发现与管理
│   └── permission-manager.js  # 权限申请封装
└── package.json     # 项目配置

3.1 权限申请封装(permission-manager.js)

跨设备访问需先申请权限,否则会被鸿蒙系统拦截。封装权限申请逻辑:

javascript

运行

// src/permission-manager.js
const { DistributedPermission } = require('@ohos/distributed_permission');

class PermissionManager {
  // 申请跨设备数据访问权限
  async requestDistributedPermission() {
    const permissionName = 'ohos.permission.DISTRIBUTED_DATASYNC'; // 核心权限
    try {
      // 检查权限是否已授予
      const granted = await DistributedPermission.checkPermission(permissionName);
      if (granted) {
        console.log('跨设备数据访问权限已授予');
        return true;
      }
      // 申请权限
      const result = await DistributedPermission.requestPermission(permissionName);
      if (result === 0) { // 0 表示申请成功
        console.log('跨设备数据访问权限申请成功');
        return true;
      } else {
        console.error('权限申请失败,错误码:', result);
        return false;
      }
    } catch (error) {
      console.error('权限操作异常:', error.message);
      return false;
    }
  }

  // 申请设备发现权限(用于获取其他设备信息)
  async requestDeviceDiscoveryPermission() {
    const permissionName = 'ohos.permission.DISTRIBUTED_DEVICE_DISCOVERY';
    try {
      const granted = await DistributedPermission.checkPermission(permissionName);
      if (granted) return true;
      const result = await DistributedPermission.requestPermission(permissionName);
      return result === 0;
    } catch (error) {
      console.error('设备发现权限申请失败:', error.message);
      return false;
    }
  }
}

module.exports = new PermissionManager();

3.2 设备发现与管理(device-manager.js)

通过鸿蒙分布式软总线发现周边鸿蒙设备,获取设备 ID、名称、类型等信息:

javascript

运行

// src/device-manager.js
const { DistributedDeviceManager } = require('@ohos/distributed-data');
const permissionManager = require('./permission-manager');

class DeviceManager {
  constructor() {
    this.deviceManager = new DistributedDeviceManager();
    this.devices = []; // 已发现的设备列表
    this.deviceChangeListener = null; // 设备变更回调
  }

  // 初始化设备发现
  async initDeviceDiscovery() {
    // 先申请设备发现权限
    const hasPermission = await permissionManager.requestDeviceDiscoveryPermission();
    if (!hasPermission) {
      throw new Error('无设备发现权限,无法初始化设备搜索');
    }

    // 注册设备变更监听器
    this.deviceManager.on('deviceChange', (devices) => {
      this.devices = devices.map(device => ({
        deviceId: device.deviceId, // 设备唯一标识
        deviceName: device.deviceName, // 设备名称
        deviceType: device.deviceType, // 设备类型(phone、tablet、pc 等)
        isOnline: device.isOnline // 在线状态
      }));
      console.log('设备列表更新:', this.devices);
      // 通知外部设备变更
      if (this.deviceChangeListener) {
        this.deviceChangeListener(this.devices);
      }
    });

    // 启动设备发现
    await this.deviceManager.startDiscovery();
    console.log('设备发现已启动,正在搜索周边鸿蒙设备...');
  }

  // 注册设备变更回调
  onDeviceChange(callback) {
    this.deviceChangeListener = callback;
  }

  // 获取当前在线设备列表
  getOnlineDevices() {
    return this.devices.filter(device => device.isOnline);
  }

  // 停止设备发现
  async stopDeviceDiscovery() {
    await this.deviceManager.stopDiscovery();
    console.log('设备发现已停止');
  }
}

module.exports = new DeviceManager();

3.3 分布式数据管理封装(ddm-manager.js)

核心模块:定义分布式数据模型、实现数据同步、监听数据变更:

javascript

运行

// src/ddm-manager.js
const { DistributedDataManager, DataSyncMode } = require('@ohos/distributed-data');
const permissionManager = require('./permission-manager');

// 1. 定义分布式数据模型(任务列表)
const TASK_DATA_STORE = 'distributed_task_store'; // 数据存储名称
const TASK_DATA_KEY = 'task_list'; // 数据键名

class DdmManager {
  constructor() {
    this.dataManager = new DistributedDataManager();
    this.dataObserver = null; // 数据变更观察者
  }

  // 初始化分布式数据管理(申请权限 + 初始化数据存储)
  async init() {
    // 申请跨设备数据同步权限
    const hasPermission = await permissionManager.requestDistributedPermission();
    if (!hasPermission) {
      throw new Error('无跨设备数据同步权限,无法初始化 DDM');
    }

    // 初始化数据存储(若不存在则创建)
    await this.dataManager.initDataStore(TASK_DATA_STORE);
    console.log('分布式数据存储初始化成功:', TASK_DATA_STORE);

    // 注册数据变更观察者
    this.dataManager.on('dataChange', (dataStore, key, value) => {
      console.log(`数据变更:${dataStore}.${key} =`, value);
      if (this.dataObserver) {
        this.dataObserver(value);
      }
    });
  }

  // 新增任务(同步至所有设备)
  async addTask(task) {
    if (!task.title || !task.content) {
      throw new Error('任务标题和内容不能为空');
    }

    // 1. 获取当前任务列表
    let taskList = await this.getTaskList() || [];
    // 2. 添加新任务(生成唯一 ID 和时间戳)
    const newTask = {
      id: Date.now().toString(), // 用时间戳作为唯一 ID
      title: task.title,
      content: task.content,
      createTime: new Date().toLocaleString(),
      isCompleted: false,
      creatorDeviceId: this.dataManager.getCurrentDeviceId() // 记录创建设备 ID
    };
    taskList.push(newTask);

    // 3. 同步数据(主动同步模式)
    await this.dataManager.setData(
      TASK_DATA_STORE,
      TASK_DATA_KEY,
      taskList,
      DataSyncMode.ACTIVE_SYNC // 主动同步:立即触发所有设备同步
    );
    console.log('任务添加成功并同步:', newTask);
    return newTask;
  }

  // 获取任务列表(从分布式存储中读取)
  async getTaskList() {
    try {
      const taskList = await this.dataManager.getData(TASK_DATA_STORE, TASK_DATA_KEY);
      return taskList || [];
    } catch (error) {
      console.error('获取任务列表失败:', error.message);
      return [];
    }
  }

  // 更新任务状态(如标记为已完成)
  async updateTaskStatus(taskId, isCompleted) {
    let taskList = await this.getTaskList() || [];
    const taskIndex = taskList.findIndex(task => task.id === taskId);
    if (taskIndex === -1) {
      throw new Error(`未找到 ID 为 ${taskId} 的任务`);
    }

    taskList[taskIndex].isCompleted = isCompleted;
    // 同步更新后的数据
    await this.dataManager.setData(
      TASK_DATA_STORE,
      TASK_DATA_KEY,
      taskList,
      DataSyncMode.ACTIVE_SYNC
    );
    console.log(`任务状态更新:${taskId} -> ${isCompleted}`);
    return taskList[taskIndex];
  }

  // 删除任务
  async deleteTask(taskId) {
    let taskList = await this.getTaskList() || [];
    const newTaskList = taskList.filter(task => task.id !== taskId);
    if (newTaskList.length === taskList.length) {
      throw new Error(`未找到 ID 为 ${taskId} 的任务`);
    }

    await this.dataManager.setData(
      TASK_DATA_STORE,
      TASK_DATA_KEY,
      newTaskList,
      DataSyncMode.ACTIVE_SYNC
    );
    console.log(`任务删除成功:${taskId}`);
    return newTaskList;
  }

  // 注册数据变更观察者
  onDataChange(observer) {
    this.dataObserver = observer;
  }

  // 销毁分布式数据连接
  async destroy() {
    await this.dataManager.closeDataStore(TASK_DATA_STORE);
    console.log('分布式数据存储已关闭');
  }
}

module.exports = new DdmManager();

3.4 Electron 主进程(main.js)

整合所有模块,处理 IPC 通信,作为渲染进程与鸿蒙 DDM 之间的桥梁:

javascript

运行

// main.js
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const ddmManager = require('./src/ddm-manager');
const deviceManager = require('./src/device-manager');

let mainWindow;

// 创建主窗口
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'renderer/preload.js'), // 预加载脚本(安全通信)
      contextIsolation: true, // 开启上下文隔离
      nodeIntegration: false // 禁用 Node.js 集成(安全最佳实践)
    }
  });

  // 加载前端页面
  mainWindow.loadFile(path.join(__dirname, 'renderer/index.html'));

  // 打开开发者工具
  mainWindow.webContents.openDevTools();

  // 窗口关闭时销毁资源
  mainWindow.on('closed', () => {
    mainWindow = null;
    ddmManager.destroy();
    deviceManager.stopDeviceDiscovery();
  });
}

// 初始化核心模块
async function initCoreModules() {
  try {
    console.log('开始初始化核心模块...');
    await ddmManager.init(); // 初始化 DDM
    await deviceManager.initDeviceDiscovery(); // 初始化设备发现
    console.log('核心模块初始化完成!');
  } catch (error) {
    console.error('核心模块初始化失败:', error.message);
    app.quit(); // 初始化失败则退出应用
  }
}

// 应用就绪后执行
app.whenReady().then(() => {
  createWindow();
  initCoreModules();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

// 处理渲染进程 IPC 通信
// 1. 获取设备列表
ipcMain.handle('get-devices', async () => {
  return deviceManager.getOnlineDevices();
});

// 2. 监听设备变更
ipcMain.on('listen-device-change', (event) => {
  deviceManager.onDeviceChange((devices) => {
    event.reply('device-change', devices); // 向渲染进程发送设备变更通知
  });
});

// 3. 添加任务
ipcMain.handle('add-task', async (event, task) => {
  return await ddmManager.addTask(task);
});

// 4. 获取任务列表
ipcMain.handle('get-task-list', async () => {
  return await ddmManager.getTaskList();
});

// 5. 更新任务状态
ipcMain.handle('update-task-status', async (event, taskId, isCompleted) => {
  return await ddmManager.updateTaskStatus(taskId, isCompleted);
});

// 6. 删除任务
ipcMain.handle('delete-task', async (event, taskId) => {
  return await ddmManager.deleteTask(taskId);
});

// 7. 监听数据变更
ipcMain.on('listen-data-change', (event) => {
  ddmManager.onDataChange((taskList) => {
    event.reply('data-change', taskList); // 向渲染进程发送数据变更通知
  });
});

// 关闭所有窗口时退出应用(Windows/Linux)
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

3.5 预加载脚本(preload.js)

为渲染进程提供安全的 IPC 通信接口(避免直接暴露 Node.js API):

javascript

运行

// renderer/preload.js
const { contextBridge, ipcRenderer } = require('electron');

// 向渲染进程暴露通信接口
contextBridge.exposeInMainWorld('electronAPI', {
  // 设备相关
  getDevices: () => ipcRenderer.invoke('get-devices'),
  listenDeviceChange: (callback) => {
    ipcRenderer.on('device-change', (event, devices) => callback(devices));
  },

  // 任务相关
  addTask: (task) => ipcRenderer.invoke('add-task', task),
  getTaskList: () => ipcRenderer.invoke('get-task-list'),
  updateTaskStatus: (taskId, isCompleted) => ipcRenderer.invoke('update-task-status', taskId, isCompleted),
  deleteTask: (taskId) => ipcRenderer.invoke('delete-task', taskId),
  listenDataChange: (callback) => {
    ipcRenderer.on('data-change', (event, taskList) => callback(taskList));
  }
});

3.6 渲染进程 UI 实现(index.html + renderer.js + style.css)

3.6.1 前端页面(index.html)

html

预览

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>鸿蒙 Electron 跨设备任务协同</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <!-- 顶部导航 -->
    <header class="header">
      <h1>鸿蒙 + Electron 跨设备任务协同</h1>
      <p>基于分布式数据管理(DDM)的多端同步方案</p>
    </header>

    <!-- 主体内容:左侧设备列表,右侧任务管理 -->
    <div class="content">
      <!-- 左侧设备列表 -->
      <div class="device-panel">
        <h2>在线设备列表</h2>
        <div id="device-list" class="device-list">
          <!-- 设备列表由 JS 动态渲染 -->
          <div class="device-item loading">正在搜索设备...</div>
        </div>
      </div>

      <!-- 右侧任务管理 -->
      <div class="task-panel">
        <h2>跨设备任务列表</h2>
        <!-- 新增任务表单 -->
        <div class="task-form">
          <input type="text" id="task-title" placeholder="任务标题" required>
          <textarea id="task-content" placeholder="任务内容" required></textarea>
          <button id="add-task-btn">添加任务(同步至所有设备)</button>
        </div>

        <!-- 任务列表 -->
        <div id="task-list" class="task-list">
          <!-- 任务列表由 JS 动态渲染 -->
          <div class="task-item loading">正在加载任务...</div>
        </div>
      </div>
    </div>

    <!-- 底部信息 -->
    <footer class="footer">
      <p>配套代码:<a href="https://github.com/xxx/harmonyos-electron-ddm-demo" target="_blank">harmonyos-electron-ddm-demo</a></p>
      <p>技术支持:鸿蒙分布式数据管理 + Electron 28.0</p>
    </footer>
  </div>

  <script src="renderer.js"></script>
</body>
</html>
3.6.2 前端逻辑(renderer.js)

javascript

运行

// renderer/renderer.js
document.addEventListener('DOMContentLoaded', async () => {
  // DOM 元素
  const deviceListEl = document.getElementById('device-list');
  const taskTitleEl = document.getElementById('task-title');
  const taskContentEl = document.getElementById('task-content');
  const addTaskBtn = document.getElementById('add-task-btn');
  const taskListEl = document.getElementById('task-list');

  // 1. 加载设备列表
  async function loadDevices() {
    try {
      const devices = await window.electronAPI.getDevices();
      renderDeviceList(devices);
    } catch (error) {
      deviceListEl.innerHTML = `<div class="device-item error">设备加载失败:${error.message}</div>`;
    }
  }

  // 渲染设备列表
  function renderDeviceList(devices) {
    if (devices.length === 0) {
      deviceListEl.innerHTML = '<div class="device-item empty">未发现在线鸿蒙设备</div>';
      return;
    }

    deviceListEl.innerHTML = devices.map(device => `
      <div class="device-item">
        <img src="https://via.placeholder.com/40" alt="${device.deviceType}">
        <div class="device-info">
          <div class="device-name">${device.deviceName}</div>
          <div class="device-type">设备类型:${formatDeviceType(device.deviceType)}</div>
          <div class="device-id">设备 ID:${device.deviceId.slice(0, 10)}...</div>
        </div>
      </div>
    `).join('');
  }

  // 格式化设备类型
  function formatDeviceType(type) {
    const typeMap = {
      'phone': '手机',
      'tablet': '平板',
      'pc': '电脑',
      'watch': '智能手表',
      'tv': '智能电视'
    };
    return typeMap[type] || '未知设备';
  }

  // 2. 加载任务列表
  async function loadTaskList() {
    try {
      const taskList = await window.electronAPI.getTaskList();
      renderTaskList(taskList);
    } catch (error) {
      taskListEl.innerHTML = `<div class="task-item error">任务加载失败:${error.message}</div>`;
    }
  }

  // 渲染任务列表
  function renderTaskList(taskList) {
    if (taskList.length === 0) {
      taskListEl.innerHTML = '<div class="task-item empty">暂无跨设备任务,点击"添加任务"创建</div>';
      return;
    }

    taskListEl.innerHTML = taskList.map(task => `
      <div class="task-item" data-task-id="${task.id}">
        <div class="task-header">
          <input type="checkbox" class="task-checkbox" ${task.isCompleted ? 'checked' : ''}>
          <h3 class="${task.isCompleted ? 'completed' : ''}">${task.title}</h3>
          <button class="delete-task-btn">删除</button>
        </div>
        <div class="task-content">${task.content}</div>
        <div class="task-meta">
          <span>创建时间:${task.createTime}</span>
          <span>创建设备:${task.creatorDeviceId.slice(0, 8)}...</span>
        </div>
      </div>
    `).join('');

    // 绑定任务状态更新事件
    document.querySelectorAll('.task-checkbox').forEach(checkbox => {
      checkbox.addEventListener('change', async (e) => {
        const taskId = e.target.closest('.task-item').dataset.taskId;
        const isCompleted = e.target.checked;
        await window.electronAPI.updateTaskStatus(taskId, isCompleted);
      });
    });

    // 绑定删除任务事件
    document.querySelectorAll('.delete-task-btn').forEach(btn => {
      btn.addEventListener('click', async (e) => {
        const taskId = e.target.closest('.task-item').dataset.taskId;
        await window.electronAPI.deleteTask(taskId);
      });
    });
  }

  // 3. 添加任务
  addTaskBtn.addEventListener('click', async () => {
    const title = taskTitleEl.value.trim();
    const content = taskContentEl.value.trim();
    if (!title || !content) {
      alert('任务标题和内容不能为空!');
      return;
    }

    try {
      await window.electronAPI.addTask({ title, content });
      // 清空表单
      taskTitleEl.value = '';
      taskContentEl.value = '';
      alert('任务添加成功,已同步至所有在线设备!');
    } catch (error) {
      alert('任务添加失败:' + error.message);
    }
  });

  // 4. 监听设备变更(实时更新设备列表)
  window.electronAPI.listenDeviceChange((devices) => {
    renderDeviceList(devices);
  });

  // 5. 监听数据变更(实时更新任务列表)
  window.electronAPI.listenDataChange((taskList) => {
    renderTaskList(taskList);
  });

  // 初始化加载
  loadDevices();
  loadTaskList();
});
3.6.3 样式文件(style.css)

css

/* renderer/style.css */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Microsoft YaHei', sans-serif;
}

body {
  background-color: #f5f7fa;
  color: #333;
  line-height: 1.6;
}

.container {
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px;
}

.header {
  text-align: center;
  margin-bottom: 30px;
  padding-bottom: 20px;
  border-bottom: 1px solid #eee;
}

.header h1 {
  color: #007dff;
  font-size: 2.2rem;
  margin-bottom: 10px;
}

.header p {
  color: #666;
  font-size: 1.1rem;
}

.content {
  display: flex;
  gap: 30px;
  margin-bottom: 30px;
}

.device-panel {
  width: 300px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
  padding: 20px;
}

.device-panel h2 {
  font-size: 1.3rem;
  margin-bottom: 20px;
  color: #333;
  border-bottom: 1px solid #eee;
  padding-bottom: 10px;
}

.device-list {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.device-item {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 15px;
  border-radius: 6px;
  background: #f9fafb;
  border: 1px solid #eee;
}

.device-item.loading, .device-item.empty, .device-item.error {
  justify-content: center;
  color: #666;
  padding: 20px;
}

.device-item.error {
  color: #ff4d4f;
  border-color: #ffccc7;
  background: #fff2f0;
}

.device-info .device-name {
  font-weight: 600;
  margin-bottom: 5px;
  color: #333;
}

.device-info .device-type, .device-info .device-id {
  font-size: 0.9rem;
  color: #666;
}

.task-panel {
  flex: 1;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
  padding: 20px;
}

.task-panel h2 {
  font-size: 1.3rem;
  margin-bottom: 20px;
  color: #333;
  border-bottom: 1px solid #eee;
  padding-bottom: 10px;
}

.task-form {
  display: flex;
  flex-direction: column;
  gap: 15px;
  margin-bottom: 30px;
  padding: 20px;
  background: #f9fafb;
  border-radius: 6px;
}

.task-form input, .task-form textarea {
  padding: 12px 15px;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-size: 1rem;
}

.task-form textarea {
  min-height: 100px;
  resize: vertical;
}

.task-form button {
  padding: 12px 15px;
  background: #007dff;
  color: #fff;
  border: none;
  border-radius: 6px;
  font-size: 1rem;
  cursor: pointer;
  transition: background 0.3s;
}

.task-form button:hover {
  background: #0066cc;
}

.task-list {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.task-item {
  padding: 20px;
  border-radius: 6px;
  background: #f9fafb;
  border: 1px solid #eee;
  position: relative;
}

.task-item.loading, .task-item.empty {
  text-align: center;
  color: #666;
  padding: 30px;
}

.task-header {
  display: flex;
  align-items: center;
  gap: 15px;
  margin-bottom: 10px;
}

.task-checkbox {
  width: 20px;
  height: 20px;
  cursor: pointer;
}

.task-header h3 {
  flex: 1;
  font-size: 1.1rem;
  color: #333;
}

.task-header h3.completed {
  text-decoration: line-through;
  color: #999;
}

.delete-task-btn {
  padding: 5px 10px;
  background: #ff4d4f;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.9rem;
}

.delete-task-btn:hover {
  background: #ff7875;
}

.task-content {
  margin-bottom: 15px;
  color: #666;
  line-height: 1.8;
}

.task-meta {
  display: flex;
  justify-content: space-between;
  font-size: 0.85rem;
  color: #999;
}

.footer {
  text-align: center;
  padding: 20px;
  border-top: 1px solid #eee;
  color: #666;
  font-size: 0.9rem;
}

.footer a {
  color: #007dff;
  text-decoration: none;
}

.footer a:hover {
  text-decoration: underline;
}

@media (max-width: 992px) {
  .content {
    flex-direction: column;
  }

  .device-panel {
    width: 100%;
  }
}

四、功能测试与验证

4.1 测试准备

  1. 确保所有测试设备(如华为手机 + 开发机)处于同一局域网;
  2. 华为手机需开启 “分布式协同” 功能(设置 → 更多连接 → 分布式协同);
  3. 开发机运行 Electron 应用:

    bash

    运行

    npm start
    
  4. 在华为手机上安装鸿蒙端测试应用(可使用 DevEco Studio 编译一个简单的鸿蒙应用,同样接入 DDM 读取 distributed_task_store 中的任务数据)。

4.2 核心功能测试用例

测试场景 操作步骤 预期结果
设备发现 启动 Electron 应用,手机开启分布式协同 Electron 应用的 “在线设备列表” 显示手机设备信息
任务添加 在 Electron 端输入任务标题和内容,点击 “添加任务” Electron 端任务列表显示新任务,手机端鸿蒙应用同步显示该任务
任务状态更新 在手机端标记任务为 “已完成” Electron 端任务自动标记为已完成(文字划横线)
任务删除 在 Electron 端删除某任务 手机端该任务同步删除
设备离线同步 手机离线后,Electron 端添加任务;手机重新上线 手机端自动同步离线期间新增的任务

4.3 调试技巧

  1. 查看鸿蒙系统日志(开发机通过 hdc 连接手机):

    bash

    运行

    hdc shell "hilog | grep distributed_data"
    
  2. 查看 Electron 应用日志:开发者工具 → Console 面板;
  3. 数据同步问题排查:检查 DataSyncMode 是否正确设置,权限是否申请成功。

五、进阶优化:提升稳定性与性能

5.1 数据传输加密

鸿蒙 DDM 支持对分布式数据进行加密传输,避免数据泄露。修改 ddm-manager.js 中的 setData 方法:

javascript

运行

// 新增加密配置
const encryptConfig = {
  encryptType: 'AES-256', // 加密算法
  key: 'your-32-byte-encryption-key' // 32字节密钥(实际项目中需安全存储)
};

// 同步数据时添加加密参数
await this.dataManager.setData(
  TASK_DATA_STORE,
  TASK_DATA_KEY,
  taskList,
  DataSyncMode.ACTIVE_SYNC,
  encryptConfig // 加密配置
);

5.2 数据冲突解决

当多个设备同时修改同一任务时,可能出现数据冲突。鸿蒙 DDM 提供冲突解决策略,可通过 setConflictResolveStrategy 配置:

javascript

运行

// 在 ddm-manager.js 的 init 方法中添加
this.dataManager.setConflictResolveStrategy({
  strategy: 'latest_write_wins', // 最新写入优先(默认策略)
  // 可选:自定义冲突解决函数
  customResolve: (localData, remoteData) => {
    // localData:本地数据,remoteData:远端数据
    // 自定义合并逻辑,例如保留本地修改的同时合并远端新增字段
    return { ...remoteData, ...localData };
  }
});

5.3 性能优化

  • 批量同步:频繁修改数据时,采用防抖策略批量同步,减少网络请求:

    javascript

    运行

    // 防抖函数
    function debounce(fn, delay = 300) {
      let timer = null;
      return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, args), delay);
      };
    }
    
    // 批量更新任务(防抖处理)
    const batchUpdateTasks = debounce(async (taskList) => {
      await this.dataManager.setData(
        TASK_DATA_STORE,
        TASK_DATA_KEY,
        taskList,
        DataSyncMode.ACTIVE_SYNC
      );
    });
    
  • 数据压缩:对大量数据(如长文本任务)进行压缩后同步:

    javascript

    运行

    const zlib = require('zlib');
    // 压缩数据
    const compressedData = zlib.deflateSync(JSON.stringify(taskList)).toString('base64');
    // 同步压缩后的数据
    await this.dataManager.setData(
      TASK_DATA_STORE,
      TASK_DATA_KEY,
      compressedData,
      DataSyncMode.ACTIVE_SYNC
    );
    // 读取时解压
    const compressedData = await this.dataManager.getData(TASK_DATA_STORE, TASK_DATA_KEY);
    const taskList = JSON.parse(zlib.inflateSync(Buffer.from(compressedData, 'base64')).toString());
    

5.4 断网重连机制

在 ddm-manager.js 中添加断网监听与重连逻辑:

javascript

运行

// 监听网络状态变化
this.dataManager.on('networkChange', (isConnected) => {
  if (isConnected) {
    console.log('网络恢复,触发数据同步...');
    this.syncData(); // 自定义同步函数,重新同步所有数据
  } else {
    console.log('网络断开,暂停数据同步');
  }
});

// 自定义同步函数
async syncData() {
  const localTaskList = await this.getTaskList();
  await this.dataManager.setData(
    TASK_DATA_STORE,
    TASK_DATA_KEY,
    localTaskList,
    DataSyncMode.ACTIVE_SYNC
  );
}

六、常见问题与排查方案

6.1 设备无法发现

  • 原因 1:设备未处于同一局域网;
  • 原因 2:未申请 ohos.permission.DISTRIBUTED_DEVICE_DISCOVERY 权限;
  • 原因 3:鸿蒙设备未开启 “分布式协同” 功能;
  • 排查:检查网络连接 → 重新申请权限 → 确认设备分布式功能已开启。

6.2 数据同步失败

  • 原因 1:未申请 ohos.permission.DISTRIBUTED_DATASYNC 权限;
  • 原因 2:数据格式不合法(如包含循环引用、超大对象);
  • 原因 3:DataSyncMode 配置错误;
  • 排查:查看应用日志 → 验证数据格式 → 检查权限申请代码。

6.3 Electron 端报错 “模块未找到”

  • 原因:鸿蒙 SDK 未正确重建,与 Electron 版本不兼容;
  • 排查:执行 npm run rebuild → 确认 Node.js 版本为 18.x → 检查 node_modules/@ohos 目录是否存在。

6.4 数据冲突导致同步异常

  • 原因:多个设备同时修改同一数据,未配置冲突解决策略;
  • 排查:配置 setConflictResolveStrategy → 采用 “最新写入优先” 或自定义合并逻辑。

七、总结与展望

本文基于鸿蒙分布式数据管理(DDM)实现了 Electron 跨设备通信方案,核心是通过鸿蒙 Node.js SDK 打通 Electron 与鸿蒙生态的连接,实现多设备数据实时同步。关键技术点包括:

  1. 鸿蒙 DDM 模块的初始化与权限申请;
  2. 分布式数据模型设计与同步策略配置;
  3. Electron 主进程与渲染进程的 IPC 通信;
  4. 设备发现与跨设备数据协同逻辑。

该方案可广泛应用于办公协同、智能家居控制、跨端文件传输等场景,例如:

  • 办公场景:多设备同步待办事项、文档编辑进度;
  • 智能家居:Electron 桌面端控制鸿蒙智能设备状态(如灯光、空调);
  • 跨端开发:多设备同步开发环境配置、调试日志。

未来展望:

  • 结合鸿蒙分布式软总线的高速传输能力,实现大文件(如视频、压缩包)跨设备传输;
  • 集成鸿蒙 AI 能力,实现跨设备语音控制、智能任务推荐;
  • 适配鸿蒙 5.0+ 新特性(如分布式账本、更精细的权限管控),提升方案安全性与稳定性。

参考资料

  1. 鸿蒙分布式数据管理官方文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/distributed_data_management-0000001154412841
  2. 鸿蒙 Node.js SDK 开发指南:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/nodejs_sdk-0000001154633060
  3. Electron 官方文档:https://www.electronjs.org/docs/latest
  4. 鸿蒙分布式权限开发指南:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/distributed_permission-0000001154858980

配套代码仓库harmonyos-electron-ddm-demo(实际发布时替换为真实仓库)技术交流:欢迎在评论区留言讨论,或通过 GitHub Issues 提交问题反馈!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐