211 lines
3.8 KiB
JavaScript
211 lines
3.8 KiB
JavaScript
import { AUTH_ENABLED, AUTH_STORAGE_KEYS } from '@/constants/auth'
|
||
import { ROUTES, TAB_ROUTES } from '@/constants/routes'
|
||
|
||
export const LOGIN_PAGE = ROUTES.LOGIN
|
||
export const HOME_PAGE = ROUTES.HOME
|
||
export const TAB_PAGES = TAB_ROUTES
|
||
|
||
let hasSetupInterceptors = false
|
||
|
||
/**
|
||
* 规范化路由,保证以 `/` 开头。
|
||
*/
|
||
function normalizeUrl(url = '') {
|
||
if (!url) {
|
||
return ''
|
||
}
|
||
|
||
if (url.startsWith('/')) {
|
||
return url
|
||
}
|
||
|
||
return `/${url}`
|
||
}
|
||
|
||
/**
|
||
* 获取不带 query 的路径。
|
||
*/
|
||
function getPath(url = '') {
|
||
return normalizeUrl(url).split('?')[0]
|
||
}
|
||
|
||
function safeDecode(value = '') {
|
||
try {
|
||
return decodeURIComponent(value)
|
||
} catch (error) {
|
||
return value
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 把页面 options 组装成 query 字符串。
|
||
*/
|
||
function buildQuery(options = {}) {
|
||
const keys = Object.keys(options)
|
||
if (!keys.length) {
|
||
return ''
|
||
}
|
||
|
||
const query = keys
|
||
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(options[key] || '')}`)
|
||
.join('&')
|
||
|
||
return query ? `?${query}` : ''
|
||
}
|
||
|
||
/**
|
||
* 获取当前页面完整地址(path + query)。
|
||
*/
|
||
function getCurrentPageUrl() {
|
||
const pages = getCurrentPages()
|
||
if (!pages.length) {
|
||
return ''
|
||
}
|
||
|
||
const current = pages[pages.length - 1]
|
||
const currentPath = current.route ? `/${current.route}` : ''
|
||
const currentQuery = current.options ? buildQuery(current.options) : ''
|
||
|
||
return `${currentPath}${currentQuery}`
|
||
}
|
||
|
||
function isLoginPage(url = '') {
|
||
return getPath(url) === LOGIN_PAGE
|
||
}
|
||
|
||
function needLogin(url = '') {
|
||
return !isLoginPage(url)
|
||
}
|
||
|
||
export function isAuthEnabled() {
|
||
return AUTH_ENABLED
|
||
}
|
||
|
||
export function isTabPage(url = '') {
|
||
return TAB_PAGES.includes(getPath(url))
|
||
}
|
||
|
||
export function getToken() {
|
||
return uni.getStorageSync(AUTH_STORAGE_KEYS.TOKEN) || ''
|
||
}
|
||
|
||
export function isLoggedIn() {
|
||
if (!AUTH_ENABLED) {
|
||
return true
|
||
}
|
||
|
||
return Boolean(getToken())
|
||
}
|
||
|
||
export function getUser() {
|
||
return uni.getStorageSync(AUTH_STORAGE_KEYS.USER) || null
|
||
}
|
||
|
||
/**
|
||
* 保存登录态。
|
||
*/
|
||
export function setAuth({ token, user } = {}) {
|
||
if (token) {
|
||
uni.setStorageSync(AUTH_STORAGE_KEYS.TOKEN, token)
|
||
}
|
||
|
||
if (user) {
|
||
uni.setStorageSync(AUTH_STORAGE_KEYS.USER, user)
|
||
}
|
||
}
|
||
|
||
export function clearAuth() {
|
||
uni.removeStorageSync(AUTH_STORAGE_KEYS.TOKEN)
|
||
uni.removeStorageSync(AUTH_STORAGE_KEYS.USER)
|
||
}
|
||
|
||
/**
|
||
* 跳转到登录页并携带重定向地址。
|
||
*/
|
||
export function redirectToLogin(targetUrl = '') {
|
||
if (!AUTH_ENABLED) {
|
||
return
|
||
}
|
||
|
||
const redirect = normalizeUrl(targetUrl || getCurrentPageUrl())
|
||
if (isLoginPage(redirect)) {
|
||
return
|
||
}
|
||
|
||
const loginUrl = redirect
|
||
? `${LOGIN_PAGE}?redirect=${encodeURIComponent(redirect)}`
|
||
: LOGIN_PAGE
|
||
|
||
uni.reLaunch({
|
||
url: loginUrl
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 登录成功后按 redirect 返回目标页。
|
||
*/
|
||
export function goAfterLogin(redirect = '') {
|
||
const target = normalizeUrl(safeDecode(redirect) || HOME_PAGE)
|
||
const targetPath = getPath(target)
|
||
|
||
if (isLoginPage(targetPath)) {
|
||
uni.switchTab({
|
||
url: HOME_PAGE
|
||
})
|
||
return
|
||
}
|
||
|
||
if (isTabPage(targetPath)) {
|
||
uni.switchTab({
|
||
url: targetPath
|
||
})
|
||
return
|
||
}
|
||
|
||
uni.reLaunch({
|
||
url: target
|
||
})
|
||
}
|
||
|
||
function guardPage(url = '') {
|
||
if (!AUTH_ENABLED) {
|
||
return true
|
||
}
|
||
|
||
if (!needLogin(url) || isLoggedIn()) {
|
||
return true
|
||
}
|
||
|
||
redirectToLogin(url)
|
||
return false
|
||
}
|
||
|
||
/**
|
||
* 初始化 uni 路由拦截器,只注册一次。
|
||
*/
|
||
export function setupAuthInterceptors() {
|
||
if (hasSetupInterceptors) {
|
||
return
|
||
}
|
||
|
||
const methods = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab']
|
||
methods.forEach((method) => {
|
||
uni.addInterceptor(method, {
|
||
invoke(args) {
|
||
return guardPage(args.url)
|
||
}
|
||
})
|
||
})
|
||
|
||
hasSetupInterceptors = true
|
||
}
|
||
|
||
export function ensureCurrentPageAuth() {
|
||
const currentUrl = getCurrentPageUrl()
|
||
if (!currentUrl) {
|
||
return
|
||
}
|
||
|
||
guardPage(currentUrl)
|
||
}
|