当前位置: 首页 > news >正文

HarmonyOS 模板市场实战:64 款内置卡片、分类补齐与搜索过滤

HarmonyOS 模板市场实战:64 款内置卡片、分类补齐与搜索过滤

一个卡片工具如果只展示用户已经创建的卡片,首屏很容易空。这个项目采用了“真实用户数据 + 内置模板目录”的组合:用户数据为空时,首页和分类页仍然能展示完整内容;用户创建卡片后,管理页再承载真实卡片。

本章围绕模板目录、分类补齐和搜索过滤展开实现拆解。

内置模板不是写在页面里

项目的模板目录放在AppDataService.ets

interfaceTemplateCatalogItem{id:string;title:string;subtitle:string;detail:string;value:string;footer:string;badge:string;tone:ToneName;categoryId:CardCategoryId;tags:string[];tabs:CatalogTabKey[];popularity:number;}

一条模板包含展示文案、分类、标签、所属 Tab 和热度。页面不直接维护模板,只调用服务层方法:

appDataService.getCategoryCards('recommend',this.searchText)appDataService.getCategoryRows(this.selectedCategoryId,this.searchText)appDataService.getCategoryHotRows()

这样模板市场、分类页、详情页都能使用同一份目录。

分类元信息单独维护

分类 ID 是内部 key,用户看到的是中文名、色调和标记:

constCATEGORY_META_COUNTDOWN:CategoryMeta={label:'倒计时',tone:'rose',mark:'倒'};

这个元信息用于:

  • 分类概览卡标题。
  • 列表行左侧标记。
  • 详情页类别中文展示。
  • fallback 卡片的色调。

不要在页面里到处写countdown -> 倒计时,否则后期改文案会很痛苦。

分类概览:真实数据不足时用模板补齐

分类页的“分类概览”不是简单读取用户卡片。真实用户卡片可能只覆盖一两个分类,如果直接展示,就会造成页面严重空白。

项目的策略是:

  1. 先按真实卡片分组。
  2. 缺失分类时,从内置模板目录生成分类 fallback。
  3. recommend视图覆盖 8 个分类。

fallback 卡片由服务层创建:

privatecreateCategoryOverviewFallbackCard(categoryId:CardCategoryId,templates:TemplateCatalogItem[]):ShowcaseCardModel|undefined{constcategoryTemplates=templates.filter((item)=>item.categoryId===categoryId);if(!categoryTemplates.length){returnundefined;}constcategoryMeta=this.getCategoryMeta(categoryId);return{id:`category-overview-${categoryId}`,title:categoryMeta.label,subtitle:`${categoryTemplates.length}款可用卡片`,value:`${categoryTemplates.length}`,footer:this.getCategoryOverviewFooter(categoryId),tone:categoryMeta.tone,categoryId:categoryId,imageKey:imageKeyForCategory(categoryId)};}

注意这里带的是categoryId,不是templateId。因为概览卡的语义是“进入分类”,不是“进入某一张模板详情”。

热门列表:列表项再携带 templateId

分类概览点击后,页面会显示同类模板列表。列表项才应该携带templateId

consttemplateId:string=item.templateId?item.templateId:item.id;router.pushUrl({url:RoutePaths.cardDetail,params:{templateId:templateId}});

这样用户路径是:

分类概览卡 -> 同类模板列表 -> 模板详情 -> 添加到我的卡片

这个路径比直接从分类概览进某张默认模板更清晰。

搜索过滤覆盖多个字段

模板搜索不只搜标题,也包含副标题、详情、footer 和 tags:

privategetFilteredTemplates(tabId:string,query:string):TemplateCatalogItem[]{constnormalizedQuery:string=query.trim();returnTEMPLATE_CATALOG.filter((item)=>item.tabs.indexOf(tabIdasCatalogTabKey)>=0).filter((item)=>{if(!normalizedQuery.length){returntrue;}constsourceText=[item.title,item.subtitle,item.detail,item.footer,item.tags.join(' ')].join(' ');returnincludesText(sourceText,normalizedQuery);}).sort((left,right)=>right.popularity-left.popularity);}

这种搜索对模板市场更友好。用户搜“考试”“备份”“喝水”,都能命中相关模板。

图片资源也按模板 ID 映射

每个模板都有对应图片,资源映射放在CardImages.ets

exportfunctionimageKeyForTemplate(templateId:string,categoryId:CardCategoryId):string{switch(templateId){case'birthday':return'template-birthday';case'exam-countdown':return'template-exam-countdown';case'weather-brief':return'template-weather-brief';default:returnimageKeyForCategory(categoryId);}}

如果新增模板但没补图片,项目会回退到分类图。这个 fallback 可以保证不崩,但长期不应该依赖。新增模板时最好同步补:

  • TEMPLATE_CATALOG
  • card_template_<templateId>.png
  • CardImages.ets映射

页面侧保持简单

分类页只关心数据和点击:

Grid(){ForEach(this.filteredCategoryCards(),(item:ShowcaseCardModel)=>{GridItem(){ShowcaseCard({item:item,compactBadge:true,onCardClick:()=>{this.openShowcaseCard(item);}})}},(item:ShowcaseCardModel)=>item.id)}

分类数据怎么补齐、图片怎么映射、搜索怎么过滤,页面都不直接处理。

验证清单

模板目录调整后,需要检查:

  1. recommend分类概览是否覆盖 8 个分类。
  2. 每个分类下是否有足够模板,不出现空列表。
  3. 搜索关键字能命中标题、标签和详情文案。
  4. 分类概览点击后进入同类列表,而不是直接详情。
  5. 列表项进入详情时带templateId
  6. 新增模板图片是否在CardImages.ets中映射。

小结

模板市场的重点不是“塞更多假数据”,而是把内置模板当作正式数据源管理。这个项目把模板目录、分类元信息、搜索过滤、图片映射都收在服务层和资源层,让页面只负责展示和交互。

对卡片类、工具类、模板类应用来说,这种设计可以同时解决首屏空、分类不足、搜索不好用和详情参数丢失几个常见问题。

模板市场不是静态列表,而是“入口、筛选、兜底”的组合题

如果只讲MarketPage.ets里的数组,会显得像一个 UI 摆放示例;必须把它拆成三条真实链路:第一条是首页/底部导航进入市场,第二条是标签、搜索和分类页之间的筛选协作,第三条是图片、标题、统计值缺失时的兜底。Project028 的市场页价值就在这里:它不是后端驱动的复杂商城,但已经具备一个可审核、可扩展的本地模板市场雏形。

MarketPage.ets中,页面同时依赖PageHeaderChipTabsSearchBarStubShowcaseCardBottomNavBar。这说明它不是孤立页面,而是复用项目基础组件来保持视觉一致。marketSummaryCard()appDataService.getMarketSummaryCard()取摘要卡,marketHeroImage()再通过cardImageResource()做图片资源解析。这里最容易被忽略的是兜底:如果摘要卡没有imageKey,页面会回退到CardImageKeys.marketLight,避免市场头图空白。

privatemarketSummaryCard():ShowcaseCardModel{returnappDataService.getMarketSummaryCard(this.selectedTab,this.normalizedQuery());}privatemarketHeroImage():Resource{constsummary:ShowcaseCardModel=this.marketSummaryCard();returncardImageResource(summary.imageKey?summary.imageKey:CardImageKeys.marketLight);}

筛选逻辑也要写清楚。市场页的本地搜索并不直接修改模板源数据,而是通过matchesQuery()过滤展示列表;分类入口则跳转到RoutePaths.category,把更细的分类浏览交给CategoryPage.ets。这种拆法适合轻量应用:市场页承担“发现”,分类页承担“检索”,详情页承担“转化”。如果把三者塞在一个页面里,后续要接远端模板、收藏、下载量排序时会很难维护。

这里的实践判断很明确:本地模板市场不是偷懒,而是阶段性架构选择。Project028 当前没有服务器,也不应该为了展示模板引入不必要的接口层。正确做法是先把数据结构、入口、筛选、兜底、跳转打稳,等模板源变成远端时,只替换数据服务,不改页面交互。

工程检查清单

  • MarketPage -> CategoryPage -> CardDetailPage的入口关系要清楚。
  • imageKey缺失时必须有兜底,避免头图或模板图空白。
  • ChipTabsSearchBarStubShowcaseCard是复用组件,不是普通装饰。
  • 轻量项目可先本地数据闭环,不必过早接入后端。
  • 真实路径:entry/src/main/ets/pages/MarketPage.etsentry/src/main/ets/pages/CategoryPage.etsentry/src/main/ets/common/CardImages.ets
http://www.jsqmd.com/news/1112353/

相关文章:

  • 让你分分钟理解 JavaScript 闭包
  • 搜索框防抖 + 竞态完整总结
  • 向量检索评测:相似度高不等于业务命中
  • ZN-044A国产手持式分析仪 守护风电通信,助力绿色能源高效运维
  • ASP.NET路由模型解析
  • 第1章. 故事的缘起
  • Shell脚本实现Nginx一键自动化部署与优化
  • 破译生命“暗物质”:高通量多因子检测如何重塑现代生物医学研究
  • OEXN:“低价高息股票再受关注”
  • 【ChatGPT编程入门黄金法则】:20年工程师亲授——零基础7天掌握Python/JS核心语法并写出可运行项目
  • YOLOv8结构化剪枝实战:基于BN系数的通道剪枝方法
  • 分布式系统的日志监控
  • Windows批处理脚本实现SSH自动化部署与文件传输
  • ChatIG架构揭秘:高效推理网关背后的技术原理
  • 3分钟解锁Windows 11任务栏自定义:Taskbar11让你重获桌面控制权
  • 把《呼吸里的爱》放回真实生活里听
  • 云原生技术26-让Pod飞起来:K8s性能调优的20个技巧,CPU、内存、网络全链路调优
  • 升级纯血鸿蒙后,小艺Agent和伴随式AI能做什么?
  • 电光机械振荡器(E-OMO)的神经形态计算应用
  • iOS开发系列--Swift语言
  • Git的优点
  • Stable Diffusion推理速度优化全攻略:从硬件到软件
  • 【信道容量】基于MIMO信道、AWGN信道、瑞利信道及Aloumati空时码信道容量Matlab仿真
  • 明天就是大年三十了,今天在家有空,想集中整理一下CQRS架构的特点以及相比传统架构的优缺点分析。先提前祝大家猴年新春快乐、万事如意、身体健康!
  • AI时代必备:100个实战场景提升效率与生活质量
  • Burp Suite实战指南:从核心模块到Web安全测试工作流
  • Cobalt Strike UAC绕过技术实战:五种经典方法原理与避坑指南
  • ActiveReportsJS如何在Angular报表设计器中构建资产负债表
  • “眼睁睁看它穿墙而过!“:连续碰撞检测的“全程盯防“之道
  • 每日热门skill:AI终于长出手了!ai-web-automation:让OpenClaw自己上网干活,我摸了3天鱼