一、引言
在当今数字化时代,电子商务已经成为商业领域中不可或缺的一部分。随着移动互联网的快速发展和技术的不断创新,构建高效、安全且用户友好的电子商务系统变得尤为重要。为了满足用户对更优质在线购物体验的需求,本项目选择使用鸿蒙ArkTs语言,旨在开发一款功能丰富的商城系统。
本商城系统的核心目标是实现用户注册和登录功能,为用户提供便捷的账户管理体验。通过充分利用鸿蒙ArkTs语言的特性,我们将设计和实现一个具有高度可扩展性、安全性和灵活性的系统,以满足现代电商的各种需求。
二、项目框架
主要实现的功能有
1、用户验证码登录
2、用户密码登录
3、注册页面
4、商城主页面
三、用户验证码登录页面
实现功能为提供几个组件和文本来达到能输入数据的效果,然后插入合适的图片来美化注册的效果,验证码实现为使用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')
})
}
}
四、用户密码登录
使用@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')
})
}
}
五、注册页面
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) // 固定标签栏
}
}