feat:路由的接入,部分类似 config.ts、interceptor.ts 的拦截,移植自 unibest3.x 代码
This commit is contained in:
44
src/router/config.ts
Normal file
44
src/router/config.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
// import { getAllPages } from '@/utils'
|
||||
|
||||
export const LOGIN_STRATEGY_MAP = {
|
||||
DEFAULT_NO_NEED_LOGIN: 0, // 黑名单策略,默认可以进入APP
|
||||
DEFAULT_NEED_LOGIN: 1, // 白名单策略,默认不可以进入APP,需要强制登录
|
||||
}
|
||||
// TODO: 1/3 登录策略,默认使用`无需登录策略`,即默认不需要登录就可以访问
|
||||
export const LOGIN_STRATEGY = LOGIN_STRATEGY_MAP.DEFAULT_NEED_LOGIN // edit by 芋艿:管理后台,默认需要登录
|
||||
export const isNeedLoginMode
|
||||
= LOGIN_STRATEGY === LOGIN_STRATEGY_MAP.DEFAULT_NEED_LOGIN
|
||||
|
||||
export const LOGIN_PAGE = '/pages/auth/login' // edit by 芋艿:自定义了登录页路径
|
||||
export const REGISTER_PAGE = '/pages/auth/register' // edit by 芋艿:自定义了注册页路径
|
||||
export const CODE_LOGIN_PAGE = '/pages/auth/code-login' // edit by 芋艿:自定义了短信登录页路径
|
||||
export const FORGET_PASSWORD_PAGE = '/pages/auth/forget-password' // edit by 芋艿:自定义了忘记密码页路径
|
||||
export const NOT_FOUND_PAGE = '/pages/error/404' // edit by 芋艿:调整 404 页面路径
|
||||
|
||||
// TODO @芋艿:【优化】貌似 unibest 这个变量没用?!
|
||||
export const LOGIN_PAGE_LIST = [
|
||||
LOGIN_PAGE,
|
||||
REGISTER_PAGE,
|
||||
CODE_LOGIN_PAGE,
|
||||
FORGET_PASSWORD_PAGE,
|
||||
]
|
||||
|
||||
// 注释 by 芋艿:在 mp 环境下,getAllPages 函数还没初始化好,所以不能直接调用。统一优化到 judgeIsExcludePath 函数里面去获取
|
||||
// 在 definePage 里面配置了 excludeLoginPath 的页面,功能与 EXCLUDE_LOGIN_PATH_LIST 相同
|
||||
// export const excludeLoginPathList = getAllPages('excludeLoginPath').map(
|
||||
// page => page.path,
|
||||
// )
|
||||
|
||||
// 排除在外的列表,白名单策略指白名单列表,黑名单策略指黑名单列表
|
||||
// TODO: 2/3 在 definePage 配置 excludeLoginPath,或者在下面配置 EXCLUDE_LOGIN_PATH_LIST
|
||||
export const EXCLUDE_LOGIN_PATH_LIST = [
|
||||
'/pages/xxx/index', // 示例值
|
||||
'/pages-sub/xxx/index', // 示例值
|
||||
// 注释 by 芋艿:在 mp 环境下,getAllPages 函数还没初始化好,所以不能直接调用。统一优化到 judgeIsExcludePath 函数里面去获取
|
||||
// ...excludeLoginPathList, // 都是以 / 开头的 path
|
||||
]
|
||||
|
||||
// 在小程序里面是否使用H5的登录页,默认为 false
|
||||
// 如果为 true 则复用 h5 的登录逻辑
|
||||
// TODO: 3/3 确定自己的登录页是否需要在小程序里面使用
|
||||
export const LOGIN_PAGE_ENABLE_IN_MP = true // edit by 芋艿:管理后台,小程序也使用自定义登录页
|
||||
@@ -1,13 +1,37 @@
|
||||
import { isMp } from '@uni-helper/uni-env'
|
||||
/**
|
||||
* by 菲鸽 on 2025-08-19
|
||||
* 路由拦截,通常也是登录拦截
|
||||
* 黑、白名单的配置,请看 config.ts 文件, EXCLUDE_LOGIN_PATH_LIST
|
||||
*/
|
||||
import { tabbarStore } from '@/tabbar/store'
|
||||
import { getAllPages, getLastPage, parseUrlToObj } from '@/utils/index'
|
||||
import { useTokenStore } from '@/store/token'
|
||||
import { isPageTabbar, tabbarStore } from '@/tabbar/store'
|
||||
import { getAllPages, getLastPage, HOME_PAGE, parseUrlToObj } from '@/utils/index'
|
||||
import { toLoginPage } from '@/utils/toLoginPage'
|
||||
import { EXCLUDE_LOGIN_PATH_LIST, isNeedLoginMode, LOGIN_PAGE, LOGIN_PAGE_ENABLE_IN_MP, NOT_FOUND_PAGE } from './config'
|
||||
|
||||
export const FG_LOG_ENABLE = false
|
||||
|
||||
let excludeListInited = false // 标记 EXCLUDE_LOGIN_PATH_LIST 是否已经根据 getAllPages('excludeLoginPath') 做过一次性补充(仅非开发环境)
|
||||
export function judgeIsExcludePath(path: string) {
|
||||
const isDev = import.meta.env.DEV
|
||||
if (!isDev) {
|
||||
// edit by 芋艿:非开发环境下,只初始化一次
|
||||
if (!excludeListInited) {
|
||||
const pages = getAllPages('excludeLoginPath')
|
||||
pages.forEach((page) => {
|
||||
if (!EXCLUDE_LOGIN_PATH_LIST.includes(page.path)) {
|
||||
EXCLUDE_LOGIN_PATH_LIST.push(page.path)
|
||||
}
|
||||
})
|
||||
excludeListInited = true
|
||||
}
|
||||
return EXCLUDE_LOGIN_PATH_LIST.includes(path)
|
||||
}
|
||||
const allExcludeLoginPages = getAllPages('excludeLoginPath') // dev 环境下,需要每次都重新获取,否则新配置就不会生效
|
||||
return EXCLUDE_LOGIN_PATH_LIST.includes(path) || (isDev && allExcludeLoginPages.some(page => page.path === path))
|
||||
}
|
||||
|
||||
export const navigateToInterceptor = {
|
||||
// 注意,这里的url是 '/' 开头的,如 '/pages/index/index',跟 'pages.json' 里面的 path 不同
|
||||
// 增加对相对路径的处理,BY 网友 @ideal
|
||||
@@ -35,6 +59,7 @@ export const navigateToInterceptor = {
|
||||
// 处理路由不存在的情况
|
||||
if (path !== '/' && !getAllPages().some(page => page.path !== path)) {
|
||||
console.warn('路由不存在:', path)
|
||||
uni.navigateTo({ url: NOT_FOUND_PAGE })
|
||||
return false // 明确表示阻止原路由继续执行
|
||||
}
|
||||
|
||||
@@ -46,6 +71,66 @@ export const navigateToInterceptor = {
|
||||
|
||||
// 处理直接进入路由非首页时,tabbarIndex 不正确的问题
|
||||
tabbarStore.setAutoCurIdx(path)
|
||||
|
||||
// 小程序里面使用平台自带的登录,则不走下面的逻辑
|
||||
if (isMp && !LOGIN_PAGE_ENABLE_IN_MP) {
|
||||
return true // 明确表示允许路由继续执行
|
||||
}
|
||||
|
||||
const tokenStore = useTokenStore()
|
||||
FG_LOG_ENABLE && console.log('tokenStore.hasLogin:', tokenStore.hasLogin)
|
||||
|
||||
// 不管黑白名单,登录了就直接去吧(但是当前不能是登录页)
|
||||
if (tokenStore.hasLogin) {
|
||||
if (path !== LOGIN_PAGE) {
|
||||
return true // 明确表示允许路由继续执行
|
||||
} else {
|
||||
console.log('已经登录,但是还在登录页', myQuery.redirect)
|
||||
const url = myQuery.redirect || HOME_PAGE
|
||||
if (isPageTabbar(url)) {
|
||||
uni.switchTab({ url })
|
||||
} else {
|
||||
uni.navigateTo({ url })
|
||||
}
|
||||
return false // 明确表示阻止原路由继续执行
|
||||
}
|
||||
}
|
||||
let fullPath = path
|
||||
|
||||
if (Object.keys(myQuery).length) {
|
||||
fullPath += `?${Object.keys(myQuery).map(key => `${key}=${myQuery[key]}`).join('&')}`
|
||||
}
|
||||
const redirectQuery = `?redirect=${encodeURIComponent(fullPath)}`
|
||||
|
||||
// #region 1/2 默认需要登录的情况(白名单策略) ---------------------------
|
||||
if (isNeedLoginMode) {
|
||||
// 需要登录里面的 EXCLUDE_LOGIN_PATH_LIST 表示白名单,可以直接通过
|
||||
if (judgeIsExcludePath(path)) {
|
||||
return true // 明确表示允许路由继续执行
|
||||
}
|
||||
// 否则需要重定向到登录页
|
||||
else {
|
||||
if (path === LOGIN_PAGE) {
|
||||
return true // 明确表示允许路由继续执行
|
||||
}
|
||||
FG_LOG_ENABLE && console.log('1 isNeedLogin(白名单策略) url:', fullPath)
|
||||
toLoginPage({ queryString: redirectQuery })
|
||||
return false // 明确表示阻止原路由继续执行
|
||||
}
|
||||
}
|
||||
// #endregion 1/2 默认需要登录的情况(白名单策略) ---------------------------
|
||||
|
||||
// #region 2/2 默认不需要登录的情况(黑名单策略) ---------------------------
|
||||
else {
|
||||
// 不需要登录里面的 EXCLUDE_LOGIN_PATH_LIST 表示黑名单,需要重定向到登录页
|
||||
if (judgeIsExcludePath(path)) {
|
||||
FG_LOG_ENABLE && console.log('2 isNeedLogin(黑名单策略) url:', fullPath)
|
||||
toLoginPage({ queryString: redirectQuery })
|
||||
return false // 修改为false,阻止原路由继续执行
|
||||
}
|
||||
return true // 明确表示允许路由继续执行
|
||||
}
|
||||
// #endregion 2/2 默认不需要登录的情况(黑名单策略) ---------------------------
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export const nativeTabbarList: NativeTabBarItem[] = [
|
||||
{
|
||||
iconPath: 'static/tabbar/personal.png',
|
||||
selectedIconPath: 'static/tabbar/personalHL.png',
|
||||
pagePath: 'pages/me/me',
|
||||
pagePath: 'pages/user/index', // edit by 芋艿:原 me 被删除,改为 user 避免 IDE linter 报错
|
||||
text: '个人',
|
||||
},
|
||||
]
|
||||
@@ -42,25 +42,25 @@ export const nativeTabbarList: NativeTabBarItem[] = [
|
||||
// TODO: 3/3. 使用 CUSTOM_TABBAR(2,3) 时,更新下面的 tabbar 配置
|
||||
// 如果需要配置鼓包,需要在 'tabbar/store.ts' 里面设置,最后在 `tabbar/index.vue` 里面更改鼓包的图片
|
||||
export const customTabbarList: CustomTabBarItem[] = [
|
||||
{
|
||||
text: '首页',
|
||||
pagePath: 'pages/index/index',
|
||||
// 注意 unocss 图标需要如下处理:(二选一)
|
||||
// 1)在fg-tabbar.vue页面上引入一下并注释掉(见tabbar/index.vue代码第2行)
|
||||
// 2)配置到 unocss.config.ts 的 safelist 中
|
||||
iconType: 'unocss',
|
||||
icon: 'i-carbon-home',
|
||||
// badge: 'dot',
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/me/me',
|
||||
text: '我的',
|
||||
// 1)在fg-tabbar.vue页面上引入一下并注释掉(见tabbar/index.vue代码第2行)
|
||||
// 2)配置到 unocss.config.ts 的 safelist 中
|
||||
iconType: 'unocss',
|
||||
icon: 'i-carbon-user',
|
||||
// badge: 10,
|
||||
},
|
||||
// {
|
||||
// text: '首页',
|
||||
// pagePath: 'pages/index/index',
|
||||
// // 注意 unocss 图标需要如下处理:(二选一)
|
||||
// // 1)在fg-tabbar.vue页面上引入一下并注释掉(见tabbar/index.vue代码第2行)
|
||||
// // 2)配置到 unocss.config.ts 的 safelist 中
|
||||
// iconType: 'unocss',
|
||||
// icon: 'i-carbon-home',
|
||||
// // badge: 'dot',
|
||||
// },
|
||||
// {
|
||||
// pagePath: 'pages/me/me',
|
||||
// text: '我的',
|
||||
// // 1)在fg-tabbar.vue页面上引入一下并注释掉(见tabbar/index.vue代码第2行)
|
||||
// // 2)配置到 unocss.config.ts 的 safelist 中
|
||||
// iconType: 'unocss',
|
||||
// icon: 'i-carbon-user',
|
||||
// // badge: 10,
|
||||
// },
|
||||
// 其他类型演示
|
||||
// 1、uiLib
|
||||
// {
|
||||
@@ -86,6 +86,37 @@ export const customTabbarList: CustomTabBarItem[] = [
|
||||
// icon: '/static/tabbar/home.png',
|
||||
// iconActive: '/static/tabbar/homeHL.png',
|
||||
// },
|
||||
// add by 芋艿:图标可到 https://icon-sets.iconify.design/carbon/ 选择。另外,需要在 uno.config.ts 的 safelist 中添加图标类名
|
||||
{
|
||||
text: '工作台',
|
||||
pagePath: 'pages/index/index',
|
||||
iconType: 'unocss',
|
||||
icon: 'i-carbon-home',
|
||||
},
|
||||
{
|
||||
text: '审批',
|
||||
pagePath: 'pages/bpm/index',
|
||||
iconType: 'unocss',
|
||||
icon: 'i-carbon-document',
|
||||
},
|
||||
{
|
||||
text: '通讯录',
|
||||
pagePath: 'pages/contact/index',
|
||||
iconType: 'unocss',
|
||||
icon: 'i-carbon-user-avatar',
|
||||
},
|
||||
{
|
||||
text: '消息',
|
||||
pagePath: 'pages/message/index',
|
||||
iconType: 'unocss',
|
||||
icon: 'i-carbon-chat',
|
||||
},
|
||||
{
|
||||
text: '我的',
|
||||
pagePath: 'pages/user/index',
|
||||
iconType: 'unocss',
|
||||
icon: 'i-carbon-user',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
@@ -111,6 +142,16 @@ export const needHideNativeTabbar = selectedTabbarStrategy === TABBAR_STRATEGY_M
|
||||
const _tabbarList = customTabbarEnable ? customTabbarList.map(item => ({ text: item.text, pagePath: item.pagePath })) : nativeTabbarList
|
||||
export const tabbarList = customTabbarEnable ? customTabbarList : nativeTabbarList
|
||||
|
||||
/**
|
||||
* 判断路径是否是 tabBar 页面
|
||||
* @param path 页面路径(支持带或不带 / 前缀)
|
||||
*/
|
||||
export function isTabBarPage(path: string): boolean {
|
||||
// 统一处理路径格式:去掉开头的 /
|
||||
const normalizedPath = path.startsWith('/') ? path.slice(1) : path
|
||||
return tabbarList.some(item => item.pagePath === normalizedPath)
|
||||
}
|
||||
|
||||
const _tabbar: TabBar = {
|
||||
// 只有微信小程序支持 custom。App 和 H5 不生效
|
||||
custom: selectedTabbarStrategy === TABBAR_STRATEGY_MAP.CUSTOM_TABBAR_WITH_CACHE,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { CustomTabBarItem, CustomTabBarItemBadge } from './types'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
import { isNeedLoginMode } from '@/router/config'
|
||||
import { FG_LOG_ENABLE, judgeIsExcludePath } from '@/router/interceptor'
|
||||
import { useTokenStore } from '@/store/token'
|
||||
import { tabbarList as _tabbarList, customTabbarEnable, selectedTabbarStrategy, TABBAR_STRATEGY_MAP } from './config'
|
||||
|
||||
// TODO 1/2: 中间的鼓包tabbarItem的开关
|
||||
@@ -38,8 +41,12 @@ const tabbarStore = reactive({
|
||||
curIdx: uni.getStorageSync('app-tabbar-index') || 0,
|
||||
prevIdx: uni.getStorageSync('app-tabbar-index') || 0,
|
||||
setCurIdx(idx: number) {
|
||||
this.curIdx = idx
|
||||
uni.setStorageSync('app-tabbar-index', idx)
|
||||
const tokenStore = useTokenStore()
|
||||
// 已登录 或 (url 需要登录 && 在白名单 || 不需要登录 && 不在黑名单) (关于 白名单|黑名单 逻辑: src/router/interceptor.ts)
|
||||
if (tokenStore.hasLogin || (isNeedLoginMode && judgeIsExcludePath(tabbarList[idx].pagePath)) || (!isNeedLoginMode && !judgeIsExcludePath(tabbarList[idx].pagePath))) {
|
||||
this.curIdx = idx
|
||||
uni.setStorageSync('app-tabbar-index', idx)
|
||||
}
|
||||
},
|
||||
setTabbarItemBadge(idx: number, badge: CustomTabBarItemBadge) {
|
||||
if (tabbarList[idx]) {
|
||||
@@ -53,6 +60,7 @@ const tabbarStore = reactive({
|
||||
return
|
||||
}
|
||||
const index = tabbarList.findIndex(item => item.pagePath === path)
|
||||
FG_LOG_ENABLE && console.log('index:', index, path)
|
||||
// console.log('tabbarList:', tabbarList)
|
||||
if (index === -1) {
|
||||
const pagesPathList = getCurrentPages().map(item => item.route.startsWith('/') ? item.route : `/${item.route}`)
|
||||
|
||||
Reference in New Issue
Block a user