鸿蒙 Next 共享工具库 App 开发实战:社区共享 + 借还系统 + 分类筛选

鸿蒙 Next 共享工具库 App 开发实战:社区共享 + 借还系统 + 分类筛选 鸿蒙 Next 共享工具库 App 开发实战社区共享 借还系统 分类筛选作者duluoSDK 版本HarmonyOS API 24 (Next)开发工具DevEco Studio语言框架ArkTS ArkUI字数约 9600 字目录引言产品概念与工具模型两 Tab 架构设计工具卡片组件分类筛选系统借还系统与状态管理详情弹窗中的内联访问社区属性与评分系统编译错误全记录第三十六款 App 全景回顾结语1. 引言1.1 工具共享的社区价值一把电钻每年平均使用时间不到 30 分钟。一个梯子一年用不了 5 次。一台高压清洗机用完后大半年闲置在角落。这些东西家家都有、家家都需要但使用频率极低。从经济角度看购买这些工具的成本远高于单次使用的价值。从社区角度看如果这些工具能在邻里之间共享所有人的生活成本都会降低。社区共享工具库的核心理念就是与其每家买一件不如共享一个工具库。1.2 本 App 的定位本 App 与二手流转App 35共享相同的社区共享基因但核心机制不同二手流转#35共享工具库#36关系一次性买卖周期性借还状态变化interestedborrowed → returned物品属性个人所有个人/社区所有归还机制无✅ 有归还功能评分系统无✅ 5 星评分1.3 三十六款 App 全景App 数量 36 代码总行数 ~19,400 行 编译错误数 ~312 个 博客总字数 ~360,000 字 技术博客数 36 篇2. 产品概念与工具模型2.1 功能需求用户故事 1我想看看邻居们分享了哪些工具可以借 用户故事 2我想按分类筛选工具 用户故事 3我想借一把电钻用两天 用户故事 4我用完了想归还 用户故事 5我想看看谁提供了工具 功能清单 ├── F1: 工具列表10 件工具 ├── F2: 分类标签筛选 ├── F3: 工具卡片名称/主人/距离/状态 ├── F4: 借出工具 ├── F5: 归还工具 ├── F6: 借还记录列表 ├── F7: 详情弹窗 └── F8: 评分展示2.2 工具数据模型interfaceTool{id:number;name:string;// 工具名称emoji:string;// 图标owner:string;// 主人如301室 张叔dist:string;// 距离/位置status:string;// 状态可借/出借中desc:string;// 描述tag:string;// 分类rating:number;// 评分1-5}9 个字段比二手流转的 Item 模型多了一个status字段。status是一个字符串但只有两个可能的值“可借和出借中”。为什么用字符串而不是布尔字符串的扩展性更强。后续如果增加维修中、已下架等状态不需要修改代码逻辑。2.3 10 件工具的社区感设计所有工具的主人以301室 张叔、“502室 李哥这样的社区身份标识而不是用户A”、“用户B”。这种设计传递了一个信息这些工具是真实的邻居在共享不是虚拟平台在运营。3. 两 Tab 架构设计3.1 Tab 配置build(){Stack(){Column().backgroundColor(C.bg)Column(){this.buildHeader()if(this.activeTab0)this.buildBrowseTab()elsethis.buildMyTab()this.buildTabBar()}if(this.showDetail)this.buildDetailOverlay()}}Tab图标功能0工具 — 浏览所有工具1借还 — 已借出工具列表3.2 首页布局┌──────────────────────────────┐ │ 共享让生活更美好 │ │ 把闲置的工具借给邻居… │ ├──────────────────────────────┤ │ [全部] [工具] [清洁] [园艺] │ ├──────────────────────────────┤ │ 电钻 │ │ 301室张叔 · 同楼 可借 │ │ 充电式手电钻… │ │ 工具 ⭐⭐⭐⭐⭐ 借出 │ ├──────────────────────────────┤ │ 梯子 │ │ 502室李哥 · 同楼 可借 │ │ ... │ └──────────────────────────────┘3.3 数据流浏览 Tab → 筛选 → 工具列表 → 点击详情 ↓ 借出 → borrowed 数组更新 → 状态变为已借出 ↓ 我的 Tab → 显示已借出工具 → 点击归还 ↓ 归还 → borrowed 数组移除 → 首页状态恢复借出和归还是双向的——借出在首页操作归还在我的 Tab 操作。两个 Tab 通过同一个borrowed数组保持状态同步。4. 工具卡片组件4.1 卡片布局┌──────────────────────────────────────┐ │ 可借 │ │ 电钻 │ │ 301室张叔 · 同楼 │ │ │ │ 充电式手电钻带一套钻头。 │ │ │ │ 工具 ⭐⭐⭐⭐⭐ 借出 │ └──────────────────────────────────────┘顶部行左侧 emoji右侧状态标签可借绿色 / 出借中灰色中间行名称 主人/距离描述行2 行限制底部行左侧分类标签 评分右侧操作按钮4.2 状态标签Text(tool.status).fontSize(13).fontColor(tool.status可借?C.accent:C.textMuted).fontWeight(tool.status可借?FontWeight.Bold:FontWeight.Normal)可借使用绿色粗体出借中使用灰色普通体。视觉权重差异明显。4.3 操作按钮if(tool.status可借){// 显示借出或已借出按钮Text(this.isBorrowed(tool.id)?✅ 已借出: 借出)}else{// 显示灰色出借中文字Text(⏳ 出借中).fontSize(13).fontColor(C.textMuted)}三态按钮可借 未借出 → 橙色 借出按钮可借 已借出 → 绿色✅ 已借出标签出借中 → 灰色文字。5. 分类筛选系统5.1 标签配置constTAGS:string[][全部,工具,清洁,园艺];4 个标签覆盖 10 件工具的分类工具5 件、清洁3 件、园艺2 件。5.2 筛选逻辑getFiltered():Tool[]{if(this.selectedTag0)returnTOOLS;constresult:Tool[][];for(consttofTOOLS){if(t.tagTAGS[this.selectedTag])result.push(t);}returnresult;}与二手流转App 35的筛选逻辑完全相同。这个方法被 ForEach 和详情弹窗两处调用。6. 借还系统与状态管理6.1 状态设计Stateborrowed:number[][];一维数组存储已借出工具的 ID。6.2 借出borrowTool(id:number):void{this.borrowed[id,...this.borrowed];promptAction.showToast({message: 已借出用时请爱惜用完及时还});}Toast 提示中包含了用时请爱惜用完及时还的善意提醒——不是在说教而是在提醒共享的规则。6.3 归还returnTool(id:number):void{constidxthis.borrowed.indexOf(id);if(idx0){constbthis.borrowed.concat([]);b.splice(idx,1);this.borrowedb;promptAction.showToast({message:✅ 已归还感谢你的诚信});}}归还操作是借出的逆操作找到索引 → 创建数组副本 → 移除 → 赋值新数组。concat([])创建新引用触发 State 更新。6.4 我的 Tab 中的归还卡片 电钻 已借出 来自 301室张叔 ✅ 记得及时归还哦 归还每张已借出卡片底部有归还按钮暖橙色点击后工具从borrowed数组移除首页卡片状态恢复。7. 详情弹窗中的内联访问7.1 内联模式Text(this.getFiltered()[this.selectedTool].emoji).fontSize(64)Text(this.getFiltered()[this.selectedTool].name).fontSize(22)Text(⭐ this.getFiltered()[this.selectedTool].rating分)Text( this.getFiltered()[this.selectedTool].owner)Text(this.getFiltered()[this.selectedTool].desc)详情弹窗中所有数据通过this.getFiltered()[this.selectedTool].xxx内联访问。重复了 8 次this.getFiltered()[this.selectedTool]。这种模式的优缺点优点零错误——没有 const 声明不会触发 10905209调用getFiltered()确保了数据始终与当前分类筛选一致不需要额外的 Helper 方法缺点代码重复——同一表达式写 8 次可读性稍差——需要从长表达式中提取出具体字段8. 社区属性与评分系统8.1 评分展示getStars(r:number):string{return⭐.repeat(r);}String.repeat()是 ES6 标准方法ArkTS 支持。⭐.repeat(5)生成⭐⭐⭐⭐⭐。与常规的4.2 分数字评分不同星级评分更适合社区场景——星越多越受欢迎简单直观。8.2 主人身份展示每件工具都标注了主人信息301室 张叔、502室 李哥。距离标注同楼、3号楼、物业。居委会有自己的工具“社区公用工具箱”评分 5 星。这个细节传递了社区支持的信息——共享不是个别热心人的行为而是社区在推动的事情。9. 编译错误全记录9.1 错误概览本 App 出现3 个编译错误。#错误代码位置原因修复110505001L205重复的方法定义删除空方法体210505001L287重复的方法定义删除空方法体3——链式编译失败修复后自动消失9.2 重复方法错误// ❌ 错误代码buildBorrowCard 被定义了两次BuilderbuildBorrowCard(id:number){// 完整实现...}BuilderbuildBorrowCard(id:number){}// ❌ 第二次定义空的原因在从二手流转App 迁移代码时buildBorrowCard方法被复制了两次。第二次是一个空的 Builder 方法占位符忘记删除了。修复删除空的 Builder 方法。9.3 三十六款 App 的错误趋势App 1: 16 ← 入门 App 10: 11 ← 模式形成 App 20: 2 ← 高效期 App 24: 48 ← AI 探索 App 31: 0 ← 零错误 App 33: 0 ← 零错误 App 34: 1 ← Text 类型 App 35: 3 ← Builder const App 36: 3 ← 重复方法App 36 的 3 个错误不是新的知识而是旧的垃圾代码。修复方式也不是学习新的 ArkTS 规则而是——删掉多余的代码。10. 第三十六款 App 全景回顾10.1 数据总览指标数值代码行数295 行编译错误数3 个2 个重复方法 1 个连锁State 变量4 个Builder 方法6 个工具数量10 件分类数量3 个Tab 数2 个弹窗数1 个外部依赖0 个10.2 共享/平台类 App 系列总结从 App 23 到 App 36共享/平台类 App 共 5 款App共享内容核心操作行数23 情绪漂流瓶心事扔出 → 捞取 → 回复44729 反向导师技能浏览 → 申请 → 等待37332 临期食品救援食品浏览 → 救援34235 二手流转物品浏览 → 联系26636 共享工具库工具浏览 → 借出 → 归还295共享类 App 的平均代码量约 345 行——远低于系列平均值 546 行。原因是共享类 App 的逻辑路径简洁浏览→操作不需要复杂的用户系统或内容创建系统。10.3 社区属性的价值5 款共享类 App 中本 App 是唯一一款强调社区概念的23 匿名漂流瓶 — 陌生人29 反向导师 — 陌生师生32 临期食品救援 — 消费者 vs 商家35 二手流转 — 陌生人36 共享工具库 —同社区邻居“301室 张叔”、“502室 李哥”——这些不是系统生成的用户名而是模拟了真实社区中的身份标识。当你知道工具的主人是楼下 301 室的张叔时你更有可能爱惜工具、及时归还。11. 结语11.1 36 款 App 的旅程从第 1 款 App白噪音到第 36 款共享工具库横跨了工具、教育、社交、情感、健康、环保、公益、平台等近 10 个领域。每一款 App 都解决了一个特定的问题——有些工具很实用慢病管理、碳足迹有些偏观念普及防骗雷达、临期食品救援有些纯属实验AI 树洞。36 款 App 没有什么宏大的主题——就是一个个独立的、小而美的概念验证。11.2 给开发者的建议重复方法是最容易避免的错误——写代码时留意是否复制了同名方法共享类 App 的代码量不需要很多——345 行平均比系列总平均低 37%社区属性是最好的信用系统——301室 张叔比用户 #12345更能让人产生信任感36 款 App 证明了 ArkUI 的能力边界——从白噪音到共享工具库ArkUI 都做得来11.3 致谢36 款 App、36 篇博客。36 不是终点。每一款 App 都有一个博客每一个博客都记录了一款 App 从零到一的完整过程。如果你从第 1 篇读到了第 36 篇——你已经见证了超过 19,000 行代码、312 个编错误、360,000 字的开发记录。现在打开 DevEco Studio去创造属于你自己的第 1 款——或者第 36 款——App 吧。附录 A核心代码速查借出工具borrowTool(id:number):void{this.borrowed[id,...this.borrowed];promptAction.showToast({message: 已借出});}归还工具returnTool(id:number):void{constidxthis.borrowed.indexOf(id);if(idx0){constbthis.borrowed.concat([]);b.splice(idx,1);this.borrowedb;}}分类筛选getFiltered():Tool[]{if(this.selectedTag0)returnTOOLS;constresult:Tool[][];for(consttofTOOLS){if(t.tagTAGS[this.selectedTag])result.push(t);}returnresult;}