feat: 增加 core-element-plus 应用,同时 core 应用将不再集成任何第三方组件库

This commit is contained in:
Hooray
2026-06-29 02:34:09 +08:00
parent 209cb17484
commit 686988cced
177 changed files with 9506 additions and 974 deletions
-1
View File
@@ -31,7 +31,6 @@
"cropperjs": "catalog:",
"dayjs": "catalog:",
"echarts": "catalog:",
"element-plus": "catalog:",
"eruda": "catalog:",
"es-toolkit": "catalog:",
"mitt": "catalog:",
@@ -5,20 +5,20 @@ function Layout() {
}
const routes: RouteRecordRaw = {
path: '/element_plus_example',
path: '/ui_example',
component: Layout,
meta: {
title: 'Element Plus',
icon: 'i-ep:element-plus',
title: 'UI',
icon: 'i-whh:jqueryui',
menu: false,
},
children: [
{
path: '',
name: 'elementPlusExample',
component: () => import('@/views/element_plus_example/index.vue'),
name: 'uiExample',
component: () => import('@/views/ui_example/index.vue'),
meta: {
title: 'Element Plus',
title: 'UI',
menu: false,
breadcrumb: false,
},
+2 -2
View File
@@ -5,7 +5,6 @@ import AuthExample from './modules/auth.example'
import BreadcrumbExample from './modules/breadcrumb.example'
import ComponentExample from './modules/component.example'
import EcologyExample from './modules/ecology.example'
import ElementPlusExample from './modules/element.plus.example'
import ExternalLinkExample from './modules/external.link.example'
import FakeExample from './modules/fake.example'
import FeatureExample from './modules/feature.example'
@@ -16,6 +15,7 @@ import MultilevelMenuExample from './modules/multilevel.menu.example'
import PluginExample from './modules/plugin.example'
import StandardModuleExample from './modules/standard.module.example'
import TabbarExample from './modules/tabbar.example'
import UiExample from './modules/ui.example'
// 固定路由(默认路由)
const constantRoutes: RouteRecordRaw[] = [
@@ -97,7 +97,7 @@ const asyncRoutes: RouteRecordMainRaw[] = [
icon: 'i-whh:jqueryui',
},
children: [
ElementPlusExample,
UiExample,
],
},
{
@@ -1,256 +0,0 @@
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElRow>
<ElButton>默认按钮</ElButton>
<ElButton type="primary">
主要按钮
</ElButton>
<ElButton type="success">
成功按钮
</ElButton>
<ElButton type="info">
信息按钮
</ElButton>
<ElButton type="warning">
警告按钮
</ElButton>
<ElButton type="danger">
危险按钮
</ElButton>
</ElRow>
<ElRow>
<ElButton plain>
朴素按钮
</ElButton>
<ElButton type="primary" plain>
主要按钮
</ElButton>
<ElButton type="success" plain>
成功按钮
</ElButton>
<ElButton type="info" plain>
信息按钮
</ElButton>
<ElButton type="warning" plain>
警告按钮
</ElButton>
<ElButton type="danger" plain>
危险按钮
</ElButton>
</ElRow>
<ElRow>
<ElButton round>
圆角按钮
</ElButton>
<ElButton type="primary" round>
主要按钮
</ElButton>
<ElButton type="success" round>
成功按钮
</ElButton>
<ElButton type="info" round>
信息按钮
</ElButton>
<ElButton type="warning" round>
警告按钮
</ElButton>
<ElButton type="danger" round>
危险按钮
</ElButton>
</ElRow>
<ElRow>
<ElButton circle>
<template #icon>
<FaIcon name="i-ep:search" />
</template>
</ElButton>
<ElButton type="primary" circle>
<template #icon>
<FaIcon name="i-ep:edit" />
</template>
</ElButton>
<ElButton type="success" circle>
<template #icon>
<FaIcon name="i-ep:check" />
</template>
</ElButton>
<ElButton type="info" circle>
<template #icon>
<FaIcon name="i-ep:message" />
</template>
</ElButton>
<ElButton type="warning" circle>
<template #icon>
<FaIcon name="i-ep:star" />
</template>
</ElButton>
<ElButton type="danger" circle>
<template #icon>
<FaIcon name="i-ep:delete" />
</template>
</ElButton>
</ElRow>
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElRow>
<ElButton disabled>
默认按钮
</ElButton>
<ElButton type="primary" disabled>
主要按钮
</ElButton>
<ElButton type="success" disabled>
成功按钮
</ElButton>
<ElButton type="info" disabled>
信息按钮
</ElButton>
<ElButton type="warning" disabled>
警告按钮
</ElButton>
<ElButton type="danger" disabled>
危险按钮
</ElButton>
</ElRow>
<ElRow>
<ElButton plain disabled>
朴素按钮
</ElButton>
<ElButton type="primary" plain disabled>
主要按钮
</ElButton>
<ElButton type="success" plain disabled>
成功按钮
</ElButton>
<ElButton type="info" plain disabled>
信息按钮
</ElButton>
<ElButton type="warning" plain disabled>
警告按钮
</ElButton>
<ElButton type="danger" plain disabled>
危险按钮
</ElButton>
</ElRow>
<ElDivider content-position="left">
文字按钮
</ElDivider>
<ElButton text>
文字按钮
</ElButton>
<ElButton type="primary" text>
文字按钮
</ElButton>
<ElButton type="success" text>
文字按钮
</ElButton>
<ElButton type="info" text>
文字按钮
</ElButton>
<ElButton type="warning" text>
文字按钮
</ElButton>
<ElButton type="danger" text>
文字按钮
</ElButton>
<ElDivider content-position="left">
图标按钮
</ElDivider>
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:edit" />
</template>
</ElButton>
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:share" />
</template>
</ElButton>
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:delete" />
</template>
</ElButton>
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:search" />
</template>
搜索
</ElButton>
<ElButton type="primary">
上传
<FaIcon name="i-ep:upload" class="el-icon--right" />
</ElButton>
<ElDivider content-position="left">
按钮组
</ElDivider>
<ElButtonGroup class="me-4">
<ElButton type="primary">
<FaIcon name="i-ep:arrow-left" class="el-icon--left" />
上一页
</ElButton>
<ElButton type="primary">
下一页
<FaIcon name="i-ep:arrow-right" class="el-icon--right" />
</ElButton>
</ElButtonGroup>
<ElButtonGroup>
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:edit" />
</template>
</ElButton>
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:share" />
</template>
</ElButton>
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:delete" />
</template>
</ElButton>
</ElButtonGroup>
<ElDivider content-position="left">
加载中
</ElDivider>
<ElButton type="primary" :loading="true">
加载中
</ElButton>
<ElDivider content-position="left">
不同尺寸
</ElDivider>
<div class="mb-4">
<ElButton size="large">
大号按钮
</ElButton>
<ElButton size="default">
默认按钮
</ElButton>
<ElButton size="small">
小号按钮
</ElButton>
</div>
<div>
<ElButton size="large" round>
大号按钮
</ElButton>
<ElButton size="default" round>
默认按钮
</ElButton>
<ElButton size="small" round>
小号按钮
</ElButton>
</div>
</div>
</template>
<style scoped>
.el-row {
margin-bottom: 20px;
}
</style>
@@ -1,76 +0,0 @@
<script setup lang="ts">
const checked = ref(true)
const checked1 = ref(false)
const checked2 = ref(true)
const checkList = ref(['选中且禁用', '复选框 A'])
const checkedCities = ref(['上海', '北京'])
const cities = ref(['上海', '北京', '广州', '深圳'])
const checkboxGroup1 = ref(['上海'])
const checked3 = ref(true)
const checked4 = ref(false)
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElCheckbox v-model="checked">
备选项
</ElCheckbox>
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElCheckbox v-model="checked1" disabled>
备选项1
</ElCheckbox>
<ElCheckbox v-model="checked2" disabled>
备选项
</ElCheckbox>
<ElDivider content-position="left">
多选框组
</ElDivider>
<ElCheckboxGroup v-model="checkList">
<ElCheckbox value="复选框 A">
复选框 A
</ElCheckbox>
<ElCheckbox value="复选框 B">
复选框 B
</ElCheckbox>
<ElCheckbox value="复选框 C">
复选框 C
</ElCheckbox>
<ElCheckbox value="禁用" disabled>
禁用
</ElCheckbox>
<ElCheckbox value="选中且禁用" disabled>
选中且禁用
</ElCheckbox>
</ElCheckboxGroup>
<ElDivider content-position="left">
可选项目数量的限制
</ElDivider>
<ElCheckboxGroup v-model="checkedCities" :min="1" :max="2">
<ElCheckbox v-for="city in cities" :key="city" :value="city">
{{ city }}
</ElCheckbox>
</ElCheckboxGroup>
<ElDivider content-position="left">
按钮样式
</ElDivider>
<ElCheckboxGroup v-model="checkboxGroup1">
<ElCheckboxButton v-for="city in cities" :key="city" :value="city">
{{ city }}
</ElCheckboxButton>
</ElCheckboxGroup>
<ElDivider content-position="left">
带有边框
</ElDivider>
<ElCheckbox v-model="checked3" value="备选项1" border>
备选项1
</ElCheckbox>
<ElCheckbox v-model="checked4" value="备选项2" border>
备选项2
</ElCheckbox>
</div>
</template>
@@ -1,54 +0,0 @@
<script setup lang="ts">
import { icons } from '@/iconify'
const icon = icons.filter(item => item.prefix === 'ep')[0]
</script>
<template>
<div>
<div class="demo">
<FaIcon name="i-ep:edit" />
<FaIcon name="i-ep:share" />
<FaIcon name="i-ep:delete" />
<ElButton type="primary">
<template #icon>
<FaIcon name="i-ep:search" />
</template>
搜索
</ElButton>
</div>
<ElDivider content-position="left">
图标集合
</ElDivider>
<div v-for="(item, index) in icon.icons" :key="index" class="list-icon">
<ElTooltip class="item" effect="dark" :content="`ep:${item}`" placement="top">
<FaIcon :name="`ep:${item}`" />
</ElTooltip>
</div>
</div>
</template>
<style scoped>
.demo {
> i {
margin: 0 20px;
font-size: 1.5em;
vertical-align: middle;
color: #606266;
}
button {
margin: 0 20px;
}
}
.list-icon {
display: inline-block;
margin: 10px;
i {
font-size: 32px;
color: #606266;
}
}
</style>
@@ -1,44 +0,0 @@
<script setup lang="ts">
const input = ref('')
const input1 = ref('')
const input2 = ref('')
const textarea = ref('')
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElInput v-model="input" placeholder="请输入内容" />
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElInput v-model="input" placeholder="请输入内容" :disabled="true" />
<ElDivider content-position="left">
可清空
</ElDivider>
<ElInput v-model="input" placeholder="请输入内容" clearable />
<ElDivider content-position="left">
密码框
</ElDivider>
<ElInput v-model="input" placeholder="请输入内容" show-password />
<ElDivider content-position="left">
带 icon 的输入框
</ElDivider>
<ElInput v-model="input1" placeholder="请选择日期">
<template #suffix>
<FaIcon name="i-ep:calendar" />
</template>
</ElInput>
<ElInput v-model="input2" placeholder="请输入内容">
<template #prefix>
<FaIcon name="i-ep:search" />
</template>
</ElInput>
<ElDivider content-position="left">
文本域
</ElDivider>
<ElInput v-model="textarea" type="textarea" :rows="2" placeholder="请输入内容" />
</div>
</template>
@@ -1,32 +0,0 @@
<script setup lang="ts">
const num = ref(1)
const num2 = ref(1)
const num3 = ref(5)
const num4 = ref(1)
const num5 = ref(1)
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElInputNumber v-model="num" :min="1" :max="10" label="描述文字" />
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElInputNumber v-model="num2" :disabled="true" />
<ElDivider content-position="left">
步数
</ElDivider>
<ElInputNumber v-model="num3" :step="2" />
<ElDivider content-position="left">
精度
</ElDivider>
<ElInputNumber v-model="num4" :precision="2" :step="0.1" :max="10" />
<ElDivider content-position="left">
按钮位置
</ElDivider>
<ElInputNumber v-model="num5" controls-position="right" :min="1" :max="10" />
</div>
</template>
@@ -1,73 +0,0 @@
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElLink href="https://element.eleme.io" target="_blank">
默认链接
</ElLink>
<ElLink type="primary">
主要链接
</ElLink>
<ElLink type="success">
成功链接
</ElLink>
<ElLink type="warning">
警告链接
</ElLink>
<ElLink type="danger">
危险链接
</ElLink>
<ElLink type="info">
信息链接
</ElLink>
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElLink disabled>
默认链接
</ElLink>
<ElLink type="primary" disabled>
主要链接
</ElLink>
<ElLink type="success" disabled>
成功链接
</ElLink>
<ElLink type="warning" disabled>
警告链接
</ElLink>
<ElLink type="danger" disabled>
危险链接
</ElLink>
<ElLink type="info" disabled>
信息链接
</ElLink>
<ElDivider content-position="left">
下划线
</ElDivider>
<ElLink underline="always">
始终有划线
</ElLink>
<ElLink underline="never">
无下划线
</ElLink>
<ElLink>悬停有下划线</ElLink>
<ElDivider content-position="left">
图标
</ElDivider>
<ElLink>
<FaIcon name="i-ep:edit" class="el-icon--left" />
编辑
</ElLink>
<ElLink>
查看
<FaIcon name="i-ep:view" class="el-icon--right" />
</ElLink>
</div>
</template>
<style scoped>
.el-link {
margin: 0 5px;
}
</style>
@@ -1,70 +0,0 @@
<script setup lang="ts">
const radio = ref('1')
const radio2 = ref('选中且禁用')
const radio3 = ref(3)
const radio4 = ref('上海')
const radio5 = ref('1')
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElRadio v-model="radio" value="1">
备选项
</ElRadio>
<ElRadio v-model="radio" value="2">
备选项
</ElRadio>
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElRadio v-model="radio2" disabled value="禁用">
备选项
</ElRadio>
<ElRadio v-model="radio2" disabled value="选中且禁用">
备选项
</ElRadio>
<ElDivider content-position="left">
单选框组
</ElDivider>
<ElRadioGroup v-model="radio3">
<ElRadio :value="3">
备选项
</ElRadio>
<ElRadio :value="6">
备选项
</ElRadio>
<ElRadio :value="9">
备选项
</ElRadio>
</ElRadioGroup>
<ElDivider content-position="left">
按钮样式
</ElDivider>
<ElRadioGroup v-model="radio4">
<ElRadioButton value="上海">
上海
</ElRadioButton>
<ElRadioButton value="北京">
北京
</ElRadioButton>
<ElRadioButton value="广州">
广州
</ElRadioButton>
<ElRadioButton value="深圳">
深圳
</ElRadioButton>
</ElRadioGroup>
<ElDivider content-position="left">
带有边框
</ElDivider>
<ElRadio v-model="radio5" value="1" border>
备选项1
</ElRadio>
<ElRadio v-model="radio5" value="2" border>
备选项2
</ElRadio>
</div>
</template>
@@ -1,22 +0,0 @@
<script setup lang="ts">
const value1 = ref()
const value2 = ref()
const value3 = ref(3.7)
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElRate v-model="value1" />
<ElDivider content-position="left">
辅助文字
</ElDivider>
<ElRate v-model="value2" show-text :texts="['极差', '差', '一般', '好', '极好']" />
<ElDivider content-position="left">
只读
</ElDivider>
<ElRate v-model="value3" disabled show-score text-color="#ff9900" score-template="{value}" />
</div>
</template>
@@ -1,60 +0,0 @@
<script setup lang="ts">
const options1 = ref([
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' },
{ value: '选项3', label: '蚵仔煎' },
{ value: '选项4', label: '龙须面' },
{ value: '选项5', label: '北京烤鸭' },
])
const value1 = ref('')
const options2 = ref([
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶', disabled: true },
{ value: '选项3', label: '蚵仔煎' },
{ value: '选项4', label: '龙须面' },
{ value: '选项5', label: '北京烤鸭' },
])
const value2 = ref('')
const value3 = ref([])
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElSelect v-model="value1" placeholder="请选择">
<ElOption v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</ElSelect>
<ElDivider content-position="left">
有禁用选项
</ElDivider>
<ElSelect v-model="value2" placeholder="请选择">
<ElOption v-for="item in options2" :key="item.value" :label="item.label" :value="item.value" :disabled="item.disabled" />
</ElSelect>
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElSelect v-model="value1" disabled placeholder="请选择">
<ElOption v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</ElSelect>
<ElDivider content-position="left">
可清空单选
</ElDivider>
<ElSelect v-model="value1" clearable placeholder="请选择">
<ElOption v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</ElSelect>
<ElDivider content-position="left">
基础多选
</ElDivider>
<ElSelect v-model="value3" multiple placeholder="请选择">
<ElOption v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</ElSelect>
<ElDivider content-position="left">
可搜索
</ElDivider>
<ElSelect v-model="value1" filterable placeholder="请选择">
<ElOption v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</ElSelect>
</div>
</template>
@@ -1,52 +0,0 @@
<script setup lang="ts">
const value1 = ref(0)
const value2 = ref(50)
const value3 = ref(36)
const value4 = ref(48)
const value5 = ref(42)
const value6 = ref(0)
const value7 = ref(0)
const value8 = ref([4, 8])
const value9 = ref(0)
function formatTooltip(val: number) {
return val / 100
}
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<span>默认</span>
<ElSlider v-model="value1" />
<span>自定义初始值</span>
<ElSlider v-model="value2" />
<span>隐藏 Tooltip</span>
<ElSlider v-model="value3" :show-tooltip="false" />
<span>格式化 Tooltip</span>
<ElSlider v-model="value4" :format-tooltip="formatTooltip" />
<span>禁用</span>
<ElSlider v-model="value5" disabled />
<ElDivider content-position="left">
离散值
</ElDivider>
<span>不显示间断点</span>
<ElSlider v-model="value6" :step="10" />
<span>显示间断点</span>
<ElSlider v-model="value6" :step="10" show-stops />
<ElDivider content-position="left">
带有输入框
</ElDivider>
<ElSlider v-model="value7" show-input />
<ElDivider content-position="left">
范围选择
</ElDivider>
<ElSlider v-model="value8" show-stops range :max="10" />
<ElDivider content-position="left">
竖向模式
</ElDivider>
<ElSlider v-model="value9" vertical height="200px" />
</div>
</template>
@@ -1,24 +0,0 @@
<script setup lang="ts">
const value = ref(true)
const value1 = ref(true)
const value2 = ref(true)
const value3 = ref(false)
</script>
<template>
<div>
<ElDivider content-position="left">
基础用法
</ElDivider>
<ElSwitch v-model="value" active-color="#13ce66" inactive-color="#ff4949" />
<ElDivider content-position="left">
文字描述
</ElDivider>
<ElSwitch v-model="value1" active-text="按月付费" inactive-text="按年付费" />
<ElDivider content-position="left">
禁用状态
</ElDivider>
<ElSwitch v-model="value2" disabled class="me-4" />
<ElSwitch v-model="value3" disabled />
</div>
</template>
@@ -1,57 +0,0 @@
<script setup lang="ts">
import Button from './components/button.vue'
import Checkbox from './components/checkbox.vue'
import Icon from './components/icon.vue'
import Input from './components/input.vue'
import InputNumber from './components/inputnumber.vue'
import Link from './components/link.vue'
import Radio from './components/radio.vue'
import Rate from './components/rate.vue'
import Select from './components/select.vue'
import Slider from './components/slider.vue'
import Switch from './components/switch.vue'
const components = {
图标: Icon,
按钮: Button,
文字链接: Link,
单选框: Radio,
多选框: Checkbox,
输入框: Input,
数字输入框: InputNumber,
选择器: Select,
开关: Switch,
滑块: Slider,
评分: Rate,
}
function open(url: string) {
window.open(url, '_blank')
}
</script>
<template>
<div>
<FaPageHeader title="Element Plus">
<template #description>
<div class="space-y-2">
<p>框架内置 Element Plus 组件库,本页仅展示部分组件,更多组件及使用说明请查看 Element Plus 官网</p>
<FaButton variant="link" class="p-0 h-auto" @click="open('https://fantastic-admin.hurui.me/guide/other-ui.html')">
不想使用 Element Plus ?
</FaButton>
</div>
</template>
<FaButton variant="outline" @click="open('https://element-plus.org/#/zh-CN')">
<FaIcon name="i-ep:link" />
Element Plus 官网
</FaButton>
</FaPageHeader>
<FaPageMain title="官方组件">
<ElTabs type="border-card">
<ElTabPane v-for="(item, key) in components" :key="key" :label="key">
<Component :is="item" />
</ElTabPane>
</ElTabs>
</FaPageMain>
</div>
</template>
+129
View File
@@ -0,0 +1,129 @@
<script setup lang="ts">
interface PreviewItem {
id: string
name: string
accent: string
src: string
}
const previewItems = [
{
id: 'ant-design-vue',
name: 'Ant Design Vue',
accent: 'oklch(0.55 0.19 253)',
src: new URL('./previews/ant-design-vue.png', import.meta.url).href,
},
{
id: 'antdv-next',
name: 'Antdv Next',
accent: 'oklch(0.61 0.17 302)',
src: new URL('./previews/antdv-next.png', import.meta.url).href,
},
{
id: 'arco-design-vue',
name: 'Arco Design Vue',
accent: 'oklch(0.59 0.2 221)',
src: new URL('./previews/arco-design-vue.png', import.meta.url).href,
},
{
id: 'element-plus',
name: 'Element Plus',
accent: 'oklch(0.62 0.18 258)',
src: new URL('./previews/element-plus.png', import.meta.url).href,
},
{
id: 'naive-ui',
name: 'Naive UI',
accent: 'oklch(0.63 0.17 143)',
src: new URL('./previews/naive-ui.png', import.meta.url).href,
},
{
id: 'tdesign',
name: 'TDesign',
accent: 'oklch(0.64 0.18 24)',
src: new URL('./previews/tdesign.png', import.meta.url).href,
},
{
id: 'vexip-ui',
name: 'Vexip UI',
accent: 'oklch(0.65 0.16 83)',
src: new URL('./previews/vexip-ui.png', import.meta.url).href,
},
] satisfies PreviewItem[]
const previewSources = computed(() => previewItems.map(item => item.src))
const guideUrl = 'https://fantastic-admin.hurui.me/guide/with-ui-libraries.html'
const { open: openImagePreview } = useFaImagePreview()
function openPreview(index: number) {
openImagePreview(previewSources.value, index)
}
function openGuide() {
window.open(guideUrl, '_blank', 'noopener,noreferrer')
}
</script>
<template>
<main class="ui-showcase text-foreground flex flex-col h-full min-h-full overflow-hidden">
<FaPageHeader
title="三方 UI 组件库"
description="Fantastic-admin 提供了多套内置三方 UI 组件库的预设模版,开箱即用。"
class="mb-0 shrink-0"
>
<FaButton variant="outline" @click="openGuide">
<FaIcon name="i-lucide:book-open" />
了解更多
</FaButton>
</FaPageHeader>
<section class="p-[clamp(16px,3vw,28px)] flex-1 min-h-0 overflow-auto" aria-label="UI library previews">
<div class="gap-4 grid grid-cols-[repeat(auto-fit,minmax(min(100%,320px),1fr))]">
<button
v-for="(item, index) in previewItems"
:key="item.id"
type="button"
class="preview-card group text-inherit p-3 text-left border border-[var(--showcase-line)] rounded-[8px] bg-background transition-[border-color,background-color,transform] duration-180 ease-in-out [font:inherit] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
:style="{ '--accent-line': item.accent }"
:aria-label="`预览 ${item.name}`"
@click="openPreview(index)"
>
<span class="rounded-[6px] bg-muted aspect-[2504/1346] block overflow-hidden">
<img :src="item.src" :alt="item.name" class="size-full block transition-transform duration-260 ease-in-out object-cover group-focus-visible:scale-[1.012] group-hover:scale-[1.012]">
</span>
<span class="mt-3 flex gap-3 min-w-0 items-center justify-between">
<span class="text-[0.92rem] font-[620] min-w-0 whitespace-nowrap text-ellipsis overflow-hidden">{{ item.name }}</span>
<FaIcon name="i-lucide:maximize-2" class="text-muted-foreground shrink-0 size-4" />
</span>
</button>
</div>
</section>
</main>
</template>
<style scoped>
.ui-showcase {
--showcase-line: color-mix(in oklch, oklch(var(--border)) 82%, transparent);
}
.preview-card:hover,
.preview-card:focus-visible {
background: color-mix(in oklch, var(--accent-line) 7%, oklch(var(--background)));
border-color: color-mix(in oklch, var(--accent-line) 62%, oklch(var(--border)));
transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
.preview-card,
.preview-card img {
transition: none;
}
.preview-card:hover,
.preview-card:focus-visible,
.preview-card:hover img,
.preview-card:focus-visible img {
transform: none;
}
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+1 -2
View File
@@ -12,8 +12,7 @@
"vite/client",
"@spiriit/vite-plugin-svg-spritemap/client",
"unplugin-turbo-console/client",
"vite-plugin-app-loading/client",
"element-plus/global"
"vite-plugin-app-loading/client"
],
"allowJs": false,
"strict": true,