dashboard (#6)
* feat(dashboard): 增加dashboard示例 * feat(chart-ui): 增加图表UI组件库 * feat(dashboard): 完善dashboard示例pull/48/MERGE
parent
303a200427
commit
6f0c05dd50
|
@ -37,6 +37,7 @@
|
||||||
"@vben/styles": "workspace:*",
|
"@vben/styles": "workspace:*",
|
||||||
"@vben/types": "workspace:*",
|
"@vben/types": "workspace:*",
|
||||||
"@vben/universal-ui": "workspace:*",
|
"@vben/universal-ui": "workspace:*",
|
||||||
|
"@vben/chart-ui": "workspace:*",
|
||||||
"@vben/utils": "workspace:*",
|
"@vben/utils": "workspace:*",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"ant-design-vue": "^4.2.3",
|
"ant-design-vue": "^4.2.3",
|
||||||
|
|
|
@ -1,7 +1,249 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
defineOptions({ name: 'WelCome' });
|
defineOptions({ name: 'WelCome' });
|
||||||
|
import { Dashboard } from '@vben/universal-ui';
|
||||||
|
import { echartsInstance as echarts } from '@vben/chart-ui';
|
||||||
|
const cardList = ref([
|
||||||
|
{
|
||||||
|
title: '访问数',
|
||||||
|
extra: '月',
|
||||||
|
leftContent: '2000',
|
||||||
|
rightContent: 'flat-color-icons:conference-call',
|
||||||
|
leftFooter: '总访问数',
|
||||||
|
color: 'green',
|
||||||
|
rightFooter: '5000',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '销售额',
|
||||||
|
extra: '日',
|
||||||
|
leftContent: '$1350',
|
||||||
|
rightContent: 'flat-color-icons:sales-performance',
|
||||||
|
leftFooter: '总销售额',
|
||||||
|
color: 'red',
|
||||||
|
rightFooter: '$550000',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const chartTabs = ref([
|
||||||
|
{
|
||||||
|
name: '1',
|
||||||
|
title: '流量趋势',
|
||||||
|
option: {
|
||||||
|
color: ['#80FFA5', '#00DDFF', '#37A2FF', '#FF0087', '#FFBF00'],
|
||||||
|
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
// label: {
|
||||||
|
// backgroundColor: '#6a7985',
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['Line 1', 'Line 2', 'Line 3', 'Line 4', 'Line 5'],
|
||||||
|
},
|
||||||
|
toolbox: {
|
||||||
|
feature: {
|
||||||
|
saveAsImage: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Line 1',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0,
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(128, 255, 165)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(1, 191, 236)',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series',
|
||||||
|
},
|
||||||
|
data: [140, 232, 101, 264, 90, 340, 250],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Line 2',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0,
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(0, 221, 255)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(77, 119, 255)',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series',
|
||||||
|
},
|
||||||
|
data: [120, 282, 111, 234, 220, 340, 310],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Line 3',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0,
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(55, 162, 255)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(116, 21, 219)',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series',
|
||||||
|
},
|
||||||
|
data: [320, 132, 201, 334, 190, 130, 220],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Line 4',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0,
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(255, 0, 135)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(135, 0, 157)',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series',
|
||||||
|
},
|
||||||
|
data: [220, 402, 231, 134, 190, 230, 120],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Line 5',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0,
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(255, 191, 0)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(224, 62, 76)',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series',
|
||||||
|
},
|
||||||
|
data: [220, 302, 181, 234, 210, 290, 150],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '2',
|
||||||
|
title: '访问量',
|
||||||
|
option: {
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: [
|
||||||
|
120,
|
||||||
|
{
|
||||||
|
value: 200,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#a90000',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
150,
|
||||||
|
80,
|
||||||
|
70,
|
||||||
|
110,
|
||||||
|
130,
|
||||||
|
],
|
||||||
|
type: 'bar',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>dashboard</div>
|
<Dashboard :cardList="cardList" :chartTabs="chartTabs"></Dashboard>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
{
|
||||||
|
"name": "@vben/chart-ui",
|
||||||
|
"version": "5.0.0",
|
||||||
|
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||||
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||||
|
"directory": "packages/business/chart-ui"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "pnpm vite build",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"sideEffects": [
|
||||||
|
"**/*.css"
|
||||||
|
],
|
||||||
|
"main": "./dist/index.mjs",
|
||||||
|
"module": "./dist/index.mjs",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"development": "./src/index.ts",
|
||||||
|
"default": "./dist/index.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"default": "./dist/index.mjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vben-core/design": "workspace:*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vben-core/preferences": "workspace:*",
|
||||||
|
"echarts": "^5.5.0",
|
||||||
|
"vue": "^3.4.29"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vben/types": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { echartsInstance, ECOption } from './index';
|
||||||
|
import { onMounted, ref, unref, warn } from 'vue';
|
||||||
|
import { usePreferences } from '@vben-core/preferences';
|
||||||
|
const { isDark } = usePreferences();
|
||||||
|
interface Props {
|
||||||
|
height?: string;
|
||||||
|
width?: string;
|
||||||
|
}
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
height: '500px',
|
||||||
|
width: '100%',
|
||||||
|
});
|
||||||
|
|
||||||
|
const instance = ref();
|
||||||
|
const instanceRef = ref(HTMLElement);
|
||||||
|
onMounted(() => {
|
||||||
|
instance.value = echartsInstance.init(
|
||||||
|
instanceRef.value,
|
||||||
|
isDark.value ? 'dark' : '',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const setChart = (option: ECOption, clear: boolean = true) => {
|
||||||
|
const c = unref(instance);
|
||||||
|
if (!c) {
|
||||||
|
warn('instance is null');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (clear) c.clear();
|
||||||
|
c.setOption(option);
|
||||||
|
};
|
||||||
|
defineExpose({ setChart });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="instanceRef" :style="{ height, width }"></div>
|
||||||
|
</template>
|
|
@ -0,0 +1,59 @@
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import { BarChart, LineChart, PieChart, RadarChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
|
||||||
|
// 数据集组件
|
||||||
|
DatasetComponent,
|
||||||
|
// 内置数据转换器组件 (filter, sort)
|
||||||
|
TransformComponent,
|
||||||
|
LegendComponent,
|
||||||
|
ToolboxComponent,
|
||||||
|
} from 'echarts/components';
|
||||||
|
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import type {
|
||||||
|
// 系列类型的定义后缀都为 SeriesOption
|
||||||
|
BarSeriesOption,
|
||||||
|
LineSeriesOption,
|
||||||
|
} from 'echarts/charts';
|
||||||
|
import type {
|
||||||
|
// 组件类型的定义后缀都为 ComponentOption
|
||||||
|
TitleComponentOption,
|
||||||
|
TooltipComponentOption,
|
||||||
|
GridComponentOption,
|
||||||
|
DatasetComponentOption,
|
||||||
|
} from 'echarts/components';
|
||||||
|
import type { ComposeOption } from 'echarts/core';
|
||||||
|
|
||||||
|
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
|
||||||
|
export type ECOption = ComposeOption<
|
||||||
|
| BarSeriesOption
|
||||||
|
| LineSeriesOption
|
||||||
|
| TitleComponentOption
|
||||||
|
| TooltipComponentOption
|
||||||
|
| GridComponentOption
|
||||||
|
| DatasetComponentOption
|
||||||
|
>;
|
||||||
|
|
||||||
|
// 注册必须的组件
|
||||||
|
echarts.use([
|
||||||
|
TitleComponent,
|
||||||
|
PieChart,
|
||||||
|
RadarChart,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
BarChart,
|
||||||
|
LineChart,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer,
|
||||||
|
LegendComponent,
|
||||||
|
ToolboxComponent,
|
||||||
|
]);
|
||||||
|
export const echartsInstance = echarts;
|
||||||
|
export { default as chart } from './chart.vue';
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "@vben/tsconfig/web.json",
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { defineConfig } from '@vben/vite-config';
|
||||||
|
|
||||||
|
export default defineConfig();
|
|
@ -48,6 +48,7 @@
|
||||||
"@vben/locales": "workspace:*",
|
"@vben/locales": "workspace:*",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"@vueuse/integrations": "^10.11.0",
|
"@vueuse/integrations": "^10.11.0",
|
||||||
|
"@vben/chart-ui": "workspace:*",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"vue": "^3.4.30",
|
"vue": "^3.4.30",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.0"
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { VbenIcon, Badge } from '@vben-core/shadcn-ui';
|
||||||
|
defineOptions({ name: 'DashboardCard' });
|
||||||
|
import type { CardItem } from './typings';
|
||||||
|
interface Props {
|
||||||
|
item: CardItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="rounded-lg border-2 border-solid">
|
||||||
|
<div class="flex justify-between p-2">
|
||||||
|
<div class="">
|
||||||
|
<slot name="title">{{ item.title }}</slot>
|
||||||
|
</div>
|
||||||
|
<div class="text-xs" :class="`bg-${item.color}-500`">
|
||||||
|
<slot name="extra"
|
||||||
|
><Badge>{{ item.extra }}</Badge></slot
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ml-2 mr-2">
|
||||||
|
<div class="m-2 flex justify-between">
|
||||||
|
<div class="text-4xl">
|
||||||
|
<slot name="leftContent">{{ item.leftContent }}</slot>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<slot name="rightContent"
|
||||||
|
><VbenIcon :icon="item.rightContent" class="size-10"
|
||||||
|
/></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="m-2 flex justify-between">
|
||||||
|
<div>
|
||||||
|
<slot name="leftFooter">{{ item.leftFooter }}</slot>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<slot name="rightFooter">{{ item.rightFooter }}</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { chart } from '@vben/chart-ui';
|
||||||
|
defineOptions({ name: 'ChartCard' });
|
||||||
|
import type { ChartItem } from './typings';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
interface Props {
|
||||||
|
item: ChartItem;
|
||||||
|
}
|
||||||
|
const chartRef = ref();
|
||||||
|
onMounted(() => {
|
||||||
|
chartRef.value.setChart(props.item.option);
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="rounded-lg border-2 border-solid">
|
||||||
|
<div class="">
|
||||||
|
{{ item.title }}
|
||||||
|
</div>
|
||||||
|
<chart ref="chartRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,41 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Tabs, TabsList, TabsTrigger } from '@vben-core/shadcn-ui';
|
||||||
|
import { chart } from '@vben/chart-ui';
|
||||||
|
defineOptions({ name: 'ChartTab' });
|
||||||
|
import type { ChartItem } from './typings';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
interface Props {
|
||||||
|
items: ChartItem[];
|
||||||
|
}
|
||||||
|
const chartRef = ref();
|
||||||
|
onMounted(() => {
|
||||||
|
change(0);
|
||||||
|
});
|
||||||
|
const change = (i) => {
|
||||||
|
const item = props.items[i];
|
||||||
|
if (!item) return;
|
||||||
|
item.option && chartRef.value.setChart(item.option);
|
||||||
|
};
|
||||||
|
const props = withDefaults(defineProps<Props>(), {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="rounded-lg border-2 border-solid">
|
||||||
|
<Tabs
|
||||||
|
:defaultValue="items[0].name"
|
||||||
|
className="w-[400px]"
|
||||||
|
@update:modelValue="change"
|
||||||
|
>
|
||||||
|
<TabsList className="flex w-full ">
|
||||||
|
<TabsTrigger
|
||||||
|
:value="index"
|
||||||
|
v-for="(item, index) in items"
|
||||||
|
:key="index"
|
||||||
|
>{{ item.title }}</TabsTrigger
|
||||||
|
>
|
||||||
|
</TabsList>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
<chart ref="chartRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,152 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { CardItem, ChartItem } from './typings';
|
||||||
|
defineOptions({ name: 'Dashboard' });
|
||||||
|
import Card from './card.vue';
|
||||||
|
import ChartTab from './chartTab.vue';
|
||||||
|
import ChartCard from './chartCard.vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
cardList: CardItem[];
|
||||||
|
chartTabs: ChartItem[];
|
||||||
|
}
|
||||||
|
const itemA = ref({
|
||||||
|
title: '玫瑰图',
|
||||||
|
option: {
|
||||||
|
legend: {
|
||||||
|
top: 'bottom',
|
||||||
|
},
|
||||||
|
toolbox: {
|
||||||
|
show: true,
|
||||||
|
feature: {
|
||||||
|
mark: { show: true },
|
||||||
|
dataView: { show: true, readOnly: false },
|
||||||
|
restore: { show: true },
|
||||||
|
saveAsImage: { show: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Nightingale Chart',
|
||||||
|
type: 'pie',
|
||||||
|
radius: [50, 200],
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
roseType: 'area',
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 40, name: 'rose 1' },
|
||||||
|
{ value: 38, name: 'rose 2' },
|
||||||
|
{ value: 32, name: 'rose 3' },
|
||||||
|
{ value: 30, name: 'rose 4' },
|
||||||
|
{ value: 28, name: 'rose 5' },
|
||||||
|
{ value: 26, name: 'rose 6' },
|
||||||
|
{ value: 22, name: 'rose 7' },
|
||||||
|
{ value: 18, name: 'rose 8' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const itemB = ref({
|
||||||
|
title: '雷达图',
|
||||||
|
option: {
|
||||||
|
legend: {
|
||||||
|
data: ['Allocated Budget', 'Actual Spending'],
|
||||||
|
},
|
||||||
|
radar: {
|
||||||
|
// shape: 'circle',
|
||||||
|
indicator: [
|
||||||
|
{ name: 'Sales', max: 6500 },
|
||||||
|
{ name: 'Administration', max: 16000 },
|
||||||
|
{ name: 'Information Technology', max: 30000 },
|
||||||
|
{ name: 'Customer Support', max: 38000 },
|
||||||
|
{ name: 'Development', max: 52000 },
|
||||||
|
{ name: 'Marketing', max: 25000 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Budget vs spending',
|
||||||
|
type: 'radar',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: [4200, 3000, 20000, 35000, 50000, 18000],
|
||||||
|
name: 'Allocated Budget',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: [5000, 14000, 28000, 26000, 42000, 21000],
|
||||||
|
name: 'Actual Spending',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const itemC = ref({
|
||||||
|
title: '饼图',
|
||||||
|
option: {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: '5%',
|
||||||
|
left: 'center',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['40%', '70%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 2,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center',
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: 40,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 1048, name: 'Search Engine' },
|
||||||
|
{ value: 735, name: 'Direct' },
|
||||||
|
{ value: 580, name: 'Email' },
|
||||||
|
{ value: 484, name: 'Union Ads' },
|
||||||
|
{ value: 300, name: 'Video Ads' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
cardList: () => [],
|
||||||
|
chartTabs: () => [],
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="grid grid-cols-4 gap-4 p-2">
|
||||||
|
<Card v-for="item in cardList" :key="item.title" :item="item" />
|
||||||
|
</div>
|
||||||
|
<div class="p-2"><ChartTab :items="chartTabs" /></div>
|
||||||
|
<div class="grid grid-cols-3 gap-2 p-2">
|
||||||
|
<ChartCard :item="itemA" />
|
||||||
|
<ChartCard :item="itemB" />
|
||||||
|
<ChartCard :item="itemC" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,3 @@
|
||||||
|
export { default as DashboardLayout } from './layout.vue';
|
||||||
|
export { default as Dashboard } from './dashboard.vue';
|
||||||
|
export { default as chartCard } from './chartCard.vue';
|
|
@ -0,0 +1,7 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
defineOptions({ name: 'DashboardLayout' });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>dashboardLayout</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,17 @@
|
||||||
|
interface CardItem {
|
||||||
|
title: string;
|
||||||
|
extra: string;
|
||||||
|
leftContent: string;
|
||||||
|
rightContent: string;
|
||||||
|
color?: string;
|
||||||
|
leftFooter: string;
|
||||||
|
rightFooter: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ChartItem {
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
options: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { CardItem, ChartItem };
|
|
@ -8,3 +8,4 @@ export * from './notification';
|
||||||
export * from './preferences';
|
export * from './preferences';
|
||||||
export * from './theme-toggle';
|
export * from './theme-toggle';
|
||||||
export * from './user-dropdown';
|
export * from './user-dropdown';
|
||||||
|
export * from './dashboard';
|
||||||
|
|
Loading…
Reference in New Issue