PanJiaChen / vue-element-admin

:tada: A magical vue admin https://panjiachen.github.io/vue-element-admin
MIT License
87.55k stars 30.43k forks source link

动态路由成功从后台获取菜单,但点击后转向404页面 #3143

Open hiddenlong opened 4 years ago

hiddenlong commented 4 years ago

已从后台读取菜单,成功在前台显示了 但点击菜单后,转向有问题

1、如果静态路由里配置了404,那么会跳转到404页面 2、如果删除静态路由的404配置,整个页面就会跳转到一个空白的页面(左边菜单也没了)

努力的经过: 1、把从后台某个菜单写成前台静态的菜单,然后与后台动态菜单进行对比 对比如下图: image image 上图是前台静态的menu,在调试的时候看见的数据

image 20200427182402 上图是后台动态菜单,加载到routers之后的数据

2、对比了下动态加载的组件,如图下图: image 静态菜单是可以加载成功的,转向正常;(上图的per/perm是静态页面的路由)

点击后台菜单后,per/setper并没有动态加载出资源页面 很困惑.... 本来想追踪menu的点击事件,但不晓得咋入手了... 问题到这儿,不知道该怎么进行下去了。 不知道哪位大佬能帮忙看看问题?

注意:前台的页面是实际存在的...与前台静态写的menu我从后台读取出来,同样显示404。404这个问题和后台无关,还没到后台的部分。

zhoupeihuang commented 4 years ago

点击后台菜单后,后台返回路由数据,but 你的路由 没有侧边和顶部栏的原因 是在 component:Layout里面的Layout是一个变量,而你的返回的是一个常量,解析的时候 会 router = [{ path: '', hidden: true, component: Layout,......}] Layout 会预先 去 解析,但是路由解析不了这个 所以导致成未知的 从而进入了404

hiddenlong commented 4 years ago

@zhoupeihuang 再贴代码上来,帮忙看看分析分析怎么解决?

zhoupeihuang commented 4 years ago

明天吧,下班了

---原始邮件--- 发件人: "hiddenlong"<notifications@github.com> 发送时间: 2020年6月30日(周二) 晚上8:12 收件人: "PanJiaChen/vue-element-admin"<vue-element-admin@noreply.github.com>; 抄送: "Mention"<mention@noreply.github.com>;"zhoupeihuang"<625506370@qq.com>; 主题: Re: [PanJiaChen/vue-element-admin] 动态路由成功从后台获取菜单,但点击后转向404页面 (#3143)

@zhoupeihuang 再贴代码上来,帮忙看看分析分析怎么解决?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

zhoupeihuang commented 4 years ago

1、如果静态路由里配置了404,那么会跳转到404页面 2、如果删除静态路由的404配置,整个页面就会跳转到一个空白的页面(左边菜单也没了) NO1:静态路由删除 path:"*" == 404 否则的确会所有都是404 NO2:条件空白页是 页面装载时候 没加入 左侧菜单,此处叫做Layout组件集合 你可以 静态路由配置加入roles and hidden:true 这个是所有静态都是加入这个,相当于一个完整的路由权限表 写在前端 然后后台获取的路由权限 routerList 再执行一遍filterAsyncRoutes 具体 https://juejin.im/post/591aa14f570c35006961acac 从权限篇哪里看 wechat :xiaopei727771

hiddenlong commented 4 years ago

No2就是我现在的解决方案,缺陷在于菜单增加后,前端也必须在静态菜单上添加,感觉不完美...我看见有人直接从后台读取菜单,并显示的,但按照他们那种方式,还是始终解决不了,动态创建layout为空的问题...

`/**

zhoupeihuang commented 4 years ago

你的addrouters 呢

zhoupeihuang commented 4 years ago

实现的时候 别忘记告诉我 感激

625506370@qq.com

发件人: hiddenlong 发送时间: 2020-07-01 10:59 收件人: PanJiaChen/vue-element-admin 抄送: zhoupeihuang; Mention 主题: Re: [PanJiaChen/vue-element-admin] 动态路由成功从后台获取菜单,但点击后转向404页面 (#3143) No2就是我现在的解决方案,缺陷在于菜单增加后,前端也必须在静态菜单上添加,感觉不完美...我看见有人直接从后台读取菜单,并显示的,但按照他们那种方式,还是始终解决不了,动态创建layout为空的问题... /** 后台查询的菜单数据拼装成路由格式的数据 @param routes */ export function generaMenu(routes, data) { data.forEach(item => { // alert(JSON.stringify(item)) const menu = { path: item.path === '#' ? item.id + 'key' : item.path, component: item.component === '#' ? Layout : () => import(@/views${item.component}), hidden: item.hidden, redirect: item.redirect, children: [], name: 'menu' + item.id, meta: item.meta // meta: { title: item.name, id: item.id, roles: ['admin'] } } if (item.children) { generaMenu(menu.children, item.children) } routes.push(menu) }) } 我觉得应该是这个地方出了问题。 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

hiddenlong commented 4 years ago

1、src/permission.js 关键:store.dispatch('permission/generateRoutes', roles)

router.beforeEach(async(to, from, next) => {
  ......
      try {
        // get user info
        // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
        const { roles } = await store.dispatch('user/getInfo')
        // generate accessible routes map based on roles
        const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
        // dynamically add accessible routes
        router.addRoutes(accessRoutes)
        // hack method to ensure that addRoutes is complete
        // set the replace: true, so the navigation will not leave a history record
        next({ ...to, replace: true })
      } catch (error) {
        // remove token and go to login page to re-login
        await store.dispatch('user/resetToken')
        Message.error(error || 'Has Error')
        next(`/login?redirect=${to.path}`)
        NProgress.done()
      }
    ......
})

2.store/permission.js 关键:generateRoutes,generaMenu

generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      const loadMenuData = []
      // 先查询后台并返回左侧菜单数据并把数据添加到路由
      getAuthMenu(state.token).then(response => {
        let data = response
        if (response.code !== 20000) {
          alert(JSON.stringify('菜单数据加载异常'))
          // throw new Error('菜单数据加载异常')
        } else {
          data = response.data
          Object.assign(loadMenuData, data)
          const tempAsyncRoutes = Object.assign([], asyncRoutes)
          // tempAsyncRoutes = asyncRoutes
          generaMenu(tempAsyncRoutes, loadMenuData)
          let accessedRoutes
          if (roles.includes('admin')) {
            // alert(JSON.stringify(asyncRoutes))
            accessedRoutes = tempAsyncRoutes || []
          } else {
            accessedRoutes = filterAsyncRoutes(tempAsyncRoutes, roles)
          }
          commit('SET_ROUTES', accessedRoutes)
          resolve(accessedRoutes)
        }
        // generaMenu(asyncRoutes, data)
      }).catch(error => {
        console.log(error)
      })
    })
  }
export function generaMenu(routes, data) {
  data.forEach(item => {
    // alert(JSON.stringify(item))
    const menu = {
      path: item.path === '#' ? item.id + '_key' : item.path,
      component: item.component === '#' ? Layout : () => import(`@/views${item.component}`),
      hidden: item.hidden,
      redirect: item.redirect,
      children: [],
      name: 'menu_' + item.id,
      meta: item.meta
      // meta: { title: item.name, id: item.id, roles: ['admin'] }
    }

    if (item.children) {
      generaMenu(menu.children, item.children)
    }
    routes.push(menu)
  })
}
hiddenlong commented 4 years ago

目前问题还为解决...等项目完成之后再回头来看看这个问题吧

ddumk commented 3 years ago

我们项目中用户拥有不同角色,角色可以动态配置不同的权限,API获取用户权限列表进而展示不同的菜单,同样遇到这个问题,除了上面提到的No2,请问兄弟还有什么更好的解决方案吗?

hewei7senderjoy commented 3 years ago

我困惑了3个小时后,莫名奇妙解决了这个问题。 要解决问题要有逆向思维,不要想着后端获取路由-》拼接路由route-》add到左侧菜单这条路。 要先把所有可能的路由都放进去,然后再把菜单显示filter出去。也就是在export const asyncRoutes 这个里面,把所有可能的路由配置上。 然后再filterAsyncRoutes 这里面去filter。 如果asyncRoutes 原来没有这个路由,永远是404

hiddenlong commented 3 years ago

可能和nodejs的便宜环境有关系,现在使用了另外一个基于该项目的开源项目。已经没有这个问题了。

hiddenlong commented 3 years ago

https://github.com/elunez/eladmin-web