山海万灵 HarmonyOS 文化知识实战(11):护照收藏与进度统计

发布时间:2026/11/14 0:05:34

山海万灵 HarmonyOS 文化知识实战(11):护照收藏与进度统计 一、把探索行为收敛成一份可恢复的进度文化知识应用中的“收藏”并不只是给卡片切换一个图标。山海万灵把一次神兽发现同时映射到图鉴收录、地域探索比例、护照印章和下次进入时的区域位置。如果这些结果由各页面各自保存重复发现、切换区域和重启恢复很容易出现不一致。工程把可变的探索数据定义为ShanhaiLocalProgress版本号、已发现神兽 ID、已选地域、已选展厅与更新时间放在同一份记录中。图鉴资料、地域资料和展厅资料仍然属于启动数据不与用户进度混存。这样重置进度只影响本机探索记录不会删除知识内容或远端资料。export interface ShanhaiLocalProgress { schemaVersion: number; discoveredIds: string[]; selectedRegionId: string; selectedHallId: string; updatedAt: number; } export function createEmptyShanhaiLocalProgress(): ShanhaiLocalProgress { return { schemaVersion: SHANHAI_LOCAL_PROGRESS_SCHEMA_VERSION, discoveredIds: [], selectedRegionId: , selectedHallId: , updatedAt: 0 }; }二、Preferences 只保存原子字段领域状态保持完整形状仓储以shanhai_local_progress作为 Preferences 文件名分别写入 schema、发现 ID 串、地域 ID、展厅 ID 和更新时间。ID 在写入前去重并以分隔符序列化读取失败、类型不符或存储不可用时返回空进度而不是把异常值直接交给页面。async save(progress: ShanhaiLocalProgress): Promisevoid { const store: preferences.Preferences | null await this.getStore(); if (store null) { return; } await store.put(KEY_SCHEMA_VERSION, SHANHAI_LOCAL_PROGRESS_SCHEMA_VERSION); await store.put(KEY_DISCOVERED_IDS, this.serializeIds(progress.discoveredIds)); await store.put(KEY_SELECTED_REGION_ID, progress.selectedRegionId); await store.put(KEY_SELECTED_HALL_ID, progress.selectedHallId); await store.put(KEY_UPDATED_AT, progress.updatedAt); await store.flush(); }这里有两个边界需要保留。第一flush()使一次用户动作对应一次明确的落盘完成点第二仓储层吞掉的是持久化异常页面仍可继续浏览当前内容并由同步状态提示后续动作。页面不需要知道键名或序列化格式。三、发现神兽时一次性更新图鉴、护照和位置ShanhaiAppViewModel.discoverBeast是状态更新入口。它先判断目标是否存在再判断是否已经发现新发现的 ID 只追加到复制后的数组。随后把神兽所属地域和展厅写为当前探索位置持久化后用启动数据与本地进度重新生成聚合结果。const alreadyDiscovered: boolean this.localProgress.discoveredIds.indexOf(beast.id) 0; const discoveredIds: string[] this.localProgress.discoveredIds.slice(); if (!alreadyDiscovered) { discoveredIds.push(beast.id); } this.localProgress this.normalizeLocalProgress(bootstrap, { schemaVersion: SHANHAI_LOCAL_PROGRESS_SCHEMA_VERSION, discoveredIds: discoveredIds, selectedRegionId: beast.regionId, selectedHallId: beast.hallId, updatedAt: Date.now() }); await this.persistLocalProgress(); const mergedBootstrap: ShanhaiBootstrap this.applyLocalProgress(bootstrap, this.localProgress);这种顺序避免了“页面先改了计数、存储失败后无法恢复”的双源状态。重复发现不会再次增加记录但仍会返回已有发现的提示无效 ID 则保持原进度不变。四、进度和护照印章都由发现记录推导地域进度不单独保存百分比。视图模型遍历地域的beastIds统计已经发现的数量再计算百分比和“已收录 x/y”状态。护照印章也遵循同一条规则一个地域的全部神兽都在discoveredIds中时该地域才进入passportRegionIds。private derivePassportRegionIds(regions: RegionItem[], discoveredIds: string[]): string[] { return regions .filter((region: RegionItem) region.beastIds.length 0 region.beastIds.every((beastId: string) discoveredIds.indexOf(beastId) 0)) .map((region: RegionItem) region.id); } private applyDiscoveryProgressToRegions(regions: RegionItem[], discoveredIds: string[]): RegionItem[] { return regions.map((region: RegionItem): RegionItem { const discoveredCount: number region.beastIds .filter((beastId: string) discoveredIds.indexOf(beastId) 0).length; const progress: number region.beastIds.length 0 ? 0 : Math.round(discoveredCount * 100 / region.beastIds.length); return { ...region, progress: progress, status: 已收录 discoveredCount / region.beastIds.length }; }); }从同一个事实源派生统计能保证档案页的“已发现”和“护照印章”与地图卡片的区域进度始终对应。地域没有目录时进度固定为 0避免除零和虚假的完成印章。五、页面只消费结果并保留可见的失败出口本次验证安装了当前构建的山海万灵包在图鉴中完成九尾狐的发现动作后回到档案页。页面回读显示“已发现 3 种神兽”和“护照印章 1 枚”说明发现记录已经驱动统计和印章结果而不是只改变详情页上的局部控件。随后结束应用进程并重新启动同一包档案页仍保留 3 条发现记录、1 枚护照印章以及最近探索地域“青丘”。这只验证本机 Preferences 的恢复链路本文不把它扩展为云端同步、跨设备迁移或网络请求成功的结论。验收时还应把“发现”和“完成地域”分开观察前者直接增加 discoveredIds后者要等一个地域目录中的全部神兽都已收录才产生护照印章。这样既能避免单次发现被误记为地域完成也让 UI 上的两个数字能追溯到不同的派生规则。若存储层暂时不可用应用仍可保留本次会话中的知识浏览和状态展示下一次启动按空进度恢复不把未落盘的数据伪装成持久结果。页面层调用syncDiscovery后回写discoveredIds、passportRegionIds、地域和展厅数据。新出现的印章会被标记为高亮目标本地 fallback 状态会转换为页面可读的同步提示。失败时不伪造成功结果而是保留当前内容并显示重试路径。档案页把发现数和护照印章数作为明确的Prop传入统计面板统计组件不读取 Preferences。这样窄屏、宽屏和主题切换只影响排版不会改变进度计算。场景进度写入页面结果首次发现神兽追加 ID、更新地域与展厅位置图鉴、地域进度和护照候选一起重算重复发现保留原 ID 集合不重复计数继续展示关联探索提示存储读取异常使用空进度知识资料仍可浏览进度从初始状态开始本地进度重置清空进度仓储图鉴资料、个人档案和远端数据保持不变六、验收要覆盖恢复、重复动作和局部重置这条链路的验收不应只看一个数字。应先在图鉴中完成一次发现确认档案统计、地域进度和护照印章基于同一条记录更新再重启应用检查发现 ID、当前地域和展厅位置是否恢复。随后重复触发同一神兽确认计数不增加最后打开本地进度重置确认框检查取消不会变更记录确认重置后只回到探索初始状态。对于网络数据源不可用的场景继续检查本地 fallback 是否保留可浏览内容并让同步横幅提供重试入口。这样持久化失败、无效目标和重复动作都有明确的状态边界而不是由页面临时补丁掩盖。七、总结山海万灵用一份版本化的本地进度记录承载发现、地域和展厅选择Preferences 负责持久化原子字段视图模型负责归一化、去重和派生统计ArkUI 页面只展示已经聚合的结果。收藏、护照印章与探索进度因此共享同一条数据链路重置也能准确限定在本机探索状态内。
延伸阅读

更多相关文章

2026/11/12 6:45:10

.NET架构进阶:微服务、DDD与云原生核心难点实战解析

1. 这篇文章真正要解决的问题 很多 .NET 开发者工作三五年后,会陷入一个尴尬的境地:日常业务开发游刃有余,CRUD、API接口、页面渲染信手拈来,但一旦被问到“如何设计一个高可用的微服务架构”、“如何保证分布式事务的一致性”、“…

2026/11/12 10:21:28

Unity游戏实时翻译实战:XUnity.AutoTranslator部署与原理详解

1. 项目概述:当Unity游戏遇到语言壁垒作为一名在游戏本地化和工具开发领域摸爬滚打了十多年的老手,我见过太多玩家因为语言问题,与优秀的独立游戏或小众作品失之交臂。对于使用Unity引擎开发的游戏而言,文本资源往往被封装在特定的…

2026/11/13 23:51:13

电工作业证模拟考试怎么报名?洛阳涧西区应届生必须知道的全流程

电工作业证模拟考试怎么报名?洛阳涧西区应届生必须知道的全流程 你刚毕业,手里只有一张毕业证书,但想找个电工相关的工作,发现企业都要求持有【电工作业证】,不然连面试资格都没有。电工作业证模拟考试怎么报名?你是不是也正愁找不到靠谱的渠道?别急,…

2026/11/13 23:51:13

广州电工证办理时间官方回应外省证书能否转过来

广州电工证办理时间官方回应外省证书能否转过来 之前考的证在外省能不能转过来? 官方回应 已经明确,广州电工证办理时间虽然有明确的规定,但外省证书在符合一定条件的情况下是可以异地转入的。不少学员在跨省就业时都遇到过这个问题,本文将从广州电工证…

2026/11/13 23:51:13

建委技工建筑电工证全国通用怎么考?新手必看避坑指南

建委技工建筑电工证全国通用怎么考?新手必看避坑指南 你是不是也正为找不到工作而发愁?手里没有建委技工建筑电工证,连面试机会都少得可怜。特别是在建筑行业,建委技工建筑电工证是入行的“敲门砖”,没有它,连工地都进不去,更别谈上岗了。别再犹豫,…

2026/11/13 23:51:13

沙雅电工证含金量高不高?报名渠道怎么选不被坑

沙雅电工证含金量高不高?报名渠道怎么选不被坑 不知道去哪报名怕被中介坑,沙雅电工证的含金量到底值不值得考?作为一个常年在工地跑的劳务班组负责人,我深知特种作业证书在一线施工中的分量。最近带班组做低压线路改造,甲方一再强调必须持证上岗,否则直…

2026/11/13 23:51:13

吉林电工证网上学习官方回应:电工证没到手,工作就没了

吉林电工证网上学习官方回应:电工证没到手,工作就没了 你还在等电工证吗?别再拖了, 急需特种作业证才能上岗找工作 ,这个锅不背谁背?最近有位朋友来找我,说他已经在工地干了三个月,连个正式电工证都没拿到,结果被老板安排“走人”。他不是不想考,…

2026/11/13 23:46:11

大石桥安监局电工证千万别踩坑:实操考试心里没底怕挂科怎么破

大石桥安监局电工证千万别踩坑:实操考试心里没底怕挂科怎么破 你是不是也这样?一想到要参加 大石桥安监局电工证 的实操考试,心里就直打鼓,生怕挂科,影响工作机会,甚至还要重新交钱重新考?这事儿真不是小事,一不小心就可能被“踩坑”,耽误时间还伤…

2026/11/13 22:33:32

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/13 22:32:11

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/13 12:14:39

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑