在这里插入图片描述
在这里插入图片描述

实例:健康数据(Health)|技术:14 天记录、数值梯度、趋势可视化

一、种子数据的设计目标

实例 14 的种子数据要撑起「仪表盘 + 趋势图 + 周汇总」,设计目标:

  1. 14 天记录:近两周连续记录——柱状图 7 根柱有数据、周汇总有值;
  2. 数值合理:体重 72~74kg 微波动、步数 5000~12000、睡眠 6~8.5h、心率 62~72、饮水 1000~2000ml、运动 10~60min——真实健康数据范围;
  3. 趋势可见:体重「先高后低」(74→72kg 下降趋势)、睡眠「有起伏」——趋势箭头与柱状图有故事;
  4. 今天有记录:最近一天(today)有数据——今日概览卡显示大数字。

二、14 天健康记录种子数据

日期(距今天) 体重kg 步数 睡眠h 心率 饮水ml 运动min 备注
13 天前 74.2 6000 6.5 68 1200 20 加班
12 天前 74.0 8200 7.0 67 1500 30
11 天前 73.8 4500 6.0 70 1000 15 熬夜
10 天前 73.9 9800 7.5 65 1800 40
9 天前 73.6 7600 8.0 64 1600 35 跑了 5km
8 天前 73.7 5200 6.5 69 1100 20
7 天前 73.4 9000 7.0 66 1700 30
6 天前 73.5 6800 6.8 67 1400 25
5 天前 73.2 11000 7.8 63 1900 45 晨跑
4 天前 73.0 8800 7.2 65 1600 30
3 天前 73.1 5800 6.5 68 1200 20
2 天前 72.8 10200 7.6 63 1800 40
1 天前 72.5 9200 7.4 64 1700 35 游泳
今天 72.3 8300 7.5 65 1500 30

设计要点

  • 14 天连续record_date 从 daysAgo(13) 到 today 逐日填充——柱状图近 7 天(daysAgo(6)~today)恰好 7 根柱;
  • 体重下降趋势:74.2 → 72.3(-1.9kg)——本周均值(72.6)vs 上周均值(73.7)差 -1.1kg → 趋势箭头「↓ 较上周 -1.1kg」绿色(减重健康);
  • 步数起伏:4500(熬夜)~ 11000(晨跑)——有故事的数据(备注解释异常值);
  • 睡眠起伏:6.0(熬夜)~ 8.0(跑了 5km 睡得香)——柱状图高低错落;
  • 今天有记录:72.3kg/8300 步/7.5h——今日概览卡数字饱满。

三、代码实现

const today = HealthDao.today();
for (let i = 13; i >= 0; i--) {
  const date = HealthDao.daysAgo(i);
  const seed = seedByIndex(i);   // 按偏移取对应数值(见第二节表格)
  const values: relationalStore.ValuesBucket = {
    record_date: date, weight: seed.weight, steps: seed.steps,
    sleep_hours: seed.sleep, heart_rate: seed.heart,
    water: seed.water, exercise_minutes: seed.exercise,
    remark: seed.remark,
  };
  await store.insert(HealthDao.TABLE, values);
}

逐日插入daysAgo(13)daysAgo(0)(今天)循环——日期字符串由工具函数生成,数值按表格映射。幂等保护:查 health COUNT,非空即返回。

与前面实例种子的差异:健康种子是「按日期生成的连续序列」而非「固定数组」——因为 record_date 依赖运行时日期(today/daysAgo),不能写死。动态日期种子是时序类应用的特点。

四、注入后的仪表盘效果预测

区块 预期效果
今日概览 体重 72.3kg · 步数 8300 · 睡眠 7.5h · 心率 65bpm
体重趋势 「↓ 较上周 -1.1kg」绿色(减重中)
睡眠柱状图 7 根柱高低错落(6.0~8.0h),今天高亮深蓝
周汇总 日均步数 ~8457 · 日均饮水 ~1585ml · 日均运动 ~32min
记录列表 7 行(近 7 天),今天在最上(ASC 倒序看最新?按日期降序显示)

演示脚本:指着今日概览说「今天体重 72.3、步数 8300、睡眠 7.5 小时」→ 指体重趋势「本周比上周轻了 1.1 公斤,绿色箭头」→ 指柱状图「昨天睡得最好 8 小时,前天熬夜只有 6 小时」→ 指周汇总「日均八千四百步、一千五百毫升水、半小时运动」→ 滚动看 7 天明细 → 点一行编辑(把睡眠改成 8h)→ 柱状图与汇总刷新。

五、验证方法

  1. hilog 日志:搜 HealthDao,看到「已填充 14 天健康记录」;
  2. 页面显示:今日概览 72.3/8300/7.5/65、趋势「↓ -1.1kg」、柱状图 7 柱、周汇总有值;
  3. 数据库直查
    SELECT COUNT(*) FROM health;  -- 14
    SELECT AVG(weight) FROM health WHERE record_date >= '2024-06-19';  -- ≈72.6(本周)
    SELECT AVG(weight) FROM health WHERE record_date >= '2024-06-12' AND record_date <= '2024-06-18';  -- ≈73.7(上周)
    SELECT AVG(steps) FROM health;  -- ≈8400
    SELECT MAX(sleep_hours) FROM health;  -- 8.0
    
  4. 交互验证:新增(今天已有 → 提示编辑)、编辑、删除、刷新。

六、FAQ

Q1:为什么体重是「缓慢下降」而不是波动?
A:体重趋势是页面的叙事核心——「↓ -1.1kg 绿色」需要两周均值差。缓慢下降(74.2→72.3)让趋势箭头有说服力。真实健康数据也是「微趋势 + 日波动」(73.7→73.5→73.8),种子数据略去噪音突出趋势。种子数据要「讲一个趋势故事」

Q2:为什么今天必须有记录?
A:今日概览卡显示 todayRecord——今天没记录则四格全显示「-」,仪表盘失去「今日」的即时感。today 有数据是健康 Demo 的必然要求(用户打开 App 先看今天)。

Q3:步数为什么从 4500 到 11000 波动这么大?
A:真实步数就是「工作日 vs 运动日」的波动——4500(熬夜/久坐)、11000(晨跑)。备注(跑了 5km / 熬夜)解释异常值,让数据「讲得通」。数值波动的背后要有备注支撑

Q4:14 天的数据量够吗?
A:近 7 天柱状图 + 周汇总 + 上周对比——14 天恰好覆盖「本周 7 天 + 上周 7 天」两个统计窗口。再少(7 天)上周对比没数据,再多(30 天)Demo 冗余。种子数量 = 统计窗口的覆盖需求

Q5:插入的日期顺序为什么从旧到新?
A:for (let i = 13; i >= 0; i--)——先插 13 天前再插今天。虽然插入顺序不影响查询结果(排序在查询时做),但从旧到新让 id 与日期同序(id 小的日期旧),便于调试。种子插入顺序从旧到新是时序数据的习惯。

Q6:体重 72.3 这种小数怎么保证精度?
A:weight 是 REAL 类型,72.3 原样存储。显示时 toFixed(1) 保持一位小数。REAL 存小数 + 展示层格式化——数据层不截断,展示层控制精度。

七、文章小结

本篇文章展示了实例 14 的种子数据:14 天连续健康记录(体重下降趋势 74.2→72.3 + 步数/睡眠起伏 + 今天有数据)。核心是「趋势故事的种子设计」——体重缓慢下降让趋势箭头(↓ -1.1kg 绿)有说服力,睡眠起伏让柱状图高低错落,备注解释异常值。14 天恰好覆盖本周 + 上周两个统计窗口,仪表盘一开屏就数字饱满。

下一篇(14-5)是实例 14 的收官文章,展示 HealthPage 全量代码与运行效果。

八、附录:种子数据的代码级补全与效果复盘

本附录把实例 14 种子数据「从表格到代码」的完整链路补齐:14 天种子表的字段级数值、initSeedData 全量代码、注入后的仪表盘效果预测与验证 SQL——方便直接对照落地版代码逐行核对。

8.1 14 天种子数据表补全(含设计意图列)

日期(距今天) 体重kg 步数 睡眠h 心率 饮水ml 运动min 备注 设计意图
13 天前 74.2 6000 6.5 68 1200 20 加班 体重起点(14 天最高值)
12 天前 74.0 8200 7.0 67 1500 30 平稳回落
11 天前 73.8 4500 6.0 70 1000 15 熬夜 步数/睡眠双谷值
10 天前 73.9 9800 7.5 65 1800 40 运动日反弹
9 天前 73.6 7600 8.0 64 1600 35 跑了 5km 睡眠峰值(运动助眠)
8 天前 73.7 5200 6.5 69 1100 20 小低谷
7 天前 73.4 9000 7.0 66 1700 30 上周收尾
6 天前 73.5 6800 6.8 67 1400 25 本周第一日
5 天前 73.2 11000 7.8 63 1900 45 晨跑 步数峰值(11000)
4 天前 73.0 8800 7.2 65 1600 30
3 天前 73.1 5800 6.5 68 1200 20
2 天前 72.8 10200 7.6 63 1800 40
1 天前 72.5 9200 7.4 64 1700 35 游泳
今天 72.3 8300 7.5 65 1500 30 今日概览数据源

补全说明:原表格只给了数值,这里补上「设计意图」列——每一行都能讲出「为什么是这个数」。种子数据不是随机数,而是**「趋势 + 事件」双线叙事**:趋势线(体重 74.2→72.3)保证统计结果稳定,事件线(熬夜/晨跑/游泳)让柱状图起伏有解释。

8.2 种子设计复盘

三件事是这套种子的核心:

  1. 体重下降趋势:14 天从 74.2kg 缓降到 72.3kg(-1.9kg),日均约 -0.14kg。上周均值(73.7)vs 本周均值(72.6)差 -1.1kg——趋势箭头「↓ 较上周 -1.1kg」绿色成立。若体重随机波动(72 与 74 交替),两周均值差趋近 0,箭头就消失了——趋势必须「缓慢且单向」
  2. 步数起伏:4500(熬夜久坐)到 11000(晨跑)——跨度 6500 步,柱状图高低分明。且异常值都有备注解释(熬夜/跑了 5km/游泳),用户点开明细「讲得通」——数值波动的背后要有备注支撑
  3. 今天有数据:today 行(72.3/8300/7.5/65)是今日概览卡的数据源——没有它四格全「-」,仪表盘失去开屏即用的即时感。

复盘结论:种子数据的价值 = 让页面每个区块「首屏即有故事」。数值要服务于页面结构——统计窗口 7 天 → 数据至少 14 天;趋势箭头 → 两周均值差;今日卡 → today 必须有记录。

8.3 initSeedData 全量代码

static async initSeedData(context: common.Context): Promise<void> {
  const store = await HealthDao.getStore(context);
  // 幂等保护:已有记录直接返回,避免重复填充冲掉用户数据
  const countResult = await store.querySql(
    `SELECT COUNT(*) AS c FROM ${HealthDao.TABLE}`);
  if (countResult.goToNextRow() &&
      countResult.getLong(countResult.getColumnIndex('c')) > 0) {
    hilog.info(0x0000, 'HealthDao', '健康数据已存在,跳过种子');
    return;
  }
  // 14 天种子:从旧到新插入,id 与日期同序,便于调试
  for (let i = 13; i >= 0; i--) {
    const date = HealthDao.daysAgo(i);
    const seed = seedByIndex(i);   // 按偏移取 8.1 表格对应数值
    const values: relationalStore.ValuesBucket = {
      record_date: date,
      weight: seed.weight,
      steps: seed.steps,
      sleep_hours: seed.sleep,
      heart_rate: seed.heart,
      water: seed.water,
      exercise_minutes: seed.exercise,
      remark: seed.remark,
    };
    await store.insert(HealthDao.TABLE, values);
  }
  hilog.info(0x0000, 'HealthDao', '已填充 14 天健康记录');
}

seedByIndex(i) 返回 { weight, steps, sleep, heart, water, exercise, remark } 结构——i 从 13(13 天前)到 0(今天)逐行映射 8.1 表格。动态日期种子的关键:日期由 daysAgo(i) 运行时生成,数值由固定表驱动——日期动态、数值可控,两者解耦。

8.4 注入后的仪表盘效果预测

区块 预期效果 数据来源
今日概览 体重 72.3kg · 步数 8300 · 睡眠 7.5h · 心率 65bpm today 行(daysAgo(0))
体重趋势 「↓ 较上周 -1.1kg」绿色箭头(减重健康) 本周均值 72.6 vs 上周均值 73.7
睡眠柱状图 7 根柱 6.0~8.0h 高低错落,今天高亮深蓝 daysAgo(6)~today 范围查询
周汇总 日均步数 ~8457 · 日均饮水 ~1585ml · 日均运动 ~32min 本周 7 天 AVG
记录列表 7 行明细,今天在最上(日期降序) 近 7 天查询

演示话术:今日概览「今天 72.3 公斤、八千三百步、睡了七小时半」→ 趋势「这周比上周轻了 1.1 公斤」→ 柱状图「前天熬夜只睡 6 小时,前天跑了 5 公里那天睡了 8 小时」→ 周汇总「日均八千四百步、一千五百毫升水」。

8.5 验证 SQL(直查数据库核对)

-- 总数:应为 14
SELECT COUNT(*) FROM health;
-- 本周体重均值:≈72.6(减重趋势的「今」)
SELECT AVG(weight) FROM health
  WHERE record_date >= (SELECT date('now', '-6 day'));
-- 上周体重均值:≈73.7(趋势对比的「昨」)
SELECT AVG(weight) FROM health
  WHERE record_date >= (SELECT date('now', '-13 day'))
    AND record_date < (SELECT date('now', '-6 day'));
-- 步数峰值:11000(晨跑日)
SELECT MAX(steps) FROM health;
-- 睡眠峰值:8.0(跑了 5km 日)
SELECT MAX(sleep_hours) FROM health;
-- 今日记录:应返回 1 行(72.3/8300/7.5/65)
SELECT * FROM health WHERE record_date = (SELECT date('now'));

与正文第五节的区别:这里用 date('now', '-6 day') 动态日期,不写死 ‘2024-06-19’——演示环境日期会变,验证 SQL 与种子一样要「动态日期」

8.6 FAQ

Q1:为什么在 seedByIndex 里写死 14 组数,而不是用公式生成?
A:公式生成的数值「太均匀」——真实健康数据恰恰是不均匀的(熬夜日步数骤降、运动日睡眠好)。写死 14 组数让异常值(4500 步、6.0h)可控、备注可对应,页面「讲得出故事」。种子数据优先「可控」而非「随机」

Q2:initSeedData 为什么每次启动都查 COUNT?
A:幂等保护。健康页 onPageShow 会调用 initSeedData,若用户已新增/删除过记录,COUNT>0 直接跳过——不会把用户数据冲掉。种子只在空库执行一次,之后由用户数据接管。

Q3:今天(today)的记录是怎么保证存在的?
A:循环 i 从 13 到 0,daysAgo(0) 就是当天——种子天然包含 today 行。这是「动态日期种子」相比「固定数组种子」的优势:不管哪天打开 App,今天都有数据,今日概览卡永不落空。

Q4:周汇总的日均值为什么有小数点(8457)?
A:AVG(steps) 返回 REAL(8457.14…),展示层 Math.round 取整。数据层保留精度、展示层格式化——与体重 toFixed(1) 同一原则,数据层不截断,展示层控制精度

Q5:如果演示当天恰好跨周(比如周三),趋势对比还准吗?
A:准。「本周」按 daysAgo(6)~today 滚动取 7 天,「上周」取前 7 天——两个窗口永远相邻且各 7 天,与日历周无关。滚动窗口让趋势对比在任何演示日期都成立

Logo

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

更多推荐