HarmonyOS应用实战-启示散页-07-收藏功能别只存文本:用去重、来源和刷新时间串起来
HarmonyOS应用实战-启示散页-07-收藏功能别只存文本用去重、来源和刷新时间串起来收藏功能很容易被写成“把当前答案文本放进数组”。这在第一天能用但很快会遇到问题同一句答案来自不同题库怎么办用户改了题库名后收藏来源怎么显示重复点收藏要不要出现两条收藏后列表为什么不刷新答案之书的收藏应该存来源、去重和时间而不是只存一段字符串。这篇文章会把问题拆成四个可落地的点收藏记录保存 answerId、deckId、answerText 和创建时间。用组合 key 去重避免同一答案重复收藏。收藏写入后发出刷新信号列表从 Service 重读。处理题库被删除、答案被改名后的来源展示。1. 只存文本会丢掉来源答案文本本身不是稳定身份。不同题库可能都有“先等等”同一题库的答案也可能被用户编辑。收藏如果只存文本后续无法跳回来源题库也无法区分用户收藏的是哪一次抽取结果。interfaceFavoriteRecord{id:string;deckId:string;answerId:string;answerText:string;question?:string;createdAt:number;}收藏记录保存快照文本同时保存来源 id。快照用于展示来源 id 用于追踪和去重。2. 收藏入口使用 DrawAnswerResult收藏按钮通常在抽取结果页。这个页面不应该自己拼来源字段而是直接使用DrawAnswerResult。这样收藏、历史和分享都从同一个领域结果出发。privateasyncaddFavorite():Promisevoid{if(!this.result){return;}awaitFavoriteService.addFromDraw(this.result);promptAction.showToast({message:已收藏});}页面负责触发收藏FavoriteService 负责判断能不能收藏以及怎么保存。3. 组合 key 去重更符合业务如果只按 answerText 去重不同题库里的同一句会被误认为同一个收藏如果只按 answerId 去重导入或迁移后也可能冲突。答案之书可以用 deckId answerId 作为主要去重键必要时再用文本兜底。functionfavoriteKey(item:FavoriteRecord):string{return${item.deckId}:${item.answerId};}constexists:booleanrecords.some((item:FavoriteRecord):boolean{returnfavoriteKey(item)${result.deckId}:${result.answer.id};});if(exists){return;}去重规则要体现产品语义用户收藏的是某个题库中的某条答案而不是全应用唯一的一段文字。4. 保存前生成快照展示时不依赖来源仍存在收藏记录里保留answerText是必要的。即使用户后来删除题库收藏列表仍应该能显示当时收藏的答案而不是整条记录变成空白。来源信息可以显示为“原题库已删除”。constrecord:FavoriteRecord{id:newId(fav),deckId:result.deckId,answerId:result.answer.id,answerText:result.answer.text,question:result.question,createdAt:result.drawnAt};快照和来源不是二选一。快照保证展示稳定来源保证追踪能力。5. 收藏列表从 Service 组装展示模型收藏页不要直接读 FavoriteRepository 后自己查题库名。Service 可以一次性读取收藏、题库索引和题库摘要组装成页面需要的展示模型。这样题库被删除、重命名、数据损坏时兜底口径只有一处。interfaceFavoriteViewItem{id:string;answerText:string;deckName:string;sourceState:active|missing;createdAtText:string;}asynclistViewItems():PromiseFavoriteViewItem[]{constfavorites:FavoriteRecord[]awaitFavoriteRepository.loadAll();constdecks:Mapstring,DeckSummaryawaitDeckService.loadSummaryMap();returnfavorites.map((item:FavoriteRecord):FavoriteViewItemthis.toViewItem(item,decks));}页面拿到的是可展示对象不需要知道来源题库怎么查也不需要重复处理 missing 状态。6. 写入后刷新信号要独立收藏列表和题库列表不是同一类数据。答案之书应该为收藏单独准备LastFavoriteUpdateAt避免收藏变化误触发题库列表重载也避免题库变化时收藏页不更新。awaitFavoriteRepository.saveAll(nextRecords);AppStorage.setOrCreate(AppStorageKey.LastFavoriteUpdateAt,Date.now());StorageLink(lastFavoriteUpdateAt)Watch(reloadFavorites)lastFavoriteUpdateAt:number0;刷新信号按数据域拆开页面才能按需重读。一个全局 updateAt 后期会变成性能和排障负担。7. 取消收藏也要走同一条链路删除收藏不能只在页面数组里 splice。页面本地移除看起来很快但重启后又回来或者其他页面仍显示已收藏。取消收藏要更新 Repository并发出同一条刷新信号。asyncremoveFavorite(id:string):Promisevoid{constrecords:FavoriteRecord[]awaitFavoriteRepository.loadAll();constnext:FavoriteRecord[]records.filter((item:FavoriteRecord):booleanitem.id!id);awaitFavoriteRepository.saveAll(next);AppStorage.setOrCreate(AppStorageKey.LastFavoriteUpdateAt,Date.now());}收藏的增删都要走持久化闭环。页面数组只是当前渲染结果不是数据源。8. 数量和空态从真实记录计算首页或个人页如果展示收藏数量不要手动 1 或 -1。更稳的做法是在页面出现时从 FavoriteService 读取或者监听收藏刷新信号后重新计算。这样跨页面返回、删除和恢复都不会让数字漂移。privateasyncreloadCount():Promisevoid{constrecords:FavoriteRecord[]awaitFavoriteRepository.loadAll();this.favoriteCountrecords.length;}本地计数也要尊重单一数据源。手动增减在多入口场景里迟早会错。9. 验证与排障收藏验证要覆盖重复收藏、删除来源题库、编辑答案文本、取消收藏后重启、收藏列表和首页数量同步。重点不是按钮能点而是每个入口看到的是同一份数据。验证点 1. 同一答案连续点收藏只出现一条 2. 删除来源题库后收藏仍显示 answerText 3. 取消收藏后重启应用不再出现 4. 收藏数量和列表条数一致 5. LastFavoriteUpdateAt 只在收藏变化时更新如果收藏页不刷新优先检查刷新信号和页面重读不要先改列表渲染。如果后续收藏列表要支持按题库筛选也不要把筛选条件下沉到 Repository。Repository 返回原始收藏Service 根据deckId、来源状态和时间组装展示模型页面只切换筛选条件。这样题库被删除、重命名或迁移后筛选结果仍然从同一个模型推出来不会每个页面各写一套来源兜底。验证清单清应用数据后从冷启动进入确认默认数据、页面状态和日志分支符合预期。对本文涉及的写路径准备正常、空值、重复、越界四类输入确认错误停在 Service 或 Repository。页面返回、重新进入、切换题库、收藏、历史或删除后确认对应刷新信号触发重新读取。修改资源或模块归属后重新构建确认 HAP、HAR、HSP 的依赖方向没有反转。涉及真机体验、备份恢复、发布素材的内容单独记录是否已经在设备或平台侧验证。常见问题与处理现象先看哪里处理方式重复收藏出现多条去重 key 是否存在使用 deckId answerId 去重来源题库删除后收藏空白是否保存 answerText 快照收藏记录保留展示文本取消收藏后重启又回来是否只改页面数组删除必须写回 Repository首页收藏数不准是否手动加减计数从 Service 重读真实数量小结收藏不是文本数组而是带来源的用户选择记录。保存快照、保留来源、按组合 key 去重再用独立刷新信号联动页面收藏功能才经得起后续编辑和删除。

相关新闻

PLC维修工程师实战指南:多品牌故障排查与维护技巧

PLC维修工程师实战指南:多品牌故障排查与维护技巧

1. PLC维修工程师的日常挑战作为一名从业十年的工业自动化工程师,我每天的工作台前总是堆满了各种品牌的PLC——从西门子S7系列到台达DVP系列,从三菱FX到欧姆龙CP1E。维修这些工业控制设备最令人头疼的,不是复杂的故障现象,而是不…

2026/7/22 4:21:32阅读更多 →
GBKtoUTF-8:告别中文乱码,让文本文件跨平台无压力

GBKtoUTF-8:告别中文乱码,让文本文件跨平台无压力

GBKtoUTF-8:告别中文乱码,让文本文件跨平台无压力 【免费下载链接】GBKtoUTF-8 To transcode text files from GBK to UTF-8 项目地址: https://gitcode.com/gh_mirrors/gb/GBKtoUTF-8 你是否曾经遇到过这样的情况?打开一个文档&#…

2026/7/21 2:52:18阅读更多 →
PC硬件市场波动解析:存储芯片涨价原因与应对策略

PC硬件市场波动解析:存储芯片涨价原因与应对策略

1. 当前PC硬件市场的异常波动现象最近走进电脑城或者浏览电商平台的DIY配件页面,相信不少朋友都会倒吸一口凉气——内存和固态硬盘的价格就像坐上了火箭,早中晚三个时段刷新页面可能看到三个不同的价格标签。我上周帮朋友装机时就亲历了这一幕&#xff1…

2026/7/22 4:14:06阅读更多 →
HDVPSS GRPX模块:嵌入式图形叠加与混合的硬件加速实践

HDVPSS GRPX模块:嵌入式图形叠加与混合的硬件加速实践

1. 项目概述:深入理解HDVPSS的图形处理核心在嵌入式视频处理系统的开发中,图形叠加与混合是绕不开的核心需求。无论是安防监控中的OSD(屏幕显示)信息叠加,还是医疗影像中的标注与测量,亦或是工业HMI界面中的…

2026/7/22 4:22:27阅读更多 →
剧情长片预告片制作全流程:从剪辑到输出的专业技术方案

剧情长片预告片制作全流程:从剪辑到输出的专业技术方案

在电影制作和预告片剪辑领域,如何将原始素材转化为能够精准传达影片风格、吸引目标观众并符合电影节展映要求的预告片,是一项需要系统方法和专业工具支撑的技术工作。虽然《扔你的猫》作为一部入围FIRST青年电影展主竞赛单元的剧情长片,其预告…

2026/7/22 4:22:27阅读更多 →
计算机发展史:从机械计算到量子计算的演进历程

计算机发展史:从机械计算到量子计算的演进历程

1. 计算机发展编年史概述计算机发展史是一部人类智慧与技术进步的史诗,从最初的机械计算装置到今天的量子计算机,这段跨越近两个世纪的历程彻底改变了人类社会的运作方式。作为一名从业十余年的计算机工程师,我经常需要向新人讲解这段历史&am…

2026/7/22 4:22:27阅读更多 →
【搜索召回率暴跌真相】:BERT微调失效?Embedding维度错配?AI搜索工程师必须立即排查的6个致命配置项

【搜索召回率暴跌真相】:BERT微调失效?Embedding维度错配?AI搜索工程师必须立即排查的6个致命配置项

更多请点击: https://kaifayun.com 第一章:搜索召回率暴跌的系统性归因分析 搜索召回率的突然下降往往不是单一故障点所致,而是多层系统耦合失效的结果。需从数据、模型、服务、基础设施四个维度同步排查,避免陷入局部优化陷阱。…

2026/7/22 4:22:27阅读更多 →
AI搜索工具怎么选?5大维度实测对比(响应速度、事实准确率、多跳推理、隐私策略、API开放度)

AI搜索工具怎么选?5大维度实测对比(响应速度、事实准确率、多跳推理、隐私策略、API开放度)

更多请点击: https://intelliparadigm.com 第一章:AI搜索工具怎么选?5大维度实测对比(响应速度、事实准确率、多跳推理、隐私策略、API开放度) 选择AI搜索工具不能仅凭宣传口径,必须基于可复现的实测数据。…

2026/7/22 4:22:27阅读更多 →
Python字符串拼接性能优化:从+、join到f-string的实战指南

Python字符串拼接性能优化:从+、join到f-string的实战指南

1. 项目概述:为什么字符串拼接值得深究?刚接触Python那会儿,我也觉得字符串拼接不就是加号连一连的事儿吗?直到后来在项目中处理日志、拼接SQL、生成动态配置,甚至是在做性能敏感的数据处理时,才被现实狠狠…

2026/7/22 4:20:25阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →