ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

【华夏二十四节气|07】HarmonyOS 6.0.2(22) ArkTS 节气搜索实战:多字段匹配与四态闭环

【华夏二十四节气|07】HarmonyOS 6.0.2(22) ArkTS 节气搜索实战:多字段匹配与四态闭环

【华夏二十四节气|07】HarmonyOS 6.0.2(22) ArkTS 节气搜索实战:多字段匹配与四态闭环

本文唯一核验标记:AGC18-HMOS-15-07-SEARCH-POEM-GAP

证据边界:本文的“当前实现”以本轮复核的SearchPage.etsSolarTermModel.etsSolarTermService.etssolar_terms.json为准;文中构建通过记录属于历史证据,本轮未重新执行构建,不将其表述为新的构建结果。架构扩展和性能优化段落均为建议实现,不代表当前工程已经具备对应能力。

二十四节气只有 24 条主记录,搜索不需要服务器、倒排索引或复杂数据库,但“小数据”并不等于可以忽略搜索合同。用户输入“饺子”时希望命中冬至美食,输入诗句时希望找到对应节气,输入空格时不应看到莫名其妙的空页;加载失败、无结果和返回详情也都需要明确状态。

本文基于真实 HarmonyOS 工程D:\huawei\one5(华夏二十四节气),复核SearchPage.etsSolarTermModel.etsSolarTermService.ets。审计开始时,源码只检索名称、摘要、描述、习俗、食物和养生字段;本轮已经把诗词、物候、加载态、错误态、空状态、清除入口和结果数量合入SearchPage.ets,并以assembleHap通过 ArkTS 编译。下文保留修复前证据,同时给出修复后的复核输出。

一、搜索对象来自本地 rawfile

SolarTermService首次加载:

const buf: Uint8Array = await rm.getRawFileContent('solar_terms.json'); const decoder = util.TextDecoder.create('utf-8'); const text = decoder.decodeToString(buf); this.bundle = JSON.parse(text) as SolarTermBundle;

搜索页不访问网络,而是从应用包内的solar_terms.json取得数据。加载完成后使用内存数组过滤,因此断网不会阻止搜索。

这也限定了结果范围:搜索只能命中当前安装包携带的节气内容,不能声称检索互联网诗词库或实时资讯。

二、数据模型决定可搜索字段

真实SolarTerm包含:

export interface SolarTerm { id: string; order: number; name: string; season: Season; summary: string; description: string; phenology: string[]; customs: string[]; food: string[]; health: string[]; poems: SolarTermPoem[]; }

搜索字段应该根据用户意图选择,而不是把对象序列化后做一次粗糙匹配。名称、简介、习俗、美食、养生、物候与诗词都有不同展示价值。

id、顺序和季节是结构字段,是否参与搜索需要明确产品需求。当前页面没有检索这些字段。

三、页面加载完成后保存全部节气

SearchPage 维护:

@State keyword: string = ''; @State loading: boolean = true; @State allTerms: SolarTerm[] = [];

aboutToAppear()调用loadData(),等待服务加载后把all()结果赋给allTerms。关键词变化触发重新构建,matchedTerms()从这份内存数组计算结果。

当前记录只有 24 条,直接保存全部内容并同步过滤是合适的最小方案,不需要分页接口或后台 Worker。

四、真实搜索入口是 TextInput

搜索栏使用:

TextInput({ placeholder: '搜索节气、习俗、美食…', text: this.keyword }) .onChange((value: string) => { this.keyword = value; })

用户每次输入都会更新@State keyword。页面没有“搜索”按钮,也没有提交动作;体验属于即时过滤。

对于 24 条本地记录,即时过滤延迟很小。若以后数据增长到数万条,再考虑防抖、预索引或后台计算,而不是提前增加复杂度。

五、空关键词返回全部 24 条

真实逻辑先执行:

const k = this.keyword.trim(); if (!k) return this.allTerms;

空字符串或只包含空格的输入都会展示全部节气。这个行为使搜索页也可以作为节气索引页,而不是空白初始页。

如果产品希望初始状态显示“输入关键词开始搜索”,就需要单独定义 idle 状态。不能一边返回全部数据,一边在文案中声称默认不展示内容。

六、当前匹配采用精确子串

每个字段通过:

text.indexOf(k) >= 0

判断关键词是否是原字符串的连续子串。中文名称、短语和食物名适合这种策略,行为直观、可预测。

它不支持拼音、错别字纠正、同义词、分词组合或相关度排序。输入“清 明”也不会自动命中“清明”,这些都不是当前源码能力。

七、名称、摘要和描述已经覆盖

真实条件首先检查:

t.name.indexOf(k) >= 0 || t.summary.indexOf(k) >= 0 || t.description.indexOf(k) >= 0

名称适合精确定位节气,摘要和描述则允许用户用内容概念搜索。例如数据里出现的气候、农事或季节性词汇,可以通过简介命中。

但结果行只展示namesummary,若命中发生在 description,用户未必知道为什么出现。高亮或命中来源提示可以改善可解释性。

八、习俗、食物和养生使用some

数组字段通过:

t.customs.some(s => s.indexOf(k) >= 0) || t.food.some(s => s.indexOf(k) >= 0) || t.health.some(s => s.indexOf(k) >= 0)

任意元素命中,就保留整个节气。搜索“踏青”“春饼”或某种养生建议时,不需要先把数组拼成大字符串。

some()在找到第一个匹配项后即可停止,语义也清楚。对 24 条数据,这种写法比建立复杂索引更容易维护和测试。

九、初版诗词搜索缺口与修复结果

SolarTerm明确定义:

export interface SolarTermPoem { title: string; author: string; content: string; }

初版matchedTerms()没有读取t.poems。因此输入诗名、作者或诗句不会因为诗词字段而命中,除非同一关键词偶然出现在摘要或描述中。

本轮已经完成代码改造,并通过补丁后的源码静态复核与assembleHap构建。这里保留初版缺口,是为了让读者理解修复动机,而不是把它描述成当前版本的未完成项。

十、补齐诗名、作者和正文

可复用的纯函数写法如下:

private poemMatches( poems: SolarTermPoem[], keyword: string ): boolean { return poems.some((poem: SolarTermPoem) => poem.title.indexOf(keyword) >= 0 || poem.author.indexOf(keyword) >= 0 || poem.content.indexOf(keyword) >= 0 ); }

当前源码采用同等语义的内联some()条件,已经把诗名、作者与正文加入过滤。诗词是结构化对象数组,必须分别检查标题、作者和正文,不能把对象直接转字符串。

回归用例应选择只出现在诗句而不出现在其他字段的关键词,避免测试出现假阳性。

十一、物候字段已经纳入匹配合同

模型里有phenology: string[]。初版过滤条件遗漏了它,本轮已经将物候数组纳入匹配合同,用户输入真实物候词时可以返回对应节气。

当前实现与习俗字段一致:

|| t.phenology.some( (item: string) => item.indexOf(k) >= 0 )

代码已经支持物候匹配。后续若在占位文案中直接写出“物候”,还应结合窄屏宽度验证文字是否截断;这属于界面文案优化,不影响本轮搜索合同。

十二、把搜索合同集中到一个方法

继续把条件写在页面里会越来越长。可以将单条匹配提取为:

private matches(t: SolarTerm, k: string): boolean { return this.includes(t.name, k) || this.includes(t.summary, k) || this.includes(t.description, k) || this.arrayIncludes(t.customs, k) || this.arrayIncludes(t.food, k) || this.arrayIncludes(t.health, k) || this.arrayIncludes(t.phenology, k) || this.poemMatches(t.poems, k); }

这样字段清单成为可审查合同,单元测试也能逐字段覆盖。页面的matchedTerms()只负责 trim 与 filter。

十三、当前搜索没有大小写归一化

节气内容主要是中文,但模型中可能出现英文、拉丁符号或 ID。indexOf()区分大小写,Springspring不等价。

如果决定支持拉丁文本,可以在比较两端执行:

const normalized = value.toLocaleLowerCase().normalize('NFKC');

归一化策略要保持一致,并验证目标 HarmonyOS ArkTS 运行环境支持的字符串方法。中文不需要无意义地转小写,但全角半角与兼容字符仍可能受益。

十四、不要擅自删除正文中的空格

trim()只移除关键词两端空白,不会删除中间空格。这个行为保护了诗句和短语的原始结构。

如果为了“更宽松匹配”把所有空格都删除,可能产生意外命中,也会改变英文作者名和标点语义。更稳妥的方式是明确提供“连续子串”合同。

需要支持多关键词时,应先定义 AND、OR 和排序规则,再实现分词,不能简单split(' ')后随意组合。

验收时应准备含前后空格、连续空格、中文标点和英文作者名的关键词,分别记录标准化前后结果,确保规则没有破坏诗词原文或产生无法解释的宽泛命中。

十五、当前结果顺序保持原始节气顺序

filter()不改变未删除元素的相对顺序,因此结果沿用solar_terms.json的数组顺序,通常对应节气序。

当前没有相关度评分:名称命中与描述命中的位置一样,不会把更精确结果置顶。对于 24 条数据,这可能足够;若要排序,可定义名称精确匹配、名称包含、数组字段、长描述的分值。

排序必须稳定,分值相同的结果仍应按节气顺序展示。

若加入相关度排序,测试应同时断言分值与次级排序,不要只看首条结果;否则数据内容微调后,同分结果可能在不同构建中出现顺序漂移。

十六、匹配函数在每次构建时执行

ResultList 直接调用:

ForEach(this.matchedTerms(), ...)

关键词状态变化会触发构建并重新扫描所有字段。24 条数据与短文本下,计算量很小,无需缓存。

若内容扩大,应该先用性能分析确认重建成本,再考虑把结果维护为@State、添加防抖或预先生成规范化搜索文档。过早缓存会增加状态同步风险。

十七、loading 状态已经进入四态渲染

虽然页面有:

@State loading: boolean = true;

初版loadData()会切换它,但ResultList()没有对应分支。修复后,ResultList()首先判断this.loading,显示LoadingProgress和“正在加载节气数据”,不会把首次加载误呈现为空结果。

当前实现让状态变量与可见 UI 保持一致。即使 rawfile 很小,也保留了可测试的加载态,为未来数据量增长和解析耗时变化留下明确行为。

十八、try/catch/finally建立错误与重试闭环

初版加载只有try/finally。本轮实现调整为:

try { await SolarTermService.instance.ensureLoaded(getContext(this)); this.allTerms = SolarTermService.instance.all().slice(); } catch (_) { this.allTerms = []; this.errorMessage = '节气数据加载失败,请重试'; } finally { this.loading = false; }

JSON 解析或资源读取失败时,页面进入 error 分支并提供“重新加载”入口。这样loading / error / empty / content四态拥有独立判定,加载失败不会伪装成“没有搜索结果”。

十九、无结果空状态与恢复入口

修复后,关键词无法命中任何节气时会进入专用空状态:

if (this.matchedTerms().length === 0) { EmptyView({ text: '未找到相关节气' }) }

当前页面同时显示查询词和“清除关键词”入口,用户可以一步恢复全部 24 条结果。若后续扩大数据规模,可把结果在一个方法中计算后传给 Builder,减少同一轮构建中的重复过滤。

二十、搜索框清除与结果数量闭环

当前TextInput右侧会在关键词非空时显示“清除”,点击后重置keyword与导航提示。用户无需逐字删除,即可回到全部节气。

结果区域显示“共 N 条结果”,用户可以直接判断关键词是否过宽;提示位于列表顶部,没有增加额外卡片层级。

清除操作应同时恢复输入、结果和键盘焦点,不能只把视觉文本清空却保留旧状态。

清除按钮还应具备可访问性说明与稳定触控尺寸,并只在关键词非空时显示或启用;自动化测试可断言清除后keyword为空且结果数量恢复为全部节气。

二十一、命中原因需要可解释

结果行只显示:

Text(t.name) Text(t.summary)

若关键词命中food或诗词正文,summary 中可能没有该词。用户会疑惑结果为何出现。

可以返回:

interface SearchHit { term: SolarTerm; field: 'name' | 'custom' | 'food' | 'poem' | 'other'; snippet: string; }

列表第二行显示命中片段,并高亮关键词。这样补齐诗词后,诗句命中才真正可见,而不只是过滤数组里的隐藏逻辑。

二十二、高亮必须处理重复和边界

简单高亮可以用indexOf()找到第一个位置,拆成前、中、后三段。关键词为空时不能进入拆分,否则会产生无意义片段。

多次出现时,要决定只高亮首处还是全部;长文本应先生成围绕命中的短 snippet,再设置maxLines和省略。

ArkUI 可以用 Span 组合不同样式,但构造富文本应放在 helper 中,保持 Builder 声明式。

高亮测试应包含关键词位于开头、结尾、重复出现以及包含正则特殊字符的情况;实现若只使用indexOf(),就不应引入不必要的正则转义风险。

二十三、结果摘要缺少溢出约束

当前Text(t.summary)没有显式:

.maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis })

真实数据摘要若变长,列表行高度会扩大,影响扫描效率。在手机横屏、小窗口或系统字体放大时更明显。

名称列使用layoutWeight(1)的父容器是正确基础,再补充行数与溢出策略即可提升适配稳定性。

二十四、路由参数使用稳定 ID

点击结果行时构造:

const params: TermDetailParams = { termId: t.id }; router.pushUrl({ url: Routes.TermDetail, params })

页面不传整份对象,而是让详情页用稳定 ID 回查内容。这与收藏、历史模块使用同一身份策略。

结果排序或高亮变化不会影响路由合同,rawfile 内容更新也不需要修改页面间大对象传递。

二十五、路由异常已经提供可见反馈

初版源码末尾使用空catch,点击失败时没有反馈。本轮改为设置页面状态:

router.pushUrl({ url: Routes.TermDetail, params }).catch(() => { this.navigationMessage = '详情页打开失败,请重试'; });

结果数量栏会同步显示提示,用户可以继续搜索或重试。后续若接入日志,应只记录公共错误码、路由名与termId,不写入完整节气内容。

二十六、ForEach Key 使用t.id

(t: SolarTerm) => t.id

稳定 ID 作为 Key 能让 ArkUI 在过滤变化时识别同一节气行。它优于数组索引,因为删除前部结果不会改变其他行身份。

这要求数据源保证 ID 唯一。加载solar_terms.json时应验证重复 ID,否则列表复用和详情路由都会出现不确定行为。

二十七、all()暴露了服务内部数组

SolarTermService.all()当前返回:

return this.bundle ? this.bundle.terms : [];

SearchPage 只读取并过滤,没有修改它,因此真实路径没有破坏缓存。但公共调用者若执行sort()splice(),会直接改变服务内部顺序。

更安全的服务可以返回slice()或只读数组。小数据复制成本低,能加强数据所有权。

二十八、数据加载也需要结构校验

JSON.parse(text) as SolarTermBundle只是类型断言,运行时不会验证terms是否数组,也不会验证customsfoodpoems是否存在。

搜索大量调用字符串方法和some(),坏数据可能直接导致构建异常。加载边界应校验每个可搜索字段,缺失的可选数组可规范化为空数组。

错误应停留在 Service 层并映射为页面 error 状态,而不是让某一个异常节气拖垮整个页面。

二十九、字段权重比模糊算法更重要

若要改善排序,先建立简单可解释的权重:

名称完全相等 100 名称包含 80 习俗/食物/诗词 50 摘要/描述/养生 30

分值相同按order排序。用户能理解“清明”排在名称只包含“清”的结果前,也方便测试。

在只有 24 条数据时,没有必要先引入编辑距离或向量检索。可解释、可复现的排序更适合离线文化内容。

三十、最小单元测试按字段组织

至少准备以下互斥用例:

  1. 只在名称出现的关键词;
  2. 只在习俗数组出现的关键词;
  3. 只在食物数组出现的关键词;
  4. 只在养生数组出现的关键词;
  5. 只在诗名出现的关键词;
  6. 只在作者出现的关键词;
  7. 只在诗句正文出现的关键词;
  8. 空字符串与纯空格;
  9. 完全无结果的关键词。

其中 5 至 7 在修复前源码应失败,用来证明诗词缺口;本轮补齐诗词与物候条件后,这些用例已经具备进入通过集的代码基础。测试记录能力演进,而不是只挑现有代码能过的案例。

三十一、页面手工验收关注状态转换

打开搜索页时应看到全部节气或明确 loading;输入名称后结果收窄;输入食物与习俗词时出现可解释结果;输入不存在词时显示无结果状态。

补齐诗词后,输入作者和诗句验证对应节气。点击结果进入详情,再返回时关键词是否保留,需要按页面路由生命周期实际确认。

还要测试快速输入、清除、系统字体放大、横屏、小窗口、键盘弹出与返回键,确保搜索栏和结果都可达。

每一步都应记录关键词、结果数量、首条结果、命中来源和页面状态;返回详情后若关键词重置,也要明确这是当前生命周期行为还是回归缺陷。

三十二、性能优化先守住 24 条事实

每次输入扫描 24 条记录,即使检查多个短数组,成本仍很低。当前最重要的问题是能力缺口和状态表达,而不是 CPU 优化。

如果未来节气扩展成大规模传统文化库,可以在加载时生成规范化文档:

interface SearchDocument { term: SolarTerm; normalizedText: string; }

但文档拼接会丢失命中字段信息,因此还需保存字段索引。数据规模没有增长前,不必支付这份复杂度。

三十三、隐私与网络边界

关键词只保存在@State keyword,源码没有把搜索词写入 Preferences、日志或网络。页面离开后,短期 UI 状态随组件生命周期结束。

隐私材料不应声称收集搜索历史,也不能把本地搜索包装成在线推荐。若以后保存最近搜索,要提供清除入口、容量上限和本地处理说明。

搜索词可能反映用户兴趣,即使是文化应用也应遵守最小化原则。

验证时可在工程内搜索 Preferences、日志、HTTP 与分析 SDK 调用,并在断网环境操作搜索页;只有代码证据与运行观察都一致,才能写出“本地搜索且不保存关键词”的隐私结论。

三十四、上架审核需要真实描述

当前可准确描述为“支持按节气名称、简介、习俗、美食和养生内容搜索”。在诗词条件补齐并通过真实数据测试前,不应在应用商店声称已支持诗名、作者和诗句搜索。

如果版本说明写“多字段搜索”,审核人员应能从页面快速进入,看到无结果提示,并通过可复查关键词验证字段命中。

页面加载失败、点击无响应和文本溢出都可能影响运行稳定与布局审核,应在发布前覆盖。

发布素材若展示诗词关键词,应使用已经补齐诗词匹配的同一构建包,并保留测试关键词与命中截图;否则应从描述、截图和标签中移除该能力,避免审核素材超前于代码。

三十五、推荐的搜索职责分层

职责
SolarTermService加载并校验本地数据
SearchMatcher规范化关键词、字段匹配与评分
SearchPage输入、状态和结果展示
Router用稳定 termId 打开详情

匹配逻辑从页面抽出后,可以用纯数据测试诗词、习俗和食物,不需要启动 ArkUI。页面只负责 loading、error、empty、content 四态。

这不是为 24 条数据制造框架,而是让“搜索哪些字段”成为一个清晰、可回归的业务合同。

三十六、发布前检查清单

  1. rawfile 加载失败时显示错误与重试;
  2. 空关键词行为与产品说明一致;
  3. 名称、摘要、描述、习俗、食物和养生可命中;
  4. 诗名、作者、诗句在补齐代码后可命中;
  5. 物候是否参与搜索有明确决定;
  6. 无结果时显示关键词和清除入口;
  7. 命中片段能解释结果来源;
  8. 长摘要在小窗口与大字体下不溢出;
  9. 结果 Key 唯一稳定,路由失败有反馈;
  10. 搜索词不被无声明地持久化或上传;
  11. 24 条数据下无不必要防抖和后台任务;
  12. 应用介绍不超出当前安装包真实能力。

这份清单把功能、性能、隐私和审核口径放在同一条验收链上。

三十七、可直接落地的状态闭环补丁

针对源码审计发现的诗词字段和页面状态边界,可以在不引入网络、数据库或第三方依赖的前提下完成一次小范围改造。补丁仍以SolarTermService提供的 24 条本地数据为唯一输入,只把匹配合同和页面状态显式化:

type SearchPageState = 'loading' | 'content' | 'empty' | 'error'; interface SearchHit { term: SolarTerm; fields: string[]; } private normalize(value: string): string { return value.trim().toLocaleLowerCase('zh-CN'); } private poemMatches(term: SolarTerm, keyword: string): boolean { const poems = term.poems ?? []; return poems.some((poem: SolarTermPoem) => { return this.normalize(poem.title).includes(keyword) || this.normalize(poem.author).includes(keyword) || this.normalize(poem.content).includes(keyword); }); }

页面加载时使用try/catch/finally收敛状态,而不是让异常和零结果共享空白区域:

private async loadTerms(): Promise<void> { this.pageState = 'loading'; try { await SolarTermService.instance.ensureLoaded(getContext(this)); this.allTerms = SolarTermService.instance.all().slice(); this.pageState = this.allTerms.length > 0 ? 'content' : 'empty'; } catch (error) { this.pageState = 'error'; } }

搜索结果使用SearchHit返回命中字段。名称、简介、习俗、食物、养生和诗词分别记录来源,页面既能显示“共 3 条”,也能展示“命中:诗句”,避免用户面对结果却不知道为何命中。空关键词继续返回 24 条完整数据;规范化后的非空关键词没有结果时进入empty;rawfile 解析失败进入error并提供重试;只有正常匹配才进入content

这次改造的验收矩阵可以固定为四组:名称输入“冬至”命中 1 条,食物输入真实 JSON 中的已有词命中对应节气,诗名或诗句输入命中包含该诗词的节气,不存在的随机词进入无结果状态。再补充纯空格、快速连续输入、加载失败和详情返回四个边界,就形成从数据加载、字段匹配、状态渲染到路由的完整闭环。本轮补丁已经合入当前源码并通过构建,但没有执行真机输入法、滚动和路由交互测试,因此不把“编译通过”扩大成“真机全链路通过”。

三十八、总结

华夏二十四节气的搜索页已经具备一个轻量离线搜索的核心:从 rawfile 加载 24 条节气,TextInput 实时更新关键词,名称、摘要、描述、习俗、食物和养生通过indexOf()some()进行同步过滤,稳定 ID 用于列表复用与详情路由。

本轮已经补齐诗名、作者、诗句与物候匹配,并建立 loading/error/empty/content 四态、清除入口、结果数量和路由失败提示。仍未实现的是命中来源标签、文本高亮、拼音搜索、错别字纠正和相关度排序;这些能力不在本文通过项中。标题中的多字段搜索由真实源码与构建结果支撑,不再是一句超出源码的宣传。

本文部分内容由 AI 辅助整理,所有源码结论均以文中所列本地工程文件为复核依据。

三十九、2026-07-27 修复后复核:源码与构建双证据

本轮复核固定在应用版本1.0.1targetSdkVersion 6.0.2(22)compatibleSdkVersion 6.0.2(22)。数据源仍是entry/src/main/resources/rawfile/solar_terms.json,实际包含 24 条节气;搜索实现仍以SearchPage.ets为准。下面的检查在补丁合入后再次执行,用来确认当前源码覆盖范围。

$search = Get-Content -Raw -Encoding UTF8 ` 'entry/src/main/ets/pages/SearchPage.ets' $terms = Get-Content -Raw -Encoding UTF8 ` 'entry/src/main/resources/rawfile/solar_terms.json' | ConvertFrom-Json [pscustomobject]@{ termCount = $terms.terms.Count hasTextInput = $search.Contains('TextInput') matchesPoems = $search.Contains('t.poems') matchesPhenology = $search.Contains('t.phenology') declaresLoading = $search.Contains('@State loading') rendersLoading = $search.Contains('if (this.loading)') hasCatch = $search.Contains('catch (') swallowsRouteError = $search.Contains('.catch(() => {})') } | ConvertTo-Json

在上述版本源码上执行,实际输出如下:

{ "termCount": 24, "hasTextInput": true, "matchesPoems": true, "matchesPhenology": true, "declaresLoading": true, "rendersLoading": true, "hasCatch": true, "swallowsRouteError": false }

这组结果给出了一条可复查的边界:当前版本已经有TextInput和 24 条本地数据,poemsphenology已进入匹配,loading已渲染为页面分支,数据加载具有catch错误态,详情路由也不再使用空回调吞错。清除关键词、结果数量和无结果提示同样位于当前SearchPage.ets

构建命令使用 DevEco Studio 26.0.0.461 自带 hvigor:

hvigorw.bat --no-daemon assembleHap

原工程目录包含命令行校验不接受的全角括号,因此将同一份源码复制到临时 ASCII 路径后执行;实际结果为BUILD SUCCESSFUL in 17 s 400 msCompileArkTSPackageHapSignHap均完成。构建仍有项目既存的废弃 API 和兼容性警告,但没有新增 ArkTS 编译错误。

复核时还应把“纯逻辑可验证”和“真机才能验证”分开。字段匹配、空关键词返回 24 条、稳定 ID 和命中来源可以通过纯数据测试;输入法联想、返回键行为、滚动手感、错误态视觉以及详情路由失败提示,必须在 HarmonyOS 真机或模拟器中检查。本轮没有执行真机交互测试,所以不写“真机已通过”。这一限制同样是复核结果的一部分。

唯一复核标记:AGC18-HMOS-15-07-STATIC-AUDIT-V2


AI 辅助声明:本文在人工核对真实工程源码、数据文件和页面状态后,使用 AI 辅助整理结构、润色表达并生成配图;代码能力、工程状态与验证边界均以文中列出的本地证据为准。

CSDN-SERIES:ALL-163252527

返回列表