做完一组踝泵,用户在疼痛标签上补了一句“5/10”,觉得碍眼,顺手点了叉。如果这个叉的回调把整张训练卡一起清掉,随访里就只剩“今天没练”,治疗师看到的是另一个故事。ChipV2 不负责区分这两种删除,它只把点击、关闭、禁用和无障碍描述这几个交互位交给页面。

分析:关闭一个标签,可能删掉三种不同的东西

先看组件本身提供了什么。API 26.0.0 的 ChipV2 用 activated 表示激活态,allowClose 决定是否渲染关闭入口,onClicked 与 onClose 分别承接点击和关闭,另有 accessibilityDescription 供读屏使用。组件从 26.0.0 起支持,配合 @ComponentV2 使用。

这些参数只描述“组件长什么样、被点到了哪里”,没有一句话规定关闭等于删除。业务至少要拆出三个对象:训练事实,记录患者做了哪些动作、是否完成、是否中途停止;观察记录,记录疼痛数值、位置、记录时间和是否纳入本次随访;随访投影,决定这次要发给治疗师什么内容。

把三者揉成一个状态,问题马上出现。onClose 里顺手清空记录卡,被删掉的是训练事实;把 activated 解释成“有痛/无痛”,暂停分享就变成了“症状消失”;提交之后还允许关掉标签,用户看到的和已经发出去的摘要就对不上。

所以页面里先把所有权写死:Chip 只碰观察记录与分享投影,训练事实归训练模块,任何回调都进不了那块数据。

疼痛标签的点击、关闭、撤销与保存分别改哪一层(示意图)

· 疼痛标签的点击、关闭、撤销与保存分别改哪一层——四步操作对应三层数据。

功能描述:训练事实、疼痛记录、随访摘要各存各的

页面顶部先放“本次训练记录”卡,列出踝泵训练完成、股四头肌等长收缩完成和中途主动停止三项。这块内容不订阅 Chip 的任何事件,卡片下方直接写给用户看:“下面的疼痛记录只描述你的感受,不会改动上面这几条”。

观察记录至少有六项状态:数值、位置、记录时间、是否纳入随访、是否已保存、是否可撤销。activated 只绑定“是否纳入随访”这一项,数值和训练项目不参与切换。用户点一下就在发送与不发送之间切换,反馈里分别说明“治疗师会在随访摘要里看到”或“只留在本机”。

关闭动作只让观察记录从页面消失,同时记下撤销资格对应的会话修订。撤销时先比较这个基线与当前修订,一致才恢复同一条记录,不一致就丢弃资格并提示撤销已失效。这样旧页面上的按钮没法在数据前进之后,把一条历史观察重新拉回队列。

保存是单向的。函数内先查三件事:记录仍可见、已设为发送、尚未保存。通过后才写入稳定编号,把会话修订推进一格,标签置为禁用、关闭入口不再渲染,说明文字换成“已发送,需要更正请追加一条”。之后无论点标签还是点保存,都不会产生第二次提交。

禁用颜色和消失的叉只是视觉门,不是安全边界。保存函数自己会把三个条件再查一遍,迟到事件、连点和别的入口调用都走同一道校验。真实产品里的更正应当新建一条引用原记录的新版本,而不是回头修改已经发出去的内容。

无障碍描述也要跟着状态走。草稿阶段读屏应当说明点一下会改发送、点叉只移除这条记录且可以撤销;保存之后则要说明记录已发送、更正需要追加。光靠激活底色和灰化颜色,屏幕朗读的用户拿不到这些后果。

案例:从“会发送”到“已发送”的六步

进入页面时,标签是激活态,右侧写“会发送”,摘要卡说“随访里会包含这条疼痛记录”,保存按钮可点,撤销按钮是灰的。

点一下标签,它变灰,右侧变成“不发送”,保存按钮立刻变灰,摘要卡改成“暂时不包含”,反馈写着“只留在本机,训练记录不变”。回头看一眼训练卡,三项仍然是完成、完成、中途停止,数值 5/10 也没有被动过。再点一下就能切回“会发送”。

点标签右侧的叉,标签消失,页面显示“这条疼痛记录已移除”,撤销按钮亮起,保存按钮保持灰色。卡片上只剩位置和记录时间,反馈说明训练记录不受影响。整条路径里没有任何删除训练数据的调用。

点“撤销移除”,原来那条记录回来,仍显示“会发送”,反馈写“还是原来那条记录,没有重复计数”。撤销恢复的是同一个观察对象,不会新建第二个编号,训练卡的三项也没有被重新计数。

点“发给治疗师并保存”,标签变灰并显示“已发送”,叉不再渲染,两个按钮同时禁用,状态卡写“已保存,不能再改”。此时再点标签或保存,界面没有任何变化,函数里的三重校验直接把事件挡回去。

边界也都落在按钮状态上:移除之后保存不可点,撤销之后才能继续;保存之后撤销入口一起关闭,也不存在“先移除再保存”的组合。代码里还实现了修订变化后拒绝旧撤销令牌的分支,但这一版没有接真实服务端推送,这里只按界面实际跑到的状态描述。

运行截图

疼痛记录初始激活并纳入随访摘要

· 疼痛记录初始激活并纳入随访摘要——保存可点,撤销未激活。

点标签暂停发送但训练记录保持

· 点标签暂停发送但训练记录保持——数值与三项训练仍为原值。

再次点标签恢复发送

· 再次点标签恢复发送——摘要卡回到“包含这条记录”。

点叉只移除疼痛记录并开放撤销

· 点叉只移除疼痛记录并开放撤销——训练卡三项没有变化。

撤销后恢复同一条记录

· 撤销后恢复同一条记录——没有新建第二条,也没有重复计数。

保存后标签锁定且关闭入口消失

· 保存后标签锁定且关闭入口消失——需要更正只能追加。

代码片段:回调只改自己拥有的状态

组件配置只做状态映射,不在参数里塞业务判断:

ChipV2({
  chipV2Options: new ChipV2Options({
    label: new ChipV2Label({ text: '疼痛 5/10' }),
    activated: this.includedInFollowUp,
    enabled: !this.submitted,
    allowClose: !this.submitted,
    accessibilityDescription: this.submitted
      ? '这条疼痛记录已保存;需要更正时追加新记录'
      : '点一下切换是否发给治疗师;点叉只移除这条记录,可以撤销',
    onClicked: () => { this.toggleFollowUpInclusion(); },
    onClose: () => { this.closeDraftObservation(); }
  })
})

关闭只处理观察记录和撤销资格,训练数据不在这个函数里出现:

private closeDraftObservation(): void {
  if (this.submitted || !this.observationVisible) {
    return;
  }
  this.observationVisible = false;
  this.includedInFollowUp = false;
  this.undoAvailable = true;
  this.undoBaseRevision = this.sessionRevision;
}

撤销与保存各自先做前置校验,按钮变灰只是第一层:

private undoRemoval(): void {
  if (!this.undoAvailable) {
    return;
  }
  if (this.undoBaseRevision !== this.sessionRevision || this.submitted) {
    this.undoAvailable = false;
    return;
  }
  this.observationVisible = true;
  this.includedInFollowUp = true;
}

private submitObservation(): void {
  if (!this.observationVisible || !this.includedInFollowUp || this.submitted) {
    return;
  }
  this.submitted = true;
  this.undoAvailable = false;
  this.sessionRevision += 1;
}

三段代码各管一件事:onClicked 切换分享投影,onClose 移除记录并开放撤销,保存函数推进修订并锁死入口。训练记录不出现在这三个函数里,任何一条路径都碰不到它。

总结

ChipV2 把激活、关闭、禁用和无障碍说明打包成一个原生组件,用起来省事,但它没有义务替业务区分“移除一条观察”和“删掉一次训练”。组件给的是交互位,所有权得由页面写死。

这个页面把训练事实、疼痛记录和随访摘要拆成三层:点击只改分享投影,关闭只移除可撤销的记录,保存后锁定并只允许追加更正。页面已构建并安装到模拟器,六种状态都实际点过;真实服务端的修订冲突、分享授权范围和幂等写入还没接,不能拿界面状态当成已经验证。

官方资料

Logo

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

更多推荐