mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-04 07:27:41 +08:00
feat: add about page
This commit is contained in:
parent
727c0fe3c0
commit
710e119397
@ -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",
|
||||
|
@ -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";
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
};
|
||||
|
@ -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: "关于"
|
||||
};
|
||||
|
@ -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();
|
||||
|
32
src/router/modules/about.ts
Normal file
32
src/router/modules/about.ts
Normal 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;
|
@ -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;
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
136
src/views/about.vue
Normal 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 是一个基于Vue3、Vite2、TypeScript、Element-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>
|
@ -8,6 +8,6 @@ import { Amap } from "/@/components/ReMap";
|
||||
|
||||
<style scoped>
|
||||
.main-content {
|
||||
margin: 0;
|
||||
margin: 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -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>
|
||||
|
@ -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
9
types/global.d.ts
vendored
@ -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>;
|
||||
|
@ -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__)
|
||||
}
|
||||
};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user