HarmonyOS智能家居——能耗监测页面与数据可视化

📅 2026/7/14 4:54:38
HarmonyOS智能家居——能耗监测页面与数据可视化
能耗监测页面是智能家居 App 里唯一一个纯数据展示页面——没有开关、没有滑块、没有可操作的状态切换所有数据都是只读的。从截图看页面分四个区域顶部三栏统计卡片、24 小时用电分布柱状图、各房间能耗横向条形图、节能建议。实现上用了两个 BuilderECard 和 RoomEnergy代码量是所有页面里最少的。完整效果数据依赖import{ENERGY_DATA,EnergyRecord}from../services/DeviceData只导入了ENERGY_DATA和EnergyRecord没有导入 DEVICES、ROOMS 或任何操作函数。这说明能耗页面的数据来源只有 7 条能耗记录和其他页面的数据没有交叉。从 DeviceData 的定义看ENERGY_DATA是一个固定数组exportconstENERGY_DATA:EnergyRecord[][{time:0时,usage:0.3},{time:4时,usage:0.2},{time:8时,usage:1.5},{time:12时,usage:2.1},{time:16时,usage:1.8},{time:20时,usage:2.8},{time:24时,usage:0.8},]7 条记录代表 24 小时内 7 个时间点的用电量。数据是写死的 mock没有从真实电表获取。三栏统计卡片Row({space:12}){this.ECard(今日用电,2.8,kWh,A)this.ECard(预计本月,86,kWh,#FF9F43)this.ECard(同比上月,↓12,%,#00B894)}.width(100%).padding({left:16,right:16}).margin({bottom:16})三个卡片横向排列每个卡片用不同的颜色编码今日用电紫色主色#6C5CE7中性数据预计本月橙色#FF9F43预警色——月度预估如果偏高可以用暖色提醒同比上月绿色#00B894正面数据——下降 12% 是好事用绿色表示ECard BuilderBuilderECard(label:string,value:string,unit:string,color:string){Column(){Text(value).fontSize(28).fontWeight(FontWeight.Bold).fontColor(color)Text(unit).fontSize(11).fontColor(T3).margin({top:2})Text(label).fontSize(11).fontColor(T2).margin({top:4})}.layoutWeight(1).padding(16).backgroundColor(#FFFFFF).borderRadius(14)}四层信息数值大号彩色、单位小号灰色、标签小号灰色、背景白底圆角。layoutWeight(1)让三个卡片平分水平空间。注意value是string类型而不是number——因为↓12包含了符号不能用纯数字表示。在需要显示符号前缀↑、↓、±的场景里字符串比数字更灵活。24 小时用电分布柱状图Column(){Text(24小时用电分布).fontSize(16).fontWeight(FontWeight.Bold).fontColor(T1).width(100%).margin({bottom:12})Row(){ForEach(ENERGY_DATA,(e:EnergyRecord){Column(){Text(e.usagekWh).fontSize(9).fontColor(T2).margin({bottom:4})Column(){}.width(22).height(e.usage*40).borderRadius(11).linearGradient({angle:180,colors:[[A,0],[#A78BFA,1]]})Text(e.time).fontSize(9).fontColor(T3).margin({top:4})}.alignItems(HorizontalAlign.Center).layoutWeight(1)})}.width(100%).height(140).alignItems(VerticalAlign.Bottom)}和首页的能耗柱状图结构一样但有两个区别区别一柱子上方有数值标签Text(e.usagekWh).fontSize(9).fontColor(T2).margin({bottom:4})首页的柱状图没有显示具体数值用户只能通过柱子高度估算用电量。能耗页面加了数值标签后用户可以看到精确数字如 “2.8kWh”更适合做数据分析。区别二柱子高度系数更大首页的柱子高度是e.usage * 30能耗页面是e.usage * 40。因为能耗页面的柱状图区域更高140vp vs 80vp需要更大的高度范围来充分利用空间。柱状图的布局原理Row(){ForEach(ENERGY_DATA,(e:EnergyRecord){Column(){/* 数值标签 柱子 时间标签 */}.alignItems(HorizontalAlign.Center).layoutWeight(1)})}.height(140).alignItems(VerticalAlign.Bottom)所有柱子放在一个Row里layoutWeight(1)让每根柱子平分水平空间。alignItems(VerticalAlign.Bottom)让所有柱子底部对齐——这是柱状图的标准布局方式保证不同高度的柱子从同一基准线向上生长。height(140)固定了整个图表区域的高度。柱子的最大高度是2.8 * 40 112vp加上上下标签各约 15vp总高度约 142vp和 140vp 的容器高度基本匹配。如果以后能耗数据的范围变化比如最大值超过 5 kWh需要调整* 40的系数或容器高度。各房间能耗横向条形图Text(各房间能耗).fontSize(16).fontWeight(FontWeight.Bold).fontColor(T1).width(100%).padding({left:16}).margin({bottom:8})Column({space:10}){this.RoomEnergy(️ 客厅,1.2,40)this.RoomEnergy(️ 卧室,0.8,28)this.RoomEnergy( 厨房,0.5,18)this.RoomEnergy( 书房,0.2,8)this.RoomEnergy( 浴室,0.1,6)}五个房间的能耗用横向条形图展示。每个条形图有三部分房间名称固定 80vp 宽、条形弹性宽度、数值右对齐。RoomEnergy BuilderBuilderRoomEnergy(name:string,usage:number,pct:number){Row(){Text(name).fontSize(13).fontColor(T1).width(80)Row(){}.width(pct*2).height(8).borderRadius(4).backgroundColor(A40).margin({left:8,right:8}).layoutWeight(1)Text(usage kWh).fontSize(12).fontWeight(FontWeight.Bold).fontColor(A)}.width(100%)}三个参数房间名称、用电量、百分比宽度。条形的宽度用pct * 2计算——客厅的pct是 40条形宽度就是 80vp。百分比值是手动设定的40、28、18、8、6不是从数据计算的。这种手动指定比例的做法在原型阶段是合理的——如果要从真实数据计算比例需要先找出最大值再用usage / maxUsage * 100算出每个房间的相对比例。条形的颜色.backgroundColor(A40)A 40是主色的 25% 透明度0x40 / 0xFF 25.1%。半透明的紫色条形在白色卡片背景上形成一个柔和的色块比纯色更不刺眼。条形的高度只有 8vp圆角 4vp半圆视觉上是一根细长的圆角条。这种细条设计适合横向条形图——如果条形太粗比如 20vp五行条形图会占据太多垂直空间挤压其他区域。房间名称的 emoji 前缀Text(️ 客厅).fontSize(13).fontColor(T1).width(80)每个房间名称前加了 emoji 图标️ 客厅、️ 卧室、 厨房、 书房、 浴室和首页房间卡片的图标一致。emoji 让纯文字的列表有了视觉锚点用户可以快速扫描找到目标房间。固定width(80)保证所有房间名称对齐——不管名称是两个字“卧室”还是三个字加上 emoji 后右侧的条形都从同一位置开始。节能建议Column(){Text( 节能建议).fontSize(16).fontWeight(FontWeight.Bold).fontColor(T1).width(100%).margin({bottom:8})Text(• 空调调高1°C可节省约10%能耗).fontSize(13).fontColor(T2).lineHeight(22)Text(• 离家时关闭不必要的电器).fontSize(13).fontColor(T2).lineHeight(22)Text(• 使用智能插座定时关闭待机设备).fontSize(13).fontColor(T2).lineHeight(22)}三条硬编码的节能建议用圆点符号•作为列表前缀。和美食详情页的品尝建议一样这些建议是通用的、静态的不根据实际能耗数据动态生成。lineHeight(22)设置了 22px 的行高fontSize(13) × 1.7 ≈ 22比标准行高1.5 倍稍宽松。建议文字通常比较长更宽松的行高能提升可读性。整个页面的静态特征能耗页面是智能家居 App 里唯一一个没有State的页面——所有数据都是硬编码的常量没有用户交互没有状态变更。这和安防页面形成了对比——安防页面虽然也不复杂但有State alarm和State doorLocked两个可切换的状态。能耗页面的纯静态特征是由它的功能定位决定的——能耗监测是一个只看不操作的页面。用户来这里是为了了解用电情况不是为了控制设备。设备控制在首页和房间页完成能耗页面只负责展示分析结果。这种展示型页面不需要状态管理的规律在很多 App 里都适用——统计页面、报告页面、详情展示页面通常都是纯静态的不需要State。两个 Builder 的设计取舍Builder参数用途使用次数ECardlabel, value, unit, color顶部统计卡片3 次RoomEnergyname, usage, pct房间能耗条形图5 次两个 Builder 都只在 EnergyPage 里使用没有跨页面复用。ECard 的四参数设计和安防页面的 StatusCard 类似都是数值 标签 颜色但字段含义不同——ECard 的 value 是能耗数值StatusCard 的 status 是状态文字。RoomEnergy 的pct参数是一个设计上的简化——它直接指定了条形的相对宽度而不是从usage计算。这种手动指定比例的做法避免了先找最大值再算百分比的计算逻辑代码更简单。代价是如果usage数据变化需要手动更新pct值。在原型阶段这是可接受的真实 App 应该从数据自动计算。