HarmonyOS 应用 · 寝室投票结果页深度解析:isWin 冠军标记与 Stack 占比条

项目编号:49-dorm-vote 技术栈:HarmonyOS ArkTS · ArkUI 声明式 UI · Stage 模型 本篇页面:结果页 ProfileTab.ets(91 行) 系列导航:(一)首页 · (二)创建 · (三)投票 · (四)结果

49 结果页首屏


一、ResultItem interface:isWin 胜出布尔位

interface ResultItem {
  id: number;
  emoji: string;
  name: string;
  votes: number;
  percent: number;
  isWin: boolean;
}

六个字段:id 是 key 锚点,emoji 是选项图标,name 是选项名,votes 是得票数,percent 是得票占比,isWin 是"是否胜出"的布尔位。isWin 是结果页的核心状态字段——驱动 👑 皇冠、票数颜色、占比条颜色三态变化。

  private results: ResultItem[] = [
    { id: 1, emoji: '🍛', name: '麻辣香锅', votes: 2, percent: 50, isWin: true },
    { id: 2, emoji: '🍜', name: '黄焖鸡米饭', votes: 1, percent: 25, isWin: false },
    { id: 3, emoji: '🍔', name: '汉堡炸鸡', votes: 1, percent: 25, isWin: false },
    { id: 4, emoji: '🍕', name: '披萨意面', votes: 0, percent: 0, isWin: false }
  ];

四个选项:麻辣香锅 2 票 50% 胜出、黄焖鸡/汉堡炸鸡各 1 票 25%、披萨 0 票。总票数 4 与投票页"3/4 人已投"对应——结果页是已结束投票的最终统计。


二、页面骨架:WinnerCard + ResultList

  build() {
    Column() {
      this.Header()
      Scroll() {
        Column({ space: 14 }) {
          this.WinnerCard()
          this.SectionTitle('投票详情')
          this.ResultList()
        }
        .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 内三块:WinnerCard(冠军卡)+ SectionTitle(分区标题)+ ResultList(结果列表)。与班费统计页的三块图表不同,结果页先给结论(冠军卡)再看明细——投票结果的核心是"谁赢了"。


三、WinnerCard:粉色渐变冠军卡

  @Builder
  WinnerCard() {
    Column({ space: 10 }) {
      Text('🏆').fontSize(44)
      Text('麻辣香锅').fontSize(20).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
      Text('以 2 票(50%)胜出').fontSize(13).fontColor('#FFFFFF').opacity(0.9)
    }
    .width('100%').padding(24).borderRadius(D.rLg)
    .linearGradient({ angle: 135, colors: [[C.primary, 0.0], [C.accent, 1.0]] })
  }

44 号 🏆 + 20 号加粗白色胜出项 + 13 号白色半透明"以 2 票(50%)胜出"。linearGradient 135° 从 C.primary(#FF6B9D)到 C.accent(#FF9DBA),粉色渐变 + 🏆 的组合传递"庆祝/胜出"的氛围。三行纵向堆叠——图标 → 胜者 → 数据,冠军卡是投票结果的"颁奖台"。


四、ResultList:isWin 驱动的三态 + Stack 占比条

  @Builder
  ResultList() {
    Column({ space: 12 }) {
      ForEach(this.results, (r: ResultItem) => {
        Column({ space: 8 }) {
          Row({ space: 10 }) {
            Text(r.emoji).fontSize(22)
            Text(r.name).fontSize(14).fontWeight(FontWeight.Medium).fontColor(C.text).layoutWeight(1)
            if (r.isWin) {
              Text('👑').fontSize(16)
            }
            Text(r.votes + ' 票').fontSize(13).fontColor(r.isWin ? C.primary : C.textDim)
          }.width('100%')
          Stack({ alignContent: Alignment.Start }) {
            Row().width('100%').height(10).backgroundColor(C.cardSoft).borderRadius(5)
            Row().width(r.percent + '%').height(10)
              .backgroundColor(r.isWin ? C.primary : C.textDim).borderRadius(5)
          }.width('100%')
        }
        .width('100%').padding(14).backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
      }, (r: ResultItem) => r.id.toString())
    }.width('100%')
  }

isWin 驱动三态变化——皇冠、票数色、占比条色三路分支:

// 皇冠:胜出项显示 👑
if (r.isWin) { Text('👑').fontSize(16) }

// 票数颜色:主色粉 vs 灰色
.fontColor(r.isWin ? C.primary : C.textDim)

// 占比条颜色:粉色 vs 灰色
.backgroundColor(r.isWin ? C.primary : C.textDim)

胜出项(麻辣香锅)显示 👑 皇冠 + 粉色票数 + 粉色占比条,落选项灰色系——冠军的视觉突出与"一枝独秀"的排序表达。

Stack 双层占比条——与班费统计页的 CatChart 同款手法:

Stack({ alignContent: Alignment.Start }) {
  // 底层:100% 宽浅灰轨道
  Row().width('100%').height(10).backgroundColor(C.cardSoft).borderRadius(5)
  // 上层:percent% 宽彩色条
  Row().width(r.percent + '%').height(10).backgroundColor(r.isWin ? C.primary : C.textDim).borderRadius(5)
}

Alignment.Start 让彩色条从左对齐。10px 高度比班费统计页的 8px 粗——结果页的占比条更醒目。50%/25%/25%/0% 的占比直观呈现票数分布。

49 结果页详情列表

49 结果页完整列表

49 结果页冠军卡


五、跨页数据自洽:结果页与投票页的联动

  • "麻辣香锅"胜出 ↔ 投票页四个选项之一(id: 4 麻辣香锅)——结果页与投票页同源
  • 总票数 4 ↔ 投票页"3/4 人已投"——Demo 中结果页比投票页多 1 票(模拟有人后续投票)
  • 50% = 2/4 票 ↔ total: 4 人数——占比按总人数计算
  • 👑 胜出标记 ↔ 首页"已结束"投票的结果展示——首页"查看结果"按钮的落地页

六、可演进方向

方向现状改法收益
数据来源静态数组从投票记录动态统计结果随投票更新
平票处理仅单冠军平票时并列显示多个 👑平票场景覆盖
投票人明细无显示"谁投了这项"透明化投票
结果分享无生成结果图 + 分享卡片传播投票结果
时间维度无展示投票时间线(何时开/关)投票过程可追溯

结果页是投票的最终呈现——WinnerCard 粉色渐变的"颁奖台" + ResultList 的 isWin 驱动三态 + Stack 占比条。从条件渲染的 👑 皇冠到双层占比条的叠加技巧,每一层都有明确的职责边界。

系列导航:(一)首页 · (二)创建 · (三)投票 · (四)结果

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐