使用鸿蒙制作简易应用
目录写在前面
核心代码
前端(鸿蒙)
登录
LoginPage.ets
HttpUtil.ets
ReqUtil.ets
标签页
TabsPage.ets
首页
GridPage.ets
MyGrid.ets
待办
TodoPage.ets
ItemComponent.ets
TaskDataModel.ets
我的
ListPage.ets
MyList.ets
后端(使用Springboot)
Entity
User.java
Controller
LoginController.java
Mapper
UserMapper.java
UserMapper.xml
Service
LoginService.java
LoginServiceImpl.java
Common
AppFinal.java
ResponseBody.java
‘效果预览
登录页面
首页
待办
我的
写在前面
学习鸿蒙时尝试编写的一个简易应用,记录下实现的代码。
核心代码
前端(鸿蒙)
登录
LoginPage.ets
import { getData } from '../utils/HttpUtil'
import { loginUrl } from '../utils/ReqUtil'
import router from '@ohos.router';
@Entry
@Component
struct LoginPage{
@State message: string = 'Hello World'
loginData: any = {
username: '',
password: ''
}
build() {
Column(){
Image($r('app.media.logo')).width(90).margin({ top: 110 })
Text('登录界面').fontSize(30).fontWeight(800).margin({ top: 20 })
Text('登录账号以使用更多服务').fontColor('rgb(153,148,148)').margin( {top: 10 })
TextInput({ placeholder: '账号' }).margin({ top: 50 })
.onChange((value) => {
this.loginData.username = value;
})
TextInput({ placeholder: '密码' }).margin({ top: 15 })
.onChange((value) => {
this.loginData.password = value;
})
Row(){
Text("短信验证码登录").fontColor('rgb(0, 125, 254)')
Text("忘记密码").fontColor('rgb(0, 125, 254)')
}.width('100%').margin({ top: 10 }).justifyContent(FlexAlign.SpaceBetween)
Button('登录').width('100%').margin({ top: 80 })
.onClick(() =>{
//获取账号密码
console.log(JSON.stringify(this.loginData));
//发起请求
getData(loginUrl, this.loginData).then(res => {
if(res != -1) {
//登录成功
//将res里面的用户数据保存到缓存
//跳转到首页
router.pushUrl({url: 'pages/TabsPage'})
}
})
})
Text('注册账号').fontColor('rgb(0,125,254)').margin({ top: 10 })
Text('其他登录方式').fontColor('rgb(153,148,148)').margin({ top: 60 })
Row(){
Image($r('app.media.login_method1')).width(60)
Image($r('app.media.login_method2')).width(60)
Image($r('app.media.login_method3')).width(60)
}.width('100%').margin({ top: 15}).justifyContent(FlexAlign.SpaceEvenly)
}.width('100%').height('100%').padding(20)
}
}
HttpUtil.ets
//弹窗模块
import promptAction from '@ohos.promptAction';
//1.引入http模块
import http from '@ohos.net.http';
//url常量
const BASE_URL: string = 'http://localhost:8080'
//封装函数,参数:url(请求地址),发送的数据:data
export const getData = (url: string, data?: any) => {
//拼接请求接口
url = BASE_URL + url;
//2.创建请求
let httpRequest = http.createHttp();
//3.订阅请求头
httpRequest.on('headerReceive', (header) => {
console.log(JSON.stringify(header));
})
//4.发起请求
let promise = httpRequest.request(url, {
//请求方式
method: http.RequestMethod.POST,
//连接超时时间
connectTimeout: 20000,
//读取超时时间
readTimeout: 20000,
//添加请求头
header: {
'Content-type': 'application/json',
'Token': 'dwiaojdoiwjio32131'
},
//发送的数据
extraData: data
});
//5.处理相应内容
return promise.then((value: any) => {
//判断请求是否成功
if(value.responseCode == 200) {
//请求成功
//业务逻辑
let res = `${value.result}`;
let resData = JSON.parse(res);
//业务逻辑状态码:根据自己的后端返回值来判断
if(resData.status == 200) {
//console.log('200');
return resData;
} else {
//console.log('-1');
//提示用户
promptAction.showToast({
message: resData.message, //message为后端返回的信息
duration: 2000,
bottom: 400
})
return -1;
}
console.log(resData.status)
console.log(res);
}
})
}
ReqUtil.ets
export const loginUrl: string = '/login/login'; //登录接口
标签页
TabsPage.ets
import { GridPage } from '../pages/GridPage'
import { ListPage } from'../pages/ListPage'
import { TodoPage } from './TodoPage';
@Entry
@Component
struct TabsPage{
@State message: string = 'Hello World'
//页签控制器
private tabController: TabsController = new TabsController();
//用户当前选择的页签下标
@State currentIndex: number = 0;
//页签按钮构造器
@Builder tabBuilder(title: string, index: number, selectImage: Resource, normalImage: Resource){
Column(){
//图片,如果当前下标和用户选择的下标一致:显示被选中的图片,否则:未被选中的图片
Image(this.currentIndex == index ? selectImage : normalImage).width(25)
//文字,如果当前下标和用户选择的下标一致:显示被选中的文字颜色,否则:未被选中的文字颜色
Text(title).fontColor(this.currentIndex == index ? 'rgb(1,124,254)' : 'rgb(200,200,200)')
}.width('100%').height(40)
}
build() {
Tabs({ barPosition: BarPosition.End, index:0, controller: this.tabController}) {
//首页
TabContent() {
/*Column() {
}.width('100%').height('100%').backgroundColor('rgb(81,198,224)')*/
GridPage();
}.tabBar(this.tabBuilder('首页', 0, $r('app.media.home_selected'), $r('app.media.home_normal')))
//待办
TabContent() {
/*Column() {
}.width('100%').height('100%').backgroundColor('rgb(147,228,75)')*/
TodoPage()
}.tabBar(this.tabBuilder('待办', 1, $r('app.media.discover_selected'), $r('app.media.discover_normal')))
//我的
TabContent() {
/*Column() {
}.width('100%').height('100%').backgroundColor('rgb(218,121,114)')*/
ListPage()
}.tabBar(this.tabBuilder('我的', 2, $r('app.media.mine_selected'), $r('app.media.mine_normal')))
}
.onChange((index) => {
//console.log(index + "")
//下标赋值给当前用户选择的下标
this.currentIndex = index;
})
}
}
首页
GridPage.ets
import { MyGrid } from '../components/MyGrid';
@Component
export struct GridPage{
@State message: string = 'Hello World'
//定义数据
dataArray: object[] = [
{text:'我的最爱', image: $r('app.media.love')},
{text:'历史记录', image: $r('app.media.record')},
{text:'消息', image: $r('app.media.news')},
{text:'购物车', image: $r('app.media.shopping')},
{text:'我的目标', image: $r('app.media.target')},
{text:'圈子', image: $r('app.media.circle')},
{text:'收藏', image: $r('app.media.favorite')},
{text:'回收站', image: $r('app.media.storage')},
]
build() {
Column() {
//标题
Text('首页').fontSize(40).fontWeight(FontWeight.Bold).width('100%')
//网格布局按钮
Grid(){
//循环渲染
ForEach(this.dataArray, (item) => {
GridItem(){
MyGrid({text: item.text, image: item.image})
}
})
}.columnsTemplate('1fr 1fr 1fr 1fr').rowsTemplate('1fr 1fr').columnsGap(20).rowsGap(20)
.backgroundColor(Color.White).height(150).borderRadius(30).margin({ top: 20 }).padding(15)
}.width('100%').height('100%').padding(20).backgroundColor('rgb(245,241,240)')
}
}
MyGrid.ets
@Component
export struct MyGrid{
private text: string; //菜单名称
private image: Resource; //图片资源
build() {
Column(){
Image(this.image).width(30)
Text(this.text).fontSize(14).margin({ top: 5 })
}
}
}
待办
TodoPage.ets
importItemComponentfrom '../components/ItemComponent'
import { TaskDataModel } from '../components/TaskDataModel'
@Component
export struct TodoPage {
private totalData: Array<string> = [] //待办列表所有的数据
aboutToAppear() { // 初始化数据
this.totalData = new TaskDataModel().getData()
}
build() {//构建入口的UI界面
Column({ space : 6} ) {
Text('待办')
.fontSize(28)
.lineHeight(33)
.fontWeight(FontWeight.Bold)
.width('80%')
.margin({
top: 24,
bottom: 12
})
.textAlign(TextAlign.Start)
//循环渲染
ForEach(this.totalData, (item: string) =>{
ItemComponent({ task_content: item })
})
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
ItemComponent.ets
importItemComponentfrom '../components/ItemComponent'
import { TaskDataModel } from '../components/TaskDataModel'
@Component
export struct TodoPage {
private totalData: Array<string> = [] //待办列表所有的数据
aboutToAppear() { // 初始化数据
this.totalData = new TaskDataModel().getData()
}
build() {//构建入口的UI界面
Column({ space : 6} ) {
Text('待办')
.fontSize(28)
.lineHeight(33)
.fontWeight(FontWeight.Bold)
.width('80%')
.margin({
top: 24,
bottom: 12
})
.textAlign(TextAlign.Start)
//循环渲染
ForEach(this.totalData, (item: string) =>{
ItemComponent({ task_content: item })
})
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
}
}
TaskDataModel.ets
export class TaskDataModel {
private tasks: Array<string> = [
"早起晨练",
"准备早餐",
"阅读名著",
"学习ArkTS",
"看剧放松"
]
getData(): Array<string> {
return this.tasks
}
}
我的
ListPage.ets
import { MyList } from '../components/MyList'
@Component
export struct ListPage{
@State message: string = 'Hello World'
//数据数组
dataArray: object[] = [
{text:'推送通知', image: $r('app.media.news')},
{text:'数据管理', image: $r('app.media.data')},
{text:'菜单设置', image: $r('app.media.menu')},
{text:'关于', image: $r('app.media.about')},
{text:'清除缓存', image: $r('app.media.storage')},
{text:'隐私协议', image: $r('app.media.privacy')},
]
build() {
Column() {
//标题
Text('我的').fontSize(40).fontWeight(FontWeight.Bold).width('100%')
//个人信息
Row() {
Image($r('app.media.account')).width(50).margin({ left: 20 })
Column(){
Text('李先生').fontSize(25).fontWeight(800)
Text('2471004754@qq.com').fontColor('rgb(120,120,120)')
}.alignItems(HorizontalAlign.Start).margin({ left: 15 }).height(60).justifyContent(FlexAlign.SpaceBetween)
}.width('100%').height(100).backgroundColor(Color.White).margin({ top: 40 }).borderRadius(30)
//菜单栏
Column() {
List({ space: 20 }) {
//循环渲染
ForEach(this.dataArray, (item) => {
ListItem(){
MyList({text: item.text, image: item.image});
}
})
}.divider({ strokeWidth : 2, color: 'rgb(238,238,238)'})
}.width('100%').height(400).backgroundColor(Color.White).borderRadius(30).margin({ top: 30 }).padding(20)
}.width('100%').height('100%').backgroundColor('rgb(245,241,240)').padding(20)
}
}
MyList.ets
@Component
export struct MyList{
private text: string; //菜单名称
private image: Resource; //菜单图片
build() {
Row(){
Row(){
//图片,菜单名称
Image(this.image).width(30)
Text(this.text).margin({ left: 10 }).fontSize(20)
}
//向右的箭头
Image($r('app.media.right_grey')).width(20)
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
}
}
后端(使用Springboot)
Entity
User.java
package com.example.loginproject.entity;
import lombok.Data;
@Data
public class User {
private Integer id;
private String username;
private String password;
}
Controller
LoginController.java
package com.example.loginproject.controller;
import com.example.loginproject.common.AppFinal;
import com.example.loginproject.common.ResponseBody;
import com.example.loginproject.entity.User;
import com.example.loginproject.mapper.UserMapper;
import com.example.loginproject.service.LoginService;
import com.sun.net.httpserver.HttpServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/login")
public class LoginController{
@Resource
private UserMapper userMapper;
@RequestMapping("/login")
public ResponseBody<User> login(@RequestBody User user,
HttpServletRequest request) {
User userInfo = userMapper.login(user.getUsername(), user.getPassword());
int status = 400;
String message = "用户或密码错误!";
if (userInfo != null && userInfo.getId() > 0) {
// 登录成功
status = 200;
message = "success";
// 将用户对象存储到 session 中
HttpSession session = request.getSession();
session.setAttribute(AppFinal.USERINFO_SESSION_KEY, userInfo);
}
return new ResponseBody<>(status, message, userInfo,-1);
}
}
Mapper
UserMapper.java
package com.example.loginproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.loginproject.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
public User login(String username, String password);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.loginproject.mapper.UserMapper">
<select id="login" resultType="com.example.loginproject.entity.User">
select * from user where username=#{username} and password=#{password}
</select>
</mapper>
Service
LoginService.java
package com.example.loginproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.loginproject.entity.User;
public interface LoginService extends IService<User> {
}
LoginServiceImpl.java
package com.example.loginproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.loginproject.entity.User;
import com.example.loginproject.mapper.UserMapper;
import com.example.loginproject.service.LoginService;
import org.springframework.stereotype.Service;
@Service
public class LoginServiceImpl extends ServiceImpl<UserMapper, User> implements LoginService {
}
Common
AppFinal.java
package com.example.loginproject.common;
public class AppFinal {
// userinfo 存放到 session 中的 key
public static final String USERINFO_SESSION_KEY = "USERINFO_SESSION_KEY";
public static final String TERM_SESSION_KEY = "TERM_SESSION_KEY";
}
ResponseBody.java
package com.example.loginproject.common;
import lombok.Data;
@Data
public class ResponseBody<T> {
private int status;//code-200success-400failure
private String message;//msg-success-failure
private T data;//data
private Long total;//records count,无效用-1表示
public ResponseBody(int status, String message, T data,long total) {
this.status = status;
this.message = message;
this.data = data;
this.total = total;//records count
}
}
‘效果预览
登录页面
https://i-blog.csdnimg.cn/direct/487ce89ab97e422d8af75fbf3403374f.png
该页面只实现了登录功能,其他功能暂未实现。
https://i-blog.csdnimg.cn/direct/027d3bc6844249b1b6da06dba1498390.png
登录成功后跳转至首页。
首页
https://i-blog.csdnimg.cn/direct/59682e944038418a8804e1045181a4bf.png
仅实现了页面展示。
待办
https://i-blog.csdnimg.cn/direct/2293e1c3ef9c4a899b80ea5e3400457f.png
点击后可以标记已办
https://i-blog.csdnimg.cn/direct/9fe8c035422a42a9ad0904aa2b1a5121.png
再次点击重置
https://i-blog.csdnimg.cn/direct/288f03929e21412cb4c894a09fe43296.png
我的
https://i-blog.csdnimg.cn/direct/7e871dc804e0457f87dd711355d89563.png
仅实现了页面展示。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]