UNPKG

qn-lcdp

Version:

青能科技低代码前端

216 lines (201 loc) 4.87 kB
/** * 路由权限控制模块 */ import Queue from '$ui/utils/queue' import loginMiddleware from './middleware/login' import roleMiddleware from './middleware/role' import canMiddleware from './middleware/can' // 路由控制中间件 const middlewareMap = { login: loginMiddleware, role: roleMiddleware, can: canMiddleware } // 中间件解析缓存 const Caches = {} /** * 解析中间件配置信息 * @param {string} action 配置信息,如:login / role:admin|user,true / can:add|update|delete,true * @param {string} nameSplit 中间件名称分隔符,默认 : * @param {string} paramSplit 参数个数分隔符,默认 , * @param {string} argSplit 值个数分隔符,默认 | * @return {object} */ function parser(action = '', { nameSplit, paramSplit, argSplit }) { let middleware = Caches[action] if (middleware) return middleware const arr = action.trim().split(nameSplit) const name = arr[0] const params = (arr[1] || '').trim().split(paramSplit) const args = params[0] ? params[0].trim().split(argSplit) : [] const required = !!params[1] middleware = Caches[action] = { name, args, required } return middleware } /** * 队列任务处理函数 * @param {Access} instance 实例 * @param {string} action 中间件配置 * @return {Promise<any>} */ function task(instance, action) { const params = parser(action, instance.options) const middleware = middlewareMap[params.name] return middleware ? middleware(instance, params) : Promise.resolve(middleware) } /** * 处理鉴权通过 * @param {Access} instance 实例 * @param {Function} next 路由跳转函数 * @param {Queue} queue 队列实例 */ function handleComplete(instance, next, queue) { next() queue.destroy() } /** * 处理鉴权不通过情况 * @param {Access} instance 实例 * @param {Function} next 路由跳转函数 * @param {Object} middleware 中间件 * @param {string} action 中间件配置 * @param {Queue} queue 队列实例 */ function handleFail(instance, next, middleware, action, queue) { const { progress } = instance.options progress && progress.done() queue.destroy() // 未登录 if (middleware.name === 'login') { const { loginPath, loginPathIsRoute } = instance.options if (loginPathIsRoute) { next && next(loginPath) } else { next && next(false) window.location.href = loginPath } } else { // 权限不足 const { authorizePath, authorizePathIsRoute } = instance.options if (authorizePathIsRoute) { next && next(authorizePath) } else { next && next(false) window.location.href = authorizePath } } } /** * 从匹配的路由提取access中间件 * @param to * @return {*[]} */ function getAccess(to) { const matched = to.matched let access = [] matched.forEach(match => { if (match.meta.access) { access = access.concat(match.meta.access) } }) // 去重 return [...new Set(access)] } /** * 队列任务 * @param instance * @param {Access} instance 实例 * @param {Array} access * @param {function} handleComplete 鉴权通过处理函数 * @param {function} handleFail 降权不通过处理函数 * @param {Function} next 路由跳转函数 */ export function queueTasks({ instance, access, handleComplete, handleFail, next }) { // Queue 会修改传入的数组,需要克隆断开引用再传入 new Queue(task.bind(this, instance), access.slice()) .$once('error', handleFail.bind(this, instance, next)) .$once('complete', handleComplete.bind(this, instance, next)) .start() } /** * 路由守卫 * @param {Access} instance Access实例 */ export default function (instance) { const { router, $router, progress, beforeEach, afterEach, preprocess } = instance.options if (!router || !$router) return // 执行路由鉴权 const run = function (to, next) { const access = getAccess(to) // 路由没有配置中间件,即不用鉴权 if (!access.length) { next() return } queueTasks({ instance, access, handleComplete, handleFail, next }) } $router.beforeEach((to, from, next) => { progress && progress.start() // 优先使用 beforeEach if (beforeEach) { beforeEach.call(instance, to, from, next) return } // 执行预处理 if (preprocess) { preprocess.call(instance, { to, from, access: instance, next }).then(() => { run(to, next) }).catch(e => { $router.replace('/error') }) } else { run(to, next) } }) $router.afterEach((to, from) => { progress && progress.done() if (afterEach) { afterEach.call(instance, to, from) } }) }