This commit is contained in:
xiaojibeier
2026-07-06 03:36:46 +08:00
parent 300b15aa9f
commit f3726f0810
506 changed files with 221985 additions and 1 deletions
+7
View File
@@ -0,0 +1,7 @@
import VabCard from './index.vue'
VabCard.install = function(app) {
app.component(VabCard.name, VabCard)
}
export default VabCard
+81
View File
@@ -0,0 +1,81 @@
<template>
<el-card :body-class="props.bodyClass" :body-style="props.bodyStyle" :class="['vab-card', $attrs.class]" :shadow="props.shadow">
<template v-if="$slots.header || props.title" #header>
<slot v-if="$slots.header" name="header"></slot>
<template v-else>{{ props.title }}</template>
</template>
<el-skeleton v-if="props.skeleton" animated :loading="skeletonShow" :rows="props.skeletonRows">
<template #default>
<slot></slot>
</template>
</el-skeleton>
<slot v-else></slot>
<template v-if="$slots.footer" #footer>
<slot name="footer"></slot>
</template>
</el-card>
</template>
<script setup>
import { ref, onBeforeUnmount } from 'vue'
import { ElCard } from 'element-plus'
// 定义组件名称
defineOptions({
name: 'VabCard',
})
// 定义 props
const props = defineProps({
...ElCard.props,
shadow: {
type: String,
default: 'never',
},
skeleton: {
type: Boolean,
default: false,
},
skeletonRows: {
type: Number,
default: 5, // 显示的数量会比传入的数量多 1
},
title: {
type: String,
default: '',
},
})
const skeletonShow = ref(true)
const timer = setTimeout(() => {
skeletonShow.value = false
}, 500)
onBeforeUnmount(() => {
if (timer) clearTimeout(timer)
})
</script>
<style lang="scss" scoped>
.vab-card {
:deep() {
.el-card__header {
font-weight: 500;
color: inherit;
background: inherit;
[class*='ri-'] {
background-image: linear-gradient(120deg, #bd34fe 30%, var(--el-color-primary));
background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.el-skeleton {
height: 100%;
overflow: hidden;
}
}
}
</style>
+7
View File
@@ -0,0 +1,7 @@
import VabColorfulCard from './index.vue'
VabColorfulCard.install = function(app) {
app.component(VabColorfulCard.name, VabColorfulCard)
}
export default VabColorfulCard
+92
View File
@@ -0,0 +1,92 @@
<template>
<el-card
:body-style="props.bodyStyle"
class="vab-colorful-card"
:shadow="props.shadow"
:style="
props.style
? props.style
: {
background: `linear-gradient(135deg, ${props.colorFrom} 15%, ${props.colorTo} 85%)`,
}
"
>
<!-- 头部插槽 -->
<template v-if="$slots.header" #header>
<slot name="header"></slot>
</template>
<!-- 使用 Iconify -->
<Icon v-if="props.icon" :icon="props.icon" class="card-icon" />
<!-- 默认插槽 -->
<slot></slot>
</el-card>
</template>
<script setup>
import { ElCard } from 'element-plus'
import { Icon } from '@iconify/vue' // 导入 Iconify
// 定义组件名称
defineOptions({
name: 'VabColorfulCard',
})
// 定义 props
const props = defineProps({
bodyStyle: {
type: [String, Object],
default: ''
},
shadow: {
type: String,
default: 'always',
},
colorFrom: {
type: String,
default: '',
},
colorTo: {
type: String,
default: '',
},
title: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
style: {
type: Object,
default: () => ({}),
},
})
</script>
<style lang="scss" scoped>
.vab-colorful-card {
position: relative;
min-height: 120px;
cursor: pointer;
border: 1px solid rgba(0, 0, 0, 0.1); // 更淡的边框
border-radius: 4px; // 稍微小一点的圆角
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); // 更轻的阴影
transition: all 0.25s;
:deep(.el-card__header) {
color: var(--el-color-white);
}
:deep(.el-card__body) {
padding: 20px;
}
.card-icon {
position: absolute;
right: 20px;
font-size: 60px;
transform: rotate(15deg);
}
}
</style>
+7
View File
@@ -0,0 +1,7 @@
import VabCount from './index.vue'
VabCount.install = function(app) {
app.component(VabCount.name, VabCount)
}
export default VabCount
+106
View File
@@ -0,0 +1,106 @@
<template>
<span>{{ displayValue }}</span>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { isNumber } from '@/utils/validate'
import { TransitionPresets, useTransition } from '@vueuse/core'
defineOptions({
name: 'VabCount',
})
const props = defineProps({
startValue: {
type: Number,
required: false,
default: 0,
},
endValue: {
type: Number,
required: false,
default: 20,
},
duration: {
type: Number,
required: false,
default: 3000,
},
autoplay: {
type: Boolean,
required: false,
default: true,
},
decimals: {
type: Number,
required: false,
default: 0,
validator(value) {
return value >= 0
},
},
decimal: {
type: String,
required: false,
default: '.',
},
separator: {
type: String,
required: false,
default: ',',
},
prefix: {
type: String,
required: false,
default: '',
},
suffix: {
type: String,
required: false,
default: '',
},
useEasing: {
type: Boolean,
required: false,
default: true,
},
easingFn: {
type: Array,
default: () => [0.2, 0.2, 0, 1],
},
})
const source = ref(props.startValue)
const output = useTransition(source, {
duration: props.duration,
transition: props.useEasing ? props.easingFn : TransitionPresets.linear,
})
const formatNumber = (num) => {
num = num.toFixed(props.decimals)
num += ''
const x = num.split('.')
let x1 = x[0]
const x2 = x.length > 1 ? props.decimal + x[1] : ''
const rgx = /(\d+)(\d{3})/
if (props.separator && !isNumber(props.separator)) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, `$1${props.separator}$2`)
}
}
return props.prefix + x1 + x2 + props.suffix
}
const displayValue = computed(() => formatNumber(output.value))
watch(
props,
(props) => {
if (props.autoplay) {
source.value = props.endValue
}
},
{ immediate: true }
)
</script>
+23
View File
@@ -0,0 +1,23 @@
import VabColorfulCard from './components/VabColorfulCard'
import VabCard from './components/VabCard'
import VabCount from './components/VabCount'
// 导入样式
import './styles/vab.scss'
const components = [
VabColorfulCard,
VabCard,
VabCount,
// 其他组件...
]
export default {
install(app) {
components.forEach(component => {
app.component(component.name, component)
})
}
}
export { VabColorfulCard, VabCard, VabCount }
+16
View File
@@ -0,0 +1,16 @@
@use 'normalize.css';
@use 'element-plus/theme-chalk/src/index';
@use './var.scss' as *;
// 基础样式
body {
font-size: var(--el-font-size-base);
color: var(--el-color-black);
background: var(--el-background-color);
}
// 卡片样式
.vab-card {
border-radius: var(--el-border-radius-base);
transition: var(--el-transition);
}
+36
View File
@@ -0,0 +1,36 @@
@use './variables.scss' as *;
:root {
//背景色
--el-background-color: #f6f8f9;
//菜单背景色
--el-menu-background-color: #282c34;
//菜单文字颜色
--el-menu-color-text: #ffffff;
// 主题色
--el-color-primary: #{$base-color-primary};
--el-color-primary-light-1: #{$vab-color-primary-light-1};
--el-color-primary-light-2: #{$vab-color-primary-light-2};
--el-color-primary-light-3: #{$vab-color-primary-light-3};
--el-color-primary-light-4: #{$vab-color-primary-light-4};
--el-color-primary-light-5: #{$vab-color-primary-light-5};
--el-color-primary-light-6: #{$vab-color-primary-light-6};
--el-color-primary-light-7: #{$vab-color-primary-light-7};
--el-color-primary-light-8: #{$vab-color-primary-light-8};
--el-color-primary-light-9: #{$vab-color-primary-light-9};
// 成功色
--el-color-success: #{$base-color-success};
--el-color-success-light: #{$vab-color-success-light};
--el-color-success-lighter: #{$vab-color-success-lighter};
// 白色
--el-color-white: #ffffff;
--el-color-warning: #{$base-color-warning};
--el-color-danger: #{$base-color-danger};
--el-transition-duration: 0.25s;
--el-transition: all var(--el-transition-duration) cubic-bezier(0.42, 0, 0.58, 1);
}
+26
View File
@@ -0,0 +1,26 @@
@use "sass:color";
/**
* @description 全局主题变量配置
*/
$base-color-primary: #4e88f3;
$base-color-success: #13ce66;
$base-color-warning: #e6a23c;
$base-color-danger: #fd4e4e;
$base-color-error: #fd4e4e;
$base-color-text: #909399;
$vab-color-primary: $base-color-primary;
$vab-color-primary-light-1: color.mix(white, $base-color-primary, 10%);
$vab-color-primary-light-2: color.mix(white, $base-color-primary, 20%);
$vab-color-primary-light-3: color.mix(white, $base-color-primary, 30%);
$vab-color-primary-light-4: color.mix(white, $base-color-primary, 40%);
$vab-color-primary-light-5: color.mix(white, $base-color-primary, 50%);
$vab-color-primary-light-6: color.mix(white, $base-color-primary, 60%);
$vab-color-primary-light-7: color.mix(white, $base-color-primary, 70%);
$vab-color-primary-light-8: color.mix(white, $base-color-primary, 80%);
$vab-color-primary-light-9: color.mix(white, $base-color-primary, 90%);
$vab-color-success: $base-color-success;
$vab-color-success-light: color.mix(white, $base-color-success, 80%);
$vab-color-success-lighter: color.mix(white, $base-color-success, 90%);