阐述
开发uni-app之前建议大家先看看 manifest.json 配置项各参数,对整个项目开发是有帮助的
文档路径:https://uniapp.dcloud.io/collocation/manifest?id=%E5%AE%8C%E6%95%B4-manifestjson
我先归纳一下登录逻辑
目前我先归纳小程序的登录
登陆授权我分两大步:1.登录授权获取用户信息 2.后续使用检测登录态
登录授权:
因为授权的弹框是可以取消的,取消之后第二次打开则是无效,所以解决这个问题,我使用两个api uni.getSetting uni.openSetting ,一个是获取用户当前获取权限的状态,一个是打开权限设置并授权。
当用户不授权的时候,做一个同样的Buttn按钮去模拟登录,提示用户已经取消授权需要手动开启授权权限,当点击授权完时,需要取得用户code,uniapp提供检测当前环境的api uni.getProvider ,所以先取得环境在获取code,当拿到code iv encryptedData 时就要可以调用后台接口拿到用户对应的信息,并缓存下来,代码例子:
//login.vue
<template>
<view class="login">
<image src="../../static/images/loginLogo.png" class="logo"></image>
<button class="login-button" type="primary" @click="openSetting" v-if="status==0">微信登录</button>
<button class="login-button" type="primary" open-type="getUserInfo" @getuserinfo="getuserinfo" v-else>微信登录</button>
<view class="phone-login">手机号登录/注册</view>
</view>
</template>
<script>
import {getProvider,login,getCode} from '@/api/request/login/login.js'
import {getSetting} from '@/api/request/login/authorize.js'
export default {
components: {
},
data() {
return {
code: '',
status: 0 //2未操作 1已经授权 0拒绝授权
}
},
onLoad() {
},
onShow() {
(async () => {
//获取授权状态
this.status = await getSetting()
//获取服务商信息
let provider = await getProvider();
//获取code
this.code = await getCode(provider[0])
})()
},
methods: {
getuserinfo(e) {
if (!this.code) {
uni.showToast({
icon: 'none',
title: '正在加载中,稍等一下',
duration: 2000
});
return
}
if (e.detail && e.detail.errMsg == 'getUserInfo:ok') {
e.detail.code = this.code//add code
login(e.detail, res => {
//授权成功之后的回调
uni.showToast({
title: '获取用户信息成功',
duration: 2000
});
setTimeout(() => {
uni.redirectTo({
url: '/pages/index/index'
});
}, 2000)
})
} else {
//授权成功之后的回调
uni.showToast({
icon: 'none',
title: '已拒绝授权',
duration: 2000
});
//用户拒绝授权
this.status = 0
}
},
openSetting() {
uni.showModal({
title: '提示',
content: '你已经取消过授权,需设置授权权限',
confirmText: '设置',
success: function(res) {
if (res.confirm) {
uni.openSetting({
success(res) {
}
})
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
</style>
//验证授权状态 2未操作 1已经授权 0拒绝授权
const getSetting = function() {
const promise= new Promise((resolve,reject) => {
uni.getSetting({
success(res) {
let authSetting=res.authSetting
//授权成功
if(authSetting['scope.userInfo']){
resolve(1)
return
}
//拒绝授权
if(authSetting['scope.userInfo']===false){
resolve(0)
return
}
resolve(2)
},
fail(res) {
reject(res)
}
})
}).catch(res=>{
uni.showToast({
icon:'none',
title: res.errMsg || '获取授权状态失败',
duration: 2000
});
})
return promise
}
export {
getSetting,//验证授权状态
}
//login.js
import {
authDo
} from '@/api/mpLogin/home.js'
//获取服务商信息
const getProvider = () => {
const promise = new Promise((resolve, reject) => {
uni.getProvider({
service: 'oauth', //服务类型 登录授权
success: function(res) {
resolve(res.provider)
},
fail(res) {
reject(res)
}
});
}).catch(res => {
uni.showToast({
icon: 'none',
title: res.errMsg || '获取服务商信息失败',
duration: 2000
});
})
return promise
}
//获取code
const getCode = provider => {
if (!provider) {
uni.showToast({
icon: 'none',
title: '获取服务商信息失败',
duration: 2000
});
return
}
const promise = new Promise((resolve, reject) => {
uni.login({
provider: provider,
success: function(loginRes) {
if (loginRes && loginRes.code) {
resolve(loginRes.code)
} else {
reject(loginRes)
}
}
});
}).catch(res => {
uni.showToast({
icon: 'none',
title: res.errMsg || '获取code失败',
duration: 2000
});
})
return promise
}
//登录授权
const login = async function(e,func) {
//获取服务商信息
// let provider = await getProvider();
//获取code
// let code = await getCode(provider[0])
//小程序授权微信
let param = {
code:e.code,
encryptedData: e.encryptedData,
iv: e.iv
}
let res = await authDo(param);
if (res.resultCode != '0000') {
uni.showToast({
icon: 'none',
title: res.resultMessage,
duration: 2000
});
return
}
let data = res.result || {}
//储存用户信息到本地
uni.setStorageSync('user', data);
func&&func(data)
}
export {
login,//登录授权
getCode,//获取code
getProvider//获取服务商信息
}
检测登录态
app.vue onShow 里检查登录态,这里分两步,一步是判断有用户缓存 没有前往登录 如有缓存则判断登录态,需要用uni.checkSession检查登录态是否过期,未过期不需要执行其他操作,如过期,需要获取code以及缓存里存的session 调用后台接口刷新登录态,代码如下:
//app.vue
<script>
import {
checkLoginStatus
} from '@/api/request/login/checkLoginStatus.js' //检查登录状态
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App show')
// #ifdef MP
//检查登录状态
checkLoginStatus()
// #endif
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
@import "css/flex.css";
@import "css/public.css";
</style>
//checkSession.js
//检测session是否过期
//0未过期 1已过期
const check=()=>{
const promise= new Promise((resolve,reject) => {
uni.checkSession({
success() {
console.log('状态未过期')
//未过期
resolve(0)
},
fail() {
console.log('状态已过期')
//已过期
resolve(1)
}
})
}).catch(res=>{
uni.showToast({
icon:'none',
title: res.errMsg || '验证session失效',
duration: 2000
});
})
return promise
}
export default check
//checkLoginStatus.js
import check from "@/api/request/login/checkSession.js" //检验sessing是否过期 0未过期 1已过期
import {
getCode,
getProvider
} from "@/api/request/login/login.js"
import {
wxLoginState
} from "@/api/mpLogin/home.js"
//用户缓存信息
const user = (uni.getStorageSync('user'));
//跳转至小程序登录页
const toLogin = () => {
// uni.showToast({
// icon: 'none',
// title: '您的登录已过期,跳转至授权页',
// mask: true,
// duration: 2000
// });
setTimeout(() => {
uni.redirectTo({
url: '/pages/login/index'
});
}, 2000)
}
//小程序登录态刷新
const loadLoginState = async function() {
let access3rdToken = user.access3rdToken //平台sessionId
let provider = await getProvider() //获取服务商信息
let code = await getCode(provider[0]) //获取code
let param = {
access3rdToken,
code
}
let res = await wxLoginState(param);
if (res.resultCode != '0000') {
uni.showToast({
icon: 'none',
title: res.resultMessage,
duration: 2000
});
return
}
console.log('刷新成功')
}
//判断登录状态
const checkLoginStatus = async function() {
if (user) {
// 检查 session_key 是否过期
let status = await check()
//已过期
if (status == 1) {
//小程序登录态刷新
loadLoginState()
} else {
//未过期
console.log('执行下一步操作')
}
} else {
// 无skey,作为首次登录
toLogin();
}
}
export {
checkLoginStatus, //判断登录状态
toLogin, //跳转至小程序登录页
loadLoginState //小程序登录态刷新
}