一、引言

  在当今数字化时代,电子商务已经成为商业领域中不可或缺的一部分。随着移动互联网的快速发展和技术的不断创新,构建高效、安全且用户友好的电子商务系统变得尤为重要。为了满足用户对更优质在线购物体验的需求,本项目选择使用鸿蒙ArkTs语言,旨在开发一款功能丰富的商城系统。

  本商城系统的核心目标是实现用户注册和登录功能,为用户提供便捷的账户管理体验。通过充分利用鸿蒙ArkTs语言的特性,我们将设计和实现一个具有高度可扩展性、安全性和灵活性的系统,以满足现代电商的各种需求。

二、项目框架

『江鸟中原』鸿蒙大作业 _验证码

主要实现的功能有

1、用户验证码登录
2、用户密码登录
3、注册页面
4、商城主页面

三、用户验证码登录页面

『江鸟中原』鸿蒙大作业 _验证码_02

  实现功能为提供几个组件和文本来达到能输入数据的效果,然后插入合适的图片来美化注册的效果,验证码实现为使用http.createHttp()方法创建一个HTTP请求对象 将其赋值给名为httpRequest的变量,填写HTTP请求的URL地址,自定义URL地址,请求的参数可以在extraData中指定。根据自身业务添加header字段123。

主要源代码为:

// 引入包名
import http from '@ohos.net.http';
import router from '@ohos.router';
import prompt from '@ohos.prompt';
import CommonConstants from '../common/constants/CommonConstants';
@Entry
@Component
struct LoginByVerify {

  private code:string = "";
  private phone:string = "";

  build() {
    Column() {

      Text('Welcome to Login')
        .fontColor(Color.Blue)
        .fontSize(30)
        .fontStyle(FontStyle.Italic)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 90 })

      Image('https://img0.baidu.com/it/u=4211255290,3029166540&fm=253&fmt=auto&app=138&f=JPEG?w=480&h=480') .width(90)
        .height(90).borderRadius(90)

      Text('短信验证登录')
        .fontSize(20)
        .margin({ top: 20 })

      TextInput({ placeholder: '请输入手机号' }).margin({ top: 40 })
        .onChange((value: string)=>{
          this.phone = value;
        })
      Row() {
        TextInput(
          { placeholder: '请输入验证码' })
          .margin({ top: 20 })
          .width(250)
          .onChange((value: string) => {
            this.code = value;
          })
        Text('获取验证码').fontSize(15).fontColor(Color.Blue).width(100).margin({ top: 30 })
          .onClick(()=>{
            let httpRequest = http.createHttp();
            //   使用http.createHttp()方法创建一个HTTP请求对象 将其赋值给名为httpRequest的变量
            httpRequest.request(
              // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
              "http://localhost:8082/user/senCode",
              // 在extraData字段中添加了一个JSON对象,用于存储用户输入的电话,以便发送给服务端
              {
                extraData: {
                  "phone":this.phone,
                },
              }, (err, data) => {
              if (this.phone == '') {
                prompt.showToast({
                  message: '请填写您的电话!',
                  duration: 2000,
                  bottom:35
                });
              }else if (this.phone.length<11||this.phone.length>11){
                prompt.showToast({
                  message: '请填写正确的电话!正确号码为11位',
                  duration: 2000,
                  bottom:350,
                });
              }else {
                // @ts-ignore
                console.log(data.result);
                // @ts-ignore
                const response = JSON.parse(data.result);
                const object = response.object;
                console.log(object);

                prompt.showToast({
                  message: '验证码为:' + object.data,
                  duration: 2000,
                  bottom: 350,
                });
              }
            }
            );
          })
      }
      // @ts-ignore
      Button('登录').width(255).margin({ top: 30 })
        .onClick(()=>{

          let httpRequest = http.createHttp();

          httpRequest.request(
            // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
            "http://localhost:8082/user/loginByVerify?phone="+this.phone+"&&code="+this.code,
            {
              // method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET
              // 开发者根据自身业务需要添加header字段123
              // extraData: {
              //   "phone":this.phone,
              //   "code":this.code,
              // },
            }, (err, data) => {
            // @ts-ignore
            const response = JSON.parse(data.result);
            const code = response.code;
            console.log(code);
            if (code=='200') {
              router.pushUrl({ url: 'pages/MainPage' })
              console.info('Result:'+data.result)
            }else if (code=='400'){
              prompt.showToast({
                message: '电话输入错误(或验证码过期)',
                duration: 2000,
                bottom:350,
              });
              console.log("电话错误!")
            }else if (code=='500'){
              prompt.showToast({
                message: '验证码错误',
                duration: 2000,
                bottom:350,
              });
              console.log("验证码错误!")
            }
          }
          );
        })

      Button('普通登录').width(310).margin({ top: 20 }).onClick(()=>{
        router.pushUrl({url: 'pages/LoginPage'})
      })

    }.padding(20)
    .backgroundImage('https://img0.baidu.com/it/u=3497555920,4022296154&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=749')
    .backgroundImageSize({
      width: '100%',
      height: '100%'
    })
    .height(CommonConstants.FULL_PARENT)
    .width(CommonConstants.FULL_PARENT)
    .padding({
      left: $r('app.float.page_padding_hor'),
      right: $r('app.float.page_padding_hor'),
      bottom: $r('app.float.login_page_padding_bottom')
    })
  }
}

四、用户密码登录

『江鸟中原』鸿蒙大作业 _homonyos_03


  使用@Entry和@Component注解来定义一个页面组件LoginPage。在该组件中,使用@State注解定义了一些状态,包括message、username和password。还有一个login方法用于处理登录逻辑,以及一个imageButton方法用于构建其他登录方式的按钮。

import promptAction from '@ohos.promptAction'
import http from '@ohos.net.http'
import CommonConstants from '../common/constants/CommonConstants'
import router from '@ohos.router'

@Extend(TextInput) function inputStyle () {
  .placeholderColor($r('app.color.placeholder_color'))
  .height($r('app.float.login_input_height'))
  .fontSize($r('app.float.big_text_size'))
  .backgroundColor($r('app.color.background'))
  .width(CommonConstants.FULL_PARENT)
  .padding({ left: CommonConstants.INPUT_PADDING_LEFT })
  .margin({ top: $r('app.float.input_margin_top') })
}


@Extend(Line) function lineStyle () {
  .width(CommonConstants.FULL_PARENT)
  .height($r('app.float.line_height'))
  .backgroundColor($r('app.color.line_color'))
}


@Extend(Text) function blueTextStyle () {
  .fontColor($r('app.color.login_blue_text_color'))
  .fontSize($r('app.float.small_text_size'))
  .fontWeight(FontWeight.Medium)
}


@Entry
@Component
struct LoginPage {
  @State message: string = 'Hello World'

  @State username:string = '';
  @State password:string = '';

  login(){
    if (this.username === '' || this.password === '') {
      //   当号码或密码为空,给提示
      promptAction.showToast({
        message:'账号或密码不能为空',
        duration:500
      })
    }else {
      let httpRequest = http.createHttp();
      let url = "http://localhost:8082/user/login"
      httpRequest.request(url,{
        method:http.RequestMethod.POST,
        header:{
          'Content-Type': 'application/json'
        },
        extraData:{
          username:this.username,
          password:this.password
        },
        connectTimeout:6000
      }).then((data)=>{
        console.log(data.result.toString());
        let code = JSON.parse(data.result.toString()).code;
        let user = JSON.parse(data.result.toString()).data;
        if (code==200) {
          router.replaceUrl({
            url:'pages/MainPage',
            params:{
              user
            }
          })
        }else {
          promptAction.showDialog({
            message:data.result.toString()
          })
        }
      },(error)=>{
        promptAction.showDialog({
          message:error
        })
      })
    }
  }



  @Builder imageButton(src: Resource) {
    Button({ type: ButtonType.Circle, stateEffect: true }) {
      Image(src)
    }
    .height($r('app.float.other_login_image_size'))
    .width($r('app.float.other_login_image_size'))
    .backgroundColor($r('app.color.background'))
  }

  build() {
    Column() {
      Image("https://img1.baidu.com/it/u=2229929776,4018665174&fm=253&fmt=auto&app=138&f=PNG?w=500&h=500")
        .width($r('app.float.logo_image_size'))
        .height($r('app.float.logo_image_size'))
        .margin({ top: $r('app.float.logo_margin_top'), bottom: $r('app.float.logo_margin_bottom') })

      Text('用户登录')
        .fontSize($r('app.float.page_title_text_size'))
        .fontWeight(FontWeight.Medium)
        .fontColor($r('app.color.title_text_color'))

      TextInput({placeholder:$r('app.string.account')})
        .maxLength(CommonConstants.INPUT_ACCOUNT_LENGTH)
        .type(InputType.Number)
        .inputStyle()
        .onChange((value:string)=>{
          this.username = value
        })

      Line().lineStyle()


      TextInput({placeholder:$r('app.string.password')})
        .maxLength(CommonConstants.INPUT_PASSWORD_LENGTH)
        .inputStyle()
        .onChange((value:string)=>{
          this.password = value
        })

      Line().lineStyle()
        // Button("获取验证码").onClick(() =>{
        //   console.log('111')
        // })

      Line().lineStyle()

      Row(){

      }
      .justifyContent(FlexAlign.SpaceBetween) //设置对齐方式
      .width(CommonConstants.FULL_PARENT)
      .margin({ top: $r('app.float.forgot_margin_top') })

      Button($r('app.string.login'))
        .width(CommonConstants.BUTTON_WIDTH)
        .height($r('app.float.login_button_height'))
        .fontSize($r('app.float.normal_text_size'))
        .fontWeight(FontWeight.Medium)
        .backgroundColor($r('app.color.login_button_color'))
        .margin({ top: $r('app.float.login_button_margin_top'), bottom: $r('app.float.login_button_margin_bottom') })
        .onClick(()=>{
          this.login();
          // this.getinfo();
        })

      Button('验证码登录')
        .fontSize($r('app.float.normal_text_size'))
        .fontWeight(FontWeight.Medium)
        .onClick(() =>{
          router.pushUrl({
            url:'pages/LoginByVerify'
          })
        })
      Button('注册')
        .fontSize($r('app.float.normal_text_size'))
        .fontWeight(FontWeight.Medium)
        .onClick(() =>{
          router.pushUrl({
            url:'pages/RegisterByOne'
          })
        })


    }.width('100%')
    .backgroundImage('https://img0.baidu.com/it/u=3497555920,4022296154&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=749')
    .backgroundImageSize({
      width: '100%',
      height: '100%'
    })
    // .backgroundColor($r('app.color.background'))
    .height(CommonConstants.FULL_PARENT)
    .width(CommonConstants.FULL_PARENT)
    .padding({
      left: $r('app.float.page_padding_hor'),
      right: $r('app.float.page_padding_hor'),
      bottom: $r('app.float.login_page_padding_bottom')
    })
  }
}

五、注册页面

『江鸟中原』鸿蒙大作业 _验证码_04

import http from '@ohos.net.http';
import router from '@ohos.router';
import CommonConstants from '../common/constants/CommonConstants';
@Entry
@Component
struct RegisterByOne {
  private username: string = '';
  private password: string = '';

  build() {
    Column({ space: 12 }) {
      TextInput({ placeholder: '输入用户名' }).onChange((value: string) => {
        this.username = value;
      }).margin({ top: 20 })
      TextInput({ placeholder: '输入密码' }).onChange((value: string) => {
        this.password = value;
      }).margin({ top: 20 })
      Button('注册').width(150).margin({ top: 20 }).onClick(() => {
        let httpRequest = http.createHttp();
        httpRequest.request(
          "http://localhost:8082/user/register",
          {
            method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET
            // 开发者根据自身业务需要添加header字段
            header: {
              'Content-Type': 'application/json'
            },
            // 当使用POST请求时此字段用于传递内容
            extraData: {
              "username": this.username,
              "password": this.password
            },
          }, (err, data) => {
          if (!err) {
            console.info('Result:' + JSON.stringify(data.result));
            router.pushUrl({url:"pages/MainPage"})
          }
        }
        );

      })
      Button("去登录").onClick(() => {
        router.pushUrl({url:"pages/LoginPage"})
      })
    }
    .width('100%')
    .backgroundImage('https://img0.baidu.com/it/u=3497555920,4022296154&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=749')
    .backgroundImageSize({
      width: '100%',
      height: '100%'
    })
    .height(CommonConstants.FULL_PARENT)
    .width(CommonConstants.FULL_PARENT)
    .padding({
      left: $r('app.float.page_padding_hor'),
      right: $r('app.float.page_padding_hor'),
      bottom: $r('app.float.login_page_padding_bottom')
    })

  }
}

六、主页面

主页面用build编辑器,插入相应的组件,但是由于时间问题,只能完成注册登录,写入相应的自定义组件就能改变主页面UI和实现相应的功能。

import router from '@ohos.router';
import CommonConstants from '../common/constants/CommonConstants';
import Home from '../view/Home';
import Setting  from '../view/Setting'
@Entry
@Component
struct MainPage {
  @State message: string = 'Hello World'

  @Provide user:string = JSON.stringify(router.getParams()?.['user']);


  // 用于记录当前选中的标签页的下标(0:首页;1:我的)
  @State currentIndex:number = CommonConstants.HOME_TAB_INDEX

  private tabsController:TabsController = new TabsController();

  @Builder TabBuilder(title:string,index:number,selectedImg:Resource,normalImg:Resource){
    Column(){
      Image(this.currentIndex === index ? selectedImg:normalImg)
        .width($r('app.float.mainPage_baseTab_size'))
        .height($r('app.float.mainPage_baseTab_size'))
      Text(title)
        .margin({ top: $r('app.float.mainPage_baseTab_top') })
        .fontSize($r('app.float.main_tab_fontSize'))
        .fontColor(this.currentIndex === index ? $r('app.color.mainPage_selected') : $r('app.color.mainPage_normal'))
    }
    // 设置列控件属性
    .justifyContent(FlexAlign.Center)
    .height($r('app.float.mainPage_barHeight'))
    .width(CommonConstants.FULL_PARENT)
    .onClick(()=>{
      this.currentIndex = index; // 更新当前选中的标签页下标
      this.tabsController.changeIndex(this.currentIndex); // 通知 TabsController 切换标签页
    })

  }
  build() {
    // 绘制导航栏
    Tabs({
      barPosition:BarPosition.End,
      controller:this.tabsController
    }){
      TabContent(){  //只能放一个组件
        Home()
      }
      .padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }) // 设置边距
      .backgroundColor($r('app.color.mainPage_backgroundColor')) // 设置背景色
      .tabBar(this.TabBuilder(CommonConstants.HOME_TITLE, CommonConstants.HOME_TAB_INDEX,
        $r('app.media.home_selected'), $r('app.media.home_normal'))) // 创建首页标签页文本和图片
      TabContent(){
        Setting()
      }
      .padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }) // 设置边距
      .backgroundColor($r('app.color.mainPage_backgroundColor')) // 设置背景色
      .tabBar(this.TabBuilder(CommonConstants.MINE_TITLE, CommonConstants.MINE_TAB_INDEX,
        $r('app.media.mine_selected'), $r('app.media.mine_normal'))) // 创建设置页标签页文本和图片
    }
    .width(CommonConstants.FULL_PARENT) // 宽度占据父控件(全屏)
    .backgroundColor(Color.White) // 设置背景色为白色
    .barHeight($r('app.float.mainPage_barHeight')) // 设置标签栏高度
    .barMode(BarMode.Fixed) // 固定标签栏

  }
}