uniapp登录成功后跳回原有页面
引言
在C端的页面场景中,我们经常会有几种情况到登录页:
- 区分需要登录和不用登录的页面,点击需要登录才能查看的页面
- 已经登录但是超时,用户凭证失效等原因
以上情况可以细分为两种,一种是从未登录过的,需要第一次去登录,还一种是已经登录了,但是cookie失效了,需要重新获取用户凭证,这样的话后端会将两个状态码区分,那我们前端需要根据不同的状态码进行相应的处理。
第一次登录时
当用户从未登录时,我们需要跳到登录页去登录后再返回到原有页面,这样才是正常的交互逻辑。
- 第一步需要先保存当前路由
// 记录路由地址
const fungoPreviousPage = () => {
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
let curRoute = routes[routes.length - 1].route //获取当前页面路由
let curParam = routes[routes.length - 1].options; //获取路由参数
// 拼接参数
let param = ''
for (let key in curParam) {
if (!param) {
param += key + '=' + curParam[key]
} else {
param += '&' + key + '=' + curParam[key]
}
}
uni.setStorageSync('pageUrl', param ? `/${curRoute}?${param}` : `/${curRoute}`)
}
- 登录成功后判断是否有pageUrl,有就说明回到原页面
var pageUrl = uni.getStorageSync('pageUrl')
if (pageUrl) {
// 如果为tabbar页面则用reLaunch跳转
if (['/pages/home/index'].includes(pageUrl)) {
uni.reLaunch({url: pageUrl})
} else {
uni.redirectTo({url: pageUrl})
}
//跳转后,删除url记录避免重复跳转
uni.removeStorageSync('pageUrl')
} else {
// 如果没有默认跳转到首页
uni.reLaunch({url: '/pages/home/index'})
}
-
回到原页面后点击返回需要返回到上一层页面(排除登录页)
这点要注意的是整个流程是首页-a-登录页-a,如果在a页面点击返回时是要到首页,则需要注意以下
a页面跳转到登录页时需要使用uni.redirectTo跳转,登录页跳转到a页面也需要使用uni.redirectTo
cookie失效
cookie失效了需要无感知更新cookie,这个时候需要先将请求的队列存起来,等刷新cookie再去调用原来的接口就行。
后端一般会在登录成功后返回两个token值,一个用来校验用户信息,一个用来获取新的token,我这边分为token和access_token两个字段,其实就一个时效长一个时效短。
完整代码如下
let devUrl = '';
import store from '../store/index.js'
import { loginOut } from './index.js'
const baseUrl = devUrl;
const POST = 'POST';
const UPLOAD = 'UPLOAD';
const SUCCESS_CODES = 200;
const RefreshCode = 777;
const LogoutCode = 503;
const TOKEN_ERROR = 444
const ERRCODE = 500
let promiseQueue = []
let exeQueue = false
let needBeginLogin = true
// 刷新token
async function RefreshTokenRQ(cb) {
try {
if (store.state.access_token) {
uni.request({
url: `${baseUrl}/user/refreshToken`,
data: {exchangeToken: store.state.access_token},
success(res) {
if (res.data.status === SUCCESS_CODES) {
store.commit('setToken', res.data.data)
cb && cb()
} else {
loginOut()
}
}
})
} else {
loginOut()
}
} catch (e) {}
}
const getHeader = () => {
return {
token: store.state.token,
};
};
/**
*
* @param {string} method 请求方法
* @param {string} url api地址
* @param {string} data 入参
*/
const request = async (requestObj) => {
// 显示加载中 效果
// uni.showLoading({
// title: "",
// mask: true,
// });
return new Promise((resolve, reject) => {
uni.request({
url: `${baseUrl}${requestObj.url}`,
method: requestObj.method || 'get',
data: requestObj.data || {},
header: Object.assign(getHeader(), requestObj.header || {}),
success(res) {
// 请求成功
const data = res.data;
requestMethods(requestObj, data, resolve, reject )
},
fail(err) {
console.log(err);
// 请求失败
reject(new Error('Por favor verifique a rede'));
}
});
})
}
function requestMethods (requestObj, data, resolve, reject) {
if (data.status === SUCCESS_CODES) {
if (requestObj.resolve) {
requestObj.resolve(data.data);
let promiseQueueItem = promiseQueue.shift();
if (exeQueue) {
exeQueue = false;
while (promiseQueueItem) {
request(promiseQueueItem);
promiseQueueItem = promiseQueue.shift();
promiseQueue = promiseQueue;
}
if (!promiseQueueItem) {
exeQueue = true;
needBeginLogin = true;
}
}
} else {
resolve(data.data);
}
} else {
// 其他异常
if (data.status === RefreshCode) {
try {
if (store.state.access_token) {
requestObj.resolve = resolve;
promiseQueue.push(requestObj); //请求失败了,把该请求放到promise队列,等待更新token后重新调用。
if (!needBeginLogin) {
return;
}
//防止重复刷新token。
needBeginLogin = false;
RefreshTokenRQ(() => { //获取完token以后执行回调
//重新登陆以后调用一次队列中的promise;并设置队列为可循环状态。
let promiseQueueItem = promiseQueue.shift();
if (promiseQueueItem) {
exeQueue = true;
request(promiseQueueItem);
}
}, true)
} else {
loginOut()
}
} catch (e) {}
return
} else if (data.status === LogoutCode || data.status === TOKEN_ERROR) {
loginOut()
return;
} else {
uni.showToast({
title: data.message,
icon: 'none'
});
}
reject(data);
}
}
export function get(url, data, header = {}, method = 'GET') {
return request({
url,
data,
header
})
}
export function post(url, data, header = {}, method = 'POST') {
return request({
url,
data,
method,
header
})
}
export default{
get,post
};
以上loginOut和store根据自己实际情况调整