uniapp使用uni-simple-router实现h5登录(带白名单,url携带token登录)

219 阅读3分钟

需求:

  • 首页不需要登陆
  • 点击首页的按钮,跳转需登陆页面时要弹出提示登陆对话框
  • 在需登录的页面,清掉localstorage的token,刷新页面,直接跳到登录页
  • url有token字段时实现直接登录(扫码登录场景)

安装并初始化:

  1. npm安装
npm install uni-simple-router uni-read-pages
  1. 配置vue.config.js
//vue.config.js
const TransformPages = require('uni-read-pages')
const {webpack} = new TransformPages()
module.exports = {
   configureWebpack: {
	plugins: [
		new webpack.DefinePlugin({
			ROUTES: webpack.DefinePlugin.runtimeValue(() => {
				const tfPages = new TransformPages({
					includes: ['path', 'name', 'aliasPath']
				});
				return JSON.stringify(tfPages.routes)
			}, true )
		})
	]
   }
}
  1. 新建 router/index.js文件
// router/index.js
import {RouterMount,createRouter} from 'uni-simple-router';

const router = createRouter({
	platform: process.env.VUE_APP_PLATFORM,  
	routes: [...ROUTES]
});
//全局路由前置守卫
router.beforeEach((to, from, next) => {
	next();
});
// 全局路由后置守卫
router.afterEach((to, from) => {
    console.log('跳转结束')
})

export {
	router,
	RouterMount
}
  1. main.js引入router/index.js
// main.js

import Vue from 'vue'
import App from './App'
import {router,RouterMount} from './router/index.js'
Vue.use(router)

App.mpType = 'app'
const app = new Vue({
    ...App
})

//v1.3.5起 H5端 你应该去除原有的app.$mount();使用路由自带的渲染方式
// #ifdef H5
	RouterMount(app,router,'#app')
// #endif

// #ifndef H5
	app.$mount(); //为了兼容小程序及app端必须这样写才有效果
// #endif

功能实现:

// router.js
import { RouterMount, createRouter } from "uni-simple-router";
import { getAuthorization, setAuthorization } from "@/utils/auth";
import store from "@/store/index";
import { noPsdLogin } from "@/utils/permission";

// 白名单,此白名单下的页面没有token也能进入
const whiteList = [
  "/", // 注意入口页必须直接写 '/'
  "/pages/home/index",
  "/pages/user/index",
  { pattern: /^\/pages\/login\/*/ },
];

const router = createRouter({
  platform: process.env.VUE_APP_PLATFORM,
  routes: [...ROUTES],
});
//全局路由前置守卫
router.beforeEach(async (to, from, next) => {
  const { path: to_path } = to; //拿到要去的路由path
  const { path: from_path } = from; //拿到现在的路由path
  let pass; //声明变量,是一个布尔值
  if (whiteList) {
    pass = whiteList.some((item) => {
      if (typeof item === "object" && item.pattern) {
        return item.pattern.test(to_path);
      }
      return to_path === item;
    });
  }
  if (pass) { //如果是白名单页面,就放行
    next();
  } else if (getAuthorization()) { //非白名单页面,如果有token,就获取userInfo
    //获取userinfo
    const hasGetUserInfo = Object.keys(store.state.userInfo).length !== 0;
    if (!hasGetUserInfo) {
      store.dispatch("getUserInfo");
    }
    next();
  } else { //没有token
    try {
      await noPsdLogin(); //url携带token免密登录的情况,没有此功能可以删掉
      next();
    } catch { //走到这里,localstorage无token,url也没有带token
    //下面的代码用来处理在白名单或非白名单页面刷新页面后的情况
      let from_pass; 
      if (whiteList) {
        from_pass = whiteList.some((item) => {
          if (typeof item === "object" && item.pattern) {
            return item.pattern.test(from_path);
          }
          return from_path === item;
        });
      }
      if (from_pass) { //如果要跳转到非白名单页面,弹窗提示需要登陆
        uni.showModal({
          title: "提示",
          content: "请先登录",
          success: function (res) {
            if (res.confirm) {
              next({
                path: "/pages/login/index",
                query: { redirect: from_path },
              });
            }
          },
        });
      } else { //走到这里说明无token进入了非白名单页面,直接跳登录页
        next({
          path: "/pages/login/index",
          query: { redirect: from_path }, //跳转登录页,并携带当前页用于登陆后跳转回来
        });
      }
    }
  }
});
// 全局路由后置守卫
router.afterEach((to, from) => {
  // console.log('跳转结束')
});

export { router, RouterMount };

utils/auth.js

/**
 * @description 权限存储函数
 */
const authorizationKey = 'token'

export function getAuthorization() {
  return uni.getStorageSync(authorizationKey)
}

export function setAuthorization(authorization) {
  return uni.setStorageSync(authorizationKey, authorization)
}

export function removeAuthorization(authorization) {
  return uni.removeStorageSync(authorizationKey)
}

utils/permission.js

/**
 * @description 自定义路由拦截
 */

import { setAuthorization } from "@/utils/auth";
import { getUrlParams } from "./index";
import { getFirmList } from "@/api/home";
const NOSIGNTOKEN = "sccToken"; //免登录url字段 token
export const userTypeKey = "userType"
export const scanInfoKey = "scanInfo"
export const firmListKey = "firmList"
export const checkedfirmListKey = "checkedFirmId"

export const noPsdLogin = () => {
  //判断当前页面路径上是否有token,如果有则设置localstorage
  return new Promise((resolve, reject) => {
    const urlToken = getUrlToken();
    if (urlToken) {
      setAuthorization(urlToken);
      setUserType("2") //非会员
      setScanInfo()
      resolve(urlToken);
    } else {
      reject();
    }
  });
};

const getUrlToken = () => {
  const url_string = window.location.href;
  return getUrlParams(url_string)[NOSIGNTOKEN] || "";
};

// 获取企业列表
export const getFirmListFn = () => {
  return new Promise((resolve, reject) => {
    getFirmList().then((res) => {
      if(res.data.status === "success") {
        const result = res.data?.data
        const idKey = result[0].id
        uni.setStorageSync(firmListKey, JSON.stringify(result))
        uni.setStorageSync(checkedfirmListKey, idKey)
        resolve(true)
      }else {
        reject()
      }
    }).catch(() => {
      reject()
    });
  })

};

//设置用户是否是会员 1-会员 2-普通用户
export const setUserType = (key="2") => {
  uni.setStorageSync(userTypeKey, key)
}

//扫码登录情况下保存扫码信息
export const setScanInfo = () => {
  const urlParamsObj = getUrlParams(window.location.href);
  uni.setStorageSync(scanInfoKey, JSON.stringify(urlParamsObj))
}

//获取扫码登录时保存的扫码信息
export const getScanInfo = () => {
 const res = uni.getStorageSync(scanInfoKey) || {}
 return JSON.parse(res)
}

//获取用户类型
export const getUserType = () => {
  const userType = uni.getStorageSync(userTypeKey) || "2"
  return userType
}

//获取已选中的firm
export const getCheckedFirm = () => {
  const res = JSON.parse(uni.getStorageSync(firmListKey) || {});
  const result = res.find(
    item => item.id == uni.getStorageSync(checkedfirmListKey)
  );
  return result
}