HarmonyOS 鸿蒙Next《仿盒马》app开发技术分享之环保金提现准备页

HarmonyOS 鸿蒙Next《仿盒马》app开发技术分享之 环保金提现准备页

技术栈

Appgallery connect

开发准备

上一节我们实现了环保金的收入、支出记录查询,并且在订单完成后成功创建对应的收支记录,但是我们暂时只有收入记录,并没有支出记录,这一节我们将要实现账号的环保金提现功能,从商业角度实现app应用的正向循环

功能分析

要实现提现功能,首先我们需要有对应银行卡信息的绑定,提现的金额,以及当前账号下的环保金总额,从商业角度考虑,我们还要限制一天内环保金额的提取总数,避免在某些情况下造成不必要的损失,首先我们需要判断当前账号是否绑定有对应的信息,然后我们通过对input组件进行条件判断来限制用户一些不正确的操作,然后在添加确认提现和提现记录按钮

代码实现

首先我们创建对应的绑定信息表

{
  "objectTypeName": "bind_bank",
  "fields": [
    {"fieldName": "id", "fieldType": "Integer", "notNull": true, "belongPrimaryKey": true},
    {"fieldName": "user_id", "fieldType": "Integer"},
    {"fieldName": "bank_name", "fieldType": "String"},
    {"fieldName": "bank_card", "fieldType": "String"},
    {"fieldName": "bank_people", "fieldType": "String"},
    {"fieldName": "is_verify", "fieldType": "Boolean"},
    {"fieldName": "verify_id", "fieldType": "Integer"}
  ],
  "indexes": [
    {"indexName": "field1Index", "indexList": [{"fieldName":"id","sortType":"ASC"}]}
  ],
  "permissions": [
    {"role": "World", "rights": ["Read", "Upsert", "Delete"]},
    {"role": "Authenticated", "rights": ["Read", "Upsert", "Delete"]},
    {"role": "Creator", "rights": ["Read", "Upsert", "Delete"]},
    {"role": "Administrator", "rights": ["Read", "Upsert", "Delete"]}
  ]
}

然后我们实现银行卡绑定模块,我们用组件引入的方式来实现,处理好绑定以及未绑定的展示逻辑

@Component
export struct BindAlipay {
  @Link bankList:BindBank[]
  public callback:() => void = ():void => {}
  public postCallback:() => void = ():void => {}

  @Builder
  notAlipay(){
    Row(){
      Text("您还未绑定银行卡账号,点击绑定")
        .fontColor("#FF4242")
        .fontSize(16)
    }
    .backgroundColor(Color.White)
    .padding(10)
    .margin({bottom:50})
    .onClick(e=>{ 
      this.callback()
    })
    .height(48)
    .width('100%')
  }

  @Builder bindAlipay(){
    Row(){
      Column(){
        Row(){
          Text("12212")
            .fontColor("#333333")
            .fontSize(16)
        }
        Text("预计2小时内到账(以实际到账时间为准)")
          .fontColor("#999999")
          .fontSize(15)
      }
    }
  }
  build() {
    Column() {
      if (this.bankList.length > 0){
        this.bindAlipay()
      }else {
        this.notAlipay()
      }
    }
  }
}

然后我们实现提现金额输入的模块

@Component
export struct InputItem {
  [@Consume](/user/Consume)
  moneyNum:number
  @State text: string = ''
  controller: TextInputController = new TextInputController()
  [@Consume](/user/Consume)
  isPost:boolean
  build() {
    Column() {
      Row() {
        Text("提现金额")
          .fontSize(16)
          .fontColor("#333333")
        Text("单笔提现至少1元")
          .fontSize(14)
          .fontColor("#FF4242")
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      Row() {
        Text("¥")
          .fontSize(28)
          .fontColor("#333333")
        TextInput({ text: this.text, placeholder: '输入提现金额', controller: this.controller })
          .placeholderColor("#999999")
          .placeholderFont({ size: 28, weight: 400 })
          .caretColor("#FCDB29")
          .width(400)
          .height(50)
          .backgroundColor(null)
          .type(InputType.Number)
          .margin(20)
          .fontSize(14)
          .fontColor(Color.Black)
          .onChange((value: string) => {
            this.moneyNum=Number(value)
            this.text = value
            if (this.moneyNum>0 && this.moneyNum<=300) {
              this.isPost=true
            }else {
              this.isPost=false
            }
          })
      }
      Divider().width('100%').height(1)
      Text("可提现金额¥1500.00 (单日最大提现额度:300)")
        .fontSize(15)
        .fontColor("#333333")
    }
    .padding(10)
    .backgroundColor(Color.White)
    .alignItems(HorizontalAlign.Start)
  }
}

通过定义的@Provide @Consume可以帮助我们跨组件获取值,来更好的进行逻辑判断

Column({space:15}){
  Text("确认提现")
    .width('100%')
    .fontColor(Color.White)
    .borderRadius(15)
    .padding(10)
    .textAlign(TextAlign.Center)
    .fontColor(this.isPost?Color.Black:Color.White)
    .backgroundColor(this.isPost?"#ffff6363":$r('app.color.color_999'))
    .onClick(()=>{
      if (this.isPost) {
        //拉起弹窗
      }else {
        if (this.moneyNum==0){
          showToast("提现金额单笔至少1元")
        }
        if (this.moneyNum>300) {
          showToast('单日限额300元,请重新输入')
        }
      }
    })
  Text("查看提现记录")
    .width('100%')
    .fontColor(Color.Black)
    .textAlign(TextAlign.Center)
    .backgroundColor("#ffffff")
    .padding(10)
    .borderRadius(15)
}
.margin({top:50})

然后我们在主页面调用组件

@Component
export default struct WithdrawMoneyPage {
  @State fontColor: string = '#182431'
  @State selectedFontColor: string = '#007DFF'
  @State currentIndex: number = 0
  @State alipayAcc:string=''
  @State bindAlipayName:string=''
  @State phoneCode:string=''
  [@Provide](/user/Provide)
  isPost:boolean=false
  [@Provide](/user/Provide)
  moneyNum:number=0
  @State bankList:BindBank[]= []

  @Builder TabBuilder(index: number, name: string) {
    Row() {
      Image($r('app.media.tv_card'))
        .height(17)
        .width(17)
        .margin({left:15})
      Text(name)
        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(16)
        .fontWeight(this.currentIndex === index ? 500 : 400)
        .lineHeight(22)
    }
    .height(55)
    .width('100%')
    .alignItems(VerticalAlign.Center)
  }
  build() {
    Column() {
      CommonTopBar({ title: "提现", alpha: 0, titleAlignment: TextAlign.Center ,backButton:true})
      Column(){
        BindAlipay({bankList:this.bankList,
          callback:()=>{},
          postCallback:()=>{}})
        InputItem()
        Column({space:15}){
          Text("确认提现")
            .width('100%')
            .fontColor(Color.White)
            .borderRadius(15)
            .padding(10)
            .textAlign(TextAlign.Center)
            .fontColor(this.isPost?Color.Black:Color.White)
            .backgroundColor(this.isPost?"#ffff6363":$r('app.color.color_999'))
            .onClick(()=>{
              if (this.isPost) {
                //拉起弹窗
              }else {
                if (this.moneyNum==0){
                  showToast("提现金额单笔至少1元")
                }
                if (this.moneyNum>300) {
                  showToast('单日限额300元,请重新输入')
                }
              }
            })
          Text("查看提现记录")
            .width('100%')
            .fontColor(Color.Black)
            .textAlign(TextAlign.Center)
            .backgroundColor("#ffffff")
            .padding(10)
            .borderRadius(15)
        }
        .margin({top:50})
      }
      .backgroundColor('#F1F3F5')
      .height('100%')
      .justifyContent(FlexAlign.Start)
      .padding(10)
    }
  }
}

更多关于HarmonyOS 鸿蒙Next《仿盒马》app开发技术分享之环保金提现准备页的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

鸿蒙Next开发《仿盒马》环保金提现页可采用以下技术方案:

  1. 使用ArkTS编写UI布局,通过Column/Row/Flex等容器组件构建页面结构
  2. 提现表单使用TextInput组件绑定数据
  3. 金额显示采用Text组件配合动态样式
  4. 按钮状态管理使用@State装饰器控制
  5. 页面路由通过router模块实现跳转
  6. 网络请求使用@ohos.net.http模块
  7. 用户数据持久化采用Preferences存储

关键点:

  • 需处理提现校验逻辑
  • 注意账户余额实时刷新
  • 需要对接支付SDK接口

更多关于HarmonyOS 鸿蒙Next《仿盒马》app开发技术分享之环保金提现准备页的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


从技术实现来看,这个环保金提现页面开发得很规范,主要亮点包括:

  1. 使用了ArkUI的组件化开发模式,将银行卡绑定、金额输入等模块拆分为独立组件,提高了代码复用性

  2. 合理运用了@Provide/@Consume装饰器实现跨组件状态管理,避免了复杂的属性传递

  3. 输入校验逻辑完善,包括:

    • 最小提现金额限制(1元)
    • 单日提现上限(300元)
    • 实时校验输入合法性
  4. 界面交互考虑周到:

    • 未绑定银行卡的引导提示
    • 提现按钮的状态联动
    • 错误输入的Toast提示
  5. 数据模型设计合理,bind_bank表包含了必要的银行卡信息字段

建议可以进一步完善:

  • 添加提现密码验证环节增强安全性
  • 考虑接入华为支付服务实现真实提现
  • 增加提现处理中的状态反馈

整体实现符合HarmonyOS应用开发规范,组件解耦良好,是典型的ArkUI开发实践。

回到顶部