十二条备份记录走完全流程:鸿蒙备份导出种子数据与样例
实例:数据备份导出(Backup)|技术:双表种子、导出内容样例
一、种子数据的设计目标
实例 10 的种子数据要撑起「终端控制台 + 备份记录」页面,设计目标:
- 12 条数据源记录:backup_source 表有内容可导出——资产清单叙事(华为手机、蓝牙耳机、运动鞋…);
- 4 条备份日志:backup_log 有历史可展示——最近的 4 次备份(json/csv 交替);
- 数据源叙事:12 条「家庭资产」记录(数码/服饰/食品/家居/美妆/图书六类),导出 JSON 内容有可读性;
- 日志覆盖两种格式:json 与 csv 各 2 条,列表图标 📄📊 交替。
二、12 条数据源记录
| # | 名称 | 分类 | 金额 | 备注 | 时间偏移 |
|---|---|---|---|---|---|
| 1 | 华为 Mate 60 Pro | 数码 | 6999 | 旗舰手机 | 30 天前 |
| 2 | 无线蓝牙耳机 | 数码 | 299 | 降噪款 | 28 天前 |
| 3 | 运动跑鞋 | 服饰 | 699 | 缓震系列 | 26 天前 |
| 4 | 羽绒服 | 服饰 | 1299 | 加厚款 | 24 天前 |
| 5 | 坚果礼盒 | 食品 | 159 | 春节采购 | 22 天前 |
| 6 | 进口巧克力 | 食品 | 89 | 伴手礼 | 20 天前 |
| 7 | 懒人沙发 | 家居 | 499 | 客厅用 | 18 天前 |
| 8 | 香薰蜡烛 | 家居 | 69 | 助眠 | 16 天前 |
| 9 | 保湿面霜 | 美妆 | 219 | 秋冬款 | 14 天前 |
| 10 | 口红 | 美妆 | 199 | 经典色号 | 12 天前 |
| 11 | 编程入门指南 | 图书 | 89 | 技术书 | 10 天前 |
| 12 | 科幻经典全集 | 图书 | 129 | 收藏版 | 8 天前 |
数据源叙事:一份「家庭资产清单」——从旗舰手机到科幻小说,六类 12 件,金额从 69 到 6999 跨度大。这份数据导出成 JSON 后,内容有真实感(不是 aaa/bbb 占位符),恢复导入后能直观对比「备份前后的数据一致性」。
三、4 条备份日志
| # | 文件名 | 大小 | 格式 | 时间偏移 |
|---|---|---|---|---|
| 1 | backup_a.json | 2048 | json | 7 天前 |
| 2 | backup_b.csv | 1536 | csv | 5 天前 |
| 3 | backup_c.json | 2100 | json | 3 天前 |
| 4 | backup_d.csv | 1600 | csv | 1 天前 |
日志设计:json/csv 交替、大小 1.5~2.1KB(接近 12 条数据的真实导出体积)、时间覆盖最近 7 天——备份记录列表有「📄 📊 📄 📊」的图标交替,时间显示有层次。
四、代码实现:双表种子
constnow=Date.now();constday=86400000;// 1. 数据源 12 条constsourceSeed:SourceSeed[]=[/* 见第二节表格 */];for(constsofsourceSeed){constvalues:relationalStore.ValuesBucket={name:s.name,category:s.category,amount:s.amount,note:s.note,created_time:now-s.daysAgo*day,};awaitstore.insert(BackupDao.SOURCE_TABLE,values);}// 2. 备份日志 4 条constlogSeed:BackupSeed[]=[/* 见第三节表格 */];for(constsoflogSeed){constvalues:relationalStore.ValuesBucket={file_name:s.fileName,size:s.size,source_table:BackupDao.SOURCE_TABLE,backup_time:s.backupTime,type:s.type,};awaitstore.insert(BackupDao.TABLE,values);}hilog.info(DOMAIN,TAG,'已填充数据源 12 条 + 备份日志 4 条种子数据');幂等判断:与前面实例同款——查 backup_source 的 COUNT,非空即返回。根表判断(数据源表代表「种子已注入」)。
五、导出内容的真实样例
12 条数据源导出成 JSON 的实际内容(节选前 3 条):
[{"id":1,"name":"华为 Mate 60 Pro","category":"数码","amount":6999,"note":"旗舰手机","createdTime":1750000000000},{"id":2,"name":"无线蓝牙耳机","category":"数码","amount":299,"note":"降噪款","createdTime":1750000000000},{"id":3,"name":"运动跑鞋","category":"服饰","amount":699,"note":"缓震系列","createdTime":1750000000000}]导出成 CSV 的实际内容(含表头):
id,name,category,amount,note,created_time 1,华为 Mate 60 Pro,数码,6999,旗舰手机,1750000000000 2,无线蓝牙耳机,数码,299,降噪款,1750000000000 3,运动跑鞋,服饰,699,缓震系列,1750000000000两种格式的对比演示:JSON 结构清晰(花括号嵌套、类型保留),CSV 表格友好(Excel 双击即开)。读者点「导出 JSON」后用 Device File Explorer 打开沙箱文件,看到的就是上面的内容。
六、注入后的页面效果预测
| 区块 | 预期效果 |
|---|---|
| 标题栏 | 「数据源 12 条 · 备份 4 份」 |
| 终端 | 初始日志「> 备份系统已就绪,等待指令…」 |
| 备份记录 | 4 行:backup_a.json(2.0 KB)、backup_b.csv(1.5 KB)… |
| 操作演示 | 点「导出 JSON」→ 终端「✓ 已生成 backup_xxx.json(约 2.1 KB)」→ 记录列表变 5 行 |
演示脚本:进入页面 → 终端显示就绪 → 点「查看数据源」→ 终端逐行打印「[1] 华为 Mate 60 Pro | 数码 | ¥6999…」→ 点「导出 JSON」→ 「✓ 已生成 backup_xxx.json」→ 点「导出 CSV」→ 再生成一个 .csv → 点「♻️ 恢复导入」→ 「✓ 恢复完成,共导入 12 条记录」→ 备份记录列表滚动增长。一条完整的「导出-恢复」演示路径。
七、验证方法
- hilog 日志:搜
BackupDao,看到「已填充数据源 12 条 + 备份日志 4 条种子数据」; - 页面显示:标题统计「12 条 / 4 份」、备份记录 4 行;
- 数据库直查:
SELECTCOUNT(*)FROMbackup_source;-- 12SELECTCOUNT(*)FROMbackup_log;-- 4SELECTtype,COUNT(*)FROMbackup_logGROUPBYtype;-- csv:2 json:2 - 文件验证:导出 JSON 后,Device File Explorer 找到沙箱
backup_xxx.json,内容与第五节样例结构一致。
八、FAQ
Q1:种子里的备份文件(backup_a.json 等)在沙箱里真实存在吗?
A:不存在——种子只在数据库里插了日志记录,没有创建真实文件。页面删除这些备份时会尝试 unlink 文件,文件不存在被 catch 吞掉(日志「删除文件失败(可能不存在)」)。种子日志是「模拟历史」,真实备份(doBackup)才会创建真实文件。
Q2:为什么选「家庭资产」作为数据源叙事?
A:备份场景的演示需要「值得备份的数据」——资产清单(手机、沙发、书籍)比随机数据更有「身家性命」的代入感。金额字段(69~6999)也让 CSV 导出有真实的数字列。
Q3:恢复导入后数据源的 id 会变化吗?
A:会——恢复是「清空 + 重插」,AUTOINCREMENT 生成新 id(从 1 开始或继续递增)。id 不保留是快照恢复的正常现象(内容一致即可),除非业务要求 id 稳定(那需要显式插入 id 列)。
Q4:CSV 里 created_time 是毫秒时间戳,人能看懂吗?
A:看不懂(1750000000000),但它是「机器可读」的原始值——CSV 给表格工具用,时间列保留原始时间戳让排序/筛选可用。给人看的友好时间应在展示层转换。导出保留原始值,展示层负责格式化。
Q5:备份日志的时间戳和文件名里的时间戳一致吗?
A:种子数据里不完全一致(backup_a.json 是模拟文件名),真实备份(doBackup)两者一致(文件名 = backup_时间戳)。种子模拟历史不必严格自洽,真实流程必须自洽。
九、文章小结
本篇文章展示了实例 10 的种子数据:12 条资产清单 + 4 条备份日志(json/csv 交替)。核心是「数据源叙事」(值得备份的资产)+「日志模拟」(历史备份记录),让终端页面一开屏就有内容可导出、有历史可查看。导出内容的真实样例(JSON/CSV)为演示提供了「数据长什么样」的直观参照。
下一篇(10-5)是实例 10 的收官文章,展示 BackupPage 全量代码与运行效果。
十、备份日志种子数据深度复盘
10.1 四条备份日志种子全表
备份日志的种子数据在此给出完整明细——备份名、数据源范围、备份时间、文件大小四要素齐备:
| # | 备份名 | 数据源范围 | 备份时间 | 文件大小 | 格式 |
|---|---|---|---|---|---|
| 1 | backup_a.json | backup_source 全部 12 条 | 7 天前 | 2048 B | json |
| 2 | backup_b.csv | backup_source 全部 12 条 | 5 天前 | 1536 B | csv |
| 3 | backup_c.json | backup_source 全部 12 条 | 3 天前 | 2100 B | json |
| 4 | backup_d.csv | backup_source 全部 12 条 | 1 天前 | 1600 B | csv |
四要素的设计逻辑:备份名带扩展名——前端按扩展名选择列表图标(📄/📊);数据源范围固定为「全表 12 条」——备份的语义就是「整体快照」;时间用「相对今天」生成(now - daysAgo * day),保证每次安装应用演示时备份记录都「新鲜」;文件大小取「接近真实导出体积」的整数,列表格式化后显示为 1.5 KB / 2.0 KB。
10.2 种子设计复盘:范围与时间分布
数据源范围:四条日志全部指向backup_source(BackupDao.SOURCE_TABLE常量),没有出现「导出时数据源为空」的边界情况——种子日志 = 种子数据源的「备份痕迹」,两者必须配套注入,否则列表会出现「有备份记录但内容对不上」的穿帮。
时间分布复盘:四个时间偏移是 7 / 5 / 3 / 1 天前——奇数间隔。为什么不用 4/3/2/1 这种等差序列?因为真实用户的备份行为是「想起来才备份」:等间隔是理想化的均匀节奏,而 7/5/3/1 模拟了「上上周备份过、上周补了一次、前天又备份、昨天刚备完」的逐渐加密节奏——列表时间列显示「7 天前 / 5 天前 / 3 天前 / 1 天前」,层次感比等间隔更真实。
大小差异复盘:json 两条(2048 / 2100 B)比 csv 两条(1536 / 1600 B)大约 30%——这是两种格式的固有差异:JSON 每个字段都要写"字段名":(键 + 冒号 + 引号),CSV 只有值本身用逗号分隔。同样的 12 条数据,JSON 表达力强但体积大,CSV 紧凑但可读性弱——种子的大小数字本身就演示了这个 trade-off。
10.3 导出文件内容样例:JSON 结构逐字段拆解
这里给出「一条完整记录」的 JSON 结构与数据库列的对应关系:
[{"id":1,"name":"华为 Mate 60 Pro","category":"数码","amount":6999,"note":"旗舰手机","createdTime":1750000000000},{"id":2,"name":"无线蓝牙耳机","category":"数码","amount":299,"note":"降噪款","createdTime":1750000000000},{"id":3,"name":"运动跑鞋","category":"服饰","amount":699,"note":"缓震系列","createdTime":1750000000000}]字段映射:name / category / amount / note与 backup_source 四列一一对应;createdTime是created_time的驼峰化(导出时把下划线键转成驼峰,符合 JSON 惯例);id保留原主键——导出的 JSON 是数据库行的直接投影,恢复导入时按字段名重新组装 insert。
类型保留:amount是数字(6999 不带引号)、createdTime是数字时间戳、字符串都带引号——JSON 的「类型自描述」让它比 CSV 更适合作「可再解析的备份载体」。CSV 则把所有值都当文本,恢复时需要parseInt还原类型。
10.4 注入后的备份列表效果预测
种子注入完成后,备份记录列表的四行预期渲染效果:
| 行 | 图标 | 文件名 | 格式化大小 | 相对时间 |
|---|---|---|---|---|
| 1 | 📄 | backup_a.json | 2.0 KB | 7 天前 |
| 2 | 📊 | backup_b.csv | 1.5 KB | 5 天前 |
| 3 | 📄 | backup_c.json | 2.1 KB | 3 天前 |
| 4 | 📊 | backup_d.csv | 1.6 KB | 1 天前 |
列表交互预测:点击任意一行弹出操作菜单(删除 / 查看内容);点删除走「日志 + 文件」双删除——种子日志的文件并不存在,删除时 catch 记录「删除文件失败(可能不存在)」但日志记录本身被删掉,列表从 4 行变 3 行。种子日志的「删除容错」正是真实文件可能被手动清掉的兜底设计——双删除任何一步失败都不影响另一步。
10.5 验证方法
- 终端验证:进入页面,终端区显示「> 备份系统已就绪,等待指令…」,备份记录区 4 行;
- 数据库直查(DevEco 的 DB Inspector 或自查 SQL):
SELECTCOUNT(*)FROMbackup_source;-- 12SELECTCOUNT(*)FROMbackup_log;-- 4SELECTtype,COUNT(*)FROMbackup_logGROUPBYtype;-- csv:2 json:2SELECTfile_name,size,backup_timeFROMbackup_logORDERBYbackup_timeDESC;-- 4 行,时间从近到远- 文件验证:点「导出 JSON」后,Device File Explorer 打开沙箱
backup_xxx.json,对照 10.3 的结构检查字段名与类型; - hilog 验证:搜
BackupDao,日志「已填充数据源 12 条 + 备份日志 4 条种子数据」出现一次——幂等判断保证二次启动不重复注入。
10.6 FAQ
Q1:为什么备份日志种子只有 4 条,而数据源有 12 条?
A:备份日志是「操作历史」,12 条会让页面显得臃肿;4 条(一屏内的滚动列表)既展示了 json/csv 交替的图标效果,又给「导出新增一条」留出增长空间——演示时备份记录从 4 行变 5 行、变 6 行,滚动的过程本身就是演示内容。
Q2:种子的 backup_time 和 JSON 里记录的 createdTime 是一回事吗?
A:不是。backup_time 是「备份动作发生的时间」(日志字段);createdTime 是「数据源记录被创建的时间」(业务字段)。种子日志的 backup_time = 注入时刻往前推 7/5/3/1 天;数据源的 createdTime = 注入时刻往前推 30~8 天。两张表的时间语义不同,不能混用。
Q3:恢复导入之后,备份日志会变多还是变少?
A:不变——恢复只操作 backup_source(清空 + 重插),backup_log 原样保留。所以恢复后备份记录列表还是 4 行(或加上恢复前新导出的记录),只是数据源 12 条的 id 被重建。备份日志是「审计轨迹」,恢复不动历史。
Q4:2048 B 这个大小是怎么定的?
A:手工按真实导出估算——12 条记录每条 JSON 约 160~180 字节(键名 + 值 + 引号),合计约 2.0 KB;CSV 每行约 120~130 字节,合计约 1.5 KB。种子大小取「接近但不精确」的整数,列表显示 2.0 KB / 1.5 KB 直观可信。真实备份(doBackup)会写实际字节数,种子只是模拟。
