乒乓球口袋教练 HarmonyOS 学习应用(05):搜索与分类组合过滤
一、把关键词和专项筛选放进同一个查询入口课程多起来以后用户常常先输入“反手”再把范围切到相持模块。若关键词和模块按钮分别在页面各自过滤列表条数、课程标签和点击后的详情很容易不一致。本项目把两个条件交给 SearchService.searchkeyword 先 trim 并转小写moduleId 决定课程范围再对标题、描述、关键词和子分类标签做同一轮匹配。// 简单全字段匹配标题 描述 关键词 子分类标签 export class SearchService { static search(keyword: string, moduleId?: string): SearchHit[] { const kw: string keyword.trim().toLowerCase(); return COURSES .filter(c moduleId undefined || moduleId all || c.moduleId moduleId) .filter(c SearchService.matches(c, kw)) .mapSearchHit((c: Course): SearchHit { const m: LearnModule | undefined findModule(c.moduleId); return { course: c, moduleTitle: m?.title ?? } as SearchHit; }); } private static matches(c: Course, kw: string): boolean { if (kw.length 0) return true; if (c.title.toLowerCase().indexOf(kw) 0) return true; if (c.desc.toLowerCase().indexOf(kw) 0) return true; if (c.subCategoryLabel.indexOf(kw) 0) return true; for (const k of c.keywords) { if (k.toLowerCase().indexOf(kw) 0) return true; } return false; }二、空关键词并不等于跳过模块边界模块条件的 all 不是删除筛选逻辑而是显式表示“允许所有 moduleId”。因此空关键词时仍会返回当前模块的完整课程集合输入词后也不会意外跨到发球或战术模块。这个约束让顶部筛选按钮和搜索框是两个输入却只有一个可解释的结果集合。参与者输入输出或约束模型或配置稳定标识、模式或模块字段给出可追溯的工程事实服务或系统能力经过归一化的请求返回明确结果或失败原因页面回读后的结果只渲染不保存第二份事实} private hits(): SearchHit[] { return SearchService.search(this.keyword, this.moduleFilter); } Builder resultSection() { Column() { if (this.hits().length 0) { EmptyState({ emoji: , title: 未找到相关内容, subtitle: 换个关键词试试或在分类里浏览 }); } else { this.resultTitle(); Column({ space: AppSizes.s2 }) { ForEach(this.hits(), (h: SearchHit) { this.hitRow(h); }, (h: SearchHit) h.course.id); } .padding({ left: AppSizes.s4, right: AppSizes.s4 });三、命中结果为何要带回匹配字段SearchHit 不只保存课程对象还保留 matchedFields。页面可以提示用户命中的是标题、描述还是关键词而不是把所有结果都说成标题匹配。对于“旋转”这类可能出现在描述中的词这比只调用 title.includes 更接近用户的真实预期也让后续高亮有稳定来源。Column({ space: AppSizes.s2 }) { ForEach(this.hits(), (h: SearchHit) { this.hitRow(h); }, (h: SearchHit) h.course.id); } .padding({ left: AppSizes.s4, right: AppSizes.s4 }); } } .width(100%); } Builder resultTitle() { Row() { Text(搜索结果 this.hits().length ) .fontSize(AppText.fsTitle) .fontWeight(AppText.fwSemi) .fontColor(this.palette.textPrimary) .layoutWeight(1); } .width(100%) .padding({ left: AppSizes.s4, right: AppSizes.s4, top: AppSizes.s2, bottom: AppSizes.s2 }); }四、搜索页和课程详情怎样交接点击命中项后SearchPage 传递的是 course.id课程详情再按 id 查回模型。这样搜索结果不会把一份旧课程对象塞进路由也不会因为返回搜索页而保留已经失效的对象。找不到 id 时应留在可解释的结果或空态不能拼一个默认课程继续播放。情况容易出现的错误本文采用的处理数据或配置缺项伪造默认成功状态停在可解释的失败或空态页面重进使用上一页残留对象从模型、服务或系统重新回读重复动作再写一遍相同业务事实由稳定入口或回调收敛import { packagedVideoFileName } from ./CourseVideoAssets; export interface Course { id: string; moduleId: string; subCategory: string; subCategoryLabel: string; title: string; desc: string; thumbKey: string; videoSrc?: string; durationSec: number; order: number; intro: Block[]; keyPoints: Block[]; mistakes: Block[]; training: Block[]; keywords: string[]; externalVideoRefs?: ExternalVideoRef[]; } export interface SubCategory { id: string;五、筛选回归要观察哪些具体结果回归时先在全部范围搜索一个只出现在关键词中的动作术语再切到不含该术语的专项确认结果归零随后清空关键词确认当前专项课程恢复最后点击一条命中课程、返回并重进搜索页检查标题、专项标签和命中字段仍来自同一条查询链路。验收阶段实际动作回读重点前置确认启动正确 bundle 或打开目标页标题、入口与模块身份主题操作执行搜索、切换、完成或跳转服务/系统返回的结果重进检查返回、重启或切换范围后再进入事实没有依赖旧页面残留六、实现边界与维护顺序搜索词、专项模块和课程字段在同一条查询链路中收敛避免页面分别筛选后出现标题、分类与结果数量互相矛盾。 新增需求时应先补齐模型、配置或服务合同再调整页面入口把同一个判断复制到多个组件短期看似方便后续会使结果无法回读。ArkTS 状态管理的基础机制可参考 HarmonyOS 官方文档。七、继续扩展时的约束搜索条件的归一化必须早于排序。先把关键词转换为可比较的值再确定模块范围最后计算匹配字段结果才能稳定复现。若把排序写在页面中用户从课程详情返回后可能看到同一关键词却是另一种顺序测试也无法知道变化来自课程数据还是渲染时机。对于不存在的 moduleId服务不应该宽容地退回全部课程那会让路由或按钮传错参数时看起来仍有结果。明确返回空集合配合页面空态更容易暴露调用链错误。真正需要全量搜索时调用方显式传 all使阅读代码的人一眼能看懂扩大范围是有意的。后续若加入历史搜索或远程建议词历史项只保存用户输入不缓存旧 SearchHit。重新打开历史词时仍需经过当前 SearchService这样课程下架、关键词修改和模块调整才能立刻反映到结果中。结果数量为何必须从命中集合计算搜索页标题中的数量直接来自 hits().length而不是由输入框事件维护一个计数器。前者会随关键词、模块和课程模型重算后者容易在清空输入、返回页面或课程数据变化后留下旧数字。对于用户而言数量、每一行课程和命中说明应始终是同一集合的三个投影。匹配规则改变时怎样验收增加一个关键词字段后要准备标题不含该词但 keywords 含该词的课程确认它被召回再准备同词但不同模块的课程确认模块筛选排除它。两组数据分别覆盖匹配能力和范围能力不能只用一条“搜索成功”的截图混在一起。

相关新闻

Layerdivider终极指南:5分钟掌握AI智能分层技术,轻松分离复杂图像元素

Layerdivider终极指南:5分钟掌握AI智能分层技术,轻松分离复杂图像元素

Layerdivider终极指南:5分钟掌握AI智能分层技术,轻松分离复杂图像元素 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 你是否曾经…

2026/7/30 11:54:02阅读更多 →
5分钟快速上手Pure Admin Thin:超轻量Vue3后台管理系统框架

5分钟快速上手Pure Admin Thin:超轻量Vue3后台管理系统框架

5分钟快速上手Pure Admin Thin:超轻量Vue3后台管理系统框架 【免费下载链接】pure-admin-thin vue-pure-admin官方精简版 项目地址: https://gitcode.com/gh_mirrors/pu/pure-admin-thin Pure Admin Thin是基于Vue 3和Element Plus构建的超轻量级后台管理系统…

2026/7/30 11:52:02阅读更多 →
专业级微信公众号数据采集工具:wechat_articles_spider深度解析与实战指南

专业级微信公众号数据采集工具:wechat_articles_spider深度解析与实战指南

专业级微信公众号数据采集工具:wechat_articles_spider深度解析与实战指南 【免费下载链接】wechat_articles_spider 微信公众号文章的爬虫 项目地址: https://gitcode.com/gh_mirrors/we/wechat_articles_spider 在当今内容驱动的数字时代,微信公…

2026/7/30 11:52:02阅读更多 →
Unity安卓热更新实战:ILRuntime+AssetBundle方案全流程解析

Unity安卓热更新实战:ILRuntime+AssetBundle方案全流程解析

1. 项目概述:为什么我们需要热更? 在移动游戏开发,尤其是Unity安卓项目中,热更新(Hotfix/Hot Update)早已不是“锦上添花”的功能,而是项目稳定运营和快速迭代的“生命线”。想象一下&#xff0…

2026/7/30 13:10:30阅读更多 →
【机器学习案列-43】AI数据中心用水用电分析

【机器学习案列-43】AI数据中心用水用电分析

🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

2026/7/30 13:10:30阅读更多 →
不要把 Skill 写成 Prompt

不要把 Skill 写成 Prompt

不要把 Skill 写成 Prompt:Agent Skill 调优的系统方法与实战心得 Skill 是 Agent 可按需加载的一组领域规则、工作流、工具说明、约束和验证方法。真正有效的 Skill,不是写得越长越好,而是让模型在正确的任务上被正确触发、以最小上下文完成…

2026/7/30 13:10:30阅读更多 →
2027年二建备考启动!3款口碑题库,按需挑选不踩坑

2027年二建备考启动!3款口碑题库,按需挑选不踩坑

26年二级建造师考试已经顺利落下帷幕,发挥不理想、或是计划首次报考2027年二建的考生,现在正是开启提前备考的黄金窗口期。二建知识点繁多、考点细碎,如果等到考前两三个月再突击,很容易时间紧张、复习不充分。提早规划&#xff0…

2026/7/30 13:10:30阅读更多 →
roLabelImg 傻瓜式使用教程

roLabelImg 傻瓜式使用教程

🍼 roLabelImg 傻瓜式使用教程(手把手版)假设你已经安装好了 roLabelImg,下面从打开软件开始,一步一步教你标注。第 0 步:准备工作(先建好文件夹) 在你的电脑上,提前建好…

2026/7/30 13:10:30阅读更多 →
如何高效使用kill-doc脚本:免费文档下载终极攻略

如何高效使用kill-doc脚本:免费文档下载终极攻略

如何高效使用kill-doc脚本:免费文档下载终极攻略 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您…

2026/7/30 13:08:30阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/30 12:22:27阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 🚀 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 你是否曾经因为iOS系统的严格…

2026/7/30 0:00:58阅读更多 →
[GESP202606 四级] 扫雷

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:00:58阅读更多 →
Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

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

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

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

2026/7/30 0:27:26阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

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

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

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

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

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

2026/7/29 14:26:42阅读更多 →