写点什么

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

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

    阅读完需:约 11 分钟

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

🚀🚀🚀🚀

鸿蒙生态为开发者提供海量的 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:188255

评论

发布
暂无评论

2个场景实例讲解GaussDB(DWS)基表统计信息估算不准的处理方案

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 6 月 PK 榜

行云堡垒V7亮点有哪些?具体看这里!

行云管家

IT运维 行云堡垒

手把手实践丨基于STM32+华为云设计的智慧烟感系统

华为云开发者联盟

云计算 华为云 华为云开发者联盟 企业号 6 月 PK 榜

中移链资源管理介绍

BSN研习社

强化学习基础篇[2]:SARSA、Q-learning算法简介、应用举例、优缺点

汀丶人工智能

人工智能 深度学习 强化学习

一文读懂责任分配矩阵,解决你80%的项目难题

敏捷开发

项目管理 Scrum 敏捷开发 责任分配矩阵 RACI矩阵

浅谈EOS区块链性能测试

BSN研习社

数字赋农:数字农业新时代,致富之路宽又阔!

加入高科技仿生人

低代码 智慧农业 数字赋能 科技兴农

我又和redis超时杠上了

蓝胖子的编程梦

redis 性能分析 云服务器 线上事故 接口超时

单点登录的三种实现方式

Authing

SSO 单点登录

圣邦股份:品类持续深挖,高端加速推进,模拟龙头稳健发展

华秋电子

数据隐私为先:EMQX Cloud BYOC 架构解析

EMQ映云科技

物联网 云服务 mqtt

Amazon CodeWhisperer 初体验

Coder9527

rocketmq4 docker安装 阿里云linux2(centos7)

folo

Docker centos RocketMQ部署

软件测试/测试开发丨Pytest测试框架学习笔记

测试人

程序员 软件测试 pytest

执行计划缓存,Prepared Statement性能跃升的秘密

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 6 月 PK 榜

全国信安标委“标准周”在昆明召开,腾讯安全受邀分享标准实践经验

说山水

GreptimeDB 设计原则 — 云原生时序数据库,解决海量数据管理挑战

Greptime 格睿科技

数据库 分布式数据库 时序数据库 云原生数据库

TiDB 落地SAS机器实践

TiDB 社区干货传送门

实践案例 应用适配 HTAP 场景实践

TiDB集群数据库灾难恢复手册

TiDB 社区干货传送门

管理与运维 备份 & 恢复

TiDB数据迁移实践DM工具

TiDB 社区干货传送门

迁移 实践案例

堡垒机重要吗?为什么?求解!

行云管家

堡垒机 安全运维 录像审计

通过FP&A实践,释放企业深度价值

智达方通

全面预算管理 财务规划和分析 FP&A

海汽集团:业财共享服务中心建设推进集团数字治理

用友BIP

财务共享

简洁实用的文本编辑器:FSNotes中文版

真大的脸盆

Mac Mac 软件 文本编辑器 文本管理 文本处理工具

羽山数据SaaS平台新增供应商API自动上架功能

羽山数据

自动 自主研发 上架

人工智能工程总体介绍

紫晖

人工智能 软件工程 数据开发

含有CPU芯片的PCB设计需要考虑的五个主要方面

华秋电子

分享几个索引创建的小 Tips

江南一点雨

MySQL

强化学习基础篇【1】:基础知识点、马尔科夫决策过程、蒙特卡洛策略梯度定理、REINFORCE 算法

汀丶人工智能

人工智能 深度学习 强化学习

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