feat: 首页改成图表展示
This commit is contained in:
@@ -24,6 +24,7 @@ export namespace CustomerApi {
|
||||
userCount: number;
|
||||
contractCount: number;
|
||||
signingRate: number;
|
||||
completionRate: number;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
78
apps/web-antd/src/views/dashboard/analytics-visits-data.vue
Normal file
78
apps/web-antd/src/views/dashboard/analytics-visits-data.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<script lang="ts" setup>
|
||||
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||||
|
||||
import type { CustomerApi } from '#/api/license/customer';
|
||||
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||
|
||||
const props = defineProps<{ dashboardValue: CustomerApi.Dashboard }>();
|
||||
const chartRef = ref<EchartsUIType>();
|
||||
const { renderEcharts } = useEcharts(chartRef);
|
||||
|
||||
function renderChart() {
|
||||
renderEcharts({
|
||||
tooltip: {},
|
||||
// legend: { bottom: 0, data: ['总授权', '已签合同'] },
|
||||
grid: { left: '8%', right: '8%', top: '20%', bottom: '20%' },
|
||||
xAxis: { type: 'value', max: 350 },
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: { show: false },
|
||||
data: [''],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
// 总授权
|
||||
name: '授权License数',
|
||||
type: 'bar',
|
||||
data: [props.dashboardValue.licenseCount],
|
||||
barWidth: 20,
|
||||
itemStyle: { color: '#5470c6' },
|
||||
z: 1,
|
||||
// label: {
|
||||
// show: true,
|
||||
// formatter: '{a}: {c}',
|
||||
// },
|
||||
},
|
||||
{
|
||||
// 已签合同
|
||||
name: '已签合同数',
|
||||
type: 'bar',
|
||||
data: [props.dashboardValue.contractCount],
|
||||
barWidth: 20,
|
||||
itemStyle: { color: '#91c7ae' },
|
||||
z: 2,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'right',
|
||||
formatter: `{c}/${props.dashboardValue.licenseCount} (${props.dashboardValue.completionRate}%)`,
|
||||
rich: { per: { color: '#333', fontWeight: 'bold' } },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
onMounted(() => {
|
||||
renderChart();
|
||||
});
|
||||
|
||||
/** 监听数据变化,重新渲染图表 */
|
||||
watch(
|
||||
() => props.dashboardValue,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
renderChart();
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<EchartsUI ref="chartRef" />
|
||||
</template>
|
||||
54
apps/web-antd/src/views/dashboard/analytics-visits-sales.vue
Normal file
54
apps/web-antd/src/views/dashboard/analytics-visits-sales.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<script lang="ts" setup>
|
||||
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||||
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||
|
||||
const props = withDefaults(defineProps<{ signingRate?: number }>(), {
|
||||
signingRate: 0,
|
||||
});
|
||||
|
||||
const chartRef = ref<EchartsUIType>();
|
||||
const { renderEcharts } = useEcharts(chartRef);
|
||||
|
||||
function renderChart() {
|
||||
renderEcharts({
|
||||
// title: { text: '签单率', left: 'center' },
|
||||
series: [
|
||||
{
|
||||
type: 'gauge',
|
||||
startAngle: 225,
|
||||
endAngle: -45,
|
||||
progress: { show: true, width: 18 },
|
||||
axisLine: { lineStyle: { width: 18 } },
|
||||
pointer: { width: 6 },
|
||||
detail: { fontSize: 24, formatter: '{value}%' },
|
||||
data: [{ value: props.signingRate }],
|
||||
},
|
||||
],
|
||||
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
renderChart();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.signingRate,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
renderChart();
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<EchartsUI ref="chartRef" />
|
||||
</template>
|
||||
@@ -0,0 +1,64 @@
|
||||
<script lang="ts" setup>
|
||||
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||||
|
||||
import type { CustomerApi } from '#/api/license/customer';
|
||||
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||
|
||||
const props = defineProps<{ dashboardValue: CustomerApi.Dashboard }>();
|
||||
const chartRef = ref<EchartsUIType>();
|
||||
const { renderEcharts } = useEcharts(chartRef);
|
||||
|
||||
function renderChart() {
|
||||
renderEcharts({
|
||||
// title: { text: '员工 / 客户 / 项目', left: 'center' },
|
||||
tooltip: { trigger: 'item' },
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
roseType: 'radius',
|
||||
radius: [20, 100],
|
||||
label: { show: true, fontSize: 14 },
|
||||
data: [
|
||||
{
|
||||
value: props.dashboardValue.userCount,
|
||||
name: '员工',
|
||||
itemStyle: { color: '#4F81BD' },
|
||||
},
|
||||
{
|
||||
value: props.dashboardValue.customerCount,
|
||||
name: '客户',
|
||||
itemStyle: { color: '#9BBB59' },
|
||||
},
|
||||
{
|
||||
value: props.dashboardValue.projectCount,
|
||||
name: '项目',
|
||||
itemStyle: { color: '#C0504D' },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
renderChart();
|
||||
});
|
||||
|
||||
/** 监听数据变化,重新渲染图表 */
|
||||
watch(
|
||||
() => props.dashboardValue,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
renderChart();
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<EchartsUI ref="chartRef" />
|
||||
</template>
|
||||
@@ -1,9 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AnalysisOverviewItem, WorkbenchTrendItem } from '@vben/common-ui';
|
||||
|
||||
import { onMounted, shallowRef } from 'vue';
|
||||
import type { CustomerApi } from '#/api/license/customer';
|
||||
|
||||
import { AnalysisOverview, WorkbenchTrends } from '@vben/common-ui';
|
||||
import { onMounted, ref, shallowRef } from 'vue';
|
||||
|
||||
import { AnalysisChartCard, WorkbenchTrends } from '@vben/common-ui';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
@@ -14,14 +16,22 @@ import { getLicenseExpiry } from '#/api/license/license';
|
||||
// import { DictTag } from '#/components/dict-tag';
|
||||
import { DICT_TYPE, getDictObj } from '#/utils';
|
||||
|
||||
import AnalyticsVisitsData from './analytics-visits-data.vue';
|
||||
import AnalyticsVisitsSales from './analytics-visits-sales.vue';
|
||||
import AnalyticsVisitsSource from './analytics-visits-source.vue';
|
||||
|
||||
const overviewItems = shallowRef<AnalysisOverviewItem[]>([]);
|
||||
const trendItems = shallowRef<WorkbenchTrendItem[]>([]);
|
||||
const projectProgressItems = shallowRef<WorkbenchTrendItem[]>([]);
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
const dashboardValue = ref<CustomerApi.Dashboard>({} as CustomerApi.Dashboard);
|
||||
|
||||
onMounted(async () => {
|
||||
const data = await dashboard();
|
||||
|
||||
dashboardValue.value = data;
|
||||
|
||||
overviewItems.value = [
|
||||
{
|
||||
icon: 'icon-[streamline-plump-color--user-pin-flat] size-8 flex-shrink-0',
|
||||
@@ -105,6 +115,7 @@ onMounted(async () => {
|
||||
date: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss') || '',
|
||||
title: `${item.projectName ?? ''} `,
|
||||
status: dict,
|
||||
info: '',
|
||||
customerName: item.customerName,
|
||||
serialNo: item.serialNo,
|
||||
businessOwner: item.businessOwner,
|
||||
@@ -126,7 +137,19 @@ onMounted(async () => {
|
||||
<template #description> 今日晴,20℃ - 32℃! </template>
|
||||
</WorkbenchHeader> -->
|
||||
|
||||
<AnalysisOverview :items="overviewItems" />
|
||||
<!-- <AnalysisOverview :items="overviewItems" /> -->
|
||||
|
||||
<div class="w-full md:flex">
|
||||
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="签单率">
|
||||
<AnalyticsVisitsSales :signing-rate="dashboardValue.signingRate" />
|
||||
</AnalysisChartCard>
|
||||
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="完成度">
|
||||
<AnalyticsVisitsData :dashboard-value="dashboardValue" />
|
||||
</AnalysisChartCard>
|
||||
<AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="概览">
|
||||
<AnalyticsVisitsSource :dashboard-value="dashboardValue" />
|
||||
</AnalysisChartCard>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 flex flex-col lg:flex-row">
|
||||
<div class="lg:w mr-4 w-full">
|
||||
@@ -153,17 +176,5 @@ onMounted(async () => {
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user