《仿盒马》app开发技术分享-- 个人中心页or静态头像选择(业务逻辑)(22)


## 技术栈


Appgallery connect

## 开发准备


上一节我们实现了登录页面的业务逻辑,并且成功的实现了数据的查询,同时我们新增了用户首选项的工具类,现在主界面往登录页面跳转,登录成功后我们关闭登录页面,这时候我们就会回到个人中心页面,那么现在我们的业务逻辑是一种什么样的形式?登录成功后我们需要显示用户的信息,并且在下次登录时依旧展示个人信息。同时我们还新增了一个头像选择的静态弹窗,丰富个人信息页面


## 功能分析

我们需要注意的问题有如下几个:

1.tabs 切换的时候自定义组件是不会刷新的,所以需要处理切换时每次的刷新问题

2.切换到个人中心页面时加载登录时的用户信息

3.点击头像唤起自定义头像选择弹窗



## 代码实现


首先在登录的时候保存内容以及传递用户信息

 StorageUtils.set("user",JSON.stringify(data1[0]))

          router.back({

            url: 'pages/Index',

            params: {

              info: user

            }

          });

然后解决切换时自定义组件不刷新的问题,我们在index页面定义一个下标的tag ,然后通过@prop 传进组件内,通过监听来执行我们想要的方法

 @State currentIndexCheck: number = 3

  @Prop @Watch("onRefresh") currentIndex:number=0

   async onRefresh(): Promise {

   }

 

 现在我们切换的问题解决了,接下来要解决的是数据的传输,在上方的back中我们把用户信息传递到了index页面,所以我们需要接收一下

 

  onPageShow(): void {

    const params = this.getUIContext().getRouter().getParams() as User;

    if (params) {

      const info: User = params as User;

      if (info!=null) {

        this.controller.changeIndex(3);

        this.user=info

      }

    }

  }


通过@Provide   @Consume 来实现数据的传递


首页定义

  @Provide user: User|null=null


个人中心页定义

@Consume user: User|null;


个人中心页面刷新用户数据

async onRefresh(): Promise {

    if (this.currentIndexCheck==this.currentIndex) {

      const value = await StorageUtils.getAll('user');

      this.user=JSON.parse(value)

    }

  }


   

   填充对应的数据

    if (this.user!=null) {

            Row() {

              Image($r('app.media.background'))

                .height(55)

                .width(55)

                .borderRadius(27)

                .objectFit(ImageFit.Contain)

                .interpolation(ImageInterpolation.High)

                .onClick(()=>{

                  this.dialogController.open()

                })

              Column() {

                Text(this.user!.user_name)

                  .fontSize(24)

                  .maxLines(1)

                  .textOverflow({ overflow: TextOverflow.Ellipsis })

                Text(this.user!.is_vip?'svip':"开启vip")

                  .fontSize(14)

              }

              .alignItems(HorizontalAlign.Start)

              .margin({ left: 10 })

              Blank()

                .layoutWeight(1)

              Image($r('app.media.ic_arrow_bold'))

                .height(16)

                .width(16)

                .margin(20)

                .objectFit(ImageFit.Contain)

                .interpolation(ImageInterpolation.High)

            }

            .justifyContent(FlexAlign.Start)

            .margin({top: 30 })

          }

          到这里我们就实现了,用户信息每次登录都可以获取了




然后我们在点击头像的时候创建一个选择的弹窗,并且先把选择的头像路径返回出来


先定义弹窗并且填充数据


import { SplitLayoutModel } from "../entity/SplitLayoutModel";

import showToast from "../utils/ToastUtils";


@Preview

@CustomDialog

export struct HeadCheckDialog {

  controller: CustomDialogController;

  @Link str: string ;

  @State checkPos:number=-1

  @State headList:ESObject[]=[

    {'img':'在线图片链接'},

    {'img':'在线图片链接'},

    {'img':'在线图片链接'},

    {'img':'在线图片链接'},

    {'img':'在线图片链接'},

    {'img':'在线图片链接'}

  ]


  onItemSelected: (item: string) => void= () => {

  };


  build() {

    Column({space:20}) {

      Text("头像选择")

        .id('HeadPageHelloWorld')

        .fontSize($r('app.float.size_20'))

        .fontWeight(FontWeight.Bold)

        .fontColor(Color.Black)

        .margin({top:20})


      Grid(){

        ForEach(this.headList,(item:ESObject,index:number)=>{

          GridItem(){

            Column(){

              Image(item.img)

                .width(80)

                .height(80)

                .onClick(()=>{

                  this.str=item.img

                  this.checkPos=index

                })

                .border({width:this.checkPos==index?2:0,color:this.checkPos==index?0xff0000:null})

                .borderRadius(20)

            }

          }

        })

      }

      .columnsGap(10)

      .rowsGap(10)

      .height(300)

      .columnsTemplate('1fr 1fr 1fr 1fr')

      .width('90%')

      .padding(10)


      Text("确认")

        .width('50%')

        .textAlign(TextAlign.Center)

        .height(40)

        .fontSize(18)

        .fontColor(Color.White)

        .backgroundColor(0xff0000)

        .borderRadius(30)

        .margin({top:30})

        .onClick(()=>{

          if (this.str!='') {

            this.onItemSelected(this.str)

            // this.controller.close()

            showToast(this.str)

          }else {

            showToast("请先选择头像")

          }


        })

    }

    .borderRadius({topLeft:20,topRight:20})

    .justifyContent(FlexAlign.Start)


    .backgroundColor(Color.White)

    .height(500)

    .width('100%')

  }

}


弹窗相关

 private dialogController: CustomDialogController = new CustomDialogController({

    builder: HeadCheckDialog({

      str:this.str,

      onItemSelected:(str)=>{

        showToast(str)

        this.str=str

      }

    }),

    alignment: DialogAlignment.Bottom,

    customStyle:true

  });


到这里已经实现了个人信息的展示和头像的静态选择


请使用浏览器的分享功能分享到微信等