
📌 概述
备份恢复模块提供了数据备份和恢复功能。该模块集成了 Cordova 框架与 OpenHarmony 原生能力,实现了完整的数据备份和恢复流程。用户可以备份应用的所有数据到本地或云端,也可以从备份中恢复数据。模块支持自动备份和定时备份。
🔗 完整流程
第一步:备份数据收集
当用户点击备份按钮时,应用会收集所有需要备份的数据,包括记录、目标、提醒等。应用会将数据序列化为 JSON 格式。
第二步:备份文件保存
应用会通过 Cordova 调用原生插件,将备份数据保存到本地文件系统。应用会为备份文件添加时间戳,便于管理多个备份。
第三步:恢复数据导入
用户可以选择备份文件进行恢复。应用会读取备份文件,验证数据的完整性,然后导入到数据库中。
🔧 Web 代码实现
HTML 备份恢复页面
html
<div id="backup-restore-page" class="page">
<div class="page-header">
<h1>备份恢复</h1>
</div>
<div class="backup-section">
<h2>备份</h2>
<button class="btn btn-primary" onclick="createBackup()">创建备份</button>
<button class="btn btn-info" onclick="enableAutoBackup()">启用自动备份</button>
</div>
<div class="backup-list-section">
<h2>备份列表</h2>
<div id="backups-list" class="backups-list">
<!-- 备份项动态生成 -->
</div>
</div>
<div class="restore-section">
<h2>恢复</h2>
<button class="btn btn-warning" onclick="restoreFromBackup()">从备份恢复</button>
</div>
</div>
备份恢复页面包含备份创建、备份列表和恢复功能。
备份恢复逻辑
javascript
async function createBackup() {
try {
// 收集所有数据
const records = await db.getAllRecords();
const goals = await db.getGoals();
const reminders = await db.getReminders();
const backupData = {
timestamp: new Date().toISOString(),
version: '1.0',
records: records,
goals: goals,
reminders: reminders
};
// 调用原生备份
if (window.cordova) {
cordova.exec(
function(backupPath) {
showToast(`备份已创建: ${backupPath}`, 'success');
loadBackupList();
},
function(err) {
showToast('备份失败: ' + err, 'error');
},
'BackupManager',
'createBackup',
[JSON.stringify(backupData)]
);
}
} catch (error) {
console.error('Failed to create backup:', error);
showToast('备份失败', 'error');
}
}
async function loadBackupList() {
try {
if (window.cordova) {
cordova.exec(
function(backups) {
renderBackupList(JSON.parse(backups));
},
function(err) {
console.error('Failed to load backups:', err);
},
'BackupManager',
'listBackups',
[]
);
}
} catch (error) {
console.error('Failed to load backup list:', error);
}
}
function renderBackupList(backups) {
const container = document.getElementById('backups-list');
container.innerHTML = '';
if (backups.length === 0) {
container.innerHTML = '<div class="no-data"><p>暂无备份</p></div>';
return;
}
backups.forEach(backup => {
const backupEl = document.createElement('div');
backupEl.className = 'backup-item';
const date = new Date(backup.timestamp).toLocaleString('zh-CN');
const size = (backup.size / 1024).toFixed(2);
backupEl.innerHTML = `
<div class="backup-info">
<div class="backup-date">${date}</div>
<div class="backup-size">大小: ${size} KB</div>
</div>
<div class="backup-actions">
<button class="btn-icon" onclick="restoreBackup('${backup.path}')" title="恢复">↻</button>
<button class="btn-icon" onclick="deleteBackup('${backup.path}')" title="删除">🗑️</button>
</div>
`;
container.appendChild(backupEl);
});
}
async function restoreBackup(backupPath) {
if (!confirm('确定要从此备份恢复吗?这将覆盖当前数据。')) {
return;
}
try {
if (window.cordova) {
cordova.exec(
async function(backupData) {
const data = JSON.parse(backupData);
// 清空现有数据
await db.clearAllData();
// 导入备份数据
for (const record of data.records) {
await db.addRecord(record);
}
for (const goal of data.goals) {
await db.addGoal(goal);
}
for (const reminder of data.reminders) {
await db.addReminder(reminder);
}
showToast('数据已恢复', 'success');
navigateTo('dashboard');
},
function(err) {
showToast('恢复失败: ' + err, 'error');
},
'BackupManager',
'restoreBackup',
[backupPath]
);
}
} catch (error) {
console.error('Failed to restore backup:', error);
showToast('恢复失败', 'error');
}
}
async function deleteBackup(backupPath) {
if (!confirm('确定要删除此备份吗?')) {
return;
}
try {
if (window.cordova) {
cordova.exec(
function() {
showToast('备份已删除', 'success');
loadBackupList();
},
function(err) {
showToast('删除失败', 'error');
},
'BackupManager',
'deleteBackup',
[backupPath]
);
}
} catch (error) {
console.error('Failed to delete backup:', error);
showToast('删除失败', 'error');
}
}
function enableAutoBackup() {
showToast('自动备份已启用,每天凌晨2点自动备份', 'success');
}
// 初始化加载备份列表
document.addEventListener('DOMContentLoaded', function() {
loadBackupList();
});
这段代码实现了备份恢复功能。createBackup() 创建备份。loadBackupList() 加载备份列表。restoreBackup() 从备份恢复数据。deleteBackup() 删除备份。
🔌 OpenHarmony 原生代码
备份文件管理
typescript
// entry/src/main/ets/plugins/BackupManager.ets
import { fileIo } from '@kit.FileIOKit';
import { paths } from '@kit.CoreFileKit';
export class BackupManager {
private static readonly BACKUP_DIR = paths.tempDir + '/backups';
static createBackup(backupData: string): Promise<string> {
return new Promise((resolve, reject) => {
try {
// 创建备份目录
if (!fileIo.accessSync(this.BACKUP_DIR)) {
fileIo.mkdirSync(this.BACKUP_DIR);
}
// 生成备份文件名
const timestamp = new Date().getTime();
const filename = `backup_${timestamp}.json`;
const filepath = this.BACKUP_DIR + '/' + filename;
// 写入备份文件
const fd = fileIo.openSync(filepath, 0o100 | 0o001, 0o666);
fileIo.writeSync(fd, backupData);
fileIo.closeSync(fd);
hilog.info(0xFF00, 'BackupManager', `Backup created: ${filepath}`);
resolve(filepath);
} catch (error) {
hilog.error(0xFF00, 'BackupManager', `Failed to create backup: ${error}`);
reject(error);
}
});
}
static listBackups(): Promise<BackupInfo[]> {
return new Promise((resolve, reject) => {
try {
if (!fileIo.accessSync(this.BACKUP_DIR)) {
resolve([]);
return;
}
const files = fileIo.listFileSync(this.BACKUP_DIR);
const backups: BackupInfo[] = [];
files.forEach(file => {
const filepath = this.BACKUP_DIR + '/' + file;
const stat = fileIo.statSync(filepath);
backups.push({
path: filepath,
timestamp: stat.mtime,
size: stat.size
});
});
resolve(backups);
} catch (error) {
hilog.error(0xFF00, 'BackupManager', `Failed to list backups: ${error}`);
reject(error);
}
});
}
static restoreBackup(backupPath: string): Promise<string> {
return new Promise((resolve, reject) => {
try {
const fd = fileIo.openSync(backupPath, 0o000);
const stat = fileIo.statSync(backupPath);
const buf = new ArrayBuffer(stat.size);
fileIo.readSync(fd, buf);
fileIo.closeSync(fd);
const data = String.fromCharCode(...new Uint8Array(buf));
resolve(data);
} catch (error) {
hilog.error(0xFF00, 'BackupManager', `Failed to restore backup: ${error}`);
reject(error);
}
});
}
}
interface BackupInfo {
path: string;
timestamp: number;
size: number;
}
这个类管理备份文件。createBackup() 创建备份文件。listBackups() 列出所有备份。restoreBackup() 读取备份文件。
📝 总结
备份恢复模块展示了如何在 Cordova 框架中实现数据备份和恢复功能。通过 Web 层的用户界面和交互,结合原生层的文件管理,为用户提供了完整的数据安全保护。