uniapp登录成功后跳回原有页面+无感刷新token

news2024/11/17 15:57:22

uniapp登录成功后跳回原有页面

引言

在C端的页面场景中,我们经常会有几种情况到登录页:

  • 区分需要登录和不用登录的页面,点击需要登录才能查看的页面
  • 已经登录但是超时,用户凭证失效等原因

以上情况可以细分为两种,一种是从未登录过的,需要第一次去登录,还一种是已经登录了,但是cookie失效了,需要重新获取用户凭证,这样的话后端会将两个状态码区分,那我们前端需要根据不同的状态码进行相应的处理。

第一次登录时

当用户从未登录时,我们需要跳到登录页去登录后再返回到原有页面,这样才是正常的交互逻辑。

  1. 第一步需要先保存当前路由

 // 记录路由地址
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}`)
}
  1. 登录成功后判断是否有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'})
   }
  1. 回到原页面后点击返回需要返回到上一层页面(排除登录页)

    这点要注意的是整个流程是首页-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根据自己实际情况调整

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1716756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动化测试实践:揭秘WebSocket在接口测试中的应用

如何写接口自动化?这个问题,但凡涉足过自动化测试的人员都能娓娓道来。Requests、urlib、jmeter、curl等等,不在话下。那么,如何获取接口的url、参数、响应等信息呢?!答案就更是随口而出:看接口…

必看项目|多维度揭示心力衰竭患者生存关键因素(生存分析、统计检验、随机森林)

1.项目背景 心力衰竭是一种严重的公共卫生问题,影响着全球数百万人的生活质量和寿命,心力衰竭的病因复杂多样,既有个体生理因素的影响,也受到环境和社会因素的制约,个体的生活方式、饮食结构和医疗状况在很大程度上决定了其心力衰竭的风险。在现代社会,随着生活水平的提…

利用英特尔 Gaudi 2 和至强 CPU 构建经济高效的企业级 RAG 应用

检索增强生成 (Retrieval Augmented Generation,RAG) 可将存储在外部数据库中的新鲜领域知识纳入大语言模型以增强其文本生成能力。其提供了一种将公司数据与训练期间语言模型学到的知识分开的方式,有助于我们在性能、准确性及安全隐私之间进行有效折衷。…

计算机网络-Traffic-Filter流量过滤策略

一、概述 为提高网络安全性,管理人员需要控制进入网络的流量,将不信任的报文丢弃在网络边界。所谓的不信任报文是指对用户来说存在安全隐患或者不愿意接收的报文。同时保证数据访问安全性,企业网络中经常会要求一些部门之间不能相互访问。 背…

金融行业专题|超融合对国密卡和国产加密技术的支持能力如何?

目前,不少金融机构都使用国密卡(满足国密算法要求的加密卡)和国产密码解决方案保障金融信息安全。而在传统虚拟化架构下,单块加密卡通常只能服务一个系统,经常会出现资源利用率低、加密处理性能不足等问题,…

神经网络与深度学习——第14章 深度强化学习

本文讨论的内容参考自《神经网络与深度学习》https://nndl.github.io/ 第14章 深度强化学习 深度强化学习 强化学习(Reinforcement Learning,RL),也叫增强学习,是指一类从与环境交互中不断学习的问题以及解决这类问题…

最简单的安卓模拟器抓包?

安装模拟器抓包似乎是有个绕不开的话题,但是现在普遍的安卓模拟器抓包会遇到以下问题: 1.证书配置繁琐 2.模拟器不兼容软件 3.系统设置繁琐。 前几天写过一次微信小程序如何抓包,现在来讲一下模拟器怎么抓包吧。首先使用的工具还是TangGo测…

开源集运wms系统

集运WMS系统是一种专为集运业务设计的仓库管理系统,它能够高效地处理来自多个来源的货物,优化存储和发货流程。 经过长时间的开发和测试,推出了我的集运WMS系统。它不仅具备传统WMS系统的所有功能,还针对集运业务的特点进行了特别…

Python轻量级的插件框架库之pluginbase使用详解

概要 在软件开发中,插件系统是一个常见的需求。插件系统允许开发者动态加载和卸载功能模块,从而提高应用程序的灵活性和可扩展性。Python的pluginbase库是一个轻量级的插件框架,旨在简化插件系统的构建过程。pluginbase库提供了一套简单易用的API,使开发者能够快速集成插件…

初步研究Pose_300W_LP datasets.py

mat文件参数解读 Color_para:颜色参数,用于描述图像的颜色属性,比如图像的亮度、对比度等信息。 亮度属性、对比度属性、饱和度属性(颜色越鲜艳)、色调属性(色调越偏向蓝色)、色温属性&#xf…

结构体(自定义类型)

1.结构体 结构体这种自定义的数据类型,让程序员可以自己创造适合的类型 结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量,可以是标量,数组,指针甚至是其他结构体 1.1.1 结构…

六西格玛培训:企业逆袭的秘密武器!——张驰咨询

为了提升企业的运营效率、产品质量和客户满意度,六西格玛培训成为了一个不可或缺的环节。以下是企业成功实施六西格玛培训的关键步骤: 一、清晰设定培训目标 首先,企业应明确六西格玛培训的具体目标,如提升产品质量、降低成本、…

武汉城投城更公司与竹云科技签署战略协议,携手构建智慧城市新未来!

2024年5月16日,武汉城投城更公司与深圳竹云科技股份有限公司(以下简称“竹云”)签订战略合作协议,双方将深入推进产业项目合作。 签约现场,双方围绕产业项目合作方向、路径和内容等进行了全面深入交流。城投城更公司党…

Windows和Linux系统部署Docker(2)

目录 一、Linux系统部署docker 前置环境: 1.安装需要的软件包, yum-util 提供yum-config-manager功能 2.添加阿里云 docker-ce 仓库 3.安装docker软件包 4.启动 docker并设置开机自启 5.查看版本: 二、windows系统部署docker 1.查看…

如何用unittest帮你快速生成自动化测试报告?

🍅 视频学习:文末有免费的配套视频可观看 🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一直以来很多使用 pythonunittest 做自动化测试的的小伙伴都在想,unittest 这个官方库…

MFC工控项目实例之一主菜单制作

1、本项目用在WIN10下安装的vc6.0兼容版实现。创建项目名为SEAL_PRESSURE的MFC对话框。在项目res文件下添加相关256色ico格式图片。 2、项目名称:密封压力试验机 主菜单名称: 系统参数 SYS_DATA 系统测试 SYS_TEST 选择型号 TYP_CHOICE 开始试验 TES_STA…

Tasker+SendSilentMail实现钉钉自动打卡

Tasker 允许用户根据自定义的“配置文件”(Profiles),在特定的“背景”(Contexts)下,执行指定的“任务”(Tasks)。以下是关于Tasker的详细介绍: 强大的自定义能力:用户可以根据自己的需求,创建各种配置文件和任务&…

vwmare虚拟机我已复制和我已移动的区别

问题 此虚拟机可能已被移动或复制。 为了配置特定的管理和网络功能,WMware Workstation需要知道是否已移动或复制了此虚拟机。 如果您不知道,请回答“我已复制该虚拟机(P)” 我已复制 意味着复制出了一个完全相同的副本。 这两个副本可以运行在一台物理…

Linux 服务器配置 SSH 服务登录失败处理

任务目标 配置 Linux 服务器ssh远程登录失败处理机制,防止黑客爆破服务器密码 操作步骤 备份原配置文件 $ sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak $ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak安装 pam_tally2 统计登陆失败次数 # 对于Debia…

CyberDAO M级共识交流会·西安站圆满落幕:共筑Web3美好未来

CyberDAO M级共识交流会于2024年5月28日在西安隆重举行,这是一场CyberDAO精英汇聚的盛会,以同心共筑,志在必达为主题口号与DAO精英携手并进,共筑CyberDAO美好宏图。CyberDAO的使命是降低WEB3的门槛,帮助用户轻松抓住行…