feat: 首页改成图表展示
This commit is contained in:
@@ -24,6 +24,7 @@ export namespace CustomerApi {
|
|||||||
userCount: number;
|
userCount: number;
|
||||||
contractCount: number;
|
contractCount: number;
|
||||||
signingRate: 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>
|
<script lang="ts" setup>
|
||||||
import type { AnalysisOverviewItem, WorkbenchTrendItem } from '@vben/common-ui';
|
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 dayjs from 'dayjs';
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||||
@@ -14,14 +16,22 @@ import { getLicenseExpiry } from '#/api/license/license';
|
|||||||
// import { DictTag } from '#/components/dict-tag';
|
// import { DictTag } from '#/components/dict-tag';
|
||||||
import { DICT_TYPE, getDictObj } from '#/utils';
|
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 overviewItems = shallowRef<AnalysisOverviewItem[]>([]);
|
||||||
const trendItems = shallowRef<WorkbenchTrendItem[]>([]);
|
const trendItems = shallowRef<WorkbenchTrendItem[]>([]);
|
||||||
const projectProgressItems = shallowRef<WorkbenchTrendItem[]>([]);
|
const projectProgressItems = shallowRef<WorkbenchTrendItem[]>([]);
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
|
const dashboardValue = ref<CustomerApi.Dashboard>({} as CustomerApi.Dashboard);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const data = await dashboard();
|
const data = await dashboard();
|
||||||
|
|
||||||
|
dashboardValue.value = data;
|
||||||
|
|
||||||
overviewItems.value = [
|
overviewItems.value = [
|
||||||
{
|
{
|
||||||
icon: 'icon-[streamline-plump-color--user-pin-flat] size-8 flex-shrink-0',
|
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') || '',
|
date: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss') || '',
|
||||||
title: `${item.projectName ?? ''} `,
|
title: `${item.projectName ?? ''} `,
|
||||||
status: dict,
|
status: dict,
|
||||||
|
info: '',
|
||||||
customerName: item.customerName,
|
customerName: item.customerName,
|
||||||
serialNo: item.serialNo,
|
serialNo: item.serialNo,
|
||||||
businessOwner: item.businessOwner,
|
businessOwner: item.businessOwner,
|
||||||
@@ -126,7 +137,19 @@ onMounted(async () => {
|
|||||||
<template #description> 今日晴,20℃ - 32℃! </template>
|
<template #description> 今日晴,20℃ - 32℃! </template>
|
||||||
</WorkbenchHeader> -->
|
</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="mt-2 flex flex-col lg:flex-row">
|
||||||
<div class="lg:w mr-4 w-full">
|
<div class="lg:w mr-4 w-full">
|
||||||
@@ -153,17 +176,5 @@ onMounted(async () => {
|
|||||||
<AnalyticsVisits />
|
<AnalyticsVisits />
|
||||||
</template>
|
</template>
|
||||||
</AnalysisChartsTabs> -->
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user