feat: add about page

This commit is contained in:
vben
2024-06-23 20:05:22 +08:00
parent d4f61c283f
commit 199d5506ac
28 changed files with 394 additions and 18 deletions

View File

@@ -6,7 +6,9 @@
--foreground: 220 13% 91%;
/* Background color for <Card /> */
--card: 222.2 84% 4.9%;
--card: 222.86deg 8.43% 16.27%;
/* --card: 222.2 84% 4.9%; */
--card-foreground: 210 40% 98%;
/* Background color for popovers such as <DropdownMenu />, <HoverCard />, <Popover /> */

View File

@@ -46,7 +46,7 @@ a:active,
a:hover,
a:link,
a:visited {
color: inherit;
// color: inherit;
text-decoration: none;
}

View File

@@ -13,10 +13,12 @@ export * from './hover-card';
export * from './icon';
export * from './input';
export * from './input-password';
export * from './link';
export * from './logo';
export * from './menu-badge';
export * from './pin-input';
export * from './popover';
export * from './render-content';
export * from './scrollbar';
export * from './segmented';
export * from './sheet';
@@ -27,6 +29,7 @@ export * from './ui/avatar';
export * from './ui/badge';
export * from './ui/breadcrumb';
export * from './ui/button';
export * from './ui/card';
export * from './ui/checkbox';
export * from './ui/dialog';
export * from './ui/dropdown-menu';

View File

@@ -0,0 +1 @@
export { default as VbenLink } from './link.vue';

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue';
import { cn } from '@vben-core/toolkit';
import { Primitive, type PrimitiveProps } from 'radix-vue';
interface Props extends PrimitiveProps {
class?: HTMLAttributes['class'];
href: string;
}
const props = withDefaults(defineProps<Props>(), {
as: 'a',
class: '',
href: '',
});
</script>
<template>
<Primitive
:as="as"
:as-child="asChild"
:class="cn('text-primary hover:text-primary-hover', props.class)"
:href="href"
target="_blank"
>
<slot></slot>
</Primitive>
</template>

View File

@@ -0,0 +1 @@
export { default as VbenRenderContent } from './render-content.vue';

View File

@@ -0,0 +1,23 @@
<script setup lang="ts">
import type { Component } from 'vue';
defineOptions({
name: 'RenderContent',
});
const props = withDefaults(
defineProps<{ content: Component | string; props?: Record<string, any> }>(),
{
props: () => ({}),
},
);
const isComponent = typeof props.content === 'object' && props.content !== null;
</script>
<template>
<component :is="content" v-bind="props" v-if="isComponent" />
<template v-else-if="!isComponent">
{{ content }}
</template>
</template>

View File

@@ -61,7 +61,7 @@ function onTransitionEnd() {
:class="{
'invisible opacity-0': !showSpinner,
}"
class="flex-center bg-overlay absolute left-0 top-0 size-full backdrop-blur-sm transition-all duration-500"
class="flex-center bg-overlay z-100 absolute left-0 top-0 size-full backdrop-blur-sm transition-all duration-500"
@transitionend="onTransitionEnd"
>
<div

View File

@@ -11,7 +11,10 @@ const props = defineProps<{
<template>
<div
:class="
cn('bg-card text-card-foreground rounded-xl border shadow', props.class)
cn(
'bg-card text-card-foreground border-border rounded-xl border shadow',
props.class,
)
"
>
<slot></slot>

View File

@@ -9,7 +9,7 @@ const props = defineProps<{
</script>
<template>
<div :class="cn('flex flex-col gap-y-1.5 p-6', props.class)">
<div :class="cn('flex flex-col gap-y-1.5 p-5', props.class)">
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,14 @@
import type { Component } from 'vue';
interface AboutProps {
description?: string;
name?: string;
title?: string;
}
interface DescriptionItem {
content: Component | string;
title: string;
}
export type { AboutProps, DescriptionItem };

View File

@@ -0,0 +1,176 @@
<script setup lang="ts">
import type { AboutProps, DescriptionItem } from './about';
import { h } from 'vue';
import { VbenLink, VbenRenderContent } from '@vben-core/shadcn-ui';
interface Props extends AboutProps {}
defineOptions({
name: 'AboutUI',
});
withDefaults(defineProps<Props>(), {
description:
'是一个基于Vue3.0、Vite 、TypeScript 等前沿技术的后台解决方案,目标是为服务中大型项目开发,提供现成的开箱解决方案及丰富的示例。',
name: 'Vben Admin Pro',
title: '关于我们',
});
const {
authorEmail,
authorName,
authorUrl,
buildTime,
dependencies = {},
devDependencies = {},
homepage,
license,
repositoryUrl,
version,
} = window.__VBEN_ADMIN_METADATA__ || {};
const vbenDescriptionItems: DescriptionItem[] = [
{
content: version,
title: '版本号',
},
{
content: license,
title: '开源许可协议',
},
{
content: buildTime,
title: '最后构建时间',
},
{
// TODO:
content: h(VbenLink, { href: homepage }, { default: () => '点击查看' }),
title: '主页',
},
{
// TODO:
content: h(
VbenLink,
{ href: repositoryUrl },
{ default: () => '点击查看' },
),
title: '文档地址',
},
{
// TODO:
content: h(
VbenLink,
{ href: repositoryUrl },
{ default: () => '点击查看' },
),
title: '预览地址',
},
{
content: h(
VbenLink,
{ href: repositoryUrl },
{ default: () => '点击查看' },
),
title: 'Github',
},
{
content: h('div', [
h(
VbenLink,
{ class: 'mr-2', href: authorUrl },
{ default: () => authorName },
),
h(
VbenLink,
{ href: `mailto:${authorEmail}` },
{ default: () => authorEmail },
),
]),
title: '作者',
},
];
const dependenciesItems = Object.keys(dependencies).map((key) => ({
content: dependencies[key],
title: key,
}));
const devDependenciesItems = Object.keys(devDependencies).map((key) => ({
content: devDependencies[key],
title: key,
}));
</script>
<template>
<div class="m-5">
<div class="bg-card rounded-md p-5">
<div>
<h3 class="text-foreground text-2xl font-semibold leading-7">
{{ title }}
</h3>
<p class="text-foreground/80 mt-3 text-sm leading-6">
<VbenLink :href="repositoryUrl">
{{ name }}
</VbenLink>
{{ description }}
</p>
</div>
<div class="mt-4">
<dl class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
<template v-for="item in vbenDescriptionItems" :key="item.title">
<div class="border-border border-t px-4 py-6 sm:col-span-1 sm:px-0">
<dt class="text-foreground text-sm font-medium leading-6">
{{ item.title }}
</dt>
<dd class="text-foreground/80 mt-1 text-sm leading-6 sm:mt-2">
<VbenRenderContent :content="item.content" />
</dd>
</div>
</template>
</dl>
</div>
</div>
<div class="bg-card mt-6 rounded-md p-5">
<div>
<h5 class="text-foreground text-lg">生产环境依赖</h5>
</div>
<div class="mt-4">
<dl class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
<template v-for="item in dependenciesItems" :key="item.title">
<div class="border-border border-t px-4 py-3 sm:col-span-1 sm:px-0">
<dt class="text-foreground text-sm">
{{ item.title }}
</dt>
<dd class="text-foreground/60 mt-1 text-sm sm:mt-2">
<VbenRenderContent :content="item.content" />
</dd>
</div>
</template>
</dl>
</div>
</div>
<div class="bg-card mt-6 rounded-md p-5">
<div>
<h5 class="text-foreground text-lg">开发环境依赖</h5>
</div>
<div class="mt-4">
<dl class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
<template v-for="item in devDependenciesItems" :key="item.title">
<div class="border-border border-t px-4 py-3 sm:col-span-1 sm:px-0">
<dt class="text-foreground text-sm">
{{ item.title }}
</dt>
<dd class="text-foreground/60 mt-1 text-sm sm:mt-2">
<VbenRenderContent :content="item.content" />
</dd>
</div>
</template>
</dl>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1 @@
export { default as About } from './about.vue';

View File

@@ -1,3 +1,4 @@
export * from './about';
export * from './authentication';
export * from './dashboard';
export * from './fallback';

View File

@@ -28,6 +28,9 @@
},
"./global": {
"types": "./global.d.ts"
},
"./window": {
"types": "./window.d.ts"
}
},
"publishConfig": {

19
packages/types/window.d.ts vendored Normal file
View File

@@ -0,0 +1,19 @@
export {};
declare global {
interface Window {
__VBEN_ADMIN_METADATA__: {
authorEmail: string;
authorName: string;
authorUrl: string;
buildTime: string;
dependencies: Record<string, string>;
description: string;
devDependencies: Record<string, string>;
homepage: string;
license: string;
repositoryUrl: string;
version: string;
};
}
}