十五条种子数据注入 项目:鸿蒙待办清单一开屏就热闹非凡

发布时间:2026/8/16 4:23:43
十五条种子数据注入 项目:鸿蒙待办清单一开屏就热闹非凡 实例待办事项清单Todo List本文提供 15 条种子数据让页面首次打开就内容丰富面板统计数字饱满一、种子数据设计思路覆盖 3 种优先级低/中/高覆盖 4 个分类工作/生活/学习/日常未完成 12 条、已完成 3 条对应统计卡未完成 12 / 已完成 3 / 高优 4时间跨度为近一周展示时间排序效果二、种子数据表15 条idtitleprioritycategorycompletedcreated_time备注1完成季度周报并提交领导2工作0周一 09:30含图表2预约明天上午的牙医1生活0周一 10:05电话 021-…3阅读《SQLite 权威指南》第 4 章1学习0周一 20:15做笔记4整理桌面文件清理垃圾0日常0周二 08:40-5给项目加异常日志上报2工作0周二 14:22需求 #1286超市采购牛奶、鸡蛋、水果1生活0周三 09:00预算 1507复习 ArkTS 状态管理1学习0周三 19:30两小时8给爸妈打电话1生活0周四 12:00半小时9修复登录页闪退问题2工作0周四 15:47紧急10缴纳水电燃气费0日常0周五 08:20-11整理照片备份到云端1日常0周五 21:0050G12准备周末分享会 PPT2工作0周六 10:00主题RDB 实践13完成健身卡续费1生活1上周 16:00已完成14更新应用隐私协议1工作1上周 11:30已完成15看完收藏的 3 篇技术文章0学习1上周 22:10已完成统计效果未完成 12其中高优先级 4id 1、5、9、12、已完成 3 → 完成率 20%底部进度条显示3/15 20%。三、种子数据 SQLINSERTINTOtodo(title,priority,category,completed,created_time,completed_time,remark)VALUES(完成季度周报并提交领导,2,工作,0,1715581800000,0,含图表),(预约明天上午的牙医,1,生活,0,1715583900000,0,电话 021-88886666),(阅读《SQLite 权威指南》第 4 章,1,学习,0,1715613300000,0,做笔记),(整理桌面文件清理垃圾,0,日常,0,1715647200000,0,),(给项目加异常日志上报,2,工作,0,1715660520000,0,需求 #128),(超市采购牛奶、鸡蛋、水果,1,生活,0,1715706000000,0,预算 150),(复习 ArkTS 状态管理,1,学习,0,1715743800000,0,两小时),(给爸妈打电话,1,生活,0,1715752800000,0,半小时),(修复登录页闪退问题,2,工作,0,1715766420000,0,紧急),(缴纳水电燃气费,0,日常,0,1715797200000,0,),(整理照片备份到云端,1,日常,0,1715850000000,0,50G),(准备周末分享会 PPT,2,工作,0,1715868000000,0,主题RDB 实践),(完成健身卡续费,1,生活,1,1715500800000,1715500800000,已完成),(更新应用隐私协议,1,工作,1,1715452200000,1715452200000,已完成),(看完收藏的 3 篇技术文章,0,学习,1,1715590200000,1715590200000,已完成);时间戳为示例值实际初始化时可用Date.now()偏移生成保证列表时间展示合理。四、DAO 内联初始化方法在TodoDao中提供initSeedData()首次启动表为空时自动填充staticasyncinitSeedData(context:common.UIAbilityContext):Promisevoid{conststoreawaitthis.getStore(context);constcountawaitstore.querySql(SELECT COUNT(*) AS c FROM${this.TABLE});lettotal0;if(count.goToNextRow())totalcount.getLong(count.getColumnIndex(c));count.close();if(total0)return;// 已有数据跳过constnowDate.now();constseed[{title:完成季度周报并提交领导,priority:2,category:工作,completed:0,createdTime:now-6*86400000,remark:含图表},// ... 其余 14 条同上表];for(constsofseed){constvalues:relationalStore.ValuesBucket{title:s.title,priority:s.priority,category:s.category,completed:s.completed,created_time:s.createdTime,completed_time:0,remark:s.remark,};awaitstore.insert(this.TABLE,values);}}五、页面效果对照面板区域填充后效果统计卡未完成12/ 已完成3/ 高优先级4全部视图15 张卡片未完成在前高优带 ⚡未完成视图12 张卡片前三张为高优任务已完成视图3 张置灰卡片带删除线底部进度条已完成 3 项 ▏▏▏▏ 20%分类标签工作 5 / 生活 4 / 学习 3 / 日常 3六、扩展建议方向做法数据更多生成 50 条时用循环 随机组合标题分组显示按 category GROUP BY 分段标题截止日期增加 due_time 字段 逾期红色提示拖动排序增加 sort_order 字段长按拖动重排七、文章小结15 条种子数据覆盖了 4 分类 × 3 优先级 × 双状态 × 一周时间跨度首次打开页面统计卡、列表、进度条全部有内容可展示视觉饱满且能直接验证排序、过滤、聚合逻辑。initSeedData()的空表判断保证重复启动不重复插入是生产环境初始化演示数据的标准做法。八、种子数据设计思路复盘1. 为什么是 15 条15 条是「演示数据黄金数量」数据量问题15 条的表现5 条列表空荡统计卡数字没分量排序效果看不出来—15 条—一屏半、有滚动感统计数字饱满50 条首屏刷屏、手工维护成本高、数字失去可读性—15 条 4 分类 × 3 优先级 12 种组合至少各出现 1 次再留 3 条给「已完成」恰好覆盖「未完成在前、高优置顶、完成率 20%」三类验证需求不浪费一条数据。2. 状态分布12 未完成 / 3 已完成未完成 12 条80%撑起未完成视图的滚动列表让统计卡「未完成 12」有分量。已完成 3 条20%不多不少——多了喧宾夺主少了进度条3/15 20%没有存在感。完成率 20% 是个「有故事」的数字一眼能读出五分之一既不显得全员躺平也不像演示数据那样 100% 完成反而真实。3. 优先级分布4 高 / 7 中 / 4 低优先级条数分布作用高24id 1、5、9、12分散在周一~周六验证高优置顶统计卡「高优 4」中17生活 / 学习 / 日常为主常规任务构成列表主体低04id 4、10、15 等验证降序时沉底高优先级刻意分散到一周各天而不是扎堆——这样无论按优先级排序还是按时间排序都能看到高优任务穿插其中避免出现「某一天全是高优」的失真画面。九、种子数据完整表格15 条#标题状态优先级分类创建时间1完成季度周报并提交领导未完成高工作周一 09:302预约明天上午的牙医未完成中生活周一 10:053阅读《SQLite 权威指南》第 4 章未完成中学习周一 20:154整理桌面文件清理垃圾未完成低日常周二 08:405给项目加异常日志上报未完成高工作周二 14:226超市采购牛奶、鸡蛋、水果未完成中生活周三 09:007复习 ArkTS 状态管理未完成中学习周三 19:308给爸妈打电话未完成中生活周四 12:009修复登录页闪退问题未完成高工作周四 15:4710缴纳水电燃气费未完成低日常周五 08:2011整理照片备份到云端未完成中日常周五 21:0012准备周末分享会 PPT未完成高工作周六 10:0013完成健身卡续费已完成中生活上周 16:0014更新应用隐私协议已完成中工作上周 11:3015看完收藏的 3 篇技术文章已完成低学习上周 22:10十、initSeedData 的幂等保护实现「幂等」指同一操作无论执行多少次结果都一致。initSeedData()必须幂等——否则每次冷启动都重复插入 15 条统计卡数字会像滚雪球一样翻倍15 → 30 → 45 …。1. 双重防线实现staticasyncinitSeedData(context:common.UIAbilityContext):Promisevoid{conststoreawaitthis.getStore(context);// 防线一空表判断——表里已有任何数据就直接返回constresultSetawaitstore.querySql(SELECT COUNT(*) AS c FROM${this.TABLE});lettotal0;if(resultSet.goToNextRow())totalresultSet.getLong(resultSet.getColumnIndex(c));resultSet.close();if(total0){console.info([TodoDao] 已有数据${total}条跳过种子注入);return;}// 防线二事务包裹——15 条要么全成功要么全回滚杜绝「插了一半」constnowDate.now();constDAY86400000,H3600000,M60000;constseed:ArrayrelationalStore.ValuesBucket[{title:完成季度周报并提交领导,priority:2,category:工作,completed:0,created_time:now-6*DAY,completed_time:0,remark:含图表},{title:预约明天上午的牙医,priority:1,category:生活,completed:0,created_time:now-6*DAY35*M,completed_time:0,remark:电话 021-88886666},{title:阅读《SQLite 权威指南》第 4 章,priority:1,category:学习,completed:0,created_time:now-6*DAY10*H45*M,completed_time:0,remark:做笔记},{title:整理桌面文件清理垃圾,priority:0,category:日常,completed:0,created_time:now-5*DAY8*H40*M,completed_time:0,remark:},{title:给项目加异常日志上报,priority:2,category:工作,completed:0,created_time:now-5*DAY14*H22*M,completed_time:0,remark:需求 #128},{title:超市采购牛奶、鸡蛋、水果,priority:1,category:生活,completed:0,created_time:now-4*DAY9*H,completed_time:0,remark:预算 150},{title:复习 ArkTS 状态管理,priority:1,category:学习,completed:0,created_time:now-4*DAY19*H30*M,completed_time:0,remark:两小时},{title:给爸妈打电话,priority:1,category:生活,completed:0,created_time:now-3*DAY12*H,completed_time:0,remark:半小时},{title:修复登录页闪退问题,priority:2,category:工作,completed:0,created_time:now-3*DAY15*H47*M,completed_time:0,remark:紧急},{title:缴纳水电燃气费,priority:0,category:日常,completed:0,created_time:now-2*DAY8*H20*M,completed_time:0,remark:},{title:整理照片备份到云端,priority:1,category:日常,completed:0,created_time:now-2*DAY21*H,completed_time:0,remark:50G},{title:准备周末分享会 PPT,priority:2,category:工作,completed:0,created_time:now-1*DAY10*H,completed_time:0,remark:主题RDB 实践},{title:完成健身卡续费,priority:1,category:生活,completed:1,created_time:now-7*DAY16*H,completed_time:now-7*DAY16*H,remark:已完成},{title:更新应用隐私协议,priority:1,category:工作,completed:1,created_time:now-7*DAY11*H30*M,completed_time:now-7*DAY11*H30*M,remark:已完成},{title:看完收藏的 3 篇技术文章,priority:0,category:学习,completed:1,created_time:now-7*DAY22*H10*M,completed_time:now-7*DAY22*H10*M,remark:已完成},];store.beginTransaction();try{for(constitemofseed)awaitstore.insert(this.TABLE,item);store.commit();console.info([TodoDao] 种子数据注入完成共${seed.length}条);}catch(e){store.rollBack();console.error([TodoDao] 种子注入失败已整体回滚,JSON.stringify(e));}}相比第四章的简化版这里把时间戳改为Date.now()相对偏移周一 now - 6*DAY再逐条加小时 / 分钟偏移保证列表时间永远锚定「最近一周」不会随真实日期漂移。2. 为什么不用「建表时一次性写入」有人会在建表 SQL 里用INSERT ... SELECT ... WHERE NOT EXISTS一步完成判空 注入但 ArkTS 的executeSql对多值 INSERT 支持不友好而且判空本身只需一次COUNT(*)成本极低。「先查后插 事务回滚」是最贴合 RDB 最佳实践、也最容易读懂的方案判空保护幂等事务保护原子性两者各司其职。十一、注入后页面效果预测与验证方法1. 效果预测页面区域预期表现统计卡未完成12/ 已完成3/ 高优4全部视图15 张卡片未完成在前高优带 ⚡底部进度条已完成 3 项 ▏▏▏▏ 20%分类标签工作 5 / 生活 4 / 学习 3 / 日常 32. SQL 验证语句真机或模拟器跑起来后可用 DevEco Studio 的 RDB 调试面板或直接在 DAO 里打日志执行以下 SQL 核对-- ① 总数与状态分布期望 15 12 未完成 3 已完成SELECTcompleted,COUNT(*)FROMtodoGROUPBYcompleted;-- ② 优先级分布期望 高4 / 中7 / 低4SELECTpriority,COUNT(*)FROMtodoGROUPBYpriority;-- ③ 分类分布期望 工作5 / 生活4 / 学习3 / 日常3SELECTcategory,COUNT(*)FROMtodoGROUPBYcategory;-- ④ 未完成视图排序高优在前同优先级按创建时间倒序SELECTid,title,priority,created_timeFROMtodoWHEREcompleted0ORDERBYpriorityDESC,created_timeDESC;-- ⑤ 幂等验证连续冷启动两次后总数仍应为 15而不是 30SELECTCOUNT(*)FROMtodo;判断标准①~③ 的数字与统计卡完全一致④ 的前三条应为高优任务id 9、12、5、1 之一⑤ 能直接证明initSeedData()的幂等保护生效。十二、FAQQ1为什么不用固定时间戳而用Date.now()偏移固定时间戳写死的是某个具体时刻半年后打开 App「昨天」的待办实际是一百多天前创建的时间语义完全错乱。用now - 偏移生成数据永远锚定「今天」演示效果不随真实时间漂移。Q2种子数据会不会污染用户的真实数据不会。initSeedData()只在表为空COUNT 0时注入用户一旦新增或删除过任何一条总数 0后续启动全部跳过。生产环境建议在设置页提供「恢复示例数据」入口先DELETE FROM todo;再重新调用注入。Q3已完成的 3 条completed_time 为什么等于 created_timecompleted_time 的语义是「何时打勾」。演示数据没有真实勾选动作把完成时间设为与创建时间相同保证状态切换逻辑读到的完成时间是合法的非 0 值不会出现「已完成了但完成时间为 0」的脏数据。Q4注入 15 条会不会卡启动15 条单条 INSERT 走本地 RDB实测毫秒级 10ms远低于首帧渲染耗时。真正的开销是每次getStore的建库动作所以initSeedData()应放在onWindowStageCreate之后异步调用不阻塞 UI 线程。