鸿蒙期末项目(2)

主界面

主界面和商店详情界面参考如下设计图(灵感严重匮乏)

img

简单起见,将整个app分为4个布局,分别是主界面、搜索界面、购物车界面,以及个人界面。

所以在app中也需要使用tab组件进行分割,且需要通过tabBar方法设置底部导航栏

Tabs({
    barPosition: BarPosition.End,
    controller: this.tabsController,
}) {
    TabContent() {
        HomeView()
    }
    .tabBar(this.TabBuilder(
        'Home',
        CommentConstant.HOME_TAB_INDEX,
        CommentConstant.HomeIconActive,
        CommentConstant.HomeIconNormal
    ))
​
    TabContent() {
        SearchView()
    }
    .tabBar(this.TabBuilder(
        'Search',
        CommentConstant.SEARCH_TAB_INDEX,
        CommentConstant.SearchIconActive,
        CommentConstant.SearchIconNormal
    ))
​
    TabContent() {
        CartView()
    }
    .tabBar(this.TabBuilder(
        'Cart',
        CommentConstant.CART_TAB_INDEX,
        CommentConstant.CartIconActive,
        CommentConstant.CartIconNormal
    ))
​
    TabContent() {
        ProfileView()
    }
    .tabBar(this.TabBuilder(
        'Profile',
        CommentConstant.PROFILE_TAB_INDEX,
        CommentConstant.ProfileIconActive,
        CommentConstant.ProfileIconNormal
    ))
}

导航栏样式的设置:

@State currentIndex: number = CommentConstant.HOME_TAB_INDEX;
private tabsController: TabsController = new TabsController();
​
@Builder
TabBuilder(title: string, index: number, selectIcon: ResourceStr, normalIcon: ResourceStr) {
    Column() {
        Image(this.currentIndex === index ? selectIcon : normalIcon)
            .width('25vp')
            .height('25vp')
​
        Text(title)
            .margin({ top: '4vp' })
            .fontSize('10fp')
            .fontColor(this.currentIndex === index ? '#e76b7a' : '#6b6b6b')
    }
    .justifyContent(FlexAlign.Center)
        .height('56vp')
        .width('100%')
        .onClick(() => {
        this.currentIndex = index;
        this.tabsController.changeIndex(index)
    })
}

即可实现如下效果

随后开始编写四个页面组件

根据页面图,整个页面分为五个部分,分别为头部位置信息和通知选项、广告栏、热门标签栏、今日推荐栏、著名品牌栏,由于五个组件仅会在主页面中使用,所以可以使用@Builder创建组件函数在主页面组件中函数式声明,简单快捷且不需要额外import,灰常好用~

由于主页面需要放下的内容过多导致一页不能放下,考虑使用Scroll滚动布局,当子节点高度超过时自动加滚动条,同时需要设置

.align(Alignment.TopStart)

保证子节点从顶部开始排列

其中在实现下面这个卡片的样式时,可以看到卡片是有四个方向的圆角的,但是如果直接放图片,图片会将上方的两个圆角覆盖住,这个时候可以使用.clip(true) 属性,意为沿边缘裁剪,即可达到下面这种效果。

实现效果如下:

Web服务器搭建和数据持久化

到目前位置,本项目的所有数据都是保存在内存中的,仅作外观测试使用,而没有实际作用。

那么如何实现数据持久化呢?

鸿蒙提供了数据库接口,其可以方便地通过一系列配置和方法读取或修改数据库中的数据。然而,使用这种方法却存在一个问题,数据库文件保存在用户本地,既无数据来源,也无法实时更新。所以更好的解决方法应当是建立服务器,客户端通过调用 api 的方式从服务器的数据库中获取数据。

所以现在项目迫切需要搭建一个javaweb服务器。

根据点餐app需求分析,可以大致抽象出如下几个数据表(使用mysql数据库)。

用户表 user

属性列描述
email邮箱
phone电话
id编号
username用户名
password密码

商店表 store

属性列描述
id编号
storeName商店名
address地址
phone电话
intro介绍
score评分
open目前是否营业
cover店铺封面
logo店铺logo
special特殊性 0-无 1-著名 2-TopRated

菜品表 dish

属性列描述
id编号
sid所属商铺编号
dishName菜名
intro介绍
price价格
discount折扣
catalog所属分类

标签表 tags

属性列描述
id编号
tagName标签名

菜品-标签表 dt

属性列描述
Did菜品编号
Tid标签标号

订单表 orders

属性列描述
id订单号
time付款时间
uid用户
price总额
state订单状态 0-待支付 1-送餐中 2-已取消 3-已完成 4-已过期
sid消费商店

订单-菜表 od

属性列描述
oid订单号
Did菜号
number选菜数量

使用sql建表

use pigdelivery;
​
create table user (
    email varchar(2048) not null,
    id int auto_increment primary key ,
    username varchar(30) not null,
    password double not null
);
​
create table store(
    id int auto_increment primary key ,
    storeName varchar(50) not null,
    intro varchar(100) not null,
    score double not null,
    open bit not null,
    cover varchar(2048) not null,
    logo varchar(2048) default 'defaultLogo.jpg',
    special int default 0 not null
);
​
create table dish(
    id int auto_increment primary key ,
    sid int not null,
    dishName varchar(50) not null,
    intro varchar(100) not null,
    price double not null,
    discount double not null,
    catalog varchar(30) not null,
    foreign key (sid) references store(id)
);
​
create table tags(
    id int auto_increment primary key ,
    tagName varchar(30) not null
);
​
create table dt(
    Did int not null,
    Tid int not null,
    foreign key (Did) references dish(id),
    foreign key (Tid) references tags(id)
);
​
create table orders(
    id int auto_increment primary key ,
    time varchar(30),
    uid int not null,
    price double not null,
    state int not null,
    sid int not null,
    foreign key (uid) references user(id),
    foreign key (sid) references store(id)
);
​
create table od(
    Oid int not null,
    Did int not null,
    number int not null,
    foreign key (Oid) references orders(id),
    foreign key (Did) references dish(id)
);

建表完成后,填入一些商店数据用于测试。


数据库建立完成后,接下来开始写Javaweb,javaweb就很好写了,按照流程一步一步来就好,这里仅仅简单地概述一下步骤:

使用Tomcat10.1.24构建服务器,通过JavaWeb编写Servlet,并使用mybatis框架连接数据库。

首先新建一个Jakarta EE项目

通过maven导入依赖的jar包,在资源目录下新建 mybatis-config.xml 用作mybatis配置文件,并按照mybatis配置文件格式填写该xml

随后写相应的Mapper接口和实体类(省略)

以登入接口为例,写一个doPost

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    EvalTran.evalJSON(req, resp);
​
    if(req.getParameter("email") != null && req.getParameter("password") != null) {
        try {
            double password = Double.parseDouble(req.getParameter("password"));
            String email = req.getParameter("email");
            User user = UserLoader.selectUser(email, password);
            if(user != null) {
                resp.getWriter().write(gson.toJson(Response.success("success")));
            } else {
                resp.getWriter().write(gson.toJson(Response.success("user not exist")));
            }
        } catch (NumberFormatException e) {
            resp.getWriter().write(gson.toJson(Response.badRequest("参数不合法")));
        }
    } else {
        resp.getWriter().write(gson.toJson(Response.badRequest("表单数据不完整")));
    }
}

javaWeb程序写好之后,回到DevEco Studio中尝试调用该url

在DevEco Studio中打开Terminal终端执行指令 npm install axios 安装axios

在model目录下编写LoginModel类

import axios from '@ohos/axios';
​
class LoginModel {
    readonly baseUrl = 'http://localhost:8080/PigDeliveryServer_war_exploded'
​
    // 当返回 0 表示登入失败, 否则返回一个数字代表登入成功后的用户id
    async verifyAccount(email: string, password: string): Promise<number> {
        return await axios.post(
            this.baseUrl + '/login',
            {
                email: email,
                password: password,
            }
        )
            .then((resp) => {
                console.log(resp.data.message + '');
            // 下面使用双等号的原因是json传输是数字类型可能会被转成字符串类型
                if(resp.data.code == 200 && resp.data.message == 'success') {
                    return parseInt(resp.data.code);
                } else {
                    return 0;
                }
            })
            .catch((error) => {
                console.log("error: " + error);
                return 0;
            })
    }
}
​
export default new LoginModel() as LoginModel;

回到之前编写的登入界面,当时为了测试登入界面,将登入按钮设计成点击就可以登入,现在,我们尝试将点击事件改成真实有效的验证方式:

Button('LogIn')
    .regButton()
    .onClick(() => {
    loginModel.verifyAccount(this.emailInput, this.passwordInput)
        .then((data) => {
        if(data === 0) {
            AlertDialog.show({
                message: '用户不存在或密码错误',
            })
        } else {
            CommentConstant.userId = data;
            router.replaceUrl({
                url: 'pages/MainPage',
            })
        }
    })
})

当点击登入按钮中,期望中进入主界面的效果并没有实现,而是出现了密码错误的提示,将服务器返回值输出后,控制台输出:

success表示服务器收到了请求,但是参数没有传递过去。

在服务器端doPost方法中编写如下代码:

BufferedReader reader = new BufferedReader(req.getReader());
StringBuilder stringBuilder = new StringBuilder();
while (reader.ready()) {
    stringBuilder.append(reader.readLine());
}
​
String json = stringBuilder.toString();
System.out.println(json);

再次请求,结果如下

ArkTs 中的 axios 直接将data中的数据以 json 字符串的形式发给了服务器,所以在服务器中还要对json的情况做处理

BufferedReader reader = new BufferedReader(req.getReader());
StringBuilder stringBuilder = new StringBuilder();
while (reader.ready()) {
    stringBuilder.append(reader.readLine());
}

String json = stringBuilder.toString();
UserTemp userTemp = gson.fromJson(json, UserTemp.class);

if(userTemp == null || userTemp.getEmail() == null || userTemp.getPassword() == null) {
    resp.getWriter().write(gson.toJson(Response.badRequest("表单数据不完整")));
} else {
    User user = UserLoader.verifyUser(userTemp.getEmail(), userTemp.getPassword());
    if(user != null) {
        resp.getWriter().write(gson.toJson(Response.success("success", String.valueOf(user.getId()))));
    } else {
        resp.getWriter().write(gson.toJson(Response.success("userNotExist")));
    }
}

改变之后,鸿蒙端测试登入成功。

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【资源说明】 1.项目代码均经过功能验证ok,确保稳定可靠运行。欢迎下载使用体验! 2.主要针对各个计算机相关专业,包括计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师、企业员工。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。在使用过程中,如有问题或建议,请及时沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 【项目介绍】 基于HarmonyOS和SpringBoot开发的扫码点餐平台app源码(含后端)+项目说明(可作毕设).zip 介绍 手机鸿蒙端的扫码点餐app,大学毕设项目 软件架构 采用前后端分离架构,前端为鸿蒙手机app,后端为springboot+mybatis 扫码采用Zxing框架 注 服务端提供了很多接口,包括用户端与商家端。 基于HarmonyOS和SpringBoot开发的扫码点餐平台app源码(含后端)+项目说明(可作毕设).zip基于HarmonyOS和SpringBoot开发的扫码点餐平台app源码(含后端)+项目说明(可作毕设).zip基于HarmonyOS和SpringBoot开发的扫码点餐平台app源码(含后端)+项目说明(可作毕设).zip基于HarmonyOS和SpringBoot开发的扫码点餐平台app源码(含后端)+项目说明(可作毕设).zip基于HarmonyOS和SpringBoot开发的扫码点餐平台app源码(含后端)+项目说明(可作毕设).zip
根据提供的引用内容,我无法直接提供完整的JavaScript期末项目的源码。但是,我可以为您提供一些关于JavaScript期末项目的一般介绍和示例。 JavaScript期末项目通常要求学生设计和开发一个具有交互性和动态功能的网页。这些项目可以涉及使用HTML、CSS和JavaScript来创建各种功能,例如表单验证、动画效果、数据展示等。 以下是一个简单的JavaScript期末项目示例,用于创建一个基本的网页表单验证功能: ```html <!DOCTYPE html> <html> <head> <title>表单验证</title> <script> function validateForm() { var name = document.forms["myForm"]["name"].value; var email = document.forms["myForm"]["email"].value; if (name == "") { alert("请输入姓名"); return false; } if (email == "") { alert("请输入电子邮件"); return false; } } </script> </head> <body> <h1>表单验证</h1> <form name="myForm" onsubmit="return validateForm()"> <label for="name">姓名:</label> <input type="text" id="name" name="name"><br><br> <label for="email">电子邮件:</label> <input type="email" id="email" name="email"><br><br> <input type="submit" value="提交"> </form> </body> </html> ``` 在这个示例中,我们创建了一个简单的表单,要求用户输入姓名和电子邮件。然后,使用JavaScript编写了一个函数`validateForm()`来验证表单数据。如果姓名或电子邮件为空,将弹出警告框并阻止表单提交。 这只是一个简单的示例,JavaScript期末项目可以更加复杂和有创意。您可以根据自己的兴趣和要求来设计和开发一个独特的项目

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值