前言
我们主要使用uniapp + uniCloud 实现小程序登录,并将用户数据存入云数据库。
小程序 wx.getUserProfile 调整,接口将被收回 详情,所以需要用户自己填写资料。
注:填写个人资料是一个组件,覆盖在登录之上而已,还是在同一个页面
uniCloud
创建 uniapp + uniCloud 项目,创建云数据库 数据表 uniCloud传送门
开始
创建项目
关联云服务空间
创建云数据库 数据表
不使用模版,输入名称直接创建即可。
编辑表结构,想了解更多可以去看云数据库 DB Schema 数据结构文档 传送门
json
{
"bsonType": "object",
"required": [],
"permission": {
"read": true,
"create": true,
"update": true,
"delete": false
},
"properties": {
"_id": {
"description": "ID,系统自动生成"
},
"nickName": {
"bsonType": "string",
"label": "昵称",
"description": "用户昵称,登录获取的"
},
"avatarUrl": {
"bsonType": "string",
"label": "头像",
"description": "用户头像图片的 URL,登录获取的"
},
"gender": {
"bsonType": "number",
"label": "性别",
"description": "用户性别,1: 男;2: 女"
},
"personalize": {
"bsonType": "string",
"label": "个性签名",
"description": "个性签名,编辑资料获取"
},
"background": {
"bsonType": "object",
"label": "个人中心背景图",
"description": "个人中心背景图,编辑资料获取"
},
"mp_wx_openid": {
"bsonType": "string",
"description": "微信小程序平台openid"
},
"register_date": {
"bsonType": "timestamp",
"description": "注册时间",
"forceDefaultValue": {
"$env": "now"
}
}
}
}
创建云函数
云函数代码
云函数 将 uni.login 取得的 code 获取到用户 session, 并对 数据库进行 增加、修改、查询 操作,第一次注册必须用户主动填写用户资料。
对云数据库的相关操作 传送门
js
'use strict';
//小程序的AppID 和 AppSecret
const mp_wx_data = {AppID: '************', AppSecret: '***********************'}
//event为客户端上传的参数
exports.main = async (event, context) => {
//使用云数据库
const db = uniCloud.database();
// 获取 `users` 集合的引用
const pro_user = db.collection('users');
// 通过 action 判断请求对象
let result = {};
switch (event.action) {
// 通过 code 获取用户 session
case 'code2Session':
const res_session = await uniCloud.httpclient.request('https://api.weixin.qq.com/sns/jscode2session', {
method: 'GET', data: {
appid: mp_wx_data.AppID,
secret: mp_wx_data.AppSecret,
js_code: event.js_code,
grant_type: 'authorization_code'
}, dataType: 'json'
}
)
const success = res_session.status === 200 && res_session.data && res_session.data.openid
if (!success) {
return {
status: -2, msg: '从微信获取登录信息失败'
}
}
//从数据库查找是否已注册过
const res_user = await pro_user.where({
mp_wx_openid: res_session.data.openid
}).get()
// 没有用户信息,进入注册
if (res_user.data && res_user.data.length === 0) {
//event.user_info 用户信息
if (event.user_info) {
//有信息则进入注册,向数据库写入数据
const register = await uniCloud.callFunction({
name: 'user',
data: {
action: 'register',
open_id: res_session.data.openid,
user_info: event.user_info
}
}).then(res => {
result = res
})
} else {
//没有信息返回{register: true}
result = {
result: {
result: {register: true}
}
}
}
} else {
result = {
result: {
result: res_user.data[0]
}
}
}
break;
//注册 向数据库写入数据
case 'register':
const res_reg = await pro_user.add({
nickName: event.user_info.nickName,
avatarUrl: event.user_info.avatarUrl,
gender: event.user_info.gender,
mp_wx_openid: event.open_id,
register_date: new Date().getTime()
})
if (res_reg.id) {
const res_reg_val = await uniCloud.callFunction({
name: 'user', data: {
action: 'getUser', open_id: event.open_id
}
}).then(res => {
result = res
})
} else {
result = {
status: -1, msg: '微信登录'
}
}
break;
case 'update':
if (event._id && event.info) {
const res_update = await pro_user.doc(event._id).update(event.info)
if (res_update.updated >= 0) {
result = {status: 200, msg: '修改成功'}
} else {
result = {status: -1, msg: '修改失败'}
}
} else {
result = {status: -1, msg: '修改失败'}
}
break;
case 'getUser':
const res_val = await pro_user.where({
mp_wx_openid: event.open_id
}).get()
return res_val.data[0]
break;
}
return result;
};
微信登录操作
如上面所说,用户需手动上传资料,对于用户头像我们需要上传至云储存。
上传用户头像
上传图片函数参数为微信本地图片路径,我们对路径用/
进行分割,取最后的图片名称进行上传
js
/**
* 上传图片至云存储
*/
export async function uploadImage(url) {
const fileName = url.split('/')
return new Promise(resolve => {
uniCloud.uploadFile({
filePath: url,
cloudPath: fileName[fileName.length - 1],
success(res) {
resolve(res)
},
fail() {
uni.showToast({
title: '图片上传失败!',
icon: 'none'
})
resolve(false)
}
})
})
}
登录函数
如果用户第一次上传资料,我们需要先上传头像并取得图片链接,再将用户资料写入数据库。
js
async wxLogin() {
if (this.userInfo && this.userInfo.avatarUrl) {
uni.showLoading({
title: '正在上传图片...',
mask: true
});
//上传头像至云储存并返回图片链接
const imageUrl = await uploadImage(this.userInfo.avatarUrl)
if (!imageUrl) {
return
}
this.userInfo = {...this.userInfo, avatarUrl: imageUrl.fileID}
}
uni.showLoading({
title: '登陆中...',
mask: true
});
const _this = this
uni.login({
provider: 'weixin',
success: (res) => {
if (res.code) {
//取得code并调用云函数
uniCloud.callFunction({
name: 'user',
data: {
action: 'code2Session',
js_code: res.code,
user_info: _this.userInfo
},
success: (res) => {
//如register为true,用户未填写资料
if (res.result.result.result.register) {
//_this.showUserInfo 显示填写资料组件
_this.showUserInfo = true
uni.hideLoading();
return
}
if (res.result.result.result._id) {
const data = {
_id: res.result.result.result._id,
mp_wx_openid: res.result.result.result.mp_wx_openid,
register_date: res.result.result.result.register_date
}
this.loginSuccess(data)
}
},
fail: () => {
this.loginFail()
}
})
}
}
})
},
登录成功与失败
在用户登录成功后将数据存入 Storage 中,添加登录过期时间,我这里设置的是七天的登录有效期。
js
loginSuccess(data) {
updateTokenStorage(data)
updateIsLoginStorage(true)
uni.showToast({
title: '登陆成功!',
icon: 'none'
});
uni.navigateBack()
},
将用户数据存入 Storage,并设置过期时间 expiresTime
js
export function updateTokenStorage(data = null) {
if (data) {
const expiresTime = new Date().getTime() + 7 * 24 * 60 * 60 * 1000
data = {...data, expiresTime: expiresTime}
}
uni.setStorageSync('user', data)
}
isLogin
用于判断是否是否登录
js
export function updateIsLoginStorage(data = null) {
uni.setStorageSync('isLogin', data)
}
登录失败
js
loginFail() {
updateTokenStorage()
updateIsLoginStorage()
uni.showToast({
title: '登陆失败!',
icon: 'none'
});
}
判断是否登录
除了判断 isLogin
还要判断 expiresTime
是否登录过期
js
//判断是否登陆
export function isLogin() {
try {
const user = uni.getStorageSync('user')
const isLogin = uni.getStorageSync('isLogin')
const nowTime = new Date().getTime()
return !!(isLogin && user && user._id && user.expiresTime > nowTime);
} catch (error) {
}
}
最后
至此就实现了微信登录并将用户信息存入数据库中,我们也可以通过云函数获取用户数据,做出用户个人主页。
以上是我做个人小程序时用的登录流程,整个小程序项目已上传至 GitHub。
小程序码