《仿盒马》app开发技术分享-- 设置安全锁(51)

鸿蒙小林
• 阅读 4

技术栈

Appgallery connect

开发准备

上一节我们实现了提现页面以及部分组件的业务逻辑,那么我们在提现这一步为了更多的安全层面的考虑,设置了一个安全锁,用户只要开启了安全锁,那么每次的提现,都需要把本地的密码提交到云端核对安全锁的内容才可以执行后续的提现步骤,如果不能解锁,那么后续的内容都无法实现,这更好的保护了用户的财产安全

功能分析

要实现这个功能首先我们需要在个人页面添加一个安全入口,然后在安全锁设置页面开启安全锁的按钮,当没有开启安全锁的时候,点击开启按钮会出现一个安全锁的弹窗,在弹窗里设置对应的密码,设置成功后保存对应的内容提交到云端,进行保存,方便后续的校验,关闭安全锁则在云端删除对应的内容

代码实现

首先我们直接在个人页面的列表中添加上对应的数据

  new SectionLine("安全",
        "设置安全锁",
        $r('app.media.anquan'),
        false),

然后给这条数据添加对应的点击事件

if (item.title=='安全'){
        if (this.user!=null) {
          router.pushUrl({url:'pages/view/LockPage'})

        }else {
          showToast("请先登录")

        }
      }

接下来创建安全锁对应的表

{
  "objectTypeName": "verify_info",
  "fields": [
    {"fieldName": "id", "fieldType": "Integer", "notNull": true, "belongPrimaryKey": true},
    {"fieldName": "open_lock", "fieldType": "Boolean"},
    {"fieldName": "lock_str", "fieldType": "String"},
    {"fieldName": "user_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"]}
  ]
}

创建对应的安全锁页面,在页面中设置好对应的参数

 @State user: User|null=null
  @State flag:boolean=false
  @State lockInfo:VerifyInfo|null=null
  @State lock_ui_visibility:boolean=false

 Column({space:10}) {
      CommonTopBar({ title: "安全锁", alpha: 0, titleAlignment: TextAlign.Center ,backButton:true})
      Row(){
        Text("安全锁")
          .fontColor(Color.Black)
          .fontSize(16)
        Image(this.lock_ui_visibility?$r('app.media.kai'):$r('app.media.guan'))
          .width(60)
          .height(30)
          .onClick(()=>{

          })
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .padding({left:10,right:10})
      Divider().width('100%').height(0.8)
        .color("#e6e6e6")
      .width('100%')

    }.width('100%').height('100%').backgroundColor(Color.White)

接下来我们创建对应的安全锁设置弹窗并整理好对应的逻辑

import { LengthUnit } from '@kit.ArkUI';

@Preview
@CustomDialog
export struct LockDialog {
  @State passwords: Number[]=[];
  @Link lock_ui_visibility:boolean
  @State message: string = '绘制您的密码图案!';
  public callback:(passwords:string)=>void=():void=>{}
  private patternLockController: PatternLockController = new PatternLockController();
  controller: CustomDialogController;
  build() {
    Column({space:20}) {
      Text(this.message).textAlign(TextAlign.Center).margin(20).fontSize(20)
        .fontColor(Color.Black)
      PatternLock(this.patternLockController)
        .sideLength(300)
        .circleRadius(9)
        .pathStrokeWidth(5)
        .activeColor('#707070')
        .selectedColor('#707070')
        .pathColor('#707070')
        .backgroundColor('#F5F5F5')
        .autoReset(true)
        .activateCircleStyle({
          color: '#707070',
          radius: { value: 16, unit: LengthUnit.VP },
          enableWaveEffect: true
        })
        .onDotConnect((index: number) => {
          console.log("onDotConnect index: " + index);
        })
        .onPatternComplete((input: Array<number>) => {
          if (input.length < 5) {
            this.message = '图案连接数不能小于5';
            return;
          }
          if (this.passwords.length > 0) {
            if (this.passwords.toString() === input.toString()) {
              this.passwords = input;
              this.message = '图案码设置完成';
              this.patternLockController.setChallengeResult(PatternLockChallengeResult.CORRECT);
              const str: string = JSON.stringify(this.passwords);
              this.callback(str)
              this.controller.close()

            } else {
              this.message = '图案码核对失败,请确认后重新绘制.';
              this.patternLockController.setChallengeResult(PatternLockChallengeResult.WRONG);
            }
          } else {
            this.passwords = input;
            this.message = "请再次绘制图案码.";
          }
        })
    }
    .borderRadius({topLeft:20,topRight:20})
    .justifyContent(FlexAlign.Start)
    .backgroundColor(Color.White)
    .height(500)
    .width('100%')
  }
}

接下来我们在页面内调用

  private dialogController: CustomDialogController = new CustomDialogController({
    builder: LockDialog({
     lock_ui_visibility:this.lock_ui_visibility,
      callback: async (str:string)=>{
        //在这里提交表单信息,成功插入之后关闭弹窗,修改安全锁按钮的状态,重新查询数据赋值lockInfo
        showToast(str)
        let info=new verify_info()
        info.id=Math.floor(Math.random() * 1000000)
        info.open_lock=true
        info.lock_str=str
        info.user_id=this.user!.user_id
        let num = await databaseZone.upsert(info);
        if (num>0) {
          this.lock_ui_visibility=true
          this.initLockInfo()
        }

      }
    }),
    alignment: DialogAlignment.Bottom,
    customStyle:false
  });

因为我们提交数据需要用户信息,首次进入页面也需要加载对应的状态所以还需要进行数据查询


  async initLockInfo(){
    const value = await StorageUtils.getAll('user');
    if (value != "") {
      this.user = JSON.parse(value)
    }
    let databaseZone = cloudDatabase.zone('default');
    let condition = new cloudDatabase.DatabaseQuery(verify_info);
    condition.equalTo("user_id", this.user?.user_id)
    let listData = await databaseZone.query(condition);
    let json = JSON.stringify(listData)
    let data: VerifyInfo[] = JSON.parse(json)
    if (data.length>0) {
      this.lock_ui_visibility=true
      this.lockInfo=data[0]
    }else {
      this.lock_ui_visibility=false

    }
  }

在生命周期方法内调用

  async aboutToAppear(): Promise<void> {


this.initLockInfo()

  }

实现开关的业务逻辑

```css build() { Column({space:10}) { CommonTopBar({ title: "安全锁", alpha: 0, titleAlignment: TextAlign.Center ,backButton:true}) Row(){ Text("安全锁") .fontColor(Color.Black) .fontSize(16) Image(this.lock_ui_visibility?$r('app.media.kai'):$r('app.media.guan')) .width(60) .height(30) .onClick(async ()=>{ if (this.lock_ui_visibility) { let info=new verify_info() info.id=this.lockInfo!.id let num = await databaseZone.delete(info); if (num>0) { this.lock_ui_visibility=false } }else { this.dialogController.open() } }) } .width('100%') .justifyContent(FlexAlign.SpaceBetween) .padding({left:10,right:10}) Divider().width('100%').height(0.8) .color("#e6e6e6") .width('100%')

}.width('100%').height('100%').backgroundColor(Color.White)

}

点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
Cocos官方插件商品升级,开发者的福音来了……
我们曾经收到不少开发者关于插件商店的吐槽,辛辛苦苦地开发插件,有了收入之后,提现却无比痛苦:开发者后台发起提现申请等待工作人员的审核往往还要提供身份证千辛万苦费尽周折终于把余额给提现了......参考阅读晓衡2019年1月的一篇文章《
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 个人中心页or静态头像选择(业务逻辑)(22)
技术栈Appgalleryconnect开发准备上一节我们实现了登录页面的业务逻辑,并且成功的实现了数据的查询,同时我们新增了用户首选项的工具类,现在主界面往登录页面跳转,登录成功后我们关闭登录页面,这时候我们就会回到个人中心页面,那么现在我们的业务逻辑是
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 旧物回收页(提交云端)(42)
技术栈Appgalleryconnect开发准备上一节我们已经实现了地址,留言,取件时间的选择,以及静态的预估重量。现在我们需要把预估重量创建出来,从云端去获取,以应对后续的其他业务逻辑,以及回收订单的创建功能分析预估重量列表的实现首先需要创建对应的表和数
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 回收金查询页面(48)
技术栈Appgalleryconnect开发准备上一节我们实现了查看当前账号下的预收益,以及当下收益,并且展示了已完成订单的列表,现在我们可以针对收益来做更多的内容了,在之前的开发中我们在个人中心页面实现了一个静态的金额展示,后续我们将会在这里展示当前账号
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 回收金提现准备页(50)
技术栈Appgalleryconnect开发准备上一节我们实现了回收金的收入、支出记录查询,并且在订单完成后成功创建对应的收支记录,但是我们暂时只有收入记录,并没有支出记录,这一节我们将要实现账号的回收金提现功能,从商业角度实现app应用的正向循环功能分析
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 绑定银行卡回显(52)
技术栈Appgalleryconnect开发准备上一节我们实现了安全锁的绑定,这一切都是为了帮助用户在提现流程上能有更好更安全的体验,现在我们开始正式着手提现相关的流程,我们先进行提现银行卡的绑定,绑定成功后我们关闭页面把数据回显到提现页功能分析首先我们要
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 回收金提现(53)
技术栈Appgalleryconnect开发准备上一节我们实现了银行卡的绑定跟回显,这一节我们要真正的实现银行卡提现的功能了,在这之前我们还需要对提现页的业务逻辑进行更进一步的优化,同时为了方便我们去进行数据间的交互,我们在个人信息模块新增了金额和积分的字
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 回收金提现记录查询(54)
技术栈Appgalleryconnect开发准备上一节我们实现了回收金提现的功能,并且成功展示了当前账户的支出列表,但是我们的提现相关的记录并没有很好的给用户做出展示,用户只知道当前账户提现扣款,并不知道回收金的去向,这一节我们就要实现回收金记录的查询添加
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 回收金提现安全锁校验(55)
技术栈Appgalleryconnect开发准备上一节我们实现了回收金提现记录的展示功能,我们回收金相关的内容更加的丰富了,在之前的业务逻辑中我们添加了一个设置安全锁的功能,虽然我们成功设置了安全锁,也把对应的表信息提交到云端,但是我们并没有在提现的流程中
鸿蒙小林 鸿蒙小林
10小时前
《仿盒马》app开发技术分享-- 订单提交逻辑完善(74)
技术栈Appgalleryconnect开发准备上一节我们实现了兑换订单的提交功能,并且成功的把数据提交到云端,但是我们的业务逻辑并没有完全实现,我们只是把数据提交到了云端,但我们的积分还存在,我们回到积分数据查看的页面也没有消费积分的记录,这一节我们要实