gogocode icon indicating copy to clipboard operation
gogocode copied to clipboard

升 element plus 路由报错:Invalid route component at extractComponentsGuards

Open Tom9402 opened this issue 3 years ago • 0 comments

  • version:0.2.26
  • playground demo: router/index.js
import * as Vue from 'vue'
import * as VueRouter from 'vue-router'
console.log(VueRouter)
/* Layout */
import Layout from '@/views/layout/Layout'
/* Router Modules */
/* import componentsRouter from './modules/components'*/

/** note: sub-menu only appear when children.length>=1
 **/

/**
* hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
* alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
*                                if not set alwaysShow, only more than one route under the children
*                                it will becomes nested mode, otherwise not show the root menu
* redirect: noredirect           if `redirect:noredirect` will no redirect in the breadcrumb
* name:'router-name'             the name is used by <keep-alive> (must set!!!)
* meta : {
    roles: ['admin','editor']    will control the page roles (you can set multiple roles)
    title: 'title'               the name show in sub-menu and breadcrumb (recommend set)
    icon: 'svg-name'             the icon show in the sidebar
    noCache: true                if true, the page will no be cached(default is false)
    breadcrumb: false            if false, the item will hidden in breadcrumb(default is true)
    affix: true                  if true, the tag will affix in the tags-view
  }
**/
export const constantRouterMap = [
  {
    path: '/redirect',
    component: Layout,
    hidden: true,
    children: [
      {
        path: '/redirect/:path*',
        component: Vue.defineAsyncComponent(
          () => import('@/views/redirect/index')
        ),
      },
    ],
  },
  {
    path: '/login',
    component: Vue.defineAsyncComponent(() => import('@/views/login/index')),
    hidden: true,
  },
  {
    path: '/auth-redirect',
    component: Vue.defineAsyncComponent(
      () => import('@/views/login/authredirect')
    ),
    hidden: true,
  },
  {
    path: '/404',
    component: Vue.defineAsyncComponent(() => import('@/views/errorPage/404')),
    hidden: true,
  },
  {
    path: '/401',
    component: Vue.defineAsyncComponent(() => import('@/views/errorPage/401')),
    hidden: true,
  },
]

export const asyncRouterMap = [
  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [
      {
        path: 'dashboard',
        component: Vue.defineAsyncComponent(
          () => import('@/views/dashboard/index')
        ),
        name: 'Dashboard',
        meta: { title: '工作台', icon: 'home', noCache: true, affix: true },
      },
    ],
  },
  {
    path: '/search',
    component: Layout,
    redirect: '/search/index',
    hidden: true,
    children: [
      {
        path: 'index',
        component: Vue.defineAsyncComponent(
          () => import('@/views/search/index')
        ),
        name: 'Search',
        meta: { title: 'search', icon: 'documentation' },
      },
    ],
  },
  {
    path: '/news',
    component: Layout,
    redirect: '/news/index',
    hidden: true,
    children: [
      {
        path: 'index',
        component: Vue.defineAsyncComponent(() => import('@/views/news/index')),
        name: 'News',
        meta: { title: 'news', icon: 'documentation' },
      },
    ],
  },
  {
    path: '/personalCenter',
    component: Layout,
    redirect: '/personalCenter/index',
    hidden: true,
    children: [
      {
        path: 'index',
        component: Vue.defineAsyncComponent(
          () => import('@/views/personalCenter/index')
        ),
        name: 'PersonalCenter',
        meta: { title: '个人中心', icon: 'documentation', affix: true },
      },
    ],
  },
  {
    path: '/customer',
    component: Layout,
    redirect: 'noredirect',
    name: 'Customer',
    meta: {
      title: '营销',
      icon: 'customer',
      permissionCode: ['001_003', '002_003'],
    },
    children: [
      {
        path: 'customerList',
        component: Vue.defineAsyncComponent(
          () => import('@/views/customer/customerList')
        ),
        name: 'CustomerList',
        meta: { title: '客户', noCache: true, permissionCode: ['001_003'] },
      },
      {
        path: 'contract',
        component: Vue.defineAsyncComponent(
          () => import('@/views/customer/contract')
        ),
        name: 'Contract',
        meta: { title: '合同', noCache: true, permissionCode: ['002_003'] },
      },
      {
        path: 'bill',
        component: Vue.defineAsyncComponent(
          () => import('@/views/customer/bill')
        ),
        name: 'Bill',
        meta: { title: '账单', noCache: true, permissionCode: ['015_008'] },
      },
    ],
  },
  {
    path: '/logistics',
    component: Layout,
    redirect: '/logistics',
    meta: { title: 'logistics', icon: 'van', permissionCode: ['003_003'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/logistics/index')
        ),
        name: 'Logistics',
        meta: { title: '物流', icon: 'van', permissionCode: ['003_003'] },
      },
    ],
  },
  {
    path: '/sample',
    component: Layout,
    redirect: '/sample',
    meta: { title: 'sample', icon: 'sample', permissionCode: ['004_002'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/sample/index')
        ),
        name: 'Sample',
        meta: { title: '样本', icon: 'sample', permissionCode: ['004_002'] },
      },
    ],
  },
  {
    path: '/experiment',
    component: Layout,
    redirect: 'noredirect',
    name: 'Experiment',
    meta: {
      title: 'experiment',
      icon: 'experiment',
      permissionCode: ['005_003', '006_003'],
    },
    children: [
      {
        path: 'nucleicAcid',
        component: Vue.defineAsyncComponent(
          () => import('@/views/experiment/nucleicAcid')
        ),
        name: 'NucleicAcid',
        meta: { title: '核酸', noCache: true, permissionCode: ['005_003'] },
      },
      {
        path: 'library',
        component: Vue.defineAsyncComponent(
          () => import('@/views/experiment/library')
        ),
        name: 'Library',
        meta: { title: '文库', noCache: true, permissionCode: ['006_003'] },
      },
    ],
  },
  {
    path: '/sequencing',
    component: Layout,
    redirect: '/sequencing',
    meta: {
      title: 'sequencing',
      icon: 'sequencing',
      permissionCode: ['007_003'],
    },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/sequencing/index')
        ),
        name: 'Sequencing',
        meta: {
          title: '测序',
          icon: 'sequencing',
          permissionCode: ['007_003'],
        },
      },
    ],
  },
  {
    path: '/analysis',
    component: Layout,
    redirect: '/analysis',
    meta: { title: 'analysis', icon: 'coding', permissionCode: ['008_003'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/analysis/index')
        ),
        name: 'Analysis',
        meta: { title: '分析', icon: 'coding', permissionCode: ['008_003'] },
      },
    ],
  },
  {
    path: '/report',
    component: Layout,
    redirect: '/report',
    meta: { title: 'report', icon: 'report', permissionCode: ['009_001'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/report/index')
        ),
        name: 'Report',
        meta: { title: '报告', icon: 'report', permissionCode: ['009_001'] },
      },
    ],
  },
  {
    path: '/verify',
    component: Layout,
    redirect: '/verify',
    meta: { title: 'verify', icon: 'report', permissionCode: ['013_001'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/verify/index')
        ),
        name: 'Verify',
        meta: { title: '审核', icon: 'edit', permissionCode: ['013_001'] },
      },
    ],
  },
  {
    path: '/charts',
    component: Layout,
    name: 'Charts',
    meta: {
      icon: 'chart',
      permissionCode: ['014_001'],
    },
    children: [
      {
        path: 'line',
        component: Vue.defineAsyncComponent(
          () => import('@/views/charts/line')
        ),
        name: 'LineChart',
        meta: { title: '统计', noCache: true },
      },
    ],
  },
  {
    path: '/set',
    component: Layout,
    redirect: '/feature',
    meta: { title: 'set', icon: 'set', permissionCode: ['010'] },
    children: [
      {
        path: 'sample',
        component: Vue.defineAsyncComponent(
          () => import('@/views/set/samplesSetting')
        ),
        name: 'SamplesSetting',
        meta: {
          title: '采样设置',
          noCache: true,
          permissionCode: ['010_001', '010_002', '010_003', '010_011'],
        },
      },
      {
        path: 'sales',
        component: Vue.defineAsyncComponent(
          () => import('@/views/set/salesSetting')
        ),
        name: 'SalesSetting',
        meta: { title: '销售设置', noCache: true, permissionCode: ['010_005'] },
      },
      {
        path: 'options',
        component: Vue.defineAsyncComponent(
          () => import('@/views/set/optionsSetting')
        ),
        name: 'OptionsSetting',
        meta: {
          title: '选项设置',
          noCache: true,
          permissionCode: [
            '010_004',
            '010_006',
            '010_009',
            '010_008',
            '010_007',
            '010_009',
            '010_018',
          ],
        },
      },
      {
        path: 'experiment',
        component: Vue.defineAsyncComponent(
          () => import('@/views/set/experimentSetting')
        ),
        name: 'ExperimentSetting',
        meta: {
          title: '实验设置',
          noCache: true,
          permissionCode: ['010_012', '010_013', '010_014', '010_015'],
        },
      },
      {
        path: 'analysis',
        component: Vue.defineAsyncComponent(
          () => import('@/views/set/analysisSetting')
        ),
        name: 'AnalysisSetting',
        meta: { title: '分析设置', noCache: true, permissionCode: ['010_016'] },
      },
    ],
  },
  /* 华丽丽的分割线*/

  { path: '*', redirect: '/404', hidden: true },
]

export const asyncBackendRouterMap = [
  {
    path: '/userAuth',
    component: Layout,
    redirect: '/userAuth',
    meta: { title: 'userAuth', icon: 'user', permissionCode: ['011_001'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/userAuth/index')
        ),
        name: 'userAuth',
        meta: { title: '用户权限', icon: 'user', permissionCode: ['011_001'] },
      },
    ],
  },
  {
    path: '/statistics',
    component: Layout,
    redirect: '/statistics',
    meta: { title: 'statistics', icon: 'data', permissionCode: ['011_002'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/statistics/index')
        ),
        name: 'statistics',
        meta: { title: '数据管理', icon: 'data', permissionCode: ['011_002'] },
      },
    ],
  },
  {
    path: '/instrument',
    component: Layout,
    redirect: '/instrument',
    meta: {
      title: 'instrument',
      icon: 'instrument',
      permissionCode: ['011_003'],
    },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/instrument/index')
        ),
        name: 'instrument',
        meta: {
          title: '仪器设备',
          icon: 'instrument',
          permissionCode: ['011_003'],
        },
      },
    ],
  },
  {
    path: '/analysisModule',
    component: Layout,
    redirect: '/analysisModule',
    meta: {
      title: 'analysisModule',
      icon: 'module',
      permissionCode: ['011_004'],
    },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/analysisModule/index')
        ),
        name: 'analysisModule',
        meta: {
          title: 'analysisModule',
          icon: 'module',
          permissionCode: ['011_004'],
        },
      },
    ],
  },
  {
    path: '/systemSetting',
    component: Layout,
    redirect: '/systemSetting',
    meta: { title: 'systemSetting', icon: 'set', permissionCode: ['011_005'] },
    children: [
      {
        path: '',
        component: Vue.defineAsyncComponent(
          () => import('@/views/systemSetting/index')
        ),
        name: 'systemSetting',
        meta: {
          title: 'systemSetting',
          icon: 'set',
          permissionCode: ['011_005'],
        },
      },
    ],
  },
]

export default VueRouter.createRouter({
  history: VueRouter.createWebHistory(),
  scrollBehavior: () => ({
    top: 0,
  }),
  routes: constantRouterMap,
})

permisson.js

import router from './router'
import store from './store'
// import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { asyncBackendRouterMap } from '@/router'
import { getRole } from '@/utils/auth'
import { getAuthInfo, deleteAuthInfo } from '@/utils/index'

NProgress.configure({ showSpinner: false }) // NProgress Configuration

// permission judge function
/* function hasPermission(roles, permissionRoles) {
  if (roles.indexOf('sagene') >= 0) return true // admin permission passed directly
  if (!permissionRoles) return true
  return roles.some(role => permissionRoles.indexOf(role) >= 0)
}*/

const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
let backendRouterMap = asyncBackendRouterMap.map((item) => item.path)
asyncBackendRouterMap.forEach((item) => {
  if (item.path === '/statistics') {
    return (backendRouterMap = backendRouterMap.concat(
      item.children.map((itm) => '/statistics/' + itm.path)
    ))
  }
})

// eslint-disable-next-line space-before-function-paren
router.beforeEach(async (to, from, next) => {
  NProgress.start() // start progress bar

  console.log(store.getters)
  console.log(getAuthInfo())
  const authInfo = getAuthInfo()

  if (authInfo) {
    // determine if there has token
    console.log(to.path)
    /* has token*/
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done() // if current page is dashboard will not trigger	afterEach hook, so manually handle it
    } else {
      // determine whether the user has obtained his permission roles through getInfo
      const hasRoles = store.getters.roles && store.getters.roles.length > 0

      authInfo.user.nickname
        ? store.dispatch('ChangeNickname', authInfo.user.nickname)
        : alert(`${authInfo.user.nickname}不存在`)
      store.dispatch('ChangeShowFrontend', !backendRouterMap.includes(to.path))
      store.dispatch(
        'ChangeShowBackendBtn',
        authInfo.permission_category.some((a) => /^011_/.test(a))
      )
      store.dispatch('ChangeShowSimulateBtn', authInfo.is_impersonate)

      // const hasRoles = getRole()
      if (hasRoles) {
        console.log('roles存在')
        console.log(to)
        /* 路由发生变化修改页面title */
        if (to.meta.title) {
          document.title = 'iSagene Cloud - ' + to.meta.title
        } else {
          document.title = 'iSagene Cloud'
        }
        console.log(
          'toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
        )
        console.log({ to, from })
        console.log({ ...to })
        if (to.matched.length === 0) {
          // next({ path: to.path })
          next()
          setTimeout(() => {
            // location.reload()
          }, 10)
        } else {
          next()
        }
      } else {
        console.log('roles不存在!!!!!!!!!')
        console.log(JSON.parse(localStorage.getItem('Permission-Route')))
        console.log(getRole())
        if (getRole()) {
          // 从cookie中获取role,并生成路由
          store.dispatch('getRoleFromCookie').then(
            () => {
              // 如果用户有权限, 但管理员修改了权限
              const shouldGotoFront =
                backendRouterMap.includes(to.path) &&
                !['011_001', '011_002', '011_003', '011_004', '011_005'].some(
                  (a) => authInfo.permission_category.includes(a)
                )
              const dataForGenerateRoutes = {
                isAdmin: authInfo.is_admin,
                permission: authInfo.permission_category,
                isFrontEndRouter:
                  shouldGotoFront || !backendRouterMap.includes(to.path),
              }
              console.log('从localStorage中获取的dataForGenerateRoutes')
              console.log(dataForGenerateRoutes)
              store
                .dispatch('GenerateRoutes', dataForGenerateRoutes)
                .then(() => {
                  // 根据roles权限生成可访问的路由表
                  // router.addRoutes(JSON.parse(localStorage.getItem('Add-Routers'))) // 动态添加可访问路由表
                  router.addRoute(store.getters.addRouters)
                  next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
                })
            },
            (error) => {
              console.log(error)
              next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
              NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
            }
          )
        } else {
          deleteAuthInfo()
          next({ path: '/' })
          NProgress.done() // if current page is dashboard will not trigger	afterEach hook, so manually handle it
        }
      }
    }
  } else {
    /* has no token*/
    if (whiteList.indexOf(to.path) !== -1) {
      // 在免登录白名单,直接进入
      next()
    } else {
      next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
    }
  }

  if (!window.localStorage) {
    console.log('浏览器不支持localStorage')
  }

  let size = 0
  Object.values(window.localStorage).forEach((item) => {
    size += item.length
  })

  const sizeToBi = (size / 1024).toFixed(2)
  if (sizeToBi > 4940) {
    alert('当前localStorage容量为' + sizeToBi + 'KB' + authInfo.toString())
  }
})

router.afterEach(() => {
  NProgress.done() // finish progress bar
})

  • your description:
Error: Invalid route component
    at extractComponentsGuards (vue-router.esm-bundler.js:1987:1)
    at vue-router.esm-bundler.js:3143:1

Tom9402 avatar Mar 21 '22 02:03 Tom9402