
系列第 8 篇。同一场球局里,手机更适合输入,平板更适合展示。协同设计要先分清职责,而不是让两台设备都拥有完整编辑权限。

一、真实问题背景
羽毛球活动现场经常会把平板放在场边,让大家看下一轮对阵和比分。手机则拿在组织者手里,负责录入队员、调整比分、结算费用。两者的使用姿态完全不同。
当前项目已经在 entry/src/main/module.json5 中声明 phone、tablet、2in1,入口页面也通过 BreakpointSystem 适配不同宽度。这说明它并不是单一手机小工具,而是已经有多设备布局意识。
二、目标与边界
手机平板协同建议分成两种模式:
- 手机控制端:创建对局、加分、撤销、结束、分享。2. 平板展示端:显示当前比分、下一场、排名、费用摘要。
边界是:第一阶段不做平板反向编辑,避免双端同时写比分。平板只读展示,手机保留主控权。
三、响应式基础已经存在
当前项目的断点系统在 common/src/main/ets/utils/BreakpointSystem.ets。它把窗口宽度变化写入 AppStorage('currentBreakpoint'),页面通过 @StorageProp 读取。
@StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm';
get isSmall(): boolean {
return this.currentBreakpoint === BreakpointConstants.BREAKPOINT_SM;
}
这套机制让手机和平板可以复用同一份业务状态,同时根据断点切换导航和页面密度。
四、展示端不等于普通大屏页面
平板展示端应该减少编辑控件。以实时计分为例,手机端需要 +1、撤销、结束、直接录入比分;平板端更应该突出:
当前比分
发球/领先状态
下一场对阵
本轮排名变化
这意味着 features/src/main/ets/scoring/LiveScoringPage.ets 后续可以拆出一个 ScoreDisplayPanel,供手机页和平板展示页复用。
五、状态来源仍然是 SessionStore
协同展示不能让每个页面维护自己的比赛副本。对局数据仍应从 SessionStore 获取。
const sessionId = SessionStore.getActiveSession();
const detail = SessionStore.getDetail(sessionId);
const stats = StatsService.calculate(detail);
SessionStore 负责事实数据,StatsService 负责计算展示摘要,页面负责渲染。这三层分清后,平板端只读就很自然。
六、手机控制端的动作流
控制端可以沿用现有计分动作:
点击 A 队 +1
更新 SessionStore
写入 AppStorage 活动对局
触发 TTS 播报
展示端刷新比分
如果后续加入跨设备通信,平板端也只需要订阅"活动对局变化",不需要知道按钮是来自手机还是手表。
七、展示端的安全策略
平板展示端要避免误操作。建议默认只读:
- 不展示删除对局。2. 不展示重置全部数据。3. 不直接修改队员名单。4. 只提供全屏、亮屏、返回首页等轻操作。
这些边界能让平板放在公共区域时更安全。
八、官方参考
HarmonyOS 的多设备体验需要同时关注应用开发、窗口适配和跨端入口能力。本文重点是当前工程如何先把页面职责拆清楚。
九、工程验收清单
common/src/main/ets/utils/BreakpointSystem.ets已覆盖 sm/md/lg/xl。-entry/src/main/ets/pages/Index.ets能按断点切换导航形态。-features/src/main/ets/stats/StatsPage.ets已通过StatsService计算统计。-features/src/main/ets/scoring/LiveScoringPage.ets已具备比分展示和计分动作。-common/src/main/ets/storage/SessionStore.ets是跨页面共享事实来源。- 验证时间:2026-06-29;当前工程目标包含 HarmonyOS 6.0/API 20+,昨日 Hvigor 构建已验证BUILD SUCCESSFUL。
十、小结
手机平板协同的第一步不是做复杂同步,而是让手机成为控制端,平板成为展示端。当前项目的响应式布局、对局存储和统计服务已经具备雏形,后续只要补展示模式和跨设备刷新通道即可。
十一、下一篇衔接
手机、平板、手表分工之后,现场输入还可以再降低打扰:用语音和手表形成双入口。下一篇继续讲这个组合。