feat: add about page

This commit is contained in:
xiaoxian521 2022-03-02 20:47:14 +08:00
parent 727c0fe3c0
commit 710e119397
17 changed files with 239 additions and 65 deletions

View File

@ -84,6 +84,14 @@ const frameRouter = {
frameSrc: "https://pure-admin-doc.vercel.app"
}
},
{
path: "/external",
name: "https://pure-admin-doc.vercel.app",
meta: {
title: "menus.externalLink",
i18n: true
}
},
{
path: "/iframe/ep",
name: "reFrameEp",

View File

@ -59,11 +59,13 @@ import arrowLeftSLine from "@iconify-icons/ri/arrow-left-s-line";
import logoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
import nodeTree from "@iconify-icons/ri/node-tree";
import ubuntuFill from "@iconify-icons/ri/ubuntu-fill";
import questionLine from "@iconify-icons/ri/question-line";
addIcon("arrow-right-s-line", arrowRightSLine);
addIcon("arrow-left-s-line", arrowLeftSLine);
addIcon("logout-circle-r-line", logoutCircleRLine);
addIcon("node-tree", nodeTree);
addIcon("ubuntu-fill", ubuntuFill);
addIcon("question-line", questionLine);
// Font Awesome 4
import faUser from "@iconify-icons/fa/user";

View File

@ -4,13 +4,13 @@
</div>
</template>
<script lang="ts" setup>
import { ref, unref, onMounted, nextTick } from "vue";
import { useRoute } from "vue-router";
import { ref, unref, onMounted, nextTick } from "vue";
const currentRoute = useRoute();
const loading = ref(false);
const frameRef = ref<HTMLElement | null>(null);
const currentRoute = useRoute();
const frameSrc = ref<string>("");
const frameRef = ref<HTMLElement | null>(null);
if (unref(currentRoute.meta)?.frameSrc) {
frameSrc.value = unref(currentRoute.meta)?.frameSrc as string;
@ -46,8 +46,9 @@ onMounted(() => {
<style lang="scss" scoped>
.frame {
height: 100vh;
z-index: 998;
&-iframe {
.frame-iframe {
width: 100%;
height: 100%;
overflow: hidden;
@ -57,6 +58,6 @@ onMounted(() => {
}
.main-content {
margin: 0;
margin: 0 !important;
}
</style>

View File

@ -33,12 +33,13 @@ export default {
permissionButton: "Button Permission",
hstabs: "Tabs Operate",
hsguide: "Guide",
externalLink: "External Link",
hsAble: "Able",
hsMenuTree: "Menu Tree",
hsWatermark: "Water Mark",
hsPrint: "Print",
hsExternalPage: "External Page",
hsPureDocument: "Pure Document",
hsEpDocument: "Element Plus Document"
hsPureDocument: "Pure Doc(Embedded)",
externalLink: "Pure Doc(External)",
hsEpDocument: "Element Plus Doc(Embedded)",
hsAbout: "About"
};

View File

@ -33,12 +33,13 @@ export default {
permissionButton: "按钮权限",
hstabs: "标签页操作",
hsguide: "引导页",
externalLink: "外链",
hsAble: "功能",
hsMenuTree: "菜单树结构",
hsWatermark: "水印",
hsPrint: "打印",
hsExternalPage: "外部页面",
hsPureDocument: "平台文档",
hsEpDocument: "Element Plus文档"
hsPureDocument: "平台文档(内嵌)",
externalLink: "平台文档(外链)",
hsEpDocument: "Element Plus文档(内嵌)",
hsAbout: "关于"
};

View File

@ -1,9 +1,10 @@
import { isUrl } from "/@/utils/is";
import { toRouteType } from "./types";
import { openLink } from "/@/utils/link";
import NProgress from "/@/utils/progress";
import { constantRoutes } from "./modules";
import { findIndex } from "lodash-unified";
import { transformI18n } from "/@/plugins/i18n";
import { split, findIndex } from "lodash-unified";
import remainingRouter from "./modules/remaining";
import { storageSession } from "/@/utils/storage";
import { Title } from "../../public/serverConfig.json";
@ -52,7 +53,7 @@ router.beforeEach((to: toRouteType, _from, next) => {
}
const name = storageSession.getItem("info");
NProgress.start();
const externalLink = to?.redirectedFrom?.fullPath;
const externalLink = isUrl(to?.name);
if (!externalLink)
to.matched.some(item => {
if (!item.meta.title) return "";
@ -65,9 +66,9 @@ router.beforeEach((to: toRouteType, _from, next) => {
});
if (name) {
if (_from?.name) {
// 如果路由包含http 则是超链接 反之是普通路由
if (externalLink && externalLink.includes("http")) {
openLink(`http${split(externalLink, "http")[1]}`);
// name为超链接
if (externalLink) {
openLink(to?.name);
NProgress.done();
} else {
next();

View File

@ -0,0 +1,32 @@
import { $t } from "/@/plugins/i18n";
const Layout = () => import("/@/layout/index.vue");
const aboutRouter = {
path: "/about",
name: "reAbout",
component: Layout,
redirect: "/about",
meta: {
icon: "question-line",
title: $t("menus.hsAbout"),
i18n: true,
rank: 12
},
children: [
{
path: "/about",
name: "reAbout",
component: () => import("/@/views/about.vue"),
meta: {
title: $t("menus.hsAbout"),
i18n: true
// extraIcon: {
// svg: true,
// name: "team-iconxinpin"
// }
}
}
]
};
export default aboutRouter;

View File

@ -1,26 +0,0 @@
import { $t } from "/@/plugins/i18n";
const Layout = () => import("/@/layout/index.vue");
const externalLink = {
path: "/external",
name: "external",
component: Layout,
meta: {
icon: "link",
title: $t("menus.externalLink"),
i18n: true,
rank: 190
},
children: [
{
path: "https://github.com/xiaoxian521/vue-pure-admin",
meta: {
title: $t("menus.externalLink"),
i18n: true,
rank: 191
}
}
]
};
export default externalLink;

View File

@ -1,11 +1,11 @@
// 静态路由
import about from "./about";
import homeRouter from "./home";
import ableRouter from "./able";
import errorRouter from "./error";
import guideRouter from "./guide";
import editorRouter from "./editor";
import nestedRouter from "./nested";
import externalLink from "./externalLink";
import flowChartRouter from "./flowchart";
import remainingRouter from "./remaining";
import componentsRouter from "./components";
@ -20,12 +20,12 @@ import { buildHierarchyTree } from "/@/utils/tree";
// 原始静态路由(未做任何处理)
const routes = [
about,
homeRouter,
ableRouter,
errorRouter,
guideRouter,
nestedRouter,
externalLink,
editorRouter,
flowChartRouter,
componentsRouter

View File

@ -94,8 +94,9 @@ export const isServer = typeof window === "undefined";
export const isClient = !isServer;
export function isUrl(path: string): boolean {
export function isUrl<T>(path: T): boolean {
const reg =
/(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
// @ts-expect-error
return reg.test(path);
}

View File

@ -1,5 +1,6 @@
export const openLink = (link: string) => {
export const openLink = <T>(link: T): void => {
const $a: HTMLElement = document.createElement("a");
// @ts-expect-error
$a.setAttribute("href", link);
$a.setAttribute("target", "_blank");
$a.setAttribute("rel", "noreferrer noopener");

136
src/views/about.vue Normal file
View File

@ -0,0 +1,136 @@
<script setup lang="ts">
export interface schemaItem {
field: string;
label: string;
}
// eslint-disable-next-line no-undef
const { pkg, lastBuildTime } = __APP_INFO__;
const { dependencies, devDependencies, version } = pkg;
const schema: schemaItem[] = [];
const devSchema: schemaItem[] = [];
Object.keys(dependencies).forEach(key => {
schema.push({ field: dependencies[key], label: key });
});
Object.keys(devDependencies).forEach(key => {
devSchema.push({ field: devDependencies[key], label: key });
});
</script>
<template>
<div>
<el-card class="box-card mb-4" shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">关于</span>
</div>
</template>
<span style="font-size: 15px">
Pure-Admin 是一个基于Vue3Vite2TypeScriptElement-Plus
的中后台解决方案它可以帮助您快速搭建企业级中后台提供现成的开箱解决方案及丰富的示例原则上不收取任何费用及版权可以放心使用不过如需二次开源比如用此平台二次开发并开源请联系作者获取许可
</span>
</el-card>
<el-card class="box-card m-4" shadow="hover">
<template #header>
<div class="card-header">
<span class="font-medium">项目信息</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="版本" label-align="left" align="left">
<el-tag>{{ version }}</el-tag>
</el-descriptions-item>
<el-descriptions-item
label="最后编译时间"
label-align="left"
align="left"
>
<el-tag>{{ lastBuildTime }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="文档地址" label-align="left" align="left">
<a href="https://pure-admin-doc.vercel.app" target="_blank">
<span style="color: var(--el-color-primary)">文档地址</span>
</a>
</el-descriptions-item>
<el-descriptions-item label="预览地址" label-align="left" align="left">
<a href="https://vue-pure-admin.vercel.app" target="_blank">
<span style="color: var(--el-color-primary)">预览地址</span>
</a>
</el-descriptions-item>
<el-descriptions-item label="Github" label-align="left" align="left">
<a
href="https://github.com/xiaoxian521/vue-pure-admin"
target="_blank"
>
<span style="color: var(--el-color-primary)">Github</span>
</a>
</el-descriptions-item>
<el-descriptions-item label="QQ交流群" label-align="left" align="left">
<a href="https://jq.qq.com/?_wv=1027&k=HntMx0dt" target="_blank"
><span style="color: var(--el-color-primary)"
>点击链接加入群聊Pure Admin</span
></a
>
</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card class="box-card m-4" shadow="hover">
<template #header>
<div class="card-header">
<span class="font-medium">生产环境依赖</span>
</div>
</template>
<el-descriptions border>
<el-descriptions-item
:label="item.label"
label-align="left"
align="left"
v-for="(item, index) in schema"
:key="index"
>
<a
:href="'https://www.npmjs.com/package/' + item.label"
target="_blank"
>
<span style="color: var(--el-color-primary)">{{ item.field }}</span>
</a>
</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card class="box-card m-4" shadow="hover">
<template #header>
<div class="card-header">
<span class="font-medium">开发环境依赖</span>
</div>
</template>
<el-descriptions border>
<el-descriptions-item
:label="item.label"
label-align="left"
align="left"
v-for="(item, index) in devSchema"
:key="index"
>
<a
:href="'https://www.npmjs.com/package/' + item.label"
target="_blank"
>
<span style="color: var(--el-color-primary)">{{ item.field }}</span>
</a>
</el-descriptions-item>
</el-descriptions>
</el-card>
</div>
</template>
<style lang="scss" scoped>
.main-content {
margin: 0 !important;
}
</style>

View File

@ -8,6 +8,6 @@ import { Amap } from "/@/components/ReMap";
<style scoped>
.main-content {
margin: 0;
margin: 0 !important;
}
</style>

View File

@ -22,22 +22,20 @@ const selectedVal = ({ left, right }): void => {
</script>
<template>
<div>
<el-card class="box-card" v-for="(item, key) in dataLists" :key="key">
<template #header>
<div class="card-header">
<span>{{ item.title }}</span>
</div>
</template>
<Selector
:HsKey="key"
:echo="item.echo"
@selectedVal="selectedVal"
:disabled="item.disabled"
/>
<h4 v-if="!item.disabled">选中范围{{ selectRange }}</h4>
</el-card>
</div>
<el-card class="box-card" v-for="(item, key) in dataLists" :key="key">
<template #header>
<div class="card-header">
<span>{{ item.title }}</span>
</div>
</template>
<Selector
:HsKey="key"
:echo="item.echo"
@selectedVal="selectedVal"
:disabled="item.disabled"
/>
<h4 v-if="!item.disabled">选中范围{{ selectRange }}</h4>
</el-card>
</template>
<style scoped>

View File

@ -220,7 +220,7 @@ const openDepot = (): void => {
<style lang="scss" scoped>
.main-content {
margin: 0;
margin: 0 !important;
}
.welcome {

9
types/global.d.ts vendored
View File

@ -16,6 +16,15 @@ declare module "vue" {
}
declare global {
const __APP_INFO__: {
pkg: {
name: string;
version: string;
dependencies: Recordable<string>;
devDependencies: Recordable<string>;
};
lastBuildTime: string;
};
interface Window {
// Global vue app instance
__APP__: App<Element>;

View File

@ -1,4 +1,6 @@
import dayjs from "dayjs";
import { resolve } from "path";
import pkg from "./package.json";
import { warpperEnv, regExps } from "./build";
import { getPluginsList } from "./build/plugins";
import { UserConfigExport, ConfigEnv, loadEnv } from "vite";
@ -19,6 +21,12 @@ const alias: Record<string, string> = {
"vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js"
};
const { dependencies, devDependencies, name, version } = pkg;
const __APP_INFO__ = {
pkg: { dependencies, devDependencies, name, version },
lastBuildTime: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss")
};
export default ({ command, mode }: ConfigEnv): UserConfigExport => {
const {
VITE_PORT,
@ -92,7 +100,8 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
chunkSizeWarningLimit: 2000
},
define: {
__INTLIFY_PROD_DEVTOOLS__: false
__INTLIFY_PROD_DEVTOOLS__: false,
__APP_INFO__: JSON.stringify(__APP_INFO__)
}
};
};