增加外链路由跳转提示页面,重构外链路由的配置方式

This commit is contained in:
hooray
2022-12-01 20:11:56 +08:00
parent 7a3ff65b05
commit 68f45dd7dc
14 changed files with 155 additions and 65 deletions
+2
View File
@@ -220,6 +220,7 @@ declare module 'vue-router' {
breadcrumb?: boolean
activeMenu?: string
cache?: boolean | string | string[]
link?: string
breadcrumbNeste?: Route.breadcrumb[]
}
}
@@ -250,6 +251,7 @@ declare namespace Menu {
defaultOpened?: boolean
auth?: string | string[]
sidebar?: boolean
link?: string
}
children?: recordRaw[]
}
+1 -1
View File
@@ -31,7 +31,7 @@ onMounted(() => {
})
function open(url: string) {
window.open(url, 'top')
window.open(url, '_blank')
}
</script>
+9 -15
View File
@@ -2,7 +2,6 @@
import { cloneDeep } from 'lodash-es'
import hotkeys from 'hotkeys-js'
import type { RouteRecordRaw } from 'vue-router'
import { isExternalLink } from '@/utils'
import eventBus from '@/utils/eventBus'
import useSettingsStore from '@/store/modules/settings'
import useRouteStore from '@/store/modules/route'
@@ -16,10 +15,11 @@ const routeStore = useRouteStore()
const menuStore = useMenuStore()
interface listTypes {
path: string
icon?: string
title?: string | Function
link?: string
breadcrumb: (string | Function | undefined)[]
path: string
}
const isShow = ref(false)
@@ -151,18 +151,12 @@ function getSourceList(arr: RouteRecordRaw[], basePath?: string, icon?: string,
}
else {
breadcrumbTemp.push(item.meta?.title)
let path = ''
if (isExternalLink(item.path)) {
path = item.path
}
else {
path = basePath ? [basePath, item.path].join('/') : item.path
}
sourceList.value.push({
path: basePath ? [basePath, item.path].join('/') : item.path,
icon: item.meta?.icon ?? icon,
title: item.meta?.title,
link: item.meta?.link,
breadcrumb: breadcrumbTemp,
path,
})
}
}
@@ -230,12 +224,12 @@ function handleScroll() {
})
}
function pageJump(url: string) {
if (isExternalLink(url)) {
window.open(url, 'top')
function pageJump(path: listTypes['path'], link: listTypes['link']) {
if (link) {
window.open(link, '_blank')
}
else {
router.push(url)
router.push(path)
}
}
</script>
@@ -284,7 +278,7 @@ function pageJump(url: string) {
</div>
</div>
<div ref="searchResultRef" class="result" :class="{ mobile: settingsStore.mode === 'mobile' }">
<a v-for="(item, index) in resultList" :key="item.path" :ref="setSearchResultItemRef" class="item" :class="{ actived: index === actived }" @click="pageJump(item.path)" @mouseover="actived = index">
<a v-for="(item, index) in resultList" :key="item.path" :ref="setSearchResultItemRef" class="item" :class="{ actived: index === actived }" @click="pageJump(item.path, item.link)" @mouseover="actived = index">
<el-icon class="icon">
<svg-icon v-if="item.icon" :name="item.icon" />
</el-icon>
+5 -5
View File
@@ -1,6 +1,6 @@
<script lang="ts" setup name="SidebarItem">
// import SidebarItem from './index.vue'
import { isExternalLink, resolveRoutePath } from '@/utils'
import { resolveRoutePath } from '@/utils'
import useSettingsStore from '@/store/modules/settings'
import type { Menu } from '@/global'
@@ -33,8 +33,8 @@ const hasChildren = computed(() => {
<template>
<div class="sidebar-item">
<router-link v-if="!hasChildren" v-slot="{ href, navigate, isActive, isExactActive }" custom :to="resolveRoutePath(basePath, item.path || '')">
<a :href="isExternalLink(resolveRoutePath(basePath, item.path || '')) ? resolveRoutePath(basePath, item.path || '') : href" :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']" :target="isExternalLink(resolveRoutePath(basePath, item.path || '')) ? '_blank' : '_self'" @click="navigate">
<router-link v-if="!hasChildren" v-slot="{ navigate, isActive, isExactActive }" custom :to="resolveRoutePath(basePath, item.path)">
<a :href="item.meta?.link ? item.meta.link : resolveRoutePath(basePath, item.path)" :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']" :target="item.meta?.link ? '_blank' : '_self'" @click="navigate">
<el-menu-item :title="item.meta?.title ?? '[ 无标题 ]'" :index="resolveRoutePath(basePath, item.path || '')">
<el-icon v-if="item.meta?.icon" class="title-icon">
<svg-icon :name="item.meta.icon" />
@@ -43,7 +43,7 @@ const hasChildren = computed(() => {
</el-menu-item>
</a>
</router-link>
<el-sub-menu v-else :title="item.meta?.title ?? '[ 无标题 ]'" :index="settingsStore.app.routeBaseOn !== 'filesystem' ? resolveRoutePath(basePath, item.path || '') : JSON.stringify(item)">
<el-sub-menu v-else :title="item.meta?.title ?? '[ 无标题 ]'" :index="settingsStore.app.routeBaseOn !== 'filesystem' ? resolveRoutePath(basePath, item.path) : JSON.stringify(item)">
<template #title>
<el-icon v-if="item.meta?.icon" class="title-icon">
<svg-icon :name="item.meta.icon" />
@@ -51,7 +51,7 @@ const hasChildren = computed(() => {
<span class="title">{{ item.meta?.title ?? '[ 无标题 ]' }}</span>
</template>
<template v-for="route in item.children">
<SidebarItem v-if="route.meta?.sidebar !== false" :key="route.path" :item="route" :base-path="resolveRoutePath(basePath, item.path || '')" />
<SidebarItem v-if="route.meta?.sidebar !== false" :key="route.path" :item="route" :base-path="resolveRoutePath(basePath, item.path)" />
</template>
</el-sub-menu>
</div>
+1 -1
View File
@@ -37,7 +37,7 @@ function userCommand(command: 'home' | 'setting' | 'hotkeys' | 'logout') {
}
}
function pro() {
window.open('https://hooray.gitee.io/fantastic-admin-pro-example/', 'top')
window.open('https://hooray.gitee.io/fantastic-admin-pro-example/', '_blank')
}
</script>
+97
View File
@@ -0,0 +1,97 @@
<script lang="ts" setup name="LinkView">
const route = useRoute()
function open() {
window.open(route.meta.link, '_blank')
}
</script>
<template>
<div class="link-view">
<transition name="link" mode="out-in" appear>
<page-main :key="route.meta.link" title="⚠️访问提醒">
<div class="container">
<div class="title">
是否访问此链接
</div>
<div class="link">
{{ route.meta.link }}
</div>
<el-button type="primary" plain round @click="open">
<template #icon>
<el-icon>
<svg-icon name="ep:link" />
</el-icon>
</template>
立即访问
</el-button>
</div>
</page-main>
</transition>
</div>
</template>
<style lang="scss" scoped>
.link-view {
display: flex;
flex-direction: column;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.page-main {
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
margin: 0 50px;
.title {
margin: 10px 0;
font-size: 22px;
color: var(--el-text-color-primary);
}
.link {
margin: 10px 0;
max-width: 300px;
font-size: 14px;
color: var(--el-text-color-disabled);
@include text-overflow(3);
}
.el-button {
margin: 20px 0;
}
}
}
}
// link 区动画
.link-enter-active {
transition: 0.2s;
}
.link-leave-active {
transition: 0.15s;
}
.link-enter-from {
opacity: 0;
transform: translateX(-20px);
}
.link-leave-to {
opacity: 0;
transform: translateX(20px);
}
</style>
+5 -1
View File
@@ -1,5 +1,6 @@
<script lang="ts" setup name="Layout">
import hotkeys from 'hotkeys-js'
import LinkView from './components/views/link.vue'
import Header from './components/Header/index.vue'
import MainSidebar from './components/MainSidebar/index.vue'
import SubSidebar from './components/SubSidebar/index.vue'
@@ -18,6 +19,8 @@ const settingsStore = useSettingsStore()
const keepAliveStore = useKeepAliveStore()
const menuStore = useMenuStore()
const isLink = computed(() => !!routeInfo.meta.link)
watch(() => settingsStore.menu.subMenuCollapse, (val) => {
if (settingsStore.mode === 'mobile') {
if (!val) {
@@ -73,10 +76,11 @@ onUnmounted(() => {
<router-view v-slot="{ Component, route }">
<transition name="main" mode="out-in" appear>
<keep-alive :include="keepAliveStore.list">
<component :is="Component" :key="route.fullPath" />
<component :is="Component" v-show="!isLink" :key="route.fullPath" />
</keep-alive>
</transition>
</router-view>
<LinkView v-if="isLink" />
</div>
<Copyright />
</div>
+14 -4
View File
@@ -5,46 +5,56 @@ const Layout = () => import('@/layouts/index.vue')
const routes: RouteRecordRaw[] = [
{
path: '/official',
redirect: '/official/fantastic-startkit',
meta: {
title: '官方周边',
icon: 'ep:grid',
},
children: [
{
path: 'https://hooray.gitee.io/fantastic-startkit/',
path: 'fantastic-startkit',
redirect: '',
name: 'officialFantasticStartkit',
meta: {
title: 'Fantastic-startkit 项目启动套件',
link: 'https://hooray.gitee.io/fantastic-startkit/',
},
},
{
path: 'https://hooray.gitee.io/one-step-admin/',
path: 'one-step-admin',
redirect: '',
name: 'officialOneStepAdmin',
meta: {
title: 'One-step-admin 干啥都快人一步的中后台框架',
link: 'https://hooray.gitee.io/one-step-admin/',
},
},
],
},
{
path: '/cooperation',
redirect: '/cooperation/vform',
meta: {
title: '战略合作',
icon: 'sidebar-cooperation',
},
children: [
{
path: 'https://www.vform666.com',
path: 'vform',
redirect: '',
name: 'cooperationVform',
meta: {
title: 'VForm 低代码表单',
link: 'https://www.vform666.com',
},
},
{
path: 'https://gitee.com/sciqtw/quickadmin',
path: 'quickadmin',
redirect: '',
name: 'cooperationQuickadmin',
meta: {
title: 'QuickAdmin 快速开发管理框架',
link: 'https://gitee.com/sciqtw/quickadmin',
},
},
],
+7 -2
View File
@@ -5,6 +5,7 @@ const Layout = () => import('@/layouts/index.vue')
const routes: RouteRecordRaw = {
path: '/link',
component: Layout,
redirect: '/link/gitee',
name: 'externalLinkExample',
meta: {
title: '外链',
@@ -12,17 +13,21 @@ const routes: RouteRecordRaw = {
},
children: [
{
path: 'https://gitee.com/hooray/fantastic-admin',
path: 'gitee',
redirect: '',
name: 'externalLinkGitee',
meta: {
title: 'Gitee 仓库',
link: 'https://gitee.com/hooray/fantastic-admin',
},
},
{
path: 'https://github.com/hooray/fantastic-admin',
path: 'github',
redirect: '',
name: 'externalLinkGithub',
meta: {
title: 'Github 仓库',
link: 'https://github.com/hooray/fantastic-admin',
},
},
],
+9 -15
View File
@@ -10,24 +10,18 @@ import menu from '@/menu'
function getDeepestPath(menu: Menu.recordRaw, rootPath = '') {
let retnPath = ''
if (menu.path !== undefined) {
if (menu.children) {
if (menu.children.some(item => item.meta?.sidebar !== false)) {
for (let i = 0; i < menu.children.length; i++) {
if (menu.children[i].meta?.sidebar !== false) {
retnPath = getDeepestPath(menu.children[i], resolveRoutePath(rootPath, menu.path))
break
}
}
}
else {
retnPath = getDeepestPath(menu.children[0], resolveRoutePath(rootPath, menu.path))
}
if (menu.children) {
const item = menu.children.find(item => item.meta?.sidebar !== false)
if (item) {
retnPath = getDeepestPath(item, resolveRoutePath(rootPath, menu.path))
}
else {
retnPath = resolveRoutePath(rootPath, menu.path)
retnPath = getDeepestPath(menu.children[0], resolveRoutePath(rootPath, menu.path))
}
}
else {
retnPath = resolveRoutePath(rootPath, menu.path)
}
return retnPath
}
@@ -68,7 +62,7 @@ function filterAsyncMenus<T extends Menu.recordMainRaw[] | Menu.recordRaw[]>(men
function getDefaultOpenedPaths(menus: Menu.recordRaw[], rootPath = '') {
const defaultOpenedPaths: string[] = []
menus.forEach((item) => {
if (item.path && item.meta?.defaultOpened && item.children) {
if (item.meta?.defaultOpened && item.children) {
defaultOpenedPaths.push(resolveRoutePath(rootPath, item.path))
const childrenDefaultOpenedPaths = getDefaultOpenedPaths(item.children, resolveRoutePath(rootPath, item.path))
if (childrenDefaultOpenedPaths.length > 0) {
+1 -7
View File
@@ -1,7 +1,6 @@
import router from '@/router'
import useSettingsStore from '@/store/modules/settings'
import useMenuStore from '@/store/modules/menu'
import { isExternalLink } from '@/utils'
export default function useMenu() {
const settingsStore = useSettingsStore()
@@ -10,12 +9,7 @@ export default function useMenu() {
function switchTo(index: number | string) {
menuStore.setActived(index)
if (settingsStore.menu.switchMainMenuAndPageJump) {
if (isExternalLink(menuStore.sidebarMenusFirstDeepestPath)) {
window.open(menuStore.sidebarMenusFirstDeepestPath, '_blank')
}
else {
void router.push(menuStore.sidebarMenusFirstDeepestPath)
}
void router.push(menuStore.sidebarMenusFirstDeepestPath)
}
}
+2 -12
View File
@@ -1,15 +1,5 @@
import path from 'path-browserify'
export function isExternalLink(path: string) {
return /^(https?:|mailto:|tel:)/.test(path)
}
export function resolveRoutePath(basePath: string, routePath: string) {
if (isExternalLink(routePath)) {
return routePath
}
if (isExternalLink(basePath)) {
return basePath
}
return basePath ? path.resolve(basePath, routePath) : routePath
export function resolveRoutePath(basePath: string, routePath?: string) {
return basePath ? path.resolve(basePath, routePath ?? '') : routePath ?? ''
}
+1 -1
View File
@@ -6,7 +6,7 @@ meta:
<script lang="ts" setup>
function open(url: string) {
window.open(url, 'top')
window.open(url, '_blank')
}
const fantasticStartkitInfo = ref({
+1 -1
View File
@@ -19,7 +19,7 @@ function getPermission() {
}
function open(url: string) {
window.open(url, 'top')
window.open(url, '_blank')
}
</script>