HarmonyOS 应用 · 寝室投票首页深度解析:ended 布尔位与双态投票按钮
HarmonyOS 应用 · 寝室投票首页深度解析:ended 布尔位与双态投票按钮
项目编号:49-dorm-vote 技术栈:HarmonyOS ArkTS · ArkUI 声明式 UI · Stage 模型 本篇页面:首页
HomeTab.ets(94 行) 系列导航:(一)首页 · (二)创建 · (三)投票 · (四)结果

一、Theme.ets:粉色主题与投票产品的色彩语义
export class C {
static readonly bg: string = '#F2F5FB';
static readonly card: string = '#FFFFFF';
static readonly cardSoft: string = '#F4F6FB';
static readonly stroke: string = '#EAEEF6';
static readonly text: string = '#1C2333';
static readonly textSub: string = '#5A6483';
static readonly textDim: string = '#9AA3BC';
static readonly primary: string = '#FF6B9D';
static readonly primarySoft: string = '#FCE7EF';
static readonly accent: string = '#FF9DBA';
static readonly warn: string = '#FF9F1C';
static readonly danger: string = '#FF5A6E';
static readonly ok: string = '#2BB673';
}
寝室投票的主色是 #FF6B9D(樱花粉),与班级任务的 #6C5CE7(深紫)、班费管理的 #00A862(翡翠绿)形成区分。粉色传递"轻社交/生活化/友好"的色彩语义——寝室投票是生活场景(外卖/值日/空调/电影),粉色比紫色更亲切、比绿色更活泼。primarySoft(#FCE7EF)浅粉做图块背景。
二、Index.ets:Tabs 容器与四 Tab 布局
Tabs({ barPosition: BarPosition.End, index: this.current }) {
TabContent() { HomeTab() }.tabBar(this.bar('首页', '🗳️', 0))
TabContent() { Func1Tab() }.tabBar(this.bar('创建', '➕', 1))
TabContent() { Func2Tab() }.tabBar(this.bar('投票', '✅', 2))
TabContent() { ProfileTab() }.tabBar(this.bar('结果', '📊', 3))
}
.barBackgroundColor('#FFFFFF')
.barHeight(60 + this.safeBottom)
.scrollable(false)
.onChange((idx: number) => { this.current = idx; })
.width('100%').height('100%').backgroundColor(C.bg)
四个 Tab:首页(🗳️)/创建(➕)/投票(✅)/结果(📊)。投票的完整生命周期:查看投票 → 创建投票 → 参与投票 → 查看结果。
三、Vote interface:ended 布尔位
interface Vote {
id: number;
emoji: string;
title: string;
options: number;
voted: number;
total: number;
ended: boolean;
}
七个字段:id 是 key 锚点,emoji 是投票图标,title 是问题,options 是选项数,voted 是已投人数,total 是总人数,ended 是"是否已结束"的布尔位。ended 是首页的核心状态字段——驱动按钮的双态变化。
private votes: Vote[] = [
{ id: 1, emoji: '🍜', title: '今晚点什么外卖?', options: 4, voted: 3, total: 4, ended: false },
{ id: 2, emoji: '🧹', title: '本周谁值日打扫', options: 4, voted: 4, total: 4, ended: true },
{ id: 3, emoji: '❄️', title: '空调温度调到几度', options: 3, voted: 2, total: 4, ended: false },
{ id: 4, emoji: '🎬', title: '周末一起看什么电影', options: 5, voted: 1, total: 4, ended: false }
];
四个投票覆盖寝室生活场景:外卖(3/4 进行中)、值日(4/4 已结束)、空调(2/4 进行中)、电影(1/4 进行中)。ended 交替 false/true,验证按钮双态的渲染正确性。值日投票 voted: 4 = total: 4 全员投完自动结束。
四、Banner:粉色渐变品牌头
@Builder
Banner() {
Row({ space: 12 }) {
Text('🗳️').fontSize(38)
Column({ space: 4 }) {
Text('民主寝室,一起决定').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
Text('4 人寝室 · 3 个进行中投票').fontSize(12).fontColor('#FFFFFF').opacity(0.9)
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
}
.width('100%').padding(18).borderRadius(D.rLg)
.linearGradient({ angle: 135, colors: [[C.primary, 0.0], [C.accent, 1.0]] })
}
38 号 🗳️ + 16 号加粗白色标语"民主寝室,一起决定" + 12 号半透明统计。linearGradient 135° 从 C.primary(#FF6B9D)到 C.accent(#FF9DBA),粉色渐变传递"轻社交"的氛围。"3 个进行中投票"实时统计 ended === false 的数量。
五、VoteList:ended 驱动的双态按钮
@Builder
VoteList() {
Column({ space: 12 }) {
ForEach(this.votes, (v: Vote) => {
Row({ space: 12 }) {
Row() { Text(v.emoji).fontSize(26) }
.width(50).height(50).backgroundColor(C.primarySoft).borderRadius(D.rSm).justifyContent(FlexAlign.Center)
Column({ space: 4 }) {
Text(v.title).fontSize(15).fontWeight(FontWeight.Medium).fontColor(C.text).maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text(v.options + ' 个选项 · ' + v.voted + '/' + v.total + ' 人已投').fontSize(12).fontColor(C.textDim)
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text(v.ended ? '已结束' : '投票').fontSize(12)
.fontColor(v.ended ? C.textDim : '#FFFFFF')
.padding({ left: 14, right: 14, top: 7, bottom: 7 })
.backgroundColor(v.ended ? C.cardSoft : C.primary).borderRadius(D.rSm)
.onClick(() => { promptAction.showToast({ message: v.ended ? '查看结果' : '参与投票' }); })
}
.width('100%').padding(14).backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
}, (v: Vote) => v.id.toString())
}.width('100%')
}
ended 驱动双态按钮——文案、字色、底色三路分支:
// 文案:已结束 vs 投票
Text(v.ended ? '已结束' : '投票')
// 字色:灰色 vs 白色
.fontColor(v.ended ? C.textDim : '#FFFFFF')
// 底色:浅灰 vs 粉色
.backgroundColor(v.ended ? C.cardSoft : C.primary)
ended === true 时按钮"已结束"灰字浅灰底(视觉弱化),点击弹"查看结果";ended === false 时按钮"投票"白字粉底(CTA 突出),点击弹"参与投票"——已结束的投票不可再投。
50×50 粉色图块:C.primarySoft 浅粉底 + 26 号 emoji,borderRadius(D.rSm) 小圆角。标题 maxLines(1) + Ellipsis 单行省略。副标题"4 个选项 · 3/4 人已投"把选项数与投票进度合并为一句。



六、可演进方向
| 方向 | 现状 | 改法 | 收益 |
|---|---|---|---|
| 投票跳转 | Toast 占位 | 跳转投票 Tab / 结果 Tab | 功能闭环 |
| 自动结束 | 静态 ended | voted === total 或倒计时自动结束 | 状态自动流转 |
| 进度条 | 纯文字 3/4 | 卡片内嵌 voted/total 进度条 | 投票进度可视化 |
| 数据源 | 静态 4 条 | 服务端拉取 + 实时刷新 | 多人同步投票 |
| 分类筛选 | 无 | 进行中/已结束分段筛选 | 快速定位 |
首页是寝室投票的概览——Banner 的粉色渐变 + VoteList 的 ended 驱动双态按钮。从条件渲染的状态按钮到 maxLines 的溢出处理,每一层都有明确的职责边界。

更多推荐




所有评论(0)