From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue | 198 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 198 insertions(+), 0 deletions(-)
diff --git a/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue
new file mode 100644
index 0000000..ade6445
--- /dev/null
+++ b/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue
@@ -0,0 +1,198 @@
+<!-- 瀹㈡埛鏉ユ簮鍒嗘瀽 -->
+<template>
+ <!-- Echarts鍥� -->
+ <el-card shadow="never">
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-skeleton :loading="loading" animated>
+ <Echart :height="500" :options="echartsOption" />
+ </el-skeleton>
+ </el-col>
+ <el-col :span="12">
+ <el-skeleton :loading="loading" animated>
+ <Echart :height="500" :options="echartsOption2" />
+ </el-skeleton>
+ </el-col>
+ </el-row>
+ </el-card>
+
+ <!-- 缁熻鍒楄〃 -->
+ <el-card class="mt-16px" shadow="never">
+ <el-table v-loading="loading" :data="list">
+ <el-table-column align="center" label="搴忓彿" type="index" width="80" />
+ <el-table-column align="center" label="瀹㈡埛鏉ユ簮" prop="source" width="100">
+ <template #default="scope">
+ <dict-tag :type="DICT_TYPE.CRM_CUSTOMER_SOURCE" :value="scope.row.source" />
+ </template>
+ </el-table-column>
+ <el-table-column align="center" label="瀹㈡埛涓暟" min-width="200" prop="customerCount" />
+ <el-table-column align="center" label="鎴愪氦涓暟" min-width="200" prop="dealCount" />
+ <el-table-column align="center" label="鏉ユ簮鍗犳瘮(%)" min-width="200" prop="sourcePortion" />
+ <el-table-column align="center" label="鎴愪氦鍗犳瘮(%)" min-width="200" prop="dealPortion" />
+ </el-table>
+ </el-card>
+</template>
+<script lang="ts" setup>
+import {
+ CrmStatisticCustomerSourceRespVO,
+ StatisticsPortraitApi
+} from '@/api/crm/statistics/portrait'
+import { EChartsOption } from 'echarts'
+import { DICT_TYPE, getDictLabel } from '@/utils/dict'
+import { isEmpty } from '@/utils/is'
+import { erpCalculatePercentage, getSumValue } from '@/utils'
+
+defineOptions({ name: 'PortraitCustomerSource' })
+const props = defineProps<{ queryParams: any }>() // 鎼滅储鍙傛暟
+
+const loading = ref(false) // 鍔犺浇涓�
+const list = ref<CrmStatisticCustomerSourceRespVO[]>([]) // 鍒楄〃鐨勬暟鎹�
+
+/** 楗煎浘閰嶇疆锛堝叏閮ㄥ鎴凤級 */
+const echartsOption = reactive<EChartsOption>({
+ title: {
+ text: '鍏ㄩ儴瀹㈡埛',
+ left: 'center'
+ },
+ tooltip: {
+ trigger: 'item'
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'left'
+ },
+ toolbox: {
+ feature: {
+ saveAsImage: { show: true, name: '鍏ㄩ儴瀹㈡埛' } // 淇濆瓨涓哄浘鐗�
+ }
+ },
+ series: [
+ {
+ name: '鍏ㄩ儴瀹㈡埛',
+ 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: []
+ }
+ ]
+}) as EChartsOption
+
+/** 楗煎浘閰嶇疆锛堟垚浜ゅ鎴凤級 */
+const echartsOption2 = reactive<EChartsOption>({
+ title: {
+ text: '鎴愪氦瀹㈡埛',
+ left: 'center'
+ },
+ tooltip: {
+ trigger: 'item'
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'left'
+ },
+ toolbox: {
+ feature: {
+ saveAsImage: { show: true, name: '鎴愪氦瀹㈡埛' } // 淇濆瓨涓哄浘鐗�
+ }
+ },
+ series: [
+ {
+ name: '鎴愪氦瀹㈡埛',
+ 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: []
+ }
+ ]
+}) as EChartsOption
+
+/** 鑾峰彇缁熻鏁版嵁 */
+const loadData = async () => {
+ // 1. 鍔犺浇缁熻鏁版嵁
+ loading.value = true
+ const sourceList = await StatisticsPortraitApi.getCustomerSource(props.queryParams)
+ // 2.1 鏇存柊 Echarts 鏁版嵁
+ if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) {
+ echartsOption.series[0]['data'] = sourceList.map((r: CrmStatisticCustomerSourceRespVO) => {
+ return {
+ name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_SOURCE, r.source),
+ value: r.customerCount
+ }
+ })
+ }
+ // 2.2 鏇存柊 Echarts2 鏁版嵁
+ if (echartsOption2.series && echartsOption2.series[0] && echartsOption2.series[0]['data']) {
+ echartsOption2.series[0]['data'] = sourceList.map((r: CrmStatisticCustomerSourceRespVO) => {
+ return {
+ name: getDictLabel(DICT_TYPE.CRM_CUSTOMER_SOURCE, r.source),
+ value: r.dealCount
+ }
+ })
+ }
+ // 3. 璁$畻姣斾緥
+ calculateProportion(sourceList)
+ list.value = sourceList
+ loading.value = false
+}
+defineExpose({ loadData })
+
+/** 璁$畻姣斾緥 */
+const calculateProportion = (sourceList: CrmStatisticCustomerSourceRespVO[]) => {
+ if (isEmpty(sourceList)) {
+ return
+ }
+ // 杩欓噷绫诲瀷涓㈠け浜嗘墍浠ラ噸鏂版悶涓彉閲�
+ const list = sourceList as unknown as CrmStatisticCustomerSourceRespVO[]
+ const sumCustomerCount = getSumValue(list.map((item) => item.customerCount))
+ const sumDealCount = getSumValue(list.map((item) => item.dealCount))
+ list.forEach((item) => {
+ item.sourcePortion =
+ item.customerCount === 0 ? 0 : erpCalculatePercentage(item.customerCount, sumCustomerCount)
+ item.dealPortion =
+ item.dealCount === 0 ? 0 : erpCalculatePercentage(item.dealCount, sumDealCount)
+ })
+}
+
+/** 鍒濆鍖� */
+onMounted(() => {
+ loadData()
+})
+</script>
--
Gitblit v1.8.0