效果如图:
最近因为做微信小程序的授权登录找了很多办法,也试了很多次,我这个人又懒,想要又简便、又能一次性拿全图片、昵称、手机号的方法,最好是那种不用写样式,就和那些app的漂亮登录页面一样。但很无奈,没有。
所以我也懒得写太复杂的,但这个写法呢,最基本的也都拿得到。
获取用户信息
原本呢通过uni.getUserInfo可以拿到用户信息,但这个方法已经被废弃了,取而代之的是uni.getUserProfile,但这个方法也很无语只会给你返回一个空白头像,然后昵称是微信用户,就没什么用。
最后还是采用的button按钮来获取手机号和用户昵称头像。记得一定要通过 form 中form-type
为submit
的button 组件收集用户输入的内容,这是最方便的。
<template>
<view>
<view class="loginLogo">
<form @submit="onSubmit(true, $event)" class="loginContent">
<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image class="avatar"
:src="formData.avatarUrl?formData.avatarUrl:'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'">
</image>
<text class="loginLogoText" v-if="isShow">授权头像</text>
</button>
<view class="nameContent">
<view class="title">昵称</view>
<input name="nickName" type="nickname" placeholder="请填写昵称" class="weui-input"
v-model="formData.nickName" />
</view>
<view class="loginBtn">
<button class="btn" form-type="submit" open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber">手机号一键登录</button>
</view>
</form>
</view>
</view>
</template>
通过将按钮上的open-type设置成对应的值,这个详见uniapp文档,然后获取头像和昵称以及返回的手机号信息。
至于返回的手机号信息是这样的:
临时头像链接持久化
但这个时候返回的头像链接是一个临时地址,就是这样 “ http://tmp/DhHcXSBdrHO045fe3561f0149fc8b6a58b175a5ca0af.jpeg ”,在浏览器根本打不开,很快就失效了,根本无法保存。
试过编译成base64再来转,但失败了。最后发现可以用uni.uploadFile方法将这个临时链接转成文件流传给后端,以此上传至服务器,生成永久链接并返回前端,这样就不会出现失效的情况了。
//头像图片持久化
uploadImage(url1) {
//uni.uploadFile将微信返回的临时地址转成文件流传输给后端,从而上传服务器,拿到永久地址
uni.uploadFile({
url: `https://qmhlsby.qmhls.com/nine/getImgUrl`,
filePath: url1,
name: 'file',
header: {
'content-type': 'application/x-www-form-urlencoded',
},
formData: {
'user': this.formData.nickName
},
success: (uploadFileRes) => {
this.formData.avatarUrl = JSON.parse(uploadFileRes.data).data;
//进入登录流程
this.uniLogin();
}
});
}
全部代码我放下面,请君一观。
全部代码如下
<!-- 登录页面 -->
<template>
<view>
<view class="loginLogo">
<form @submit="onSubmit(true, $event)" class="loginContent">
<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image class="avatar"
:src="formData.avatarUrl?formData.avatarUrl:'https://qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'">
</image>
<text class="loginLogoText" v-if="isShow">授权头像</text>
</button>
<view class="nameContent">
<view class="title">昵称</view>
<input name="nickName" type="nickname" placeholder="请填写昵称" class="weui-input"
v-model="formData.nickName" />
</view>
<view class="loginBtn">
<button class="btn" form-type="submit" open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber">手机号一键登录</button>
</view>
</form>
</view>
</view>
</template>
<script>
import {
appletLogin,
appletPhone,
nineSelect
} from "@/api/index.js";
import {
mapState,
mapMutations
} from 'vuex';
export default {
data() {
return {
iv: "",
encryptedData: '',
phoneNum: "",
openId: '',
formData: {
nickName: '',
avatarUrl: ''
},
isShow: true,
token: ""
}
},
computed: {
...mapState(['userInfo']),
},
watch: {
formData: {
handler(newVal, oldValue) {
if (newVal.avatarUrl) {
this.isShow = false;//监测isShow,如果授权头像了就隐藏 授权头像 字样
}
},
deep: true,
immediate: true
}
},
methods: {
...mapMutations(['updateUserAllInfo']),
updateUserAllInfoData(v) {
this.updateUserAllInfo(v);
},
//获取微信头像
onChooseAvatar(e) {
this.formData.avatarUrl = e.detail.avatarUrl;
console.log("eeee", e.detail);
},
onSubmit(confirm, event) {
if (confirm) {
try {
let {
nickName
} = event.detail.value;
this.formData.nickName = nickName;
} catch (e) {
//TODO handle the exception
uni.showToast({
icon: 'none',
title: e.message
});
return;
}
}
},
// 微信获取手机号信息
getPhoneNumber(data) {
if (this.formData.avatarUrl && this.formData.nickName) {
//微信小程序返回的相关数据
this.iv = data.detail.iv;
this.encryptedData = data.detail.encryptedData;
uni.showToast({
title: '登录中',
icon: 'loading',
duration: 1000,
});
//处理头像链接
this.uploadImage(this.formData.avatarUrl);
} else {
uni.showToast({
title: `请选择头像或输入昵称~`,
icon: 'none'
});
}
},
uniLogin() {
uni.login({
provider: 'univerify',
success: res => {
console.log(res)
console.log("头像和昵称---", this.formData.avatarUrl, this.formData.nickName);
//请求后台,获取openId
uni.request({
url: `https://qmhly.hls.com/nine/appletLogin`,
method: 'POST',
data: {
code: res.code,
nickName: this.formData.nickName,
avatarUrl: this.formData.avatarUrl
},
dataType: 'json',
sslVerify: false,
success: (res1) => {
console.log("用户登录返回数据----", res1.data.data);
this.openId = res1.data.data.openId;
this.token = res1.data.data.user.access_token;
let params = {
sessionKey: res1.data.data.sessionKey,
iv: this.iv,
encryptedData: this.encryptedData,
id: res1.data.data.openId,
}
//获取用户手机号
appletPhone(params).then(res2 => {
console.log("手机号返回---", res2);
this.phoneNum = res2.data.phoneNumber;
//登陆成功后,重新查询用户身份信息
this.getUserInfo(this.openId);
})
//存储token至本地
uni.setStorage({
key: 'access_token',
data: this.token,
success: function() {
console.log(
'access_token存储成功'
);
},
fail: function(error) {
console.error(
'access_token存储失败:',
error);
}
});
//将openId、nickName、avatarUrl存储到本地
// 存储OpenID
uni.setStorage({
key: 'openId',
data: res1.data.data.openId,
success: function() {
console.log(
'OpenID存储成功'
);
},
fail: function(error) {
console.error(
'OpenID存储失败:',
error);
}
});
uni.setStorage({
key: 'nickName',
data: this.formData.nickName,
success: function() {
console.log(
'nickName存储成功'
);
},
fail: function(error) {
console.error(
'nickName存储失败:',
error);
}
});
uni.setStorage({
key: 'avatarUrl',
data: this.formData.avatarUrl,
success: function() {
console.log(
'avatarUrl存储成功'
);
},
fail: function(error) {
console.error(
'avatarUrl存储失败:',
error);
}
});
}
})
}
});
},
//获取该登录用户的信息
async getUserInfo(id) {
let result2 = await nineSelect({
id: id
});
let tempArr = result2.data;
//以下是用户等级字段的处理
if (tempArr.status == 1) { //注册用户
tempArr.levelImg =
'https://cn-chengdu.aliyuncs.com/hls/wode/zhuce.png';
tempArr.levelName = '注册会员';
} else if (tempArr.status ==
2) { //银牌会员
tempArr.levelImg =
'https://cn-chengdu.aliyuncs.com/hls/wode/chuji.png';
tempArr.levelName = '银牌会员';
} else if (tempArr.status ==
3) { //金牌会员
tempArr.levelImg =
'https://cn-chengdu.aliyuncs.com/hls/wode/gaoji.png';
tempArr.levelName = '金牌会员';
}
tempArr.points = '0'; //积分功能暂未使用,为所有账号初始化为0
//将用户信息存储进仓库
this.updateUserAllInfoData(tempArr);
console.log("登录 用户信息--", this.userInfo);
uni.showToast({
title: `登陆成功~`,
icon: 'none'
});
//跳转回个人中心页面
setTimeout(() => {
uni.switchTab({
url: `/pages/wode/wode`,
success() {
var page = getCurrentPages().pop();
if (page == undefined || page == null) return;
page.onLoad();
},
fail(e) {
console.error(e);
}
})
}, 2000);
},
//头像图片持久化
uploadImage(url1) {
//uni.uploadFile将微信返回的临时地址转成文件流传输给后端,从而上传服务器,拿到永久地址
uni.uploadFile({
url: `https://qmhly.hls.com/nine/getImgUrl`,
filePath: url1,
name: 'file',
header: {
'content-type': 'application/x-www-form-urlencoded',
},
formData: {
'user': this.formData.nickName
},
success: (uploadFileRes) => {
this.formData.avatarUrl = JSON.parse(uploadFileRes.data).data;
//进入登录流程
this.uniLogin();
}
});
},
}
}
</script>
<style scoped lang="scss">
.avatar-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
outline: inherit;
.avatar {
height: 120rpx;
width: 120rpx;
border-radius: 20rpx;
}
}
.avatar-wrapper::after {
border: none;
}
.nameContent {
display: flex;
margin: 70rpx 0;
border-top: 1px solid #eee;
border-bottom: 2rpx solid #eee;
padding: 20rpx 40rpx;
width: 100vw;
box-sizing: border-box;
font-size: 28rpx;
align-items: center;
.title {
margin-right: 40rpx;
}
}
.loginLogo {
height: 700rpx;
display: flex;
justify-content: center;
align-items: center;
.loginContent {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
.loginLogoText {
font-size: 24rpx;
color: #828282;
margin-top: 20rpx;
}
}
}
.loginBtn {
width: 100%;
.btn {
width: 80%;
border-radius: 20rpx;
background-color: #ee3236;
color: white;
}
}
</style>
因为有家人说想看api/index.js的代码,所以应大家要求,这部分代码也一起放上来。
api/index.js代码如下:
env.js:
let baseApi = '';
let baseApi2 = '';
if (process.env.NODE_ENV === 'development') { // 开发环境
baseApi = 'https://qmhly.hls.com';
baseApi2 = 'http://121.226.140:8082';
} else if (process.env.NODE_ENV == 'production') { // 生产环境
baseApi = 'https://qmhly.hls.com';
baseApi2 = 'http://121.226.140:8082';
}
let baseUrl = {
baseApi,
baseApi2
}
export {
baseUrl
}
http.js:
import {
baseUrl
} from './env'
let addressURL = baseUrl.baseApi;
const http = (url = '', type = 'GET', data = {}, address = 1, header = {}) => {
return new Promise((resolve, reject) => {
if (address == 1) {
addressURL = baseUrl.baseApi;
} else if (address == 2) {
addressURL = baseUrl.baseApi2;
}
uni.request({
header,
method: type,
url: addressURL + url,
data: data,
dataType: 'json',
sslVerify: false,
})
.then((response) => {
// console.log('response', response)
if (response.statusCode === 200) {
if (response.data && response.data.status === 0) {
resolve(response.data);
} else if(response.data.status===1000){
resolve(response.data);
uni.showToast({
icon: 'none',
title: response.data.msg
})
}else {
uni.showToast({
icon: 'none',
title: response.data.msg
})
reject(false)
}
} else if (response.statusCode === 404) {
uni.showToast({
icon: 'none',
title: '请求地址不存在'
})
reject(false)
} else {
reject(false);
}
}).catch(error => {
console.log(error)
reject(error)
})
})
}
export default http
@/api/index.js:
import request from '@/utils/http.js';
//通过id查询登录权限 id须包裹在请求体
export const nineSelect = (data) => {
return request(`/nine/select`, 'GET', data, 1)
}
//登录接口
export const appletLogin = (data) => {
return request(`/nine/appletLogin`, 'POST', data, 1)
}
//获取用户手机号
export const appletPhone = (data) => {
return request(`/nine/phone`, 'POST', data, 1)
}
包括封装的请求方法,请求方法根据自己的需求进行改动,全部代码就在这里了,祝阅读愉快!