HarmonyOS
数字馆长不是把一段自由文本直接放进页面。用户先选定白泽等目标,再从神兽、故事、地图、展厅四个主题中发起讲解;页面需要保证返回内容始终属于这次选择,并且在服务不可用时仍能给出可追溯的本地导览。
主题是前端与提示词服务之间的稳定接口
CuratorGuideTopic将交互约束为BEAST、STORY、MAP、HALL四类。馆长页把当前神兽 ID 与主题一起交给onRequestGuide;仓库层再把主题映射为scene,提交到/ai/curator/explain。这样,前端不拼接不可维护的提示词文本,而是传递可版本化的业务场景。
type CuratorGuideTopic = 'BEAST' | 'STORY' | 'MAP' | 'HALL' const request = { nodeType: 'BEAST', nodeId: beastId, scene: shanhaiCuratorTopicScene(topic) } const envelope = await apiClient.postJson('/ai/curator/explain', request)服务响应除了导览正文,还带回promptId、promptVersion、traceId、cacheHit与safetyStatus。这些字段让服务端可以演进提示词和缓存策略,页面则只消费已经过契约校验的导览内容、出处和关系。
回包必须先与当前主题对齐
网络成功并不代表内容可以直接展示。HttpShanhaiRepository会先从返回内容提取主题标记,与本地同源资料生成的首句标记对照;只有目标神兽和所选主题一致,才保留服务端结果。主题错配或响应已声明fallback时,会转入本地导览重组,避免把地图说明误展示为神兽讲解。
if (guide.fallback === true || !await this.isTopicAligned(guide, topic, beast)) { return await this.createTopicAlignedFallback(beast, topic) } return guide本地导览不是一段通用兜底文案。它依据当前神兽的已登记出处、地域、展厅和学习卡生成内容;MAP主题只组织本馆路线,HALL主题只组织展厅与展品,STORY主题优先读取故事卡。每个分支都会把fallback标记为true,使页面能够区分服务端讲解与本地可用导览。
| 场景 | 请求结果 | 页面处理 |
|---|---|---|
| 服务端回包与当前主题一致 | 导览、出处、关系均可用 | 展示本轮主题的模块导览 |
| 服务端回包主题错配 | 内容不可信 | 重新组合当前目标的本地导览 |
| 网络或接口失败 | 主仓库不可继续使用 | FallbackShanhaiRepository切换到本地仓库 |
| 本地主题资料不完整 | 缺少独立故事卡或展厅数据 | 提示可继续阅读已登记详情与出处 |
页面状态与降级结果一起收敛
结果卡只认识IDLE、LOADING、AI、FALLBACK、FAILED五种状态。选择主题后先进入LOADING,旧神兽的结果不会混入新选择;当本地导览可用时状态为FALLBACK,语音讲解与结果卡仍可读取同一轮内容。若没有可展示资料,则保留当前详情和出处,并给出再次打开主题的入口。
type CuratorResultState = 'IDLE' | 'LOADING' | 'AI' | 'FALLBACK' | 'FAILED' if (resultState === 'LOADING') { return '正在同步当前神兽、出处与图谱关系;新内容准备好前不会混入上一只神兽的资料。' }这条状态链的价值在于:页面展示对象、请求主题和降级来源始终可追踪。即使接口临时不可达,读者仍能沿白泽的出处、昆仑导览地域和昆仑展厅继续浏览,而不是得到一张没有来源的空卡片。
一次可复现的验收动作
使用新构建包进入“馆长”,选择白泽并保持“神兽”主题,点击“请馆长讲解神兽模块”。结果卡回读到“白泽神兽模块导览”与“依据 1 条已登记资料”,下方同时保留四个主题入口、出处定位和“与白泽相关”的关系区。该动作验证了主题选择、结果回填与同源资料展示在同一轮状态中完成。
继续扩展时,服务端可以增加模型路由、缓存和安全策略;前端只需保持主题契约、响应字段和主题对齐规则稳定。这样,提示词迭代不会改变页面组件的职责,异常时也始终有可阅读、可追溯的降级路径。更多 ArkUI 状态管理约束可参考 HarmonyOS 官方状态管理概览。