羽球联盟 HarmonyOS NEXT 实战系列 (16/20):赛事列表、比赛状态与详情页组织

羽球联盟 HarmonyOS NEXT 实战系列 (16/20):赛事列表、比赛状态与详情页组织
文章导读赛事模块既要展示概览列表也要在详情页里承接赛程和比分信息。EventStatus用稳定枚举表达未开始、进行中、已结束三种状态列表和详情都能复用。详情页把比赛记录按日期分组避免用户面对一长串无结构信息。页面效果赛事页和普通资讯列表最大的不同在于用户要看的不是一篇正文而是一组持续变化的结构化数据。列表页更像总览负责告诉用户赛事地点、时间和当前状态详情页则要承接对阵、阶段、比分和日期让用户能顺着比赛进度往下看。如果赛事模型设计得不够清楚列表和详情就会互相拖累。列表会塞太多信息详情又只能展示一段杂糅文本。把结构化信息分层展示是这个页面体系真正的重点。实战拆解EventListPage负责解决“看见哪些赛事值得点进去”这个问题。页面通过分类 Tab 支持全部、国际赛事、国内赛事、正在进行、已结束五个入口再结合freshEvents()过滤掉已经结束太久的比赛让列表聚焦在用户更关心的近期内容上。EventDetailPage则把单个赛事进一步展开。页面先根据路由参数找到当前赛事再将matches按日期降序排序并通过groupedDates()把同一天的比赛归到一起。这样用户浏览详情时看到的是清晰的时间分组而不是一串扁平记录。这里还有一个很适合写进教程的点赛事不是文章也不是商品。它有自己的生命周期和状态流转因此模型必须包含status、category、matches这类更贴近业务的字段。只要模型足够明确列表卡片和详情页的布局就会顺着业务自然长出来。关键代码privatesortedMatches():EventMatch[]{if(this.sportEventnull||this.sportEvent!.matchesundefined){return[];}constarr:EventMatch[]this.sportEvent!.matches!.slice();arr.sort((a:EventMatch,b:EventMatch)b.date.localeCompare(a.date));returnarr;}privategroupedDates():string[]{constseen:SetstringnewSetstring();constdates:string[][];for(constmofthis.sortedMatches()){if(!seen.has(m.date)){seen.add(m.date);dates.push(m.date);}}returndates;}privatematchesOf(date:string):EventMatch[]{returnthis.sortedMatches().filter((m:EventMatch)m.datedate);}这段逻辑直接决定了详情页读起来像不像一个赛事时间线。先排序、再分组、最后按组渲染比把所有比赛平铺到一个列表里清晰得多也更方便以后加比分状态或高亮重点场次。取舍分析赛事页的主要取舍是列表里放多少信息。把比分、赛程、地点、时间、状态、对阵全塞进列表固然“信息丰富”但会极大牺牲扫读效率。羽球联盟选择让列表保留概览把细节留给详情页本质上是在用户浏览成本和信息完整度之间做分层。另一个取舍在于状态表达方式。页面当然可以直接用中文字符串写“进行中”“已结束”但一旦进入筛选、颜色映射和组件复用阶段稳定枚举会更可靠。项目用pending、ongoing、finished作为内部状态值就是为了让模型和 UI 解耦。设计落点列表页负责概览详情页负责赛程与比分不要让两者职责互相挤压。赛事状态必须有稳定枚举便于筛选、徽章显示和后续扩展。结构化比赛数据应按日期或阶段分组而不是直接拼成长文本。易踩坑不要把比分信息塞成一段普通字符串否则排序、分组和高亮都会变得困难。已结束赛事如果不做时效过滤列表很快会被旧内容淹没。状态文案可以调整状态值不要随着中文文案一起漂移。验证方式在赛事列表切换不同分类确认国际、国内、进行中、已结束筛选结果正确。点击赛事卡片进入详情确认日期分组和比赛排序符合预期。对于未开始或暂无记录的赛事确认详情页能展示合理占位文案。参考资料ArkUI List 容器ArkUI 自定义组件开发ArkTS 状态管理概览小结第 16 篇真正强调的是赛事是一类结构化业务不适合拿文章页的思路硬套。只要列表概览、状态枚举和详情分组各守其位赛事模块就会既清晰又容易继续扩展。