大厂Data+Agent 秘籍:腾讯/阿里/字节解析如何提升数据分析智能。 了解详情
写点什么

【宝藏贴】HarmonyOS 官方模板优秀案例 (第 1 期:便捷生活 · 购物中心)

  • 2025-07-28
    北京
  • 本文字数:3401 字

    阅读完需:约 11 分钟

🚀🚀🚀🚀

鸿蒙生态为开发者提供海量的 HarmonyOS 模板/组件,助力开发效率原地起飞

★一键直达生态市场组件&模板市场 , 快速应用DevEco Studio插件市场集成组件&模板 ★

如何通过行业模板,快速高效完成项目开发?

HarmonyOS 官方模板优秀案例,带您找到答案!

👉覆盖 20+行业,本帖下方以汇总形式持续更新中,点击收藏!一键三连!常看常新!

 

【第 1 期】便捷生活行业· 购物中心

一、 概述

1. 行业洞察

1) 行业痛点:

  • 传统零售流量缺失,依赖第三方平台导流,佣金成本高且较难沉淀用户;

  • 离场排队缴费耗时、找车难、支付流程复杂是用户最大的“离场焦虑”;

  • 传统积分体系感知弱、兑换门槛高、缺乏即时激励,导致会员活跃度低;

  • 传统服务链接割裂(App、小程序、收银系统独立),用户需在不同平台跳转,体验碎片化;

  • 低频使用的独立 App 极易被用户遗忘删除;公众号/小程序需主动打开,入口深且触达率低。


2) 行业常用三方 SDK

SDK 链接:

支付宝 SDK 微信支付 SDK 银联 SDK 极光 SDK 同盾SDK

神策数据 SDK 腾讯微信 SDK 高德地图 百度地图 腾讯地图定位 高德地图定位 穿山甲广告 SDK 广点通广告SDK 友盟SDK 听云 SDK 声网 agoraSDK

腾讯浏览器服务 SDK 字节跳动火山引擎增长营销套件 SDK


2. 优秀案例概览(下载模板

购物中心元服务模板是基于以上行业分析实现的参考,为行业元服务提供了常用功能的开发样例,涵盖停车缴费、自助积分、店铺导购、个人钱包、券包等多个实用场景。

  • Stage 开发模型 + 声明式 UI 开发范式

  • 分层架构设计+ 组件化拆分,支持开发者在开发时既可以选择完整使用模板,也可以根据需求单独选用其中的业务组件。

  • 集成华为账号、支付等服务,只需做少量配置和定制即可快速实现华为账号的登录、停车缴费等功能。

基于本模板构建的【XX 购物中心】元服务已正式发布上线,开发者反馈模板高度适配业务需求,显著提升了团队开发效率。


 

本模板主要页面及核心功能如下所示:

 

二、 应用架构设计

1. 分层模块化设计

  • 产品定制层:专注于满足不同设备或使用场景的个性化需求,作为应用的入口,是用户直接互动的界面。

① 本实践暂时只支持直板机,为单 HAP 包形式,包含路由根节点、底部导航栏等。

  • 基础特性层:用于存放相对独立的功能 UI 和业务逻辑实现。

① 本实践的基础特性层将应用底部导航栏的每个选项拆分成一个独立的业务功能模块,包含首页和我的。

② 每个功能模块都具备高内聚、低耦合、可定制的特点,支持产品的灵活部署。

  • 公共能力层:存放公共能力,包括公共 UI 组件、数据管理、外部交互和工具库等共享功能。

① 本实践的公共能力层分为公共基础能力和可分可合组件,均打包为 HAR 包被上层业务组件引用。

② 公共基础能力包含日志、文件处理等工具类,公共类型定义,网络库,以及弹窗、加载等公共组件。

③ 可分可合组件将包含行业特点、可完全自闭环的能力抽出独立的组件模块,支持开发者在开发中单独集成使用,详见业务组件设计章节

本模板整体工程共分为 7 个包:

  • 产品定制层

① phone HAP 包,手机设备的主入口模块

  • 基础特性层

① business_home HSP 包,首页场景

② business_mine HSP 包,我的场景

  • 公共能力层

① lib_common HAR 包,封装全局工具方法及公共组件

② module_coupon HAR 包,优惠券组件

③ module_keyboard HAR 包,车牌键盘组件

④ module_points HAR 包,自助积分组件

详细工程结构可见工程结构章节


2. 业务组件设计

为支持开发者单独获取特定场景的页面和功能,例如开发者已搭建了一个自己的购物中心元服务工程,只想单独取用本模板中的优惠券或积分功能,本模板将功能完全自闭环的部分能力抽离出独立的行业组件模块,不依赖公共基础能力包,开发者可以单独集成,开箱即用,降低使用难度。

 

三、 行业场景技术方案

1. 账号管理

1) 场景说明

元服务打开后无需用户手动登录,通过静默登录后展示默认头像和默认昵称。

用户可自行选择点击关联账号按钮获取华为账号关联手机号,可将静默登录账号与用户历史注册账号关联,同步用户历史数据资产,例如头像、昵称、生日等。


2) 技术方案

  • 静默登录

① 通过 Account Kit 实现元服务静默登录

  • 手机号获取

① 通过 Scenario Fusion Kit 的快速验证手机号Button,向用户发起手机号授权申请;

② 经用户同意后,根据获取到的 Authorization Code,以及元服务服务器使用 Client ID、Client Secret 实现服务端开发


2. 停车缴费

1) 场景说明

点击车牌号输入框拉起自定义键盘,根据车牌的位数展示省份、市区编号、车牌等自定义内容。

点击新增车牌支持存储常用车牌。

 

2) 技术方案

  • 特殊键盘绑定

通过 TextInput 组件的customKeyboard属性,传入自定义 UI,实现特殊键盘和输入框的关联。

  • 常用车牌存储:

将车牌输入能力封装成独立组件,通过bindSheet方法对当前页面绑定半模态弹框,并复用车牌输入组件。


3. 会员积分

1) 场景说明

用户在商场内消费后,可通过扫描小票二维码或拍摄小票照片等方式提交自助积分申请。

 

2) 技术方案

  • 本模板使用 Scan Kit 提供的默认界面扫码能力,实现系统级体验一致的扫码界面以及相册扫码入口。开发者也可以通过自定义界面扫码实现更定制化的界面样式和功能。

  • 使用 Media Library Kit 提供的特定接口安全Picker拉起系统图库,用户可以自行选择相册内资源或拍摄照片,开发者通过获取到的图片 uri 进行后续的分享、上传等操作。


四、 模板代码

1. 工程结构(下载模板

详细代码结构如下所示:

ShoppingMall

├─commons                           

 └─lib_common/src/main/ets

      ├─components  

        ├── AlertDialog.ets                          //警告对话框

        ├── AsWebRichText.ets                        //富文本编辑器

        ├── CallTelSheet.ets                         //电话呼叫

        ├── EmptyComp.ets                            //空白组件

        ├── LoadingDialog.ets                        //加载组件

        ├── LoginComp.ets                            //登录组件

        ├── NavHeaderBar.ets                         //页面导航栏头部组件               

        ├── PageHeaderComp.ets                       //页面标题组件

        └── SheetHeaderComp.ets                      //半模态标题组件

              

      ├─constants         

        ├── Common.ets                               //通用常量

        └── RouterMap.ets                            //路由表常量             

                         

      ├─httprequest    

        ├── AxiosHttp.ets                            // axios二次封装                   

        ├── AxiomRequest.ets                         //创建请求实例          

        ├── HttpRequest.ets                          //业务接口封装                   

        └── HttpRequestApi.ets                       //业务接口定义

      

      ├─mock/MockData.ets                              // mock数据

        

      ├─models

        ├── ParamsModel.ets                          //接口参数模型          

        ├── RequestModel.ets                         //接口请求模型

        ├── ResponseModel.ets                        //接口响应模型          

        ├── RouterModel.ets                          //路由跳转模型                   

        ├── StorageModel.ets                         //状态变量模型          

        └── TabBarModel.ets                          // Tab模型                    

              

      ├─utils

        ├── EmitUtils.ets                            //全局事件方法类

        ├── FileUtils.ets                            //文件处理方法类          

        ├── FormatUtils.ets                          //格式化方法类

        ├── GlobalUtils.ets                          //全局变量类          

        ├── Logger.ets                               //日志类

        ├── LoginUtils.ets                           //登录方法          

        ├── RouterUtil.ets                           //路由管理类      

        └── Utils.ets                                //通用方法     

      

      └─viewmodels/BaseViewModel.ets                   //基础viewmodel抽象类

├─components

 ├── module_coupon                                     //优惠券组件                     

 ├── module_keyboard                                   //车牌键盘组件

 └── module_points                                     //自助积分组件            

     

├─features

 ├─business_home/src/main/ets                          //首页模块             

    ├─components

      ├── AddPlateComp.ets                         //添加车牌组件

      └── GuideListComp.ets                        //指南列表组件                  

    ├─constants

      └── Constants.ets                            //常量定义             

    ├─pages

      ├── ConsiderateServicePage.ets               //尊享服务页面

      ├── FindCarPage.ets                          //寻车页面

      ├── FindCarResultPage.ets                    //寻车结果页面

      ├── ParkingPaymentPage.ets                   //停车缴费入口页面

      ├── PayDetailPage.ets                        //支付详情页

      ├── PayRecordPage.ets                        //缴费记录页面

      ├── PaySuccessPage.ets                       //支付成功页面

      ├── PlateNumberMgtPage.ets                   //车牌管理页面

      ├── PlateNumberPage.ets                      //停车缴费页面

      ├── ServiceDetailPage.ets                    //贴心服务二级页面

      ├── StoreGuideDetailPage.ets                 //店铺详情页面

      ├── StoreGuidePage.ets                       //店铺导航页面

      └── WebPage.ets                              //网页页面                  

    └─viewmodel

        ├── PayDetailViewModel.ets                   //支付详情视图模型

        ├── PayRecordViewModel.ets                   //缴费记录视图模型

        ├── PaySuccessViewModel.ets                  //支付成功视图模型

        ├── ServiceDetailViewModel.ets               //服务详细视图模型

        ├── StoreGuideDetailViewModel.ets            //店铺指南详细视图模型

        └── StoreGuideViewModel.ets                  //店铺指南视图模型      

 

 └─business_mine/src/main/ets                         //我的模块             

      ├──components

        ├── MenuComp.ets                            //菜单组件

        └── UserInfoComp.ets                        //用户信息组件

      ├──constants

        └── WalletConstants.ets                     //钱包常量

      ├──pages

        ├── MembershipManualPage.ets                //成员手册页面

        ├── MembershipPage.ets                      //成员页面

        ├── MinePage.ets                            //我的页面

        ├── MyCouponsPage.ets                       //我的优惠券页面

        ├── MyWalletPage.ets                        //我的钱包页面

        ├── PrivacyPage.ets                         //隐私政策页面

        ├── RechargeWalletPage.ets                  //充值钱包页面

        ├── SettingPage.ets                         //设置页面

        └── UserInfoPage.ets                        //用户信息页面

      └──viewmodel               

          ├── MinePageViewModel.ets                   //我的页面视图模型

          ├── MyWalletViewModel.ets                   //我的钱包页面视图模型

          ├── RechargeWalletViewModel.ets             //充值钱包页面视图模型

          ├── SettingPageViewModel.ets                //设置页面视图模型

          └── UserInfoViewModel.ets                   //用户信息页面视图模型

└─products

   └─entry/src/main/ets                

        ├── common/Constants.ets                        //常量定义

        ├── components/CustomTabBar.ets                 //自定义标签栏组件      

        ├── entryability/EntryAbility.ets               //主入口能力

        ├── entryformability/EntryFormAbility.ets       //表单主入口能力

        ├── pages

          ├── HomePage.ets                            //首页

          ├── Index.ets                               //入口页面

          ├── IndexPage.ets                           // Tab页面        

          └── IntroducePage.ets                       //商场介绍页面

        ├── utils/WidgetUtil.ets                        //卡片工具类

        ├── viewModels/IndexViewModel.ets               // Tab页面ViewModel      

        └── widget/pages/WidgetCard.ets                 //服务卡片        

 

2. 关键代码解读

1) 静默登录及手机号关联

  • 代码使用效果

① 当系统华为账号未登录时,打开本元服务模板,静默登录不成功,自动拉起系统半模态弹窗提示登录/注册华为账号;

② 当系统华为账号已登录时,打开本元服务模板,静默登录成功,显示“华为用户”;

③ 用户可以选择点击关联账号,将静默登录账号与已注册账号关联,为用户同步历史数据资产。注意若要完整体验该功能,对应包名的元服务需要完成对应开发前提工作

  • 核心代码实现

① 通过 AccountKit 实现静默登录。

// products/phone/src/main/ets/viewmodel/IndexViewModel.ets

private loginWithHuaweiID(): Promise<HuaweiIDResp> {

    return new Promise((resolve, reject) => {

      //创建静默登录请求

      let loginRequest = new authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest();

      loginRequest.forceLogin = false;

      let controller = new authentication.AuthenticationController();

      controller.executeRequest(loginRequest).then((data) => {

        let loginWithHuaweiIDResponse = data as authentication.LoginWithHuaweiIDResponse;

        let authCode = loginWithHuaweiIDResponse.data?.authorizationCode;

        let openId = loginWithHuaweiIDResponse.data?.openID;

        let unionId = loginWithHuaweiIDResponse.data?.unionID;

        //静默登录成功,返回账号相关的ID数据

        resolve({ openId, unionId, authCode } as HuaweiIDResp);

      }).catch((error: BusinessError) => {

        Logger.error(TAG, 'loginWithHuaweiID error: ' + JSON.stringify(error));

      }).finally(() => {

        //静默登录失败,返回空值

        resolve({

          openId: '',

          unionId: '',

          authCode: '',

        } as HuaweiIDResp);

      });

    });

  }

 

② 使用 Scenario Fusion Kit 的快速验证手机号Button请求云侧获取手机号需要的 authCode。

// commons/lib_common/src/main/ets/components/LoginComp.ets

FunctionalButton({

  params: {

    openType: functionalButtonComponentManager.OpenType.GET_PHONE_NUMBER,

    label: '',

    styleOption: {

      styleConfig: new functionalButtonComponentManager

        .ButtonConfig()

        .size({ width: 48, height: 48 })

        .borderRadius(24)

        .backgroundImage($r('app.media.ic_tab_code_pass'))

        .backgroundImageSize(ImageSize.Cover)

    },

  },

  controller: new functionalButtonComponentManager.FunctionalButtonController()

    .onGetPhoneNumber((err, data) => {

      if (err) {

        //使用该方法的元服务未获取scope权限时,使用mock账户返回结果。获取权限参考上一节【代码使用效果】的第三步【开发前提工作】

        LoginUtils.onBindFail(this.callback);

        return;

      }

      LoginUtils.onBindSuccess(data.code || '', this.callback);

    }),

})

 

③ 端侧使用获取到的 auth_code 调用接口,云侧参考服务端开发获取用户的手机号信息后,端侧将号码与登录用户进行关联,并持久化存储到本地。

// commons/lib_common/src/main/ets/utils/LoginUtils.ets

export class LoginUtils {

  /**

   *关联成功

   * @param code

   * @param callback

   */

  static onBindSuccess(code: string, callback?: () => void) {

    HttpRequestApi.getOpenLoginHm(encodeURIComponent(code)).then((res) => {

      if (res.code === HttpCode.SUCCESS) {

        let tel = res.data.userTel ?? ''

        let userInfo: UserInfoModel = AppStorageV2.connect(UserInfoModel, () => new UserInfoModel())!;

        userInfo.userInfo.userTel = `${tel.substring(0, tel.length - 8)}****${tel.substring(tel.length - 4)}`

        userInfo.isRelative = true

        if (callback) {

          callback();

        }

      } else {

        promptAction.showToast({ message: '账号关联失败,请重试~' })

      }

    }).catch(() => {

      promptAction.showToast({ message: '账号关联失败' })

    }).finally(() => {

      LoadingDialogUtil.close()

    })

  };

}

 

2) 动态服务卡片

  • 代码使用效果

① 将停车服务卡片加桌后,可显示剩余车位和用户积分(当前为纯端模拟数据);

② 点击卡片刷新按钮将刷新剩余车位数,并实时同步给元服务内停车缴费页面;

③ 在元服务内缴费消耗积分后,最新剩余积分实时同步给桌面卡片。

  • 核心代码实现

① 通过 commonEventManager 公共事件管理实现卡片事件的注册和实时通信。

import { preferences } from '@kit.ArkData';

import { BusinessError, commonEventManager } from '@kit.BasicServicesKit';

import { formBindingData, formProvider } from '@kit.FormKit';

import { Logger } from 'lib_common';

import { CardManager } from 'module_points';

 

const TAG = '[WidgetUtil]';

 

export class WidgetUtil {

  // ...

  private static readonly _formClickEventName: string = 'form_click_event_name';

 

  //发布卡片按钮点击事件

  public static publishFormClick(formId: string) {

    commonEventManager.publish(

      WidgetUtil._formClickEventName,

      { data: formId },

      (err: BusinessError) => {

        if (err) {

          Logger.error(

            TAG,

            `Failed to publish form_click_event_name. Code is ${err.code}, message is ${err.message}`,

          );

        } else {

          Logger.info(TAG, 'Succeeded in publishing form_click_event_name.');

        }

      },

    );

  }

 

  //订阅卡片按钮点击事件

  public static async subscribeFormClick(ctx: Context) {

    let subscriber: commonEventManager.CommonEventSubscriber | undefined =

      undefined;

    let subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {

      events: [WidgetUtil._formClickEventName],

      publisherPermission: '',

    };

    commonEventManager.createSubscriber(subscribeInfo, (err1, data1) => {

      if (data1) {

        subscriber = data1;

        //订阅公共事件回调

        commonEventManager.subscribe(subscriber, async (err2, data2) => {

          if (data2) {

            Logger.info(TAG, 'Succeeded in creating subscribeFormClick.');

            const formData = CardManager.get().getCardData(true);

            //在回调中获取当前的卡片数据,并通过formProvider.updateForm方法刷新卡片数据

            formProvider.updateForm(

              data2.data,

              formBindingData.createFormBindingData(formData),

            );

          }

        });

      }

    });

  }

 

  // ...

}

 

3. 模板集成

本模板提供了两种代码集成方式,供开发者自由选用。

1) 整体集成

开发者可以选择直接基于模板工程开发自己的应用工程。

  • 模板代码获取:

① 通过 IDE 插件创建模板工程,开发指导

② 通过生态市场下载源码, 下载地址

③ 通过开源仓访问源码,仓库地址

  • 打开模板工程,根据 README 说明中的快速入门章节,将自己的应用信息配置在模板工程内,即可运行并查看模板效果。


 

  • 对接开发者自己的服务器接口,转换数据结构,展示真实的云侧数据。

① 将 commons/lib_common/src/main/ets/httprequest/HttpRequestApi.ets 文件中的 mock 接口替换为真实的服务器接口。


 

② 在 commons/lib_common/src/main/ets/httprequest/HttpRequest.ets 文件中将云侧开发者自定义的数据结构转换为端侧数据结构。


 

  • 根据自己的业务内容修改模板,进行定制化开发。


2) 按需集成

若开发者已搭建好自己的应用工程,但暂未实现其中的部分场景能力,可以选择取用其中的业务组件,集成在自己的工程中。

  • 组件代码获取:

① 通过 IDE 插件下载组件源码。开发指导

② 通过生态市场下载组件源码。 下载地址

  • 下载组件源码,根据 README 中的说明,将组件包配置在自己的工程中。


 

  • 根据 API 参考和示例代码,将组件集成在自己的对应场景中。

 

以上是本期“便捷生活行业”行业优秀案例的内容,更多行业敬请期待~

欢迎下载使用行业模板“点击下载”,若您有体验和开发问题,或者迫不及待想了解 XX 行业的优秀案例,欢迎在评论区留言,小编会快马加鞭为您解答~

同时诚邀您添加下方二维码加入“组件模板活动社群”,精彩上新 &活动不错过!



👉本系列持续更新,欢迎收藏本帖!

第一期:【宝藏贴】HarmonyOS官方模板优秀案例 (第1期:便捷生活 · 购物中心)


👉HarmonyOS 组件模板相关推荐

  • 【活动 ing】HarmonyOS 组件/模板集成创新活动,报名时间截止 2025 年 8 月 30 日,点击查看

 

2025-07-28 14:182263

评论

发布
暂无评论

在数字时代,如何选择企业的知识管理软件

Baklib

建木持续集成平台v2.5.4发布

Jianmu

DevOps 持续集成 gitops 持续部署 Gitea

万物皆可集成系列:低代码如何不成为数据孤岛

葡萄城技术团队

低代码 数据孤岛 集成

搭建自己的以图搜图系统 (一):10 行代码搞定以图搜图

Zilliz

Python 机器学习 深度学习 相似度分析 以图搜图

当你的老板站在你背后,看你处理故障......

嘉为蓝鲸

运维 IT 故障 上班

2022世界人工智能大会•腾讯“智变未来”论坛:聚焦产业升级,数字赋能未来

科技热闻

AOSWAP去中心化交易所系统开发功能介绍

开发微hkkf5566

Apache Kyuubi 在小米大数据平台的应用实践

网易数帆

Java hive Apache Spark Thrift kerberos

2022 云原生编程挑战赛启动!看导师如何拆解边缘容器赛题?

阿里巴巴中间件

阿里云 云原生编程挑战赛

基于预训练模型的金融事件分析及应用

澜舟孟子开源社区

人工智能 自然语言处理 金融科技 大规模预训练模型

盘点适合中小企业的文档管理工具

Baklib

SpringCloud 注册中心(Nacos)快速入门

nacos SpringCould 9月月更

浅谈 SAP ABAP 系统里的 ALV 输出方式实现

汪子熙

前端开发 SAP abap 9月月更 ALV

了解数字机器人最新发展动向,不要错过华为数字机器人秋季发布会​

王吉伟频道

RPA 机器人流程自动化 智慧政务 机器人开发 华为数字机器人

堡垒机有录像吗?好用吗?有什么作用?

行云管家

网络安全 企业 数据安全 堡垒机 录像

C#/VB.NET 设置Word文档段落缩进

在下毛毛雨

C# .net word文档 段落缩进

干货|为什么说开源基金会的选择很关键?(下)

Orillusion

开源 WebGL 元宇宙 webgpu web3d

百余位顶级投资人齐聚无锡,DEMO CHINA创新中国峰会即将揭幕

创业邦

预训练模型在金融 NLP场景下的应用

澜舟孟子开源社区

人工智能 自然语言处理 大规模预训练模型

UI自动化助力业务效率提升

转转技术团队

UI自动化测试

使用FeatureAbility模块启动其他Ability

白晓明

OpenHarmony应用开发 FeatureAbility

高性能对象池实现

C++后台开发

后端开发 高性能服务器 内存池 对象池 C++开发

设计模式的艺术 第二十一章备忘录设计模式练习(设计一款RPG网游,为了给玩家提供更多方便,在游戏过程中可以设置一个恢复点,用于保存当前的游戏场景。如果在后续游戏过程中玩家角色“不幸牺牲”,可以返回到先前保存的场景,从所设恢复点开始重新游戏)

代廉洁

设计模式的艺术

极狐GitLab Helm Chart 已上线,玩转云原生极狐GitLab!

极狐GitLab

DevOps gitlab 云原生 Helm Kubernetes, 云原生, eBPF

重拾面向对象软件设计

阿里巴巴中间件

阿里云 技术 中间件 技术代码

数字藏品系统开发,NFT数字藏品开发说明

开源直播系统源码

软件开发 NFT 数字藏品 数字藏品软件开发 数字藏品系统

笔记 | DevOps推动科技管理敏捷转型(文末附PPT)

嘉为蓝鲸

DevOps 运维 敏捷 IT 精益

优秀的产品手册有助于留住你的客户

Baklib

中移链DDC-SDK技术对接全流程(一)

BSN研习社

看了深入Java虚拟机:JVMG1GC的算法与实现文档,我悟了

程序知音

Java JVM 垃圾回收 java架构 后端技术

数据可视化系列教程|六大组件基础知识

云智慧AIOps社区

大前端 低代码 开源项目 数据可视化 可视化大屏

【宝藏贴】HarmonyOS官方模板优秀案例
(第1期:便捷生活 · 购物中心)_HarmonyOS_HarmonyOS_InfoQ精选文章