若依框架动态路由,点击侧边栏打开新标签页(看板大屏),免登陆、页面全屏显示

2 阅读2分钟

若依框架动态路由,通过新增菜单实现侧边栏打开新标签页(看板大屏),免登陆、页面全屏显示

一、新增菜单增加:是否打开新窗口参数

image.png

 <el-col :span="12" v-if="form.menuType == 'C'">
    <el-form-item label="是否打开新窗口" prop="openNewWindow" label-width="120px">
      <el-radio-group v-model="form.openNewWindow">
        <el-radio value="1"></el-radio>
        <el-radio value="0"></el-radio>
      </el-radio-group>
    </el-form-item>
  </el-col>

二、 在store/modules/permission.js 的GenerateRoutes方法中提取打开新窗口的路由

    //设置新窗口路由
    setNewWindowRoutes(routes) {
      this.newWindowRoutes = routes
    },
    generateRoutes(roles) {
      return new Promise((resolve) => {
        // 向后端请求路由数据
        getRouters({
          systemIdentifier: activeTopNav.value
        }).then((res) => {
          const sdata = JSON.parse(JSON.stringify(res.data))
          const rdata = JSON.parse(JSON.stringify(res.data))
          const defaultData = JSON.parse(JSON.stringify(res.data))

          // 提取需要新窗口打开的路由路径
          const newWindowRoutePaths = extractNewWindowRoutes(res.data)
          console.log(newWindowRoutePaths)
          this.setNewWindowRoutes(newWindowRoutePaths)

          // 提取"openNewWindow": "1"的路由,生成指定格式, 然后动态添加到路由中,覆盖原配置的路由
          const newWindowRoutes = generateNewWindowRoutes(res.data)
          newWindowRoutes.forEach((route) => {
            router.addRoute(route)
          })

          const sidebarRoutes = filterAsyncRouter(sdata)
          const rewriteRoutes = filterAsyncRouter(rdata, false, true)
          const defaultRoutes = filterAsyncRouter(defaultData)
          const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
          asyncRoutes.forEach((route) => {
            router.addRoute(route)
          })

          this.setRoutes(rewriteRoutes)
          this.setSidebarRouters(sidebarRoutes)
          this.setDefaultRoutes(sidebarRoutes)
          this.setTopbarRoutes(defaultRoutes)
          resolve(rewriteRoutes)
        })
      })
    },
   

跟在route/index.js,将看板大屏页面配置加到路由constantRoutes中的效果一样,通过generateNewWindowRoutes 方法动态生成以下的格式,并添加动态到路由中:

  {
    path: '/chronic_datav',
    component: () => import('@/views/chronic/DataV/chronic/index.vue'),
    hidden: true
  },

对应方法的逻辑

// 提取需要新窗口打开的路由路径
function extractNewWindowRoutes(routes, parentPath = '') {
  const newWindowPaths = []
  routes.forEach((route) => {
    const currentPath = parentPath ? `${parentPath}/${route.path}` : route.path
    // 检查当前路由是否需要新窗口打开
    if (route.openNewWindow === '1') {
      newWindowPaths.push(currentPath)
    }
    // 递归检查子路由
    if (route.children && route.children.length > 0) {
      const childPaths = extractNewWindowRoutes(route.children, currentPath)
      newWindowPaths.push(...childPaths)
    }
  })
  return newWindowPaths
}

// 生成新窗口路由的函数
function generateNewWindowRoutes(routes, parentPath = '') {
  const newWindowRoutes = []
  routes.forEach((route) => {
    const currentPath = parentPath ? `${parentPath}/${route.path}` : route.path
    // 检查当前路由是否需要新窗口打开
    if (route.openNewWindow === '1') {
      const newRoute = {
        path: currentPath.startsWith('/') ? currentPath : `/${currentPath}`,
        component: loadView(route.component),
        hidden: true
      }
      newWindowRoutes.push(newRoute)
    }
    // 递归检查子路由
    if (route.children && route.children.length > 0) {
      const childRoutes = generateNewWindowRoutes(route.children, currentPath)
      newWindowRoutes.push(...childRoutes)
    }
  })
  return newWindowRoutes
}

三、免登陆: 找到项目目录下src/permission.js, 判断免登陆

//白名单
const baseWhiteList = ['/login', '/register', '/iconset/index']

// 检查是否在白名单中(包括新窗口路由)
function isInWhiteList(path) {
  // 检查基础白名单
  if (baseWhiteList.includes(path)) {
    return true
  }
  //检查新窗口路由,如果存在,则返回true
  try {
    const permissionStore = usePermissionStore()
    if (permissionStore && permissionStore.newWindowRoutes) {
      return permissionStore.newWindowRoutes.includes(path)
    }
  } catch (error) {
    // 如果 store 还未初始化,只检查基础白名单
    console.log('Permission store not initialized yet')
  }
  return false
}

//使用
 if (isInWhiteList(to.path)) {
 // 在免登录白名单,直接进入
  next()
 }

四、打开新标签页: 项目文件路径下src/layout/components/Sidebar/Link.vue文件,新增跳转方法

<template>
  <component :is="type" v-bind="linkProps()">
    <slot />
  </component>
</template>

<script setup>
import { isExternal } from '@/utils/validate'
import usePermissionStore from '@/store/modules/permission'

const props = defineProps({
  to: {
    type: [String, Object],
    required: true
  }
})

const isExt = computed(() => {
  return isExternal(props.to)
})

const type = computed(() => {
  if (isExt.value) {
    return 'a'
  }
  // 如果是新窗口路由,也使用 a 标签
  if (isNewWindow()) {
    return 'a'
  }
  return 'router-link'
})

// 使用计算属性动态获取新窗口路由
const newWindowRoutes = computed(() => {
  try {
    const permissionStore = usePermissionStore()
    return permissionStore?.newWindowRoutes || []
  } catch (error) {
    return []
  }
})

// 判断是否为新窗口打开
function isNewWindow() {
  try {
    const routes = newWindowRoutes.value
    if (!routes || routes.length === 0) {
      return false
    }
    // 简化路径获取逻辑
    let routePath = ''
    if (typeof props.to === 'string') {
      routePath = props.to
    } else if (props.to && typeof props.to === 'object' && props.to.path) {
      routePath = props.to.path
    } else {
      return false
    }
    return routes.includes(routePath)
  } catch (error) {
    return false
  }
}

function linkProps() {
  // 判断是否为外链
  if (isExt.value) {
    return {
      href: props.to,
      target: '_blank',
      rel: 'noopener'
    }
  }

  // 判断是否为新窗口打开
  if (isNewWindow()) {
    const routePath = typeof props.to === 'string' ? props.to : props.to.path
    return {
      href: routePath,
      target: '_blank',
      rel: 'noopener'
    }
  }

  return {
    to: props.to
  }
}
</script>