欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

在这里插入图片描述

📌 概述

数据备份恢复模块允许用户创建和恢复应用数据的备份。在Cordova与OpenHarmony混合开发框架下,这个模块提供了完整的备份和恢复功能,用户可以定期备份数据,并在需要时恢复数据。数据备份恢复功能的设计目标是为用户提供数据安全保障,防止数据丢失。

数据备份恢复模块采用了自动备份和手动备份的设计,用户可以根据需要选择备份方式。

🔗 完整流程

第一步:备份创建

当用户点击备份按钮时,系统首先从IndexedDB数据库中收集所有数据。系统会将数据转换为JSON格式,然后创建一个备份文件,并保存到本地存储或文件系统中。

备份过程包括数据收集、格式转换、文件创建等步骤。系统会记录备份的时间和大小,以便用户查看备份历史。

第二步:备份管理

系统会显示所有现有的备份文件,用户可以查看备份的时间、大小等信息。用户可以选择删除不需要的备份,或者下载备份文件。

第三步:数据恢复

当用户点击恢复按钮时,系统会从选定的备份文件中读取数据,然后将数据导入到IndexedDB数据库中。恢复过程包括文件读取、数据解析、验证、导入等步骤。

🔧 Web代码实现

HTML结构

数据备份恢复页面的HTML结构包含三个主要部分:备份操作、备份历史和恢复操作。备份操作部分包含创建备份和自动备份开关按钮。备份历史部分显示所有已创建的备份文件列表。恢复操作部分允许用户选择备份文件并恢复数据。

<div id="backup-page" class="page">
  <div class="page-header">
    <h1 class="page-title">数据备份恢复</h1>
  </div>

  <div class="page-content">
    <!-- 备份操作 -->
    <div class="section">
      <h2>备份操作</h2>
      <div class="form-actions">
        <button class="btn btn-primary" onclick="backupModule.createBackup()">
          创建备份
        </button>
        <button class="btn btn-default" onclick="backupModule.autoBackupToggle()">
          <span id="auto-backup-status">启用自动备份</span>
        </button>
      </div>
    </div>

    <!-- 备份列表 -->
    <div class="section">
      <h2>备份历史</h2>
      <div id="backup-list" class="backup-list">
        <!-- 动态生成的备份项目 -->
      </div>
    </div>

    <!-- 恢复操作 -->
    <div class="section">
      <h2>恢复数据</h2>
      <div class="form-group">
        <label for="restore-file" class="form-label">选择备份文件</label>
        <input 
          type="file" 
          id="restore-file" 
          class="form-input" 
          accept=".json"
        />
      </div>
      <div class="form-actions">
        <button class="btn btn-primary" onclick="backupModule.restoreBackup()">
          恢复数据
        </button>
      </div>
    </div>
  </div>
</div>

JavaScript逻辑

数据备份恢复模块的核心是BackupModule类。在初始化时,模块会从本地存储加载现有的备份列表,并检查自动备份是否启用。备份数据包括所有Bug和分类信息,以JSON格式存储。

class BackupModule {
  constructor() {
    this.backups = [];
    this.autoBackupEnabled = false;
    this.init();
  }

  async init() {
    await this.loadBackups();
    this.loadAutoBackupStatus();
  }

  async loadBackups() {
    try {
      const backupList = JSON.parse(localStorage.getItem('backup_list') || '[]');
      this.backups = backupList;
      this.renderBackups();
    } catch (error) {
      console.error('加载备份列表失败:', error);
    }
  }
}

loadBackups方法首先从本地存储获取备份列表,然后调用renderBackups方法将备份列表渲染到页面上。renderBackups方法遍历所有备份,为每个备份生成一个HTML元素,显示备份的名称、大小和时间,以及下载和删除按钮。

  renderBackups() {
    const html = this.backups.map((backup, index) => `
      <div class="backup-item">
        <div class="backup-info">
          <span class="backup-name">备份 ${index + 1}</span>
          <span class="backup-size">${(backup.size / 1024).toFixed(2)} KB</span>
        </div>
        <div class="backup-date">${utils.formatDate(backup.timestamp)}</div>
        <div class="backup-actions">
          <button class="action-btn" onclick="backupModule.downloadBackup(${index})">下载</button>
          <button class="action-btn" onclick="backupModule.deleteBackup(${index})">删除</button>
        </div>
      </div>
    `).join('');
    document.getElementById('backup-list').innerHTML = html || '<p>暂无备份</p>';
  }

createBackup方法负责创建新的备份。它首先从数据库收集所有Bug和分类数据,然后将这些数据转换为JSON格式。备份信息(包括时间戳和大小)被保存到备份列表中,而备份内容被保存为单独的localStorage项。

  async createBackup() {
    try {
      utils.showLoading('正在创建备份...');
      const bugs = await db.getAllBugs();
      const categories = await db.getAllCategories();
      
      const backupData = {
        timestamp: new Date().toISOString(),
        bugs: bugs,
        categories: categories
      };
      
      const backupContent = JSON.stringify(backupData);
      const backup = {
        timestamp: new Date().toISOString(),
        size: backupContent.length,
        content: backupContent
      };
      
      this.backups.unshift(backup);
      localStorage.setItem('backup_list', JSON.stringify(this.backups.map(b => ({
        timestamp: b.timestamp,
        size: b.size
      }))));
      localStorage.setItem(`backup_${backup.timestamp}`, backupContent);
      
      utils.hideLoading();
      utils.showSuccess('备份创建成功');
      this.renderBackups();
    } catch (error) {
      console.error('创建备份失败:', error);
      utils.hideLoading();
      utils.showError('创建备份失败');
    }
  }

restoreBackup方法处理数据恢复。用户选择一个备份文件后,系统会读取文件内容并解析JSON数据。在恢复前,系统会要求用户确认,因为恢复操作会覆盖现有数据。确认后,系统会清空现有数据并导入备份中的所有数据。

  async restoreBackup() {
    const fileInput = document.getElementById('restore-file');
    const file = fileInput.files[0];
    
    if (!file) {
      utils.showError('请选择备份文件');
      return;
    }
    
    try {
      const content = await this.readFile(file);
      const backupData = JSON.parse(content);
      
      if (confirm('确定要恢复这个备份吗?现有数据将被覆盖。')) {
        utils.showLoading('正在恢复数据...');
        await db.clearAll();
        
        for (let bug of backupData.bugs) {
          await db.addBug(bug);
        }
        for (let category of backupData.categories) {
          await db.addCategory(category);
        }
        
        utils.hideLoading();
        utils.showSuccess('数据恢复成功');
        fileInput.value = '';
      }
    } catch (error) {
      console.error('恢复备份失败:', error);
      utils.hideLoading();
      utils.showError('恢复备份失败');
    }
  }

readFile方法使用FileReader API读取用户选择的文件内容。这个方法返回一个Promise,在文件读取成功时resolve,失败时reject。downloadBackup方法允许用户下载已创建的备份文件,通过创建一个Blob对象并模拟点击下载链接来实现。

  readFile(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e) => resolve(e.target.result);
      reader.onerror = (e) => reject(e);
      reader.readAsText(file);
    });
  }

  downloadBackup(index) {
    const backup = this.backups[index];
    const content = localStorage.getItem(`backup_${backup.timestamp}`);
    const blob = new Blob([content], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `backup_${backup.timestamp}.json`;
    a.click();
    URL.revokeObjectURL(url);
  }

deleteBackup方法允许用户删除不需要的备份。系统会要求用户确认删除操作。确认后,备份文件会从localStorage中删除,备份列表也会更新。loadAutoBackupStatus和autoBackupToggle方法用于管理自动备份功能的启用和禁用状态。

  deleteBackup(index) {
    if (confirm('确定要删除这个备份吗?')) {
      const backup = this.backups[index];
      localStorage.removeItem(`backup_${backup.timestamp}`);
      this.backups.splice(index, 1);
      localStorage.setItem('backup_list', JSON.stringify(this.backups.map(b => ({
        timestamp: b.timestamp,
        size: b.size
      }))));
      this.renderBackups();
      utils.showSuccess('备份已删除');
    }
  }

  loadAutoBackupStatus() {
    this.autoBackupEnabled = JSON.parse(localStorage.getItem('auto_backup_enabled') || 'false');
    this.updateAutoBackupButton();
  }

  autoBackupToggle() {
    this.autoBackupEnabled = !this.autoBackupEnabled;
    localStorage.setItem('auto_backup_enabled', JSON.stringify(this.autoBackupEnabled));
    this.updateAutoBackupButton();
    utils.showSuccess(this.autoBackupEnabled ? '自动备份已启用' : '自动备份已禁用');
  }

  updateAutoBackupButton() {
    const btn = document.getElementById('auto-backup-status');
    btn.textContent = this.autoBackupEnabled ? '禁用自动备份' : '启用自动备份';
  }
}

const backupModule = new BackupModule();

CSS样式

备份列表的样式使用Flexbox布局,使备份项目能够垂直排列。每个备份项目包含备份信息和操作按钮。备份项目在鼠标悬停时会改变背景颜色,提高用户体验。

.backup-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.backup-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px;
  background: white;
  border-radius: 4px;
  border: 1px solid #ddd;
}

.backup-info {
  display: flex;
  align-items: center;
  gap: 15px;
}

.backup-name {
  font-weight: 500;
  color: #333;
}

.backup-size {
  color: #999;
  font-size: 12px;
}

.backup-date {
  color: #999;
  font-size: 12px;
}

.backup-actions {
  display: flex;
  gap: 8px;
}

🔌 OpenHarmony原生代码

OpenHarmony原生代码通过BackupPlugin类实现备份相关的原生功能。createBackup方法负责在原生文件系统中创建备份文件。首先获取应用的缓存目录,然后创建备份目录(如果不存在),最后将备份数据写入JSON文件。

import { hilog } from '@kit.PerformanceAnalysisKit';
import { fileIo } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';

const TAG: string = '[BackupPlugin]';
const DOMAIN: number = 0xFF00;

export class BackupPlugin {
  static async createBackup(success: Function, error: Function, args: any[]): Promise<void> {
    try {
      const context = getContext(this) as common.UIAbilityContext;
      const backupData = args[0];
      
      const backupDir = context.cacheDir + '/backups';
      const backupFile = backupDir + `/backup_${Date.now()}.json`;
      
      if (!fileIo.accessSync(backupDir)) {
        fileIo.mkdirSync(backupDir);
      }
      
      const file = fileIo.openSync(backupFile, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE);
      fileIo.writeSync(file.fd, JSON.stringify(backupData));
      fileIo.closeSync(file.fd);
      
      hilog.info(DOMAIN, TAG, `备份创建成功: ${backupFile}`);
      success(backupFile);
    } catch (err) {
      hilog.error(DOMAIN, TAG, `创建备份失败: ${err}`);
      error('创建备份失败');
    }
  }
}

Web-Native通信

Web层通过BackupBridge类与原生代码进行通信。createBackup方法使用Cordova的exec方法调用原生的BackupPlugin,将备份数据传递给原生代码。原生代码在文件系统中创建备份文件后,将文件路径返回给Web层。这个通信过程是异步的,使用Promise来处理成功和失败的回调。

class BackupBridge {
  static createBackup(backupData) {
    return new Promise((resolve, reject) => {
      if (window.cordova) {
        cordova.exec(
          (filePath) => {
            console.log('备份创建成功:', filePath);
            resolve(filePath);
          },
          (error) => {
            console.error('创建备份失败:', error);
            reject(error);
          },
          'BackupPlugin',
          'createBackup',
          [backupData]
        );
      } else {
        reject('Cordova未加载');
      }
    });
  }
}

📝 总结

数据备份恢复模块是BugTracker Pro应用中用于数据安全保护的重要功能。在Cordova与OpenHarmony混合开发框架下,它提供了完整的备份和恢复功能。通过定期备份数据,用户可以有效防止数据丢失,这大大提高了应用的可靠性。

模块采用了模块化的设计,各个功能都是独立的,易于维护和扩展。这充分展示了混合开发框架的优势。

Logo

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

更多推荐