parent
							
								
									818dc4d8e3
								
							
						
					
					
						commit
						1c034ca575
					
				|  | @ -21,5 +21,47 @@ export const RankApi = { | |||
|       url: '/crm/bi-rank/get-receivable-price-rank', | ||||
|       params | ||||
|     }) | ||||
|   }, | ||||
|   // 签约合同排行
 | ||||
|   getContractCountRank: (params: any) => { | ||||
|     return request.get({ | ||||
|       url: '/crm/bi-rank/get-contract-count-rank', | ||||
|       params | ||||
|     }) | ||||
|   }, | ||||
|   // 产品销量排行
 | ||||
|   getProductSalesRank: (params: any) => { | ||||
|     return request.get({ | ||||
|       url: '/crm/bi-rank/get-product-sales-rank', | ||||
|       params | ||||
|     }) | ||||
|   }, | ||||
|   // 新增客户数排行
 | ||||
|   getCustomerCountRank: (params: any) => { | ||||
|     return request.get({ | ||||
|       url: '/crm/bi-rank/get-customer-count-rank', | ||||
|       params | ||||
|     }) | ||||
|   }, | ||||
|   // 新增联系人数排行
 | ||||
|   getContactsCountRank: (params: any) => { | ||||
|     return request.get({ | ||||
|       url: '/crm/bi-rank/get-contacts-count-rank', | ||||
|       params | ||||
|     }) | ||||
|   }, | ||||
|   // 跟进次数排行
 | ||||
|   getFollowCountRank: (params: any) => { | ||||
|     return request.get({ | ||||
|       url: '/crm/bi-rank/get-follow-count-rank', | ||||
|       params | ||||
|     }) | ||||
|   }, | ||||
|   // 跟进客户数排行
 | ||||
|   getFollowCustomerCountRank: (params: any) => { | ||||
|     return request.get({ | ||||
|       url: '/crm/bi-rank/get-follow-customer-count-rank', | ||||
|       params | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,98 @@ | |||
| <!-- 新增联系人数排行 --> | ||||
| <template> | ||||
|   <!-- 柱状图 --> | ||||
|   <el-card shadow="never"> | ||||
|     <el-skeleton :loading="loading" animated> | ||||
|       <Echart :height="500" :options="echartsOption" /> | ||||
|     </el-skeleton> | ||||
|   </el-card> | ||||
| 
 | ||||
|   <!-- 排行列表 --> | ||||
|   <el-card shadow="never" class="mt-16px"> | ||||
|     <el-table v-loading="loading" :data="list"> | ||||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="创建人" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column label="新增联系人数(个)" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'ContactsCountRank' }) | ||||
| const props = defineProps<{ queryParams: any }>() // 搜索参数 | ||||
| 
 | ||||
| const loading = ref(false) // 加载中 | ||||
| const list = ref<BiRankRespVO[]>([]) // 列表的数据 | ||||
| 
 | ||||
| /** 柱状图配置:横向 */ | ||||
| const echartsOption = reactive<EChartsOption>({ | ||||
|   dataset: { | ||||
|     dimensions: ['nickname', 'count'], | ||||
|     source: [] | ||||
|   }, | ||||
|   grid: { | ||||
|     left: 20, | ||||
|     right: 20, | ||||
|     bottom: 20, | ||||
|     containLabel: true | ||||
|   }, | ||||
|   legend: { | ||||
|     top: 50 | ||||
|   }, | ||||
|   series: [ | ||||
|     { | ||||
|       name: '新增联系人数排行', | ||||
|       type: 'bar' | ||||
|     } | ||||
|   ], | ||||
|   toolbox: { | ||||
|     feature: { | ||||
|       dataZoom: { | ||||
|         yAxisIndex: false // 数据区域缩放:Y 轴不缩放 | ||||
|       }, | ||||
|       brush: { | ||||
|         type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 | ||||
|       }, | ||||
|       saveAsImage: { show: true, name: '新增联系人数排行' } // 保存为图片 | ||||
|     } | ||||
|   }, | ||||
|   tooltip: { | ||||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|     name: '新增联系人数(个)' | ||||
|   }, | ||||
|   yAxis: { | ||||
|     type: 'category', | ||||
|     name: '创建人' | ||||
|   } | ||||
| }) as EChartsOption | ||||
| 
 | ||||
| /** 获取新增联系人数排行 */ | ||||
| const loadData = async () => { | ||||
|   // 1. 加载排行数据 | ||||
|   loading.value = true | ||||
|   const rankingList = await RankApi.getContactsCountRank(props.queryParams) | ||||
|   // 2.1 更新 Echarts 数据 | ||||
|   if (echartsOption.dataset && echartsOption.dataset['source']) { | ||||
|     echartsOption.dataset['source'] = clone(rankingList).reverse() | ||||
|   } | ||||
|   // 2.2 更新列表数据 | ||||
|   list.value = rankingList | ||||
|   loading.value = false | ||||
| } | ||||
| defineExpose({ loadData }) | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| onMounted(() => { | ||||
|   loadData() | ||||
| }) | ||||
| </script> | ||||
|  | @ -0,0 +1,98 @@ | |||
| <!-- 签约合同排行 --> | ||||
| <template> | ||||
|   <!-- 柱状图 --> | ||||
|   <el-card shadow="never"> | ||||
|     <el-skeleton :loading="loading" animated> | ||||
|       <Echart :height="500" :options="echartsOption" /> | ||||
|     </el-skeleton> | ||||
|   </el-card> | ||||
| 
 | ||||
|   <!-- 排行列表 --> | ||||
|   <el-card shadow="never" class="mt-16px"> | ||||
|     <el-table v-loading="loading" :data="list"> | ||||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="签订人" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column label="签约合同数(个)" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'ContractCountRank' }) | ||||
| const props = defineProps<{ queryParams: any }>() // 搜索参数 | ||||
| 
 | ||||
| const loading = ref(false) // 加载中 | ||||
| const list = ref<BiRankRespVO[]>([]) // 列表的数据 | ||||
| 
 | ||||
| /** 柱状图配置:横向 */ | ||||
| const echartsOption = reactive<EChartsOption>({ | ||||
|   dataset: { | ||||
|     dimensions: ['nickname', 'count'], | ||||
|     source: [] | ||||
|   }, | ||||
|   grid: { | ||||
|     left: 20, | ||||
|     right: 20, | ||||
|     bottom: 20, | ||||
|     containLabel: true | ||||
|   }, | ||||
|   legend: { | ||||
|     top: 50 | ||||
|   }, | ||||
|   series: [ | ||||
|     { | ||||
|       name: '签约合同排行', | ||||
|       type: 'bar' | ||||
|     } | ||||
|   ], | ||||
|   toolbox: { | ||||
|     feature: { | ||||
|       dataZoom: { | ||||
|         yAxisIndex: false // 数据区域缩放:Y 轴不缩放 | ||||
|       }, | ||||
|       brush: { | ||||
|         type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 | ||||
|       }, | ||||
|       saveAsImage: { show: true, name: '签约合同排行' } // 保存为图片 | ||||
|     } | ||||
|   }, | ||||
|   tooltip: { | ||||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|     name: '签约合同数(个)' | ||||
|   }, | ||||
|   yAxis: { | ||||
|     type: 'category', | ||||
|     name: '签订人' | ||||
|   } | ||||
| }) as EChartsOption | ||||
| 
 | ||||
| /** 获取签约合同排行 */ | ||||
| const loadData = async () => { | ||||
|   // 1. 加载排行数据 | ||||
|   loading.value = true | ||||
|   const rankingList = await RankApi.getContractCountRank(props.queryParams) | ||||
|   // 2.1 更新 Echarts 数据 | ||||
|   if (echartsOption.dataset && echartsOption.dataset['source']) { | ||||
|     echartsOption.dataset['source'] = clone(rankingList).reverse() | ||||
|   } | ||||
|   // 2.2 更新列表数据 | ||||
|   list.value = rankingList | ||||
|   loading.value = false | ||||
| } | ||||
| defineExpose({ loadData }) | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| onMounted(() => { | ||||
|   loadData() | ||||
| }) | ||||
| </script> | ||||
|  | @ -13,21 +13,13 @@ | |||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="签订人" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column | ||||
|         label="合同金额(元)" | ||||
|         align="center" | ||||
|         prop="count" | ||||
|         min-width="200" | ||||
|         :formatter="fenToYuanFormat" | ||||
|       /> | ||||
|       <el-table-column label="合同金额(元)" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { fenToYuanFormat } from '@/utils/formatter' | ||||
| import { fenToYuan } from '@/utils' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'ContractPriceRank' }) | ||||
|  | @ -72,8 +64,7 @@ const echartsOption = reactive<EChartsOption>({ | |||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     }, | ||||
|     valueFormatter: fenToYuan | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|  |  | |||
|  | @ -0,0 +1,98 @@ | |||
| <!-- 新增客户数排行 --> | ||||
| <template> | ||||
|   <!-- 柱状图 --> | ||||
|   <el-card shadow="never"> | ||||
|     <el-skeleton :loading="loading" animated> | ||||
|       <Echart :height="500" :options="echartsOption" /> | ||||
|     </el-skeleton> | ||||
|   </el-card> | ||||
| 
 | ||||
|   <!-- 排行列表 --> | ||||
|   <el-card shadow="never" class="mt-16px"> | ||||
|     <el-table v-loading="loading" :data="list"> | ||||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="创建人" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column label="新增客户数(个)" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'CustomerCountRank' }) | ||||
| const props = defineProps<{ queryParams: any }>() // 搜索参数 | ||||
| 
 | ||||
| const loading = ref(false) // 加载中 | ||||
| const list = ref<BiRankRespVO[]>([]) // 列表的数据 | ||||
| 
 | ||||
| /** 柱状图配置:横向 */ | ||||
| const echartsOption = reactive<EChartsOption>({ | ||||
|   dataset: { | ||||
|     dimensions: ['nickname', 'count'], | ||||
|     source: [] | ||||
|   }, | ||||
|   grid: { | ||||
|     left: 20, | ||||
|     right: 20, | ||||
|     bottom: 20, | ||||
|     containLabel: true | ||||
|   }, | ||||
|   legend: { | ||||
|     top: 50 | ||||
|   }, | ||||
|   series: [ | ||||
|     { | ||||
|       name: '新增客户数排行', | ||||
|       type: 'bar' | ||||
|     } | ||||
|   ], | ||||
|   toolbox: { | ||||
|     feature: { | ||||
|       dataZoom: { | ||||
|         yAxisIndex: false // 数据区域缩放:Y 轴不缩放 | ||||
|       }, | ||||
|       brush: { | ||||
|         type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 | ||||
|       }, | ||||
|       saveAsImage: { show: true, name: '新增客户数排行' } // 保存为图片 | ||||
|     } | ||||
|   }, | ||||
|   tooltip: { | ||||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|     name: '新增客户数(个)' | ||||
|   }, | ||||
|   yAxis: { | ||||
|     type: 'category', | ||||
|     name: '创建人' | ||||
|   } | ||||
| }) as EChartsOption | ||||
| 
 | ||||
| /** 获取新增客户数排行 */ | ||||
| const loadData = async () => { | ||||
|   // 1. 加载排行数据 | ||||
|   loading.value = true | ||||
|   const rankingList = await RankApi.getCustomerCountRank(props.queryParams) | ||||
|   // 2.1 更新 Echarts 数据 | ||||
|   if (echartsOption.dataset && echartsOption.dataset['source']) { | ||||
|     echartsOption.dataset['source'] = clone(rankingList).reverse() | ||||
|   } | ||||
|   // 2.2 更新列表数据 | ||||
|   list.value = rankingList | ||||
|   loading.value = false | ||||
| } | ||||
| defineExpose({ loadData }) | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| onMounted(() => { | ||||
|   loadData() | ||||
| }) | ||||
| </script> | ||||
|  | @ -0,0 +1,98 @@ | |||
| <!-- 跟进次数排行 --> | ||||
| <template> | ||||
|   <!-- 柱状图 --> | ||||
|   <el-card shadow="never"> | ||||
|     <el-skeleton :loading="loading" animated> | ||||
|       <Echart :height="500" :options="echartsOption" /> | ||||
|     </el-skeleton> | ||||
|   </el-card> | ||||
| 
 | ||||
|   <!-- 排行列表 --> | ||||
|   <el-card shadow="never" class="mt-16px"> | ||||
|     <el-table v-loading="loading" :data="list"> | ||||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="员工" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column label="跟进次数(次)" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'FollowCountRank' }) | ||||
| const props = defineProps<{ queryParams: any }>() // 搜索参数 | ||||
| 
 | ||||
| const loading = ref(false) // 加载中 | ||||
| const list = ref<BiRankRespVO[]>([]) // 列表的数据 | ||||
| 
 | ||||
| /** 柱状图配置:横向 */ | ||||
| const echartsOption = reactive<EChartsOption>({ | ||||
|   dataset: { | ||||
|     dimensions: ['nickname', 'count'], | ||||
|     source: [] | ||||
|   }, | ||||
|   grid: { | ||||
|     left: 20, | ||||
|     right: 20, | ||||
|     bottom: 20, | ||||
|     containLabel: true | ||||
|   }, | ||||
|   legend: { | ||||
|     top: 50 | ||||
|   }, | ||||
|   series: [ | ||||
|     { | ||||
|       name: '跟进次数排行', | ||||
|       type: 'bar' | ||||
|     } | ||||
|   ], | ||||
|   toolbox: { | ||||
|     feature: { | ||||
|       dataZoom: { | ||||
|         yAxisIndex: false // 数据区域缩放:Y 轴不缩放 | ||||
|       }, | ||||
|       brush: { | ||||
|         type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 | ||||
|       }, | ||||
|       saveAsImage: { show: true, name: '跟进次数排行' } // 保存为图片 | ||||
|     } | ||||
|   }, | ||||
|   tooltip: { | ||||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|     name: '跟进次数(次)' | ||||
|   }, | ||||
|   yAxis: { | ||||
|     type: 'category', | ||||
|     name: '员工' | ||||
|   } | ||||
| }) as EChartsOption | ||||
| 
 | ||||
| /** 获取跟进次数排行 */ | ||||
| const loadData = async () => { | ||||
|   // 1. 加载排行数据 | ||||
|   loading.value = true | ||||
|   const rankingList = await RankApi.getFollowCountRank(props.queryParams) | ||||
|   // 2.1 更新 Echarts 数据 | ||||
|   if (echartsOption.dataset && echartsOption.dataset['source']) { | ||||
|     echartsOption.dataset['source'] = clone(rankingList).reverse() | ||||
|   } | ||||
|   // 2.2 更新列表数据 | ||||
|   list.value = rankingList | ||||
|   loading.value = false | ||||
| } | ||||
| defineExpose({ loadData }) | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| onMounted(() => { | ||||
|   loadData() | ||||
| }) | ||||
| </script> | ||||
|  | @ -0,0 +1,98 @@ | |||
| <!-- 跟进客户数排行 --> | ||||
| <template> | ||||
|   <!-- 柱状图 --> | ||||
|   <el-card shadow="never"> | ||||
|     <el-skeleton :loading="loading" animated> | ||||
|       <Echart :height="500" :options="echartsOption" /> | ||||
|     </el-skeleton> | ||||
|   </el-card> | ||||
| 
 | ||||
|   <!-- 排行列表 --> | ||||
|   <el-card shadow="never" class="mt-16px"> | ||||
|     <el-table v-loading="loading" :data="list"> | ||||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="员工" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column label="跟进客户数(个)" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'FollowCustomerCountRank' }) | ||||
| const props = defineProps<{ queryParams: any }>() // 搜索参数 | ||||
| 
 | ||||
| const loading = ref(false) // 加载中 | ||||
| const list = ref<BiRankRespVO[]>([]) // 列表的数据 | ||||
| 
 | ||||
| /** 柱状图配置:横向 */ | ||||
| const echartsOption = reactive<EChartsOption>({ | ||||
|   dataset: { | ||||
|     dimensions: ['nickname', 'count'], | ||||
|     source: [] | ||||
|   }, | ||||
|   grid: { | ||||
|     left: 20, | ||||
|     right: 20, | ||||
|     bottom: 20, | ||||
|     containLabel: true | ||||
|   }, | ||||
|   legend: { | ||||
|     top: 50 | ||||
|   }, | ||||
|   series: [ | ||||
|     { | ||||
|       name: '跟进客户数排行', | ||||
|       type: 'bar' | ||||
|     } | ||||
|   ], | ||||
|   toolbox: { | ||||
|     feature: { | ||||
|       dataZoom: { | ||||
|         yAxisIndex: false // 数据区域缩放:Y 轴不缩放 | ||||
|       }, | ||||
|       brush: { | ||||
|         type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 | ||||
|       }, | ||||
|       saveAsImage: { show: true, name: '跟进客户数排行' } // 保存为图片 | ||||
|     } | ||||
|   }, | ||||
|   tooltip: { | ||||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|     name: '跟进客户数(个)' | ||||
|   }, | ||||
|   yAxis: { | ||||
|     type: 'category', | ||||
|     name: '员工' | ||||
|   } | ||||
| }) as EChartsOption | ||||
| 
 | ||||
| /** 获取跟进客户数排行 */ | ||||
| const loadData = async () => { | ||||
|   // 1. 加载排行数据 | ||||
|   loading.value = true | ||||
|   const rankingList = await RankApi.getFollowCustomerCountRank(props.queryParams) | ||||
|   // 2.1 更新 Echarts 数据 | ||||
|   if (echartsOption.dataset && echartsOption.dataset['source']) { | ||||
|     echartsOption.dataset['source'] = clone(rankingList).reverse() | ||||
|   } | ||||
|   // 2.2 更新列表数据 | ||||
|   list.value = rankingList | ||||
|   loading.value = false | ||||
| } | ||||
| defineExpose({ loadData }) | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| onMounted(() => { | ||||
|   loadData() | ||||
| }) | ||||
| </script> | ||||
|  | @ -0,0 +1,98 @@ | |||
| <!-- 产品销量排行 --> | ||||
| <template> | ||||
|   <!-- 柱状图 --> | ||||
|   <el-card shadow="never"> | ||||
|     <el-skeleton :loading="loading" animated> | ||||
|       <Echart :height="500" :options="echartsOption" /> | ||||
|     </el-skeleton> | ||||
|   </el-card> | ||||
| 
 | ||||
|   <!-- 排行列表 --> | ||||
|   <el-card shadow="never" class="mt-16px"> | ||||
|     <el-table v-loading="loading" :data="list"> | ||||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="员工" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column label="产品销量" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'ProductSalesRank' }) | ||||
| const props = defineProps<{ queryParams: any }>() // 搜索参数 | ||||
| 
 | ||||
| const loading = ref(false) // 加载中 | ||||
| const list = ref<BiRankRespVO[]>([]) // 列表的数据 | ||||
| 
 | ||||
| /** 柱状图配置:横向 */ | ||||
| const echartsOption = reactive<EChartsOption>({ | ||||
|   dataset: { | ||||
|     dimensions: ['nickname', 'count'], | ||||
|     source: [] | ||||
|   }, | ||||
|   grid: { | ||||
|     left: 20, | ||||
|     right: 20, | ||||
|     bottom: 20, | ||||
|     containLabel: true | ||||
|   }, | ||||
|   legend: { | ||||
|     top: 50 | ||||
|   }, | ||||
|   series: [ | ||||
|     { | ||||
|       name: '产品销量排行', | ||||
|       type: 'bar' | ||||
|     } | ||||
|   ], | ||||
|   toolbox: { | ||||
|     feature: { | ||||
|       dataZoom: { | ||||
|         yAxisIndex: false // 数据区域缩放:Y 轴不缩放 | ||||
|       }, | ||||
|       brush: { | ||||
|         type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 | ||||
|       }, | ||||
|       saveAsImage: { show: true, name: '产品销量排行' } // 保存为图片 | ||||
|     } | ||||
|   }, | ||||
|   tooltip: { | ||||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|     name: '产品销量' | ||||
|   }, | ||||
|   yAxis: { | ||||
|     type: 'category', | ||||
|     name: '员工' | ||||
|   } | ||||
| }) as EChartsOption | ||||
| 
 | ||||
| /** 获取产品销量排行 */ | ||||
| const loadData = async () => { | ||||
|   // 1. 加载排行数据 | ||||
|   loading.value = true | ||||
|   const rankingList = await RankApi.getProductSalesRank(props.queryParams) | ||||
|   // 2.1 更新 Echarts 数据 | ||||
|   if (echartsOption.dataset && echartsOption.dataset['source']) { | ||||
|     echartsOption.dataset['source'] = clone(rankingList).reverse() | ||||
|   } | ||||
|   // 2.2 更新列表数据 | ||||
|   list.value = rankingList | ||||
|   loading.value = false | ||||
| } | ||||
| defineExpose({ loadData }) | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| onMounted(() => { | ||||
|   loadData() | ||||
| }) | ||||
| </script> | ||||
|  | @ -13,21 +13,13 @@ | |||
|       <el-table-column label="公司排名" align="center" type="index" width="80" /> | ||||
|       <el-table-column label="签订人" align="center" prop="nickname" min-width="200" /> | ||||
|       <el-table-column label="部门" align="center" prop="deptName" min-width="200" /> | ||||
|       <el-table-column | ||||
|         label="回款金额(元)" | ||||
|         align="center" | ||||
|         prop="count" | ||||
|         min-width="200" | ||||
|         :formatter="fenToYuanFormat" | ||||
|       /> | ||||
|       <el-table-column label="回款金额(元)" align="center" prop="count" min-width="200" /> | ||||
|     </el-table> | ||||
|   </el-card> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { RankApi, BiRankRespVO } from '@/api/crm/bi/rank' | ||||
| import { EChartsOption } from 'echarts' | ||||
| import { fenToYuanFormat } from '@/utils/formatter' | ||||
| import { fenToYuan } from '@/utils' | ||||
| import { clone } from 'unocss' | ||||
| 
 | ||||
| defineOptions({ name: 'ReceivablePriceRank' }) | ||||
|  | @ -72,8 +64,7 @@ const echartsOption = reactive<EChartsOption>({ | |||
|     trigger: 'axis', | ||||
|     axisPointer: { | ||||
|       type: 'shadow' | ||||
|     }, | ||||
|     valueFormatter: fenToYuan | ||||
|     } | ||||
|   }, | ||||
|   xAxis: { | ||||
|     type: 'value', | ||||
|  |  | |||
|  | @ -49,12 +49,42 @@ | |||
|       <el-tab-pane label="回款金额排行" name="receivablePriceRank" lazy> | ||||
|         <ReceivablePriceRank :query-params="queryParams" ref="receivablePriceRankRef" /> | ||||
|       </el-tab-pane> | ||||
|       <!-- 签约合同排行 --> | ||||
|       <el-tab-pane label="签约合同排行" name="contractCountRank" lazy> | ||||
|         <ContractCountRank :query-params="queryParams" ref="contractCountRankRef" /> | ||||
|       </el-tab-pane> | ||||
|       <!-- 产品销量排行 --> | ||||
|       <el-tab-pane label="产品销量排行" name="productSalesRank" lazy> | ||||
|         <ProductSalesRank :query-params="queryParams" ref="productSalesRankRef" /> | ||||
|       </el-tab-pane> | ||||
|       <!-- 新增客户数排行 --> | ||||
|       <el-tab-pane label="新增客户数排行" name="customerCountRank" lazy> | ||||
|         <CustomerCountRank :query-params="queryParams" ref="customerCountRankRef" /> | ||||
|       </el-tab-pane> | ||||
|       <!-- 新增联系人数排行 --> | ||||
|       <el-tab-pane label="新增联系人数排行" name="contactsCountRank" lazy> | ||||
|         <ContactsCountRank :query-params="queryParams" ref="contactsCountRankRef" /> | ||||
|       </el-tab-pane> | ||||
|       <!-- 跟进次数排行 --> | ||||
|       <el-tab-pane label="跟进次数排行" name="followCountRank" lazy> | ||||
|         <FollowCountRank :query-params="queryParams" ref="followCountRankRef" /> | ||||
|       </el-tab-pane> | ||||
|       <!-- 跟进客户数排行 --> | ||||
|       <el-tab-pane label="跟进客户数排行" name="followCustomerCountRank" lazy> | ||||
|         <FollowCustomerCountRank :query-params="queryParams" ref="followCustomerCountRankRef" /> | ||||
|       </el-tab-pane> | ||||
|     </el-tabs> | ||||
|   </el-col> | ||||
| </template> | ||||
| <script lang="ts" setup> | ||||
| import ContractPriceRank from './ContractPriceRank.vue' | ||||
| import ReceivablePriceRank from './ReceivablePriceRank.vue' | ||||
| import ContractCountRank from './ContractCountRank.vue' | ||||
| import ProductSalesRank from './ProductSalesRank.vue' | ||||
| import CustomerCountRank from './CustomerCountRank.vue' | ||||
| import ContactsCountRank from './ContactsCountRank.vue' | ||||
| import FollowCountRank from './FollowCountRank.vue' | ||||
| import FollowCustomerCountRank from './FollowCustomerCountRank.vue' | ||||
| import { defaultProps, handleTree } from '@/utils/tree' | ||||
| import * as DeptApi from '@/api/system/dept' | ||||
| import { beginOfDay, defaultShortcuts, endOfDay, formatDate } from '@/utils/formatTime' | ||||
|  | @ -76,16 +106,48 @@ const deptList = ref<Tree[]>([]) // 树形结构 | |||
| const activeTab = ref('contractPriceRank') | ||||
| const contractPriceRankRef = ref() // ContractPriceRank 组件的引用 | ||||
| const receivablePriceRankRef = ref() // ReceivablePriceRank 组件的引用 | ||||
| const contractCountRankRef = ref() // ContractCountRank 组件的引用 | ||||
| const productSalesRankRef = ref() // ProductSalesRank 组件的引用 | ||||
| const customerCountRankRef = ref() // CustomerCountRank 组件的引用 | ||||
| const contactsCountRankRef = ref() // ContactsCountRank 组件的引用 | ||||
| const followCountRankRef = ref() // FollowCountRank 组件的引用 | ||||
| const followCustomerCountRankRef = ref() // FollowCustomerCountRank 组件的引用 | ||||
| 
 | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   if (activeTab.value === 'contractPriceRank') { | ||||
|     contractPriceRankRef.value.loadData() | ||||
|   } else if (activeTab.value === 'receivablePriceRank') { | ||||
|     receivablePriceRankRef.value.loadData() | ||||
|   switch (activeTab.value) { | ||||
|     case 'contractPriceRank': | ||||
|       contractPriceRankRef.value?.loadData?.() | ||||
|       break | ||||
|     case 'receivablePriceRank': | ||||
|       receivablePriceRankRef.value?.loadData?.() | ||||
|       break | ||||
|     case 'contractCountRank': | ||||
|       contractCountRankRef.value?.loadData?.() | ||||
|       break | ||||
|     case 'productSalesRank': | ||||
|       productSalesRankRef.value?.loadData?.() | ||||
|       break | ||||
|     case 'customerCountRank': | ||||
|       customerCountRankRef.value?.loadData?.() | ||||
|       break | ||||
|     case 'contactsCountRank': | ||||
|       contactsCountRankRef.value?.loadData?.() | ||||
|       break | ||||
|     case 'followCountRank': | ||||
|       followCountRankRef.value?.loadData?.() | ||||
|       break | ||||
|     case 'followCustomerCountRank': | ||||
|       followCustomerCountRankRef.value?.loadData?.() | ||||
|       break | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // 当 activeTab 改变时,刷新当前活动的 tab | ||||
| watch(activeTab, () => { | ||||
|   handleQuery() | ||||
| }) | ||||
| 
 | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value.resetFields() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 安浩浩
						安浩浩