☰
HarmonyOS 应用 · 班费管理统计页深度解析:手写柱状图与 Stack 占比条
2026/10/5 4:37:23 网站建设 项目流程

HarmonyOS 应用 · 班费管理统计页深度解析:手写柱状图与 Stack 占比条

项目编号:47-class-fund 技术栈:HarmonyOS ArkTS · ArkUI 声明式 UI · Stage 模型 本篇页面:统计页ProfileTab.ets(116 行) 系列导航:(一)首页 · (二)收支 · (三)成员 ·(四)统计


一、CatStat interface 与月度数据

interface CatStat { id: number; name: string; amount: number; percent: number; color: string; }

五个字段:id是 key 锚点,name是分类名,amount是金额,percent是占比百分比,color是占比条颜色。color字段让每个分类用不同颜色——比统一色更易区分。

private months: string[] = ['9月', '10月', '11月', '12月']; private monthValues: number[] = [480, 320, 650, 200]; private cats: CatStat[] = [ { id: 1, name: '活动采购', amount: 480, percent: 33, color: C.primary }, { id: 2, name: '团建费用', amount: 650, percent: 45, color: C.accent }, { id: 3, name: '物资费用', amount: 320, percent: 22, color: C.warn } ];

月度数据:4 个月支出值 [480, 320, 650, 200]。分类占比:活动采购 33%(primary 绿)、团建费用 45%(accent 浅绿)、物资费用 22%(warn 橙)——三个颜色区分三类支出。


二、maxVal 方法:动态求最大值

private maxVal(): number { let m = 1; this.monthValues.forEach((v: number) => { if (v > m) { m = v; } }); let m = 1; return m; }

maxVal()遍历monthValues求最大值(650)。初始值m = 1而非 0——避免除零(柱状图高度计算value * 120 / maxVal,maxVal为 0 会除零)。柱状图最高柱对应最大值,其他柱按比例缩放。


三、页面骨架:OverviewCard + BarChart + CatChart

build() { Column() { this.Header() Scroll() { Column({ space: 14 }) { this.OverviewCard() this.BarChart() this.CatChart() } .width('100%') .padding({ left: D.pad, right: D.pad, top: 14, bottom: D.pad + this.safeBottom + 20 }) } .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top) } .width('100%').height('100%').backgroundColor(C.bg) }

Header 在 Scroll 外固定,Scroll 内三块:OverviewCard(三色概览)+ BarChart(月度柱状图)+ CatChart(分类占比条)。三块都是纯 ArkUI 组件手写——不引任何图表库。


四、OverviewCard:三色收支概览

@Builder OverviewCard() { Row() { Column({ space: 4 }) { Text('¥2000').fontSize(20).fontWeight(FontWeight.Bold).fontColor(C.ok) Text('总收入').fontSize(11).fontColor(C.textDim) }.layoutWeight(1) Column({ space: 4 }) { Text('¥1450').fontSize(20).fontWeight(FontWeight.Bold).fontColor(C.danger) Text('总支出').fontSize(11).fontColor(C.textDim) }.layoutWeight(1) Column({ space: 4 }) { Text('¥550').fontSize(20).fontWeight(FontWeight.Bold).fontColor(C.primary) Text('结余').fontSize(11).fontColor(C.textDim) }.layoutWeight(1) } .width('100%').padding({ top: 16, bottom: 16 }).backgroundColor(C.card).borderRadius(D.rLg).border({ width: 1, color: C.stroke }) }

三色统计——收入绿(C.ok)、支出红(C.danger)、结余主色绿(C.primary)。与首页 BalanceCard 的数据一致(2000/1450/550),但展示形式不同——首页用渐变大卡,统计页用三列平铺,信息密度更高。


五、BarChart:ForEach 手写柱状图

@Builder BarChart() { Column({ space: 14 }) { Text('月度支出趋势').fontSize(14).fontWeight(FontWeight.Bold).fontColor(C.text).width('100%') Row() { ForEach(this.months, (m: string, idx: number) => { Column({ space: 8 }) { Text('¥' + this.monthValues[idx]).fontSize(10).fontColor(C.textDim) Column() .width(28).height(this.monthValues[idx] * 120 / this.maxVal()) .backgroundColor(C.primary).borderRadius({ topLeft: 6, topRight: 6 }) Text(m).fontSize(11).fontColor(C.textSub) }.layoutWeight(1).justifyContent(FlexAlign.End) }, (m: string) => m) }.width('100%').height(170).alignItems(VerticalAlign.Bottom) } .width('100%').padding(16).backgroundColor(C.card).borderRadius(D.rLg).border({ width: 1, color: C.stroke }) }

纯 ArkUI 柱状图——无图表库,用Column高度模拟柱体:

// 柱高 = 当前值 * 120 / 最大值 .height(this.monthValues[idx] * 120 / this.maxVal())

120是柱高上限(px),maxVal()是最大值(650)。最大柱高 120px,其他柱按比例缩放:480→88px、320→59px、650→120px、200→37px。

柱体样式:width(28)固定宽 +backgroundColor(C.primary)绿色 +borderRadius({ topLeft: 6, topRight: 6 })仅顶部圆角——柱状图的经典形态。外层Row的alignItems(VerticalAlign.Bottom)让所有柱底部对齐,height(170)给柱状图区域固定高度。每个柱的Column用justifyContent(FlexAlign.End)让"金额→柱→月份"从下往上排。


六、CatChart:Stack 双层占比条

@Builder CatChart() { Column({ space: 14 }) { Text('支出分类占比').fontSize(14).fontWeight(FontWeight.Bold).fontColor(C.text).width('100%') ForEach(this.cats, (c: CatStat) => { Column({ space: 6 }) { Row() { Text(c.name).fontSize(13).fontColor(C.text).layoutWeight(1) Text('¥' + c.amount + ' · ' + c.percent + '%').fontSize(12).fontColor(C.textDim) }.width('100%') Stack({ alignContent: Alignment.Start }) { Row().width('100%').height(8).backgroundColor(C.cardSoft).borderRadius(4) Row().width(c.percent + '%').height(8).backgroundColor(c.color).borderRadius(4) }.width('100%') }.width('100%') }, (c: CatStat) => c.id.toString()) } .width('100%').padding(16).backgroundColor(C.card).borderRadius(D.rLg).border({ width: 1, color: C.stroke }) }

Stack 双层占比条——底灰条 + 彩色条叠加:

Stack({ alignContent: Alignment.Start }) { // 底层:100% 宽浅灰条 Row().width('100%').height(8).backgroundColor(C.cardSoft).borderRadius(4) // 上层:percent% 宽彩色条 Row().width(c.percent + '%').height(8).backgroundColor(c.color).borderRadius(4) }

Alignment.Start让彩色条从左对齐。底层 100% 灰条是"总轨道",上层percent%彩色条是"已填充"——进度条的变体。c.color让每个分类用不同颜色(primary 绿 / accent 浅绿 / warn 橙),比统一色更易区分。

标签行:左侧分类名 + 右侧"¥金额 · 百分比%",layoutWeight(1)让名称撑满左侧。


七、跨页数据自洽:统计页与首页的联动

  • ¥2000 总收入 / ¥1450 总支出 / ¥550 结余↔ 首页 BalanceCard 同款数据——两页同源
  • 月度支出 [480, 320, 650, 200]↔ 首页 RecordList 的支出记录(中秋 480 / 运动会 320 / 团建 650)+ 12 月 200(首页未展示)
  • 活动采购 480 / 团建费用 650 / 物资费用 320↔ 首页 RecordList 的支出标题——分类金额与记录金额一致
  • 45% 团建占比最高↔ 首页团建 650 是最大支出——占比与金额排序一致

八、可演进方向

方向现状改法收益
数据来源静态数组从 records 动态聚合统计随记录更新
图表交互无 onClick点击柱/条查看明细下钻分析
时间范围写死 4 个月月份选择器 + 动态切换按月查看趋势
占比计算写死 percent从 amount / 总支出计算占比自动准确
图表类型柱状+占比条增加环形图/折线图多维度可视化

统计页是班费管理的分析中枢——OverviewCard 三色概览、BarChart 手写柱状图、CatChart Stack 占比条。不引任何图表库,纯 ArkUI 组件实现数据可视化。从maxVal()的动态求最大值到 Stack 双层占比条的叠加技巧,每一层都有明确的职责边界。

系列导航:(一)首页 · (二)收支 · (三)成员 ·(四)统计

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询