【华夏二十四节气|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 首次加载:

ts 复制代码
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 包含:

ts 复制代码
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 维护:

ts 复制代码
@State keyword: string = '';
@State loading: boolean = true;
@State allTerms: SolarTerm[] = [];

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

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

四、真实搜索入口是 TextInput

搜索栏使用:

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

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

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

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

真实逻辑先执行:

ts 复制代码
const k = this.keyword.trim();
if (!k) return this.allTerms;

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

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

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

每个字段通过:

ts 复制代码
text.indexOf(k) >= 0

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

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

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

真实条件首先检查:

ts 复制代码
t.name.indexOf(k) >= 0
|| t.summary.indexOf(k) >= 0
|| t.description.indexOf(k) >= 0

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

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

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

数组字段通过:

ts 复制代码
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 明确定义:

ts 复制代码
export interface SolarTermPoem {
  title: string;
  author: string;
  content: string;
}

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

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

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

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

ts 复制代码
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[]。初版过滤条件遗漏了它,本轮已经将物候数组纳入匹配合同,用户输入真实物候词时可以返回对应节气。

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

ts 复制代码
|| t.phenology.some(
  (item: string) => item.indexOf(k) >= 0
)

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

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

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

ts 复制代码
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 不等价。

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

ts 复制代码
const normalized =
  value.toLocaleLowerCase().normalize('NFKC');

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

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

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

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

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

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

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

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

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

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

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

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

ResultList 直接调用:

ts 复制代码
ForEach(this.matchedTerms(), ...)

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

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

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

虽然页面有:

ts 复制代码
@State loading: boolean = true;

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

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

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

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

ts 复制代码
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 四态拥有独立判定,加载失败不会伪装成"没有搜索结果"。

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

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

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

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

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

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

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

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

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

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

结果行只显示:

ts 复制代码
Text(t.name)
Text(t.summary)

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

可以返回:

ts 复制代码
interface SearchHit {
  term: SolarTerm;
  field: 'name' | 'custom' | 'food' | 'poem' | 'other';
  snippet: string;
}

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

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

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

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

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

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

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

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

ts 复制代码
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })

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

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

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

点击结果行时构造:

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

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

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

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

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

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

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

二十六、ForEach Key 使用 t.id

ts 复制代码
(t: SolarTerm) => t.id

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

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

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

SolarTermService.all() 当前返回:

ts 复制代码
return this.bundle ? this.bundle.terms : [];

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

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

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

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

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

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

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

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

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

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

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

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

至少准备以下互斥用例:

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

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

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

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

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

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

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

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

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

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

ts 复制代码
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 条本地数据为唯一输入,只把匹配合同和页面状态显式化:

ts 复制代码
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 收敛状态,而不是让异常和零结果共享空白区域:

ts 复制代码
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 为准。下面的检查在补丁合入后再次执行,用来确认当前源码覆盖范围。

powershell 复制代码
$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

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

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:

powershell 复制代码
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

相关推荐
大龄秃头程序员2 小时前
Flutter 项目鸿蒙适配实战:从环境搭建到多环境打包全指南
harmonyos
贾伟康4 小时前
【万能转换器|18】HarmonyOS ArkTS 权限与隐私实战:让 module.json5、功能说明和拒绝路径一致
移动开发·harmonyos·arkts·权限管理·隐私合规
贾伟康4 小时前
【万能转换器|19】HarmonyOS ArkTS 回归测试实战:覆盖启动、空数据、异常输入和重复点击
软件测试·移动开发·harmonyos·arkts·回归测试
UnicornIT5 小时前
【HarmonyOS】时间管理类APP:做成“自适应“
ui·华为·harmonyos·鸿蒙
less_121385 小时前
HarmonyOS WPS Open SDK:不落地、水印与功能开关的合规打开策略
华为·harmonyos·wps
贾伟康6 小时前
【万能转换器|20】HarmonyOS ArkTS AppGallery 发布复查实战:核对包名、版本、设备、素材和离线声明
移动开发·harmonyos·arkts·appgallery·应用发布
OH_TPC16 小时前
HarmonyOS APP开发---“滤镜大师“图像处理App,需要用到这个库
java·图像处理·华为·harmonyos·鸿蒙
2501_9197490319 小时前
华为鸿蒙管理密码APP—小羊密码
华为·harmonyos·鸿蒙
ITUnicorn1 天前
【HarmonyOS】时间管理类APP:做成“自适应“
harmonyos