需求:
- 首页不需要登陆
- 点击首页的按钮,跳转需登陆页面时要弹出提示登陆对话框
- 在需登录的页面,清掉localstorage的token,刷新页面,直接跳到登录页
- url有token字段时实现直接登录(扫码登录场景)
安装并初始化:
- npm安装
npm install uni-simple-router uni-read-pages
- 配置
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 )
})
]
}
}
- 新建 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
}
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
}