项目过程学习

Habeet

微信一键登陆

设计的知识点有微信api的使用方法

难点在于我一开始以往常见过的小程序为例子,希望同时获取到用户的姓名和头像以及手机号,结果在大量搜索后,才发现微信官方收回了获取信息的接口以及获取手机号需要企业认证的小程序,浪费了不少时间

1.前端设置按钮,并使用uni.login获取到code,然后将这个code传到后端来获取用户唯一标识openid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<template>
<view class="NavIcon">
<view class="NavIcon1" @click="QQLogin">
<image src="@\static\NavIcon1.png" style="width: 40rpx;height: 40rpx;"</image>
</view>
<view class="NavIcon2" @click="WxLogin">
<image src="@\static\NavIcon2.png" style="width: 52.8rpx;height: 55.74rpx;"></image>
</view>
</view>
</template>
<script setup>
const WxLogin = () => {
uni.login({
provider: 'weixin', //使用微信登录
success: (loginRes) => {
user.data.code = loginRes.code
uni.request({
url: url + '/user/wxLogin',
method: "POST",
data: user.data.code,
success: (res) => {
user.data.userEmail = res.data.data.openId
console.log(res.data.data.openId)
uni.request({
url: url + '/user/home',
method: "POST",
data: user.data.userEmail,
success: (res) => {
if (res.data.code != null) {
uni.redirectTo({
url: '../../pages/Login/Login'
});
} else {
uni.redirectTo({
url: '../../pages/Wx/Wx'
});
user.data.ifUpdate = 0
}
}
})
}
})
}
});
//弹出来的提示信息
uni.showToast({
icon: "none",
title: '微信登陆中...'
});
}
</script>

2.后端接收到code,并给出appId和secret到微信提供的接口返,得到penid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public RestResp<UserRespDto> wxLogin(String code) {
String authUrl="https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code";
String appId="";
String secret="";
authUrl=authUrl+"&appid="+appId+"&secret="+secret+"&js_code="+code;

String result= HttpUtil.get(authUrl);
JSONObject jsonObject= JSONUtil.parseObj(result);

String openId=jsonObject.getStr("openid");
return RestResp.ok(UserRespDto.builder()
.openId(openId)
.build());
}

用户上传图片并回显

涉及的知识点有java后端文件上传服务器的操作,以及将文件存储为二进制流进入数据库,而后在前端再通过转化来回显文件

难点在于一开始我的思路是将文件上传到服务器之后,直接通过链接来访问,但是因为我是前后端分离的项目,而且需要使用合法域名,这点无法实现

1.用户选择图片需要一个选择框,这里使用了微信小程序自带的按钮(open-type=”chooseAvatar” 可以获取用户的微信头像,@chooseavatar则是选中后触发的方法),并嵌套一个图片

1
2
3
4
5
6
7
8
<template>
<view class="SignI">
<text>头像</text>
<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image :src="state.avatarUrl" style="width: 100rpx;height: 100rpx;" />
</button>
</view>
</template>

2.用户选择好图片后触发chooseavatar,然后在uploadFile()方法里上传微信返回的临时链接,其中uni.uploadFile将链接转化为文件传给后端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script setup>
const onChooseAvatar = (e) => {
state.avatarUrl = e.detail.avatarUrl;
uploadFile()
}
const uploadFile = () => {
uni.uploadFile({
url: url + '/user/uploadFile', //后台接口
filePath: state.avatarUrl, // 上传图片 url
name: 'file',
// formData: this.formData,
header: {
'content-type': 'multipart/form-data'
}, // header 值
success: (res) => {
const responseData = JSON.parse(res.data); // 解析JSON字符串为对象
user.data.picData = responseData.data.picData
state.avatarUrl = `data:image/jpeg;base64,${user.data.picData}`//转化为链接
},
});
}
</script>

3.后端实现层使用MultipartFile[]类接收前端传来的文件,转换为二进制数据流并存入数据库,然后把文件存入服务器指定的位置上(突然发现其实可以不用存入服务器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Override
public RestResp<UserRespDto> uploadFile(MultipartFile[] files) {
String filePath=null;
String fileName;
String filePathAll=null;
byte[] imageData=null;
// 遍历上传的多个文件
for (MultipartFile file : files) {
// 生成文件名:userEmail.jpg
fileName = userEmailAll+ "." + "jpeg";

// 生成文件保存路径
filePath = serverRootPath + fileName;

try {
// 将图片转换为二进制数据流(注意这个语句要先于transferTo,否则获取不到文件)
imageData = file.getBytes();
// 将文件保存到服务器指定目录
file.transferTo(new File(filePath));


// 将二进制数据流存入数据库
QueryWrapper<User>queryWrapper=new QueryWrapper<>();
queryWrapper.eq("user_email",userEmailAll);

User user = new User();
user.setPicData(imageData);
userDao.update(user,queryWrapper);


} catch (IOException e) {
e.printStackTrace();
// 处理文件上传失败的情况
System.out.println("文件上传失败");
return null;
}
}

// 处理文件上传成功的情况
return RestResp.ok(UserRespDto.builder().picData(imageData).build());
}

4.前端收到picData的数据开始回显图片(success的后半部分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script setup>
const onChooseAvatar = (e) => {
state.avatarUrl = e.detail.avatarUrl;
uploadFile()
}
const uploadFile = () => {
uni.uploadFile({
url: url + '/user/uploadFile', //后台接口
filePath: state.avatarUrl, // 上传图片 url
name: 'file',
// formData: this.formData,
header: {
'content-type': 'multipart/form-data'
}, // header 值
success: (res) => {
const responseData = JSON.parse(res.data); // 解析JSON字符串为对象
user.data.picData = responseData.data.picData
state.avatarUrl = `data:image/jpeg;base64,${user.data.picData}`//转化为链接
},
});
}
</script>