antdvPro路由生成逻辑

Login.vue

    handleSubmit (e) {
      validateFields(validateFieldsKey, { force: true }, (err, values) => {
          Login(loginParams)		// 调用 src/store/modules/user.js中的actions中的Login方法
      })
    },

src/store/modules/user.js

    Login ({ commit }, userInfo) {
      return new Promise((resolve, reject) => {
        login(userInfo).then(response => {			// 调用 src/api/login.js中的login函数发送请求
          const result = response.result
          // 在 localStorage 中 存 ACCESS_TOKEN
          storage.set(ACCESS_TOKEN, result.token, new Date().getTime() + 7 * 24 * 60 * 60 * 1000)
          // 将 token 存到 state 中
          commit('SET_TOKEN', result.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    }

// login接口 Mock 返回的数据 [src/mock/services/auth.js]
const login = (options) => {
  const body = getBody(options)			// 请求时携带的参数数据
  console.log('mock: body', body)
  if (!username.includes(body.username) || !password.includes(body.password)) {
    return builder({ isLogin: true }, '账户或密码错误', 401)
  }
// 定义 mock 返回的数据
  return builder({
    'id': Mock.mock('@guid'),
    'name': Mock.mock('@name'),
    'username': 'admin',
    'passwod': '',
    'avatar': 'https://gw.alipayobjects.com/zos/rmsportal/jZUIxmJycoymBprLOUbT.png',
    'status': 1,
    'telephone': '',
    'lastLoginIp': '27.154.74.117',
    'lastLoginTime': 1534837621348,
    'creatorId': 'admin',
    'createTime': 1497160610259,
    'deleted': 0,
    'roleId': 'admin',
    'lang': 'zh-CN',
    'toke': '4291d7da90057ec9aec4a71ea837f'
  }, '', 200, { 'Custom-Header': Mock.mock('@guid') })
}

之后进行路由的跳转,在src/permission.js中定义了路由导航守卫

router.beforeEach((to, from, next) => {
// 如果to.meta.title存在且不为undefined, 就设置网页标签页标题
  to.meta && typeof to.meta.title !== 'undefined' && setDocumentTitle(`${i18nRender(to.meta.title)} - ${domTitle}`)
  const token = storage.get(ACCESS_TOKEN)
  if (token) {
  	// 去往登录页则直接跳转到首页
    if (to.path === loginRoutePath) {
      next({ path: defaultRoutePath })
      NProgress.done()
    } else {
      // 有token 但去的不是登录页
      if (store.getters.roles.length === 0) {
        // request login userInfo
        store
          .dispatch('GetInfo')		// 调用 src/store/modules/user.js中的actions中的GetInfo方法
          .then(res => {
			// 调用 src/router/generator-routers.js中的 generatorDynamicRouter 函数
            generatorDynamicRouter(token).then(routers => {		
              store.commit('SET_ROUTERS', routers)			// 存到 state 中

              // 根据roles权限生成可访问的路由表
              // 动态添加可访问路由表
              resetRouter() // 重置路由 防止退出重新登录或者token过期后页面未刷新,导致的路由重复添加
              store.getters.addRouters.forEach(r => {
                router.addRoute(r)			// 添加到路由结构中
              })
              // 请求带有 redirect 重定向时,登录自动重定向到该地址
              const redirect = decodeURIComponent(from.query.redirect || to.path)
              if (to.path === redirect) {
                // set the replace: true so the navigation will not leave a history record
                next({ ...to, replace: true })
              } else {
                // 跳转到目的路由
                next({ path: redirect })
              }
            })
          })
          .catch(() => {
            notification.error({
              message: '错误',
              description: '请求用户信息失败,请重试'
            })
            // 失败时,获取用户信息失败时,调用登出,来清空历史保留信息
            store.dispatch('Logout').then(() => {
              next({ path: loginRoutePath, query: { redirect: to.fullPath } })
            })
          })
      } else {
        next()
      }
    }
  } else {
    if (allowList.includes(to.name)) {
      // 在免登录名单,直接进入
      next()
    } else {
      next({ path: loginRoutePath, query: { redirect: to.fullPath } })
      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
    }
  }
})

src/store/modules/user.js

    GetInfo ({ commit }) {
      return new Promise((resolve, reject) => {
        getInfo().then(response => {		// 调用 src/api/login.js中的getInfo函数发送请求
        
        // 对响应回来的数据处理, 并将有些信息存到 state 中
          const result = response.result
          if (result.role && result.role.permissions.length > 0) {
            const role = result.role
            role.permissions = result.role.permissions
            // 提取汇总permissions数组中每一个元素的action
            role.permissions.map(per => {
              if (per.actionEntitySet != null && per.actionEntitySet.length > 0) {
                const action = per.actionEntitySet.map(action => { return action.action })
                per.actionList = action
              }
            })
            // 汇总permissions数组中每一个元素的permissionId
            role.permissionList = role.permissions.map(permission => { return permission.permissionId })
            commit('SET_ROLES', result.role)	// 存到 state 中
            commit('SET_INFO', result)			// 存到 state 中
          } else {
            reject(new Error('getInfo: roles must be a non-null array !'))
          }
		// 存到 state 中
          commit('SET_NAME', { name: result.name, welcome: welcome() })
          commit('SET_AVATAR', result.avatar)

          resolve(response)
        }).catch(error => {
          reject(error)
        })
      })
    },

getInfo接口返回的数据

const info = options => {
  const userInfo = {
    id: '4291d7da9005377ec9aec4a71ea837f',
    name: '天野远子',
    username: 'admin',
    password: '',
    avatar: '/avatar2.jpg',
    status: 1,
    telephone: '',
    lastLoginIp: '27.154.74.117',
    lastLoginTime: 1534837621348,
    creatorId: 'admin',
    createTime: 1497160610259,
    merchantCode: 'TLif2btpzg079h15bk',
    deleted: 0,
    roleId: 'admin',
    role: {}
  }
  // role
  const roleObj = {
    id: 'admin',
    name: '管理员',
    describe: '拥有所有权限',
    status: 1,
    creatorId: 'system',
    createTime: 1497160610259,
    deleted: 0,
    permissions: [
      {
        roleId: 'admin',
        permissionId: 'dashboard',
        permissionName: '仪表盘',
        actionEntitySet: [
          {
            action: 'add',
            describe: '新增',
            defaultCheck: false
          },
          {
            action: 'update',
            describe: '修改',
            defaultCheck: false
          },
          {
            action: 'delete',
            describe: '删除',
            defaultCheck: false
          }
        ],
        actionList: null,
        dataAccess: null
      }
    ]
  }
  userInfo.role = roleObj
  return builder(userInfo)
}

src/router/generator-routers.js

export const generatorDynamicRouter = token => {
  return new Promise((resolve, reject) => {
    loginService
      .getCurrentUserNav(token)		// 调用 src/api/login.js中的getCurrentUserNav函数发送请求
      .then(res => {
        console.log('generatorDynamicRouter response:', res)
        const { result } = res
        const menuNav = []
        const childrenNav = []
        //  对 响应得到的数据进行加工处理, 生成路由表
        listToTree(result, childrenNav, 0)
        rootRouter.children = childrenNav
        menuNav.push(rootRouter)

        const routers = generator(menuNav)
        routers.push(notFoundRouter)			// 得到 路由表
        
        resolve(routers)
      })
      .catch(err => {
        reject(err)
      })
  })
}

getCurrentUserNav接口返回的数据

const userNav = options => {
  const nav = [
    // dashboard
    {
      name: 'dashboard',
      parentId: 0,
      id: 1,
      meta: {
        title: 'menu.dashboard',
        icon: 'dashboard',
        show: true
      },
      component: 'RouteView',
      redirect: '/dashboard/workplace'
    },
    {
      name: 'workplace',
      parentId: 1,
      id: 7,
      meta: {
        title: 'menu.dashboard.monitor',
        show: true
      },
      component: 'Workplace'
    },
    {
      name: 'monitor',
      path: 'https://www.baidu.com/',
      parentId: 1,
      id: 3,
      meta: {
        title: 'menu.dashboard.workplace',
        target: '_blank',
        show: true
      }
    }
  ]
  const json = builder(nav)
  console.log('json', json)
  return json
}

说白了,默认的这种方式,是通过后端返回的数据进行加工来动态生成路由的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值