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

@@ -0,0 +1,80 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
defineOptions({ name: 'AnalyticsTrends' });
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
onMounted(() => {
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
},
series: [
{
areaStyle: {},
data: [
111, 2000, 6000, 16_000, 33_333, 55_555, 64_000, 33_333, 18_000,
36_000, 70_000, 42_444, 23_222, 13_000, 8000, 4000, 1200, 333, 222,
111,
],
itemStyle: {
color: '#5ab1ef',
},
smooth: true,
type: 'line',
},
{
areaStyle: {},
data: [
33, 66, 88, 333, 3333, 6200, 20_000, 3000, 1200, 13_000, 22_000,
11_000, 2221, 1201, 390, 198, 60, 30, 22, 11,
],
itemStyle: {
color: '#019680',
},
smooth: true,
type: 'line',
},
],
tooltip: {
axisPointer: {
lineStyle: {
color: '#019680',
width: 1,
},
},
trigger: 'axis',
},
xAxis: {
axisTick: {
show: false,
},
boundaryGap: false,
data: Array.from({ length: 18 }).map((_item, index) => `${index + 6}:00`),
type: 'category',
},
yAxis: [
{
axisTick: {
show: false,
},
max: 80_000,
type: 'value',
},
],
});
});
</script>
<template>
<EchartsUI ref="chartRef" />
</template>

View File

@@ -0,0 +1,82 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
defineOptions({ name: 'AnalyticsVisitsData' });
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
onMounted(() => {
renderEcharts({
legend: {
bottom: 0,
data: ['访问', '趋势'],
},
radar: {
indicator: [
{
name: '网页',
},
{
name: '移动端',
},
{
name: 'Ipad',
},
{
name: '客户端',
},
{
name: '第三方',
},
{
name: '其它',
},
],
radius: '60%',
splitNumber: 8,
},
series: [
{
areaStyle: {
opacity: 1,
shadowBlur: 0,
shadowColor: 'rgba(0,0,0,.2)',
shadowOffsetX: 0,
shadowOffsetY: 10,
},
data: [
{
itemStyle: {
color: '#b6a2de',
},
name: '访问',
value: [90, 50, 86, 40, 50, 20],
},
{
itemStyle: {
color: '#5ab1ef',
},
name: '趋势',
value: [70, 75, 70, 76, 20, 85],
},
],
itemStyle: {
// borderColor: '#fff',
borderRadius: 10,
borderWidth: 2,
},
symbolSize: 0,
type: 'radar',
},
],
tooltip: {},
});
});
</script>
<template>
<EchartsUI ref="chartRef" />
</template>

View File

@@ -0,0 +1,46 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
defineOptions({ name: 'AnalyticsVisitsSales' });
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
onMounted(() => {
renderEcharts({
series: [
{
animationDelay() {
return Math.random() * 400;
},
animationEasing: 'exponentialInOut',
animationType: 'scale',
center: ['50%', '50%'],
color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'],
data: [
{ name: '外包', value: 500 },
{ name: '定制', value: 310 },
{ name: '技术支持', value: 274 },
{ name: '远程', value: 400 },
].sort((a, b) => {
return a.value - b.value;
}),
name: '商业占比',
radius: '80%',
roseType: 'radius',
type: 'pie',
},
],
tooltip: {
trigger: 'item',
},
});
});
</script>
<template>
<EchartsUI ref="chartRef" />
</template>

View File

@@ -0,0 +1,65 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
defineOptions({ name: 'AnalyticsVisitsSource' });
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
onMounted(() => {
renderEcharts({
legend: {
bottom: '2%',
left: 'center',
},
series: [
{
animationDelay() {
return Math.random() * 100;
},
animationEasing: 'exponentialInOut',
animationType: 'scale',
avoidLabelOverlap: false,
color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'],
data: [
{ name: '搜索引擎', value: 1048 },
{ name: '直接访问', value: 735 },
{ name: '邮件营销', value: 580 },
{ name: '联盟广告', value: 484 },
],
emphasis: {
label: {
fontSize: '12',
fontWeight: 'bold',
show: true,
},
},
itemStyle: {
// borderColor: '#fff',
borderRadius: 10,
borderWidth: 2,
},
label: {
position: 'center',
show: false,
},
labelLine: {
show: false,
},
name: '访问来源',
radius: ['40%', '65%'],
type: 'pie',
},
],
tooltip: {
trigger: 'item',
},
});
});
</script>
<template>
<EchartsUI ref="chartRef" />
</template>

View File

@@ -0,0 +1,55 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
defineOptions({ name: 'AnalyticsVisits' });
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
onMounted(() => {
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
},
series: [
{
barMaxWidth: 80,
// color: '#4f69fd',
data: [
3000, 2000, 3333, 5000, 3200, 4200, 3200, 2100, 3000, 5100, 6000,
3200, 4800,
],
type: 'bar',
},
],
tooltip: {
axisPointer: {
lineStyle: {
// color: '#4f69fd',
width: 1,
},
},
trigger: 'axis',
},
xAxis: {
data: Array.from({ length: 12 }).map((_item, index) => `${index + 1}`),
type: 'category',
},
yAxis: {
max: 8000,
splitNumber: 4,
type: 'value',
},
});
});
</script>
<template>
<EchartsUI ref="chartRef" />
</template>

View File

@@ -0,0 +1,92 @@
<script lang="ts" setup>
import type { TabsItem } from '@vben/types';
import type { AnalysisOverviewItem } from '@vben/universal-ui';
import {
SvgBellIcon,
SvgCakeIcon,
SvgCardIcon,
SvgDownloadIcon,
} from '@vben/icons';
import {
AnalysisChartCard,
AnalysisChartsTabs,
AnalysisOverview,
} from '@vben/universal-ui';
import AnalyticsTrends from './analytics-trends.vue';
import AnalyticsVisits from './analytics-visits.vue';
import AnalyticsVisitsData from './analytics-visits-data.vue';
import AnalyticsVisitsSales from './analytics-visits-sales.vue';
import AnalyticsVisitsSource from './analytics-visits-source.vue';
defineOptions({ name: 'Analytics' });
const overviewItems: AnalysisOverviewItem[] = [
{
icon: SvgCardIcon,
title: '用户量',
totalTitle: '总用户量',
totalValue: 120_000,
value: 2000,
},
{
icon: SvgCakeIcon,
title: '访问量',
totalTitle: '总访问量',
totalValue: 500_000,
value: 20_000,
},
{
icon: SvgDownloadIcon,
title: '下载量',
totalTitle: '总下载量',
totalValue: 120_000,
value: 8000,
},
{
icon: SvgBellIcon,
title: '使用量',
totalTitle: '总使用量',
totalValue: 50_000,
value: 5000,
},
];
const chartTabs: TabsItem[] = [
{
label: '流量趋势',
value: 'trends',
},
{
label: '月访问量',
value: 'visits',
},
];
</script>
<template>
<div class="p-5">
<AnalysisOverview :items="overviewItems" />
<AnalysisChartsTabs :tabs="chartTabs" class="mt-5">
<template #trends>
<AnalyticsTrends />
</template>
<template #visits>
<AnalyticsVisits />
</template>
</AnalysisChartsTabs>
<div class="mt-5 w-full md:flex">
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问数量">
<AnalyticsVisitsData />
</AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问来源">
<AnalyticsVisitsSource />
</AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">
<AnalyticsVisitsSales />
</AnalysisChartCard>
</div>
</div>
</template>

View File

@@ -1,250 +0,0 @@
<script lang="ts" setup>
// import { ref } from 'vue';
// import { echartsInstance as echarts } from '@vben/chart-ui';
defineOptions({ name: 'Welcome' });
// const cardList = ref([
// {
// color: 'green',
// extra: '月',
// leftContent: '2000',
// leftFooter: '总访问数',
// rightContent: 'flat-color-icons:conference-call',
// rightFooter: '5000',
// title: '访问数',
// },
// {
// color: 'red',
// extra: '日',
// leftContent: '$1350',
// leftFooter: '总销售额',
// rightContent: 'flat-color-icons:sales-performance',
// rightFooter: '$550000',
// title: '销售额',
// },
// ]);
// const chartTabs = ref([
// {
// name: '1',
// option: {
// color: ['#80FFA5', '#00DDFF', '#37A2FF', '#FF0087', '#FFBF00'],
// grid: {
// bottom: '3%',
// containLabel: true,
// left: '3%',
// right: '4%',
// },
// legend: {
// data: ['Line 1', 'Line 2', 'Line 3', 'Line 4', 'Line 5'],
// },
// series: [
// {
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// color: 'rgb(128, 255, 165)',
// offset: 0,
// },
// {
// color: 'rgb(1, 191, 236)',
// offset: 1,
// },
// ]),
// opacity: 0.8,
// },
// data: [140, 232, 101, 264, 90, 340, 250],
// emphasis: {
// focus: 'series',
// },
// lineStyle: {
// width: 0,
// },
// name: 'Line 1',
// showSymbol: false,
// smooth: true,
// stack: 'Total',
// type: 'line',
// },
// {
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// color: 'rgb(0, 221, 255)',
// offset: 0,
// },
// {
// color: 'rgb(77, 119, 255)',
// offset: 1,
// },
// ]),
// opacity: 0.8,
// },
// data: [120, 282, 111, 234, 220, 340, 310],
// emphasis: {
// focus: 'series',
// },
// lineStyle: {
// width: 0,
// },
// name: 'Line 2',
// showSymbol: false,
// smooth: true,
// stack: 'Total',
// type: 'line',
// },
// {
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// color: 'rgb(55, 162, 255)',
// offset: 0,
// },
// {
// color: 'rgb(116, 21, 219)',
// offset: 1,
// },
// ]),
// opacity: 0.8,
// },
// data: [320, 132, 201, 334, 190, 130, 220],
// emphasis: {
// focus: 'series',
// },
// lineStyle: {
// width: 0,
// },
// name: 'Line 3',
// showSymbol: false,
// smooth: true,
// stack: 'Total',
// type: 'line',
// },
// {
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// color: 'rgb(255, 0, 135)',
// offset: 0,
// },
// {
// color: 'rgb(135, 0, 157)',
// offset: 1,
// },
// ]),
// opacity: 0.8,
// },
// data: [220, 402, 231, 134, 190, 230, 120],
// emphasis: {
// focus: 'series',
// },
// lineStyle: {
// width: 0,
// },
// name: 'Line 4',
// showSymbol: false,
// smooth: true,
// stack: 'Total',
// type: 'line',
// },
// {
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// color: 'rgb(255, 191, 0)',
// offset: 0,
// },
// {
// color: 'rgb(224, 62, 76)',
// offset: 1,
// },
// ]),
// opacity: 0.8,
// },
// data: [220, 302, 181, 234, 210, 290, 150],
// emphasis: {
// focus: 'series',
// },
// label: {
// position: 'top',
// show: true,
// },
// lineStyle: {
// width: 0,
// },
// name: 'Line 5',
// showSymbol: false,
// smooth: true,
// stack: 'Total',
// type: 'line',
// },
// ],
// toolbox: {
// feature: {
// saveAsImage: {},
// },
// },
// tooltip: {
// axisPointer: {
// type: 'cross',
// // label: {
// // backgroundColor: '#6a7985',
// // },
// },
// trigger: 'axis',
// },
// xAxis: [
// {
// boundaryGap: false,
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
// type: 'category',
// },
// ],
// yAxis: [
// {
// type: 'value',
// },
// ],
// },
// title: '流量趋势',
// },
// {
// name: '2',
// option: {
// series: [
// {
// data: [
// 120,
// {
// itemStyle: {
// color: '#a90000',
// },
// value: 200,
// },
// 150,
// 80,
// 70,
// 110,
// 130,
// ],
// type: 'bar',
// },
// ],
// xAxis: {
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
// type: 'category',
// },
// yAxis: {
// type: 'value',
// },
// },
// title: '访问量',
// },
// ]);
</script>
<template>
<div>dashboard</div>
</template>

View File

@@ -0,0 +1,125 @@
<script lang="ts" setup>
import type {
WorkbenchProjectItem,
WorkbenchQuickNavItem,
} from '@vben/universal-ui';
import {
WorkbenchHeader,
WorkbenchProject,
WorkbenchQuickNav,
} from '@vben/universal-ui';
import { preferences } from '@vben-core/preferences';
import { useAccessStore } from '#/store';
defineOptions({ name: 'Workspace' });
const { userInfo } = useAccessStore();
const projectItems: WorkbenchProjectItem[] = [
{
color: '',
content: '不要等待机会,而要创造机会。',
date: '2021-04-01',
group: '开源组',
icon: 'carbon:logo-github',
title: 'Github',
},
{
color: '#3fb27f',
content: '现在的你决定将来的你。',
date: '2021-04-01',
group: '算法组',
icon: 'ion:logo-vue',
title: 'Vue',
},
{
color: '#e18525',
content: '没有什么才能比努力更重要。',
date: '2021-04-01',
group: '上班摸鱼',
icon: 'ion:logo-html5',
title: 'Html5',
},
{
color: '#bf0c2c',
content: '热情和欲望可以突破一切难关。',
date: '2021-04-01',
group: 'UI',
icon: 'ion:logo-angular',
title: 'Angular',
},
{
color: '#00d8ff',
content: '健康的身体是实现目标的基石。',
date: '2021-04-01',
group: '技术牛',
icon: 'bx:bxl-react',
title: 'React',
},
{
color: '#EBD94E',
content: '路是走出来的,而不是空想出来的。',
date: '2021-04-01',
group: '架构组',
icon: 'ion:logo-javascript',
title: 'Js',
},
];
const quickNavItems: WorkbenchQuickNavItem[] = [
{
color: '#1fdaca',
icon: 'ion:home-outline',
title: '首页',
},
{
color: '#bf0c2c',
icon: 'ion:grid-outline',
title: '仪表盘',
},
{
color: '#e18525',
icon: 'ion:layers-outline',
title: '组件',
},
{
color: '#3fb27f',
icon: 'ion:settings-outline',
title: '系统管理',
},
{
color: '#4daf1bc9',
icon: 'ion:key-outline',
title: '权限管理',
},
{
color: '#00d8ff',
icon: 'ion:bar-chart-outline',
title: '图表',
},
];
</script>
<template>
<div class="p-5">
<WorkbenchHeader
:avatar="userInfo?.avatar || preferences.app.defaultAvatar"
>
<template #title>
早安, {{ userInfo?.realName }}, 开始您一天的工作吧
</template>
<template #description> 今日晴20 - 32 </template>
</WorkbenchHeader>
<div class="mt-5 flex">
<div class="mr-4 w-full md:w-2/3">
<WorkbenchProject :items="projectItems" title="项目" />
</div>
<div class="w-full md:w-1/3">
<WorkbenchQuickNav :items="quickNavItems" title="快捷导航" />
</div>
</div>
</div>
</template>