HarmonyOS知识库——个人中心的标签云与数据统计展示

发布时间:2026/7/15 15:58:20

HarmonyOS知识库——个人中心的标签云与数据统计展示 知识库 App 的 ProfilePage 不是传统的设置页——它更像一个知识概览仪表盘用标签云展示知识分布、用统计卡片量化笔记成果、用渐变头像强化品牌感。这种个人中心 数据可视化的设计在工具类 App 里越来越常见。完整效果一、页面结构三个区块区块内容数据来源个人信息渐变头像 昵称 统计摘要getNotes().length getFavorites().length统计卡片笔记/收藏/标签三列getNotes() getFavorites() getAllTags()标签云所有标签及使用次数getAllTags()三个区块的数据都来自 NoteService 的查询函数——页面没有自己的 State 数据全部实时查询。二、数据加载的双重触发Statetags:TagCount[][]aboutToAppear():void{this.tagsgetAllTags()}onPageShow():void{this.tagsgetAllTags()}为什么只给 tags 加了 State笔记和收藏数没有因为 tags 需要在标签云里渲染——标签数量和顺序可能变化新增笔记带来新标签。笔记数和收藏数直接在 build 里调用getNotes().length和getFavorites().length每次 build 都重新计算不需要 State 缓存。踩坑记录最初getNotes().length写在 aboutToAppear 里赋值给 State用户新建笔记后返回 ProfilePage统计数字没更新。改成在 build 里直接调用后每次 build 都获取最新数据。三、个人信息卡片的渐变头像Row(){Stack(){Column(){}.width(56).height(56).borderRadius(28).linearGradient({angle:135,colors:[[A,0],[#A78BFA,1]]})Text().fontSize(24)}Column(){Text(知识管理者).fontSize(18).fontWeight(FontWeight.Bold).fontColor(T1)Text(累计 getNotes().length 篇笔记 · getFavorites().length 篇收藏).fontSize(12).fontColor(T3).margin({top:2})}.alignItems(HorizontalAlign.Start).margin({left:14}).layoutWeight(1)}Stack 实现渐变底座 emoji 图标Stack 让两层内容叠放——底层是渐变色圆形上层是 emoji 图标。linearGradient({ angle: 135, colors: [[A, 0], [#A78BFA, 1]] })从左上角#6C5CE7 紫色到右下角#A78BFA 浅紫色的 135° 渐变。为什么用 Stack 而不是给 Text 加背景色Text 的 backgroundColor 是纯色不支持渐变。Stack 渐变 Column 是 ArkTS 里实现渐变背景的标准方式。56×56 的尺寸 borderRadius(28) 正好是圆形。28 56/2borderRadius 设为宽高的一半就是正圆。统计摘要的实时计算Text(累计 getNotes().length 篇笔记 · getFavorites().length 篇收藏)直接在 build 里调用getNotes().length——每次 build 都重新计算。这比 State 缓存更简单——不需要 aboutToAppear 初始化不需要 onPageShow 刷新。在数据量小的场景下12 篇笔记每次 build 重新查询的性能开销可以忽略。和首页的对比首页用State favCount缓存收藏数ProfilePage 直接调用getFavorites().length。首页需要 favCount 是因为有其他 State 变化如搜索会触发 build缓存避免不必要的重复查询。ProfilePage 没有其他 State直接调用更简洁。四、统计卡片的复用BuilderStat(icon:string,value:string,label:string){Column(){Text(icon).fontSize(20).margin({bottom:4})Text(value).fontSize(18).fontWeight(FontWeight.Bold).fontColor(A)Text(label).fontSize(10).fontColor(T3)}.layoutWeight(1).padding(14).backgroundColor(#FFFFFF).borderRadius(14)}和首页的 Stat Builder 完全一样。两个页面各写了一份——因为 Builder 只能在当前组件内调用不能跨页面复用。两个页面的 Stat 调用对比页面调用数据来源首页Stat(, this.notes.length.toString(), 总笔记)State notesProfilePageStat(, getNotes().length.toString(), 笔记)直接调用 getNotes()label 不同——首页叫总笔记ProfilePage 叫笔记。因为两个页面的语境不同首页是仪表盘总笔记强调总量ProfilePage 是个人中心笔记更简洁。ProfilePage 多了一个标签统计卡片。首页统计笔记/收藏/笔记本ProfilePage 统计笔记/收藏/标签。不同的统计维度反映了两个页面的不同职责——首页关注内容管理ProfilePage 关注知识分布。五、标签云的 Flex 布局Text(标签云).fontSize(16).fontWeight(FontWeight.Bold).fontColor(T1).width(100%).padding({left:16}).margin({bottom:8})Flex({wrap:FlexWrap.Wrap}){ForEach(this.tags,(t:TagCount){Text(#t.name (t.count)).fontSize(12).fontColor(A).padding({left:10,right:10,top:5,bottom:5}).backgroundColor(A10).borderRadius(12).margin({right:6,bottom:6}).onClick((){router.pushUrl({url:pages/TagFilterPage,params:{tag:t.name}asRecordstring,Object})})})}.width(100%).padding({left:16,right:16})标签云 vs TagFilterPage 的标签网格维度ProfilePage 标签云TagFilterPage 标签网格每个标签的结构单行文字#标签名 次数两行文字标签名 次数样式浅紫背景 紫色文字白色背景 紫色文字点击行为跳转 TagFilterPage同页面切换到筛选列表尺寸较小padding 5-10较大padding 14ProfilePage 的标签云更紧凑——一屏能展示更多标签。因为标签云是概览性质的用户快速扫一眼就知道有哪些标签。TagFilterPage 的标签网格是操作性质的需要更大的点击区域方便用户选择。标签文本的拼接Text(#t.name (t.count))格式#标签名 (次数)。#前缀是 hashtag 风格(次数)用括号包裹数量。这种格式在社交媒体里很常见——用户一看就知道这是标签后面是使用次数。和首页笔记卡片的标签格式对比首页用Text( # t)只显示标签名不显示次数因为首页空间有限。ProfilePage 空间充裕可以同时显示标签名和次数。六、标签云的点击跳转.onClick((){router.pushUrl({url:pages/TagFilterPage,params:{tag:t.name}asRecordstring,Object})})点击标签跳转到 TagFilterPage并传入标签名。TagFilterPage 收到参数后直接显示该标签的筛选结果——跳过标签网格直达笔记列表。跳转链路ProfilePage → 点击标签 → TagFilterPageselectedTag标签名→ 显示筛选笔记列表。用户从看到标签到看到笔记只需要一次点击 一次跳转。七、build 里直接调用查询函数的设计build(){Column(){// ...Text(累计 getNotes().length 篇笔记 · getFavorites().length 篇收藏)// ...this.Stat(,getNotes().length.toString(),笔记)this.Stat(❤️,getFavorites().length.toString(),收藏)this.Stat(️,this.tags.length.toString(),标签)}}build 里有 4 次函数调用getNotes() 两次、getFavorites() 两次、getAllTags() 零次tags 已缓存在 State 里。为什么 getNotes 和 getFavorites 调用了两次一次在个人信息卡片的统计摘要里一次在 Stat Builder 里。两次调用返回相同结果——因为 _notes 和 _favs 在同一次 build 里不会变化。优化方案可以在 aboutToAppear 里缓存笔记数和收藏数到 Statebuild 里直接读取。但在 12 篇笔记的规模下两次查询的性能差异可以忽略不计。代码简洁性比微小的性能优化更重要。八、整体嵌套结构Column 页面容器 ├→ Row (导航栏) 返回 我的标题 └→ Scroll 可滚动内容 └→ Column ├→ Row (个人信息卡片) Stack 渐变头像 文字信息 ├→ Row Builder Stat × 3 统计卡片 ├→ Text (标签云 标题) └→ Flex(FlexWrap.Wrap) 标签云嵌套深度 3 层——和 NoteList 一样。没有底部导航栏不需要 Stack 层叠。个人信息卡片是最复杂的区块——Stack 实现渐变底座Row 实现左右布局。和首页的嵌套对比首页 4 层Stack→Scroll→Column→RowProfilePage 3 层Scroll→Column→Row。ProfilePage 更浅是因为没有底部导航栏。九、页面间的数据一致性ProfilePage 展示的数据笔记数、收藏数、标签数来自 NoteService 的查询函数。用户在 NoteEditor 新建笔记后返回 ProfilePageonPageShow重新调用getAllTags()标签云自动更新。笔记数和收藏数在 build 里直接调用getNotes().length每次 build 都获取最新数据。数据一致性的保证方式数据更新方式触发时机tagsState onPageShow 刷新页面显示时笔记数build 里直接调用 getNotes().length每次 build收藏数build 里直接调用 getFavorites().length每次 build三种数据用两种更新方式——tags 用 State 缓存笔记数和收藏数实时查询。这种混合策略在简单场景下很实用——不需要所有数据都用 State 管理直接查询更简洁。

相关新闻