28 changed files with 394 additions and 18 deletions
@ -1,9 +1,9 @@ |
|||||
<script lang="ts" setup> |
<script lang="ts" setup> |
||||
import { Fallback } from '@vben/universal-ui'; |
import { About } from '@vben/universal-ui'; |
||||
|
|
||||
defineOptions({ name: 'Menu1' }); |
defineOptions({ name: 'About' }); |
||||
</script> |
</script> |
||||
|
|
||||
<template> |
<template> |
||||
<Fallback status="hello" /> |
<About /> |
||||
</template> |
</template> |
||||
|
|||||
@ -0,0 +1,87 @@ |
|||||
|
import type { PluginOption } from 'vite'; |
||||
|
|
||||
|
import { dateUtil, getPackages, readPackageJSON } from '@vben/node-utils'; |
||||
|
|
||||
|
function resolvePackageVersion( |
||||
|
pkgsMeta: Record<string, string>, |
||||
|
name: string, |
||||
|
value: string, |
||||
|
) { |
||||
|
if (value.includes('workspace')) { |
||||
|
return pkgsMeta[name]; |
||||
|
} |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
async function resolveMonorepoDependencies() { |
||||
|
const { packages } = await getPackages(); |
||||
|
const resultDevDependencies: Record<string, string> = {}; |
||||
|
const resultDependencies: Record<string, string> = {}; |
||||
|
const pkgsMeta: Record<string, string> = {}; |
||||
|
|
||||
|
for (const { packageJson } of packages) { |
||||
|
pkgsMeta[packageJson.name] = packageJson.version; |
||||
|
} |
||||
|
|
||||
|
for (const { packageJson } of packages) { |
||||
|
const { dependencies = {}, devDependencies = {} } = packageJson; |
||||
|
for (const [key, value] of Object.entries(dependencies)) { |
||||
|
resultDependencies[key] = resolvePackageVersion(pkgsMeta, key, value); |
||||
|
} |
||||
|
for (const [key, value] of Object.entries(devDependencies)) { |
||||
|
resultDevDependencies[key] = resolvePackageVersion(pkgsMeta, key, value); |
||||
|
} |
||||
|
} |
||||
|
return { |
||||
|
dependencies: resultDependencies, |
||||
|
devDependencies: resultDevDependencies, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 用于注入项目信息 |
||||
|
*/ |
||||
|
async function viteMetadataPlugin( |
||||
|
root = process.cwd(), |
||||
|
): Promise<PluginOption | undefined> { |
||||
|
const { author, description, homepage, license, repository, version } = |
||||
|
await readPackageJSON(root); |
||||
|
|
||||
|
const buildTime = dateUtil().format('YYYY-MM-DD HH:mm:ss'); |
||||
|
|
||||
|
return { |
||||
|
async config() { |
||||
|
const { dependencies, devDependencies } = |
||||
|
await resolveMonorepoDependencies(); |
||||
|
const repositoryUrl = |
||||
|
typeof repository === 'object' ? repository.url : repository; |
||||
|
|
||||
|
const isAuthorObject = typeof author === 'object'; |
||||
|
const authorName = isAuthorObject ? author.name : author; |
||||
|
const authorEmail = isAuthorObject ? author.email : null; |
||||
|
const authorUrl = isAuthorObject ? author.url : null; |
||||
|
|
||||
|
return { |
||||
|
define: { |
||||
|
__VBEN_ADMIN_METADATA__: JSON.stringify({ |
||||
|
authorEmail, |
||||
|
authorName, |
||||
|
authorUrl, |
||||
|
buildTime, |
||||
|
dependencies, |
||||
|
description, |
||||
|
devDependencies, |
||||
|
homepage, |
||||
|
license, |
||||
|
repositoryUrl, |
||||
|
version, |
||||
|
}), |
||||
|
}, |
||||
|
}; |
||||
|
}, |
||||
|
enforce: 'post', |
||||
|
name: 'vite:inject-metadata', |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export { viteMetadataPlugin }; |
||||
@ -0,0 +1 @@ |
|||||
|
export { default as VbenLink } from './link.vue'; |
||||
@ -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> |
||||
@ -0,0 +1 @@ |
|||||
|
export { default as VbenRenderContent } from './render-content.vue'; |
||||
@ -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> |
||||
@ -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 }; |
||||
@ -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> |
||||
@ -0,0 +1 @@ |
|||||
|
export { default as About } from './about.vue'; |
||||
@ -1,3 +1,4 @@ |
|||||
|
export * from './about'; |
||||
export * from './authentication'; |
export * from './authentication'; |
||||
export * from './dashboard'; |
export * from './dashboard'; |
||||
export * from './fallback'; |
export * from './fallback'; |
||||
|
|||||
@ -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; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue