feat: add dashboard page

This commit is contained in:
vben
2024-06-23 23:18:55 +08:00
parent 199d5506ac
commit c58c0797ba
100 changed files with 1908 additions and 1081 deletions

View File

@@ -50,7 +50,7 @@
"@vueuse/core": "^10.11.0",
"class-variance-authority": "^0.7.0",
"radix-vue": "^1.8.5",
"vue": "^3.4.30",
"vue": "^3.4.31",
"vue-sonner": "^1.1.3"
}
}

View File

@@ -13,7 +13,7 @@ interface Props extends BacktopProps {}
defineOptions({ name: 'BackTop' });
const props = withDefaults(defineProps<Props>(), {
bottom: 40,
bottom: 24,
isGroup: false,
right: 40,
target: '',
@@ -32,7 +32,7 @@ const { handleClick, visible } = useBackTop(props);
<VbenButton
v-if="visible"
:style="backTopStyle"
class="bg-accent data fixed bottom-10 right-5 h-10 w-10 rounded-full"
class="bg-accent hover:bg-heavy data fixed bottom-10 right-5 z-10 h-10 w-10 rounded-full"
size="icon"
variant="icon"
@click="handleClick"

View File

@@ -0,0 +1,111 @@
<script lang="ts" setup>
import { computed, onMounted, ref, unref, watch, watchEffect } from 'vue';
import { isNumber } from '@vben-core/toolkit';
import { TransitionPresets, useTransition } from '@vueuse/core';
interface Props {
autoplay?: boolean;
color?: string;
decimal?: string;
decimals?: number;
duration?: number;
endVal?: number;
prefix?: string;
separator?: string;
startVal?: number;
suffix?: string;
transition?: keyof typeof TransitionPresets;
useEasing?: boolean;
}
defineOptions({ name: 'CountToAnimator' });
const props = withDefaults(defineProps<Props>(), {
autoplay: true,
color: '',
decimal: '.',
decimals: 0,
duration: 1500,
endVal: 2021,
prefix: '',
separator: ',',
startVal: 0,
suffix: '',
transition: 'linear',
useEasing: true,
});
const emit = defineEmits(['onStarted', 'onFinished']);
const source = ref(props.startVal);
const disabled = ref(false);
let outputValue = useTransition(source);
const value = computed(() => formatNumber(unref(outputValue)));
watchEffect(() => {
source.value = props.startVal;
});
watch([() => props.startVal, () => props.endVal], () => {
if (props.autoplay) {
start();
}
});
onMounted(() => {
props.autoplay && start();
});
function start() {
run();
source.value = props.endVal;
}
function reset() {
source.value = props.startVal;
run();
}
function run() {
outputValue = useTransition(source, {
disabled,
duration: props.duration,
onFinished: () => emit('onFinished'),
onStarted: () => emit('onStarted'),
...(props.useEasing
? { transition: TransitionPresets[props.transition] }
: {}),
});
}
function formatNumber(num: number | string) {
if (!num && num !== 0) {
return '';
}
const { decimal, decimals, prefix, separator, suffix } = props;
num = Number(num).toFixed(decimals);
num += '';
const x = num.split('.');
let x1 = x[0];
const x2 = x.length > 1 ? decimal + x[1] : '';
const rgx = /(\d+)(\d{3})/;
if (separator && !isNumber(separator)) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, `$1${separator}$2`);
}
}
return prefix + x1 + x2 + suffix;
}
defineExpose({ reset });
</script>
<template>
<span :style="{ color }">
{{ value }}
</span>
</template>

View File

@@ -0,0 +1 @@
export { default as VbenCountToAnimator } from './count-to-animator.vue';

View File

@@ -6,6 +6,7 @@ export * from './breadcrumb';
export * from './button';
export * from './checkbox';
export * from './context-menu';
export * from './count-to-animator';
export * from './dropdown-menu';
export * from './floating-button-group';
export * from './full-screen';