feat: 外链的处理逻辑以及全局视口组件封装
This commit is contained in:
parent
7305de45a0
commit
3ae0c6ed19
16
README.md
16
README.md
@ -2,8 +2,7 @@
|
||||
|
||||
### 介绍 📖
|
||||
|
||||
DC-Admin 一款基于 Vue3、TypeScript、Vite5、Pinia、Arco-Design 开源的后台管理框架,使用目前最新技术栈开发。项目提供了一些常用组件,在一定程度上提高您的开发效率。另外本项目还封装了一些常用组件、Hooks、动态路由等功能。
|
||||
|
||||
DC-Admin 一款基于 Vue3、TypeScript、Vite5、Pinia、Arco-Design 开源的后台管理框架,符合直觉的使用模式,使用目前最新技术栈开发。项目提供了一些常用组件,在一定程度上提高您的开发效率。另外本项目还封装了一些常用组件、Hooks、动态路由等功能。
|
||||
|
||||
### 在线预览 👀
|
||||
|
||||
@ -75,29 +74,18 @@ pnpm lint:eslint
|
||||
pnpm lint:prettier
|
||||
```
|
||||
|
||||
|
||||
### 项目截图 📷
|
||||
|
||||
- 登录页:
|
||||
|
||||
|
||||
|
||||
- 首页:
|
||||
|
||||
|
||||
|
||||
- 表格页:
|
||||
|
||||
|
||||
|
||||
- 用户中心:
|
||||
|
||||
|
||||
|
||||
- 系统配置页:
|
||||
|
||||
|
||||
|
||||
### 文件资源目录 📚
|
||||
|
||||
```text
|
||||
@ -153,4 +141,4 @@ DC-Admin
|
||||
|
||||
### 项目后台接口 🧩
|
||||
|
||||
建设中
|
||||
建设中
|
||||
|
||||
2
src/components.d.ts
vendored
2
src/components.d.ts
vendored
@ -9,6 +9,8 @@ declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
CodemirrorCode: typeof import('./components/codemirror-code/index.vue')['default']
|
||||
CodeView: typeof import('./components/code-view/index.vue')['default']
|
||||
ExternalLinkPage: typeof import('./components/external-link-page/index.vue')['default']
|
||||
FillPage: typeof import('./components/fill-page/index.vue')['default']
|
||||
LangProvider: typeof import('./components/lang-provider/index.vue')['default']
|
||||
MainTransition: typeof import('./components/main-transition/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
|
||||
42
src/components/external-link-page/index.vue
Normal file
42
src/components/external-link-page/index.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<FillPage>
|
||||
<div class="external-link-page">
|
||||
<div>
|
||||
<div class="star-emoji">🌍</div>
|
||||
<div class="docs-text">外链页面已经在新窗口中打开</div>
|
||||
<div class="to-page"><a-button type="primary" @click="openPage">立即前往</a-button></div>
|
||||
</div>
|
||||
</div>
|
||||
</FillPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from "vue-router";
|
||||
const route = useRoute();
|
||||
const openPage = () => {
|
||||
window.open(route.meta.link as string, "_blank");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.external-link-page {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.star-emoji {
|
||||
text-align: center;
|
||||
font-size: 100px;
|
||||
}
|
||||
.docs-text {
|
||||
text-align: center;
|
||||
color: $color-text-3;
|
||||
margin: $margin 0;
|
||||
}
|
||||
.to-page {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
48
src/components/fill-page/index.vue
Normal file
48
src/components/fill-page/index.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div
|
||||
class="fill-page-size"
|
||||
:style="{
|
||||
height: viewportHeight
|
||||
}"
|
||||
>
|
||||
<div class="fill-page-inner">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
const themeStore = useThemeConfig();
|
||||
let { isTabs, isFooter } = storeToRefs(themeStore);
|
||||
// footer: 30px
|
||||
// tabs: 40px
|
||||
// head: 60px
|
||||
const viewportHeight = computed(() => {
|
||||
// 有tabs、有footer
|
||||
if (isTabs.value && isFooter.value) {
|
||||
return `calc(100vh - 60px - 30px - 40px)`;
|
||||
} else if (!isTabs.value && isFooter.value) {
|
||||
// 无tabs,有footer
|
||||
return `calc(100vh - 60px - 30px)`;
|
||||
} else {
|
||||
// 无tabs、无footer,直接减去顶部head
|
||||
return `calc(100vh - 60px)`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.fill-page-size {
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.fill-page-inner {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: $padding;
|
||||
background: $color-bg-1;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@ -27,8 +27,21 @@ export const useRoutingMethod = () => {
|
||||
const { tabsList } = storeToRefs(routerStore);
|
||||
return tabsList.value.find((item: Menu.MenuOptions) => item.name == key);
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理外链跳转,打开一个新窗口并根据url跳转
|
||||
* @param {any} route 路由
|
||||
*/
|
||||
const openExternalLinks = (route: any) => {
|
||||
// 处理外链跳转
|
||||
if (route.meta.link && !route.meta.iframe) {
|
||||
window.open(route.meta.link as string, "_blank");
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
findLinearArray,
|
||||
findTagsList
|
||||
findTagsList,
|
||||
openExternalLinks
|
||||
};
|
||||
};
|
||||
|
||||
@ -25,6 +25,7 @@ export default {
|
||||
["user-settings"]: "user settings",
|
||||
["external-links"]: "external links",
|
||||
["link-gitee"]: "link gitee",
|
||||
["link-juejin"]: "link juejin",
|
||||
["about-project"]: "about project",
|
||||
["not-power"]: "No permission",
|
||||
["not-found"]: "Page not found",
|
||||
|
||||
@ -25,7 +25,8 @@ export default {
|
||||
["user-settings"]: "用户设置",
|
||||
["about-project"]: "关于项目",
|
||||
["external-links"]: "外部链接",
|
||||
["link-gitee"]: "链接 gitee",
|
||||
["link-gitee"]: "外链 gitee",
|
||||
["link-juejin"]: "外链 掘金",
|
||||
["not-power"]: "没有权限",
|
||||
["not-found"]: "未找到页面",
|
||||
["zh-CN"]: "中文",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<a-watermark :content="watermark" v-bind="watermarkConfig">
|
||||
<a-layout-content :class="isFooter ? 'content' : 'content-no-footer'">
|
||||
<a-layout-content :class="isFooter ? 'layout-main-content' : 'layout-main-content-no-footer'">
|
||||
<Tabs v-if="isTabs" />
|
||||
<a-scrollbar style="height: 100%; overflow: auto" :outer-class="isTabs ? 'scrollbar' : 'scrollbar-no-tabs'">
|
||||
<div>
|
||||
@ -42,10 +42,10 @@ watch(watermarkConfig, newv => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
.layout-main-content {
|
||||
height: calc(100vh - 60px - 30px); // 动态切类名-去掉header、footer
|
||||
}
|
||||
.content-no-footer {
|
||||
.layout-main-content-no-footer {
|
||||
height: calc(100vh - 60px); // 动态切类名-去掉footer
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import { initSetRouter, currentlyRoute } from "@/router/route-output";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useUserInfoStore } from "@/store/modules/user-info";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
|
||||
/**
|
||||
* 创建vue的路由示例
|
||||
@ -55,13 +56,23 @@ router.beforeEach(async (to, from, next) => {
|
||||
// 4、去非登录页,有token,校验是否动态添加过路由,添加过则放行,未添加则执行路由初始化
|
||||
const routeStore = useRoutesListStore(pinia);
|
||||
const { routeTree } = storeToRefs(routeStore);
|
||||
|
||||
// 获取外链路由的处理函数
|
||||
// 所有的路由正常放行,只不过额外判断是否是外链,如果是,则打开新窗口跳转外链
|
||||
// 外链的页面依旧正常打开,只不过不会参与缓存与tabs显示,符合路由跳转的直觉
|
||||
const { openExternalLinks } = useRoutingMethod();
|
||||
|
||||
// 如果缓存的路由是0,则说明未动态添加路由,先添加再跳转
|
||||
// 解决刷新页面404的问题
|
||||
if (routeTree.value.length == 0) {
|
||||
await initSetRouter();
|
||||
// 处理外链跳转
|
||||
openExternalLinks(to);
|
||||
// 处理完重新跳转
|
||||
next({ path: to.path, query: to.query });
|
||||
} else {
|
||||
// 处理外链跳转
|
||||
openExternalLinks(to);
|
||||
// 动态路由添加过走这里,直接放行
|
||||
next();
|
||||
// 项目内的跳转,处理跳转路由高亮
|
||||
|
||||
@ -104,9 +104,10 @@ export const currentlyRoute = (name: string) => {
|
||||
// 存入当前路由-高亮
|
||||
store.setCurrentRoute(find);
|
||||
|
||||
// 如果是外链路由则不做后续任何缓存操作: 有外链 && 内嵌false
|
||||
// 如果是外链路由则不做后续任何缓存操作,条件: 有外链 && 非内嵌
|
||||
if (find.meta.link && !find.meta.iframe) return;
|
||||
// 存入tabs栏数据:开启tabs
|
||||
|
||||
// 存入tabs栏数据,条件:开启tabs
|
||||
if (isTabs.value) store.setTabs(find);
|
||||
// 不缓存路由 || 不渲染tabs ,符合任意条件则不缓存路由
|
||||
if (!find.meta.keepAlive || !isTabs.value) return;
|
||||
|
||||
@ -318,6 +318,22 @@ export const dynamicRoutes: RouteRecordRaw[] = [
|
||||
icon: "icon-menu"
|
||||
},
|
||||
children: []
|
||||
},
|
||||
{
|
||||
path: "/external-links/link-juejin",
|
||||
name: "link-juejin",
|
||||
component: () => import("@/views/external-links/link-juejin/link-juejin.vue"),
|
||||
meta: {
|
||||
title: "link-juejin",
|
||||
hide: false,
|
||||
keepAlive: true,
|
||||
affix: false,
|
||||
link: "https://juejin.cn/user/1728883023940600", // 链接
|
||||
iframe: false, // 区分是否内链 true内链 false外链
|
||||
roles: ["admin"],
|
||||
icon: "icon-menu"
|
||||
},
|
||||
children: []
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* global style scss */
|
||||
.dc-page {
|
||||
// margin 和 padding 边距一致,是为了保持视觉上的内外统一
|
||||
margin: $padding;
|
||||
padding: $padding;
|
||||
background: $color-bg-1;
|
||||
|
||||
@ -1,9 +1,3 @@
|
||||
<template>
|
||||
<div>外部链接 gitee <a-date-picker v-model="form" placeholder="请选择日期" /></div>
|
||||
<ExternalLinkPage />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const form = ref();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
3
src/views/external-links/link-juejin/link-juejin.vue
Normal file
3
src/views/external-links/link-juejin/link-juejin.vue
Normal file
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<ExternalLinkPage />
|
||||
</template>
|
||||
Loading…
x
Reference in New Issue
Block a user