feat: crm statistics performance
							parent
							
								
									b2310b226c
								
							
						
					
					
						commit
						62655e23e5
					
				| 
						 | 
					@ -1,5 +1,3 @@
 | 
				
			||||||
import type { PageParam } from '@vben/request';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { requestClient } from '#/api/request';
 | 
					import { requestClient } from '#/api/request';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export namespace CrmStatisticsPerformanceApi {
 | 
					export namespace CrmStatisticsPerformanceApi {
 | 
				
			||||||
| 
						 | 
					@ -10,10 +8,17 @@ export namespace CrmStatisticsPerformanceApi {
 | 
				
			||||||
    lastMonthCount: number;
 | 
					    lastMonthCount: number;
 | 
				
			||||||
    lastYearCount: number;
 | 
					    lastYearCount: number;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  export interface PerformanceParams {
 | 
				
			||||||
 | 
					    times: string[];
 | 
				
			||||||
 | 
					    deptId: number;
 | 
				
			||||||
 | 
					    userId: number;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 员工获得合同金额统计 */
 | 
					/** 员工获得合同金额统计 */
 | 
				
			||||||
export function getContractPricePerformance(params: PageParam) {
 | 
					export function getContractPricePerformance(
 | 
				
			||||||
 | 
					  params: CrmStatisticsPerformanceApi.PerformanceParams,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
  return requestClient.get<CrmStatisticsPerformanceApi.Performance[]>(
 | 
					  return requestClient.get<CrmStatisticsPerformanceApi.Performance[]>(
 | 
				
			||||||
    '/crm/statistics-performance/get-contract-price-performance',
 | 
					    '/crm/statistics-performance/get-contract-price-performance',
 | 
				
			||||||
    { params },
 | 
					    { params },
 | 
				
			||||||
| 
						 | 
					@ -21,7 +26,9 @@ export function getContractPricePerformance(params: PageParam) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 员工获得回款统计 */
 | 
					/** 员工获得回款统计 */
 | 
				
			||||||
export function getReceivablePricePerformance(params: PageParam) {
 | 
					export function getReceivablePricePerformance(
 | 
				
			||||||
 | 
					  params: CrmStatisticsPerformanceApi.PerformanceParams,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
  return requestClient.get<CrmStatisticsPerformanceApi.Performance[]>(
 | 
					  return requestClient.get<CrmStatisticsPerformanceApi.Performance[]>(
 | 
				
			||||||
    '/crm/statistics-performance/get-receivable-price-performance',
 | 
					    '/crm/statistics-performance/get-receivable-price-performance',
 | 
				
			||||||
    { params },
 | 
					    { params },
 | 
				
			||||||
| 
						 | 
					@ -29,7 +36,9 @@ export function getReceivablePricePerformance(params: PageParam) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 员工获得签约合同数量统计 */
 | 
					/** 员工获得签约合同数量统计 */
 | 
				
			||||||
export function getContractCountPerformance(params: PageParam) {
 | 
					export function getContractCountPerformance(
 | 
				
			||||||
 | 
					  params: CrmStatisticsPerformanceApi.PerformanceParams,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
  return requestClient.get<CrmStatisticsPerformanceApi.Performance[]>(
 | 
					  return requestClient.get<CrmStatisticsPerformanceApi.Performance[]>(
 | 
				
			||||||
    '/crm/statistics-performance/get-contract-count-performance',
 | 
					    '/crm/statistics-performance/get-contract-count-performance',
 | 
				
			||||||
    { params },
 | 
					    { params },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,394 @@
 | 
				
			||||||
 | 
					export function getChartOptions(activeTabName: any, res: any): any {
 | 
				
			||||||
 | 
					  switch (activeTabName) {
 | 
				
			||||||
 | 
					    case 'ContractCountPerformance': {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        grid: {
 | 
				
			||||||
 | 
					          left: 20,
 | 
				
			||||||
 | 
					          right: 20,
 | 
				
			||||||
 | 
					          bottom: 20,
 | 
				
			||||||
 | 
					          containLabel: true,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        legend: {},
 | 
				
			||||||
 | 
					        series: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '当月合同数量(个)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.currentMonthCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '上月合同数量(个)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.lastMonthCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '去年同月合同数量(个)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.lastYearCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '环比增长率(%)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            yAxisIndex: 1,
 | 
				
			||||||
 | 
					            data: res.map((s: any) =>
 | 
				
			||||||
 | 
					              s.lastMonthCount === 0
 | 
				
			||||||
 | 
					                ? 'NULL'
 | 
				
			||||||
 | 
					                : (
 | 
				
			||||||
 | 
					                    ((s.currentMonthCount - s.lastMonthCount) /
 | 
				
			||||||
 | 
					                      s.lastMonthCount) *
 | 
				
			||||||
 | 
					                    100
 | 
				
			||||||
 | 
					                  ).toFixed(2),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '同比增长率(%)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            yAxisIndex: 1,
 | 
				
			||||||
 | 
					            data: res.map((s: any) =>
 | 
				
			||||||
 | 
					              s.lastYearCount === 0
 | 
				
			||||||
 | 
					                ? 'NULL'
 | 
				
			||||||
 | 
					                : (
 | 
				
			||||||
 | 
					                    ((s.currentMonthCount - s.lastYearCount) /
 | 
				
			||||||
 | 
					                      s.lastYearCount) *
 | 
				
			||||||
 | 
					                    100
 | 
				
			||||||
 | 
					                  ).toFixed(2),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        toolbox: {
 | 
				
			||||||
 | 
					          feature: {
 | 
				
			||||||
 | 
					            dataZoom: {
 | 
				
			||||||
 | 
					              xAxisIndex: false, // 数据区域缩放:Y 轴不缩放
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            brush: {
 | 
				
			||||||
 | 
					              type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            saveAsImage: { show: true, name: '客户总量分析' }, // 保存为图片
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        tooltip: {
 | 
				
			||||||
 | 
					          trigger: 'axis',
 | 
				
			||||||
 | 
					          axisPointer: {
 | 
				
			||||||
 | 
					            type: 'shadow',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        yAxis: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'value',
 | 
				
			||||||
 | 
					            name: '数量(个)',
 | 
				
			||||||
 | 
					            axisTick: {
 | 
				
			||||||
 | 
					              show: false,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            axisLabel: {
 | 
				
			||||||
 | 
					              color: '#BDBDBD',
 | 
				
			||||||
 | 
					              formatter: '{value}',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            /** 坐标轴轴线相关设置 */
 | 
				
			||||||
 | 
					            axisLine: {
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#BDBDBD',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            splitLine: {
 | 
				
			||||||
 | 
					              show: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#e6e6e6',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'value',
 | 
				
			||||||
 | 
					            name: '',
 | 
				
			||||||
 | 
					            axisTick: {
 | 
				
			||||||
 | 
					              alignWithLabel: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                width: 0,
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            axisLabel: {
 | 
				
			||||||
 | 
					              color: '#BDBDBD',
 | 
				
			||||||
 | 
					              formatter: '{value}%',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            /** 坐标轴轴线相关设置 */
 | 
				
			||||||
 | 
					            axisLine: {
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#BDBDBD',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            splitLine: {
 | 
				
			||||||
 | 
					              show: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#e6e6e6',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        xAxis: {
 | 
				
			||||||
 | 
					          type: 'category',
 | 
				
			||||||
 | 
					          name: '日期',
 | 
				
			||||||
 | 
					          data: res.map((s: any) => s.time),
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 'ContractPricePerformance': {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        grid: {
 | 
				
			||||||
 | 
					          left: 20,
 | 
				
			||||||
 | 
					          right: 20,
 | 
				
			||||||
 | 
					          bottom: 20,
 | 
				
			||||||
 | 
					          containLabel: true,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        legend: {},
 | 
				
			||||||
 | 
					        series: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '当月合同金额(元)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.currentMonthCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '上月合同金额(元)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.lastMonthCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '去年同月合同金额(元)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.lastYearCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '环比增长率(%)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            yAxisIndex: 1,
 | 
				
			||||||
 | 
					            data: res.map((s: any) =>
 | 
				
			||||||
 | 
					              s.lastMonthCount === 0
 | 
				
			||||||
 | 
					                ? 'NULL'
 | 
				
			||||||
 | 
					                : (
 | 
				
			||||||
 | 
					                    ((s.currentMonthCount - s.lastMonthCount) /
 | 
				
			||||||
 | 
					                      s.lastMonthCount) *
 | 
				
			||||||
 | 
					                    100
 | 
				
			||||||
 | 
					                  ).toFixed(2),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '同比增长率(%)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            yAxisIndex: 1,
 | 
				
			||||||
 | 
					            data: res.map((s: any) =>
 | 
				
			||||||
 | 
					              s.lastYearCount === 0
 | 
				
			||||||
 | 
					                ? 'NULL'
 | 
				
			||||||
 | 
					                : (
 | 
				
			||||||
 | 
					                    ((s.currentMonthCount - s.lastYearCount) /
 | 
				
			||||||
 | 
					                      s.lastYearCount) *
 | 
				
			||||||
 | 
					                    100
 | 
				
			||||||
 | 
					                  ).toFixed(2),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        toolbox: {
 | 
				
			||||||
 | 
					          feature: {
 | 
				
			||||||
 | 
					            dataZoom: {
 | 
				
			||||||
 | 
					              xAxisIndex: false, // 数据区域缩放:Y 轴不缩放
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            brush: {
 | 
				
			||||||
 | 
					              type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            saveAsImage: { show: true, name: '客户总量分析' }, // 保存为图片
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        tooltip: {
 | 
				
			||||||
 | 
					          trigger: 'axis',
 | 
				
			||||||
 | 
					          axisPointer: {
 | 
				
			||||||
 | 
					            type: 'shadow',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        yAxis: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'value',
 | 
				
			||||||
 | 
					            name: '金额(元)',
 | 
				
			||||||
 | 
					            axisTick: {
 | 
				
			||||||
 | 
					              show: false,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            axisLabel: {
 | 
				
			||||||
 | 
					              color: '#BDBDBD',
 | 
				
			||||||
 | 
					              formatter: '{value}',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            /** 坐标轴轴线相关设置 */
 | 
				
			||||||
 | 
					            axisLine: {
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#BDBDBD',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            splitLine: {
 | 
				
			||||||
 | 
					              show: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#e6e6e6',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'value',
 | 
				
			||||||
 | 
					            name: '',
 | 
				
			||||||
 | 
					            axisTick: {
 | 
				
			||||||
 | 
					              alignWithLabel: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                width: 0,
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            axisLabel: {
 | 
				
			||||||
 | 
					              color: '#BDBDBD',
 | 
				
			||||||
 | 
					              formatter: '{value}%',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            /** 坐标轴轴线相关设置 */
 | 
				
			||||||
 | 
					            axisLine: {
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#BDBDBD',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            splitLine: {
 | 
				
			||||||
 | 
					              show: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#e6e6e6',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        xAxis: {
 | 
				
			||||||
 | 
					          type: 'category',
 | 
				
			||||||
 | 
					          name: '日期',
 | 
				
			||||||
 | 
					          data: res.map((s: any) => s.time),
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 'ReceivablePricePerformance': {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        grid: {
 | 
				
			||||||
 | 
					          left: 20,
 | 
				
			||||||
 | 
					          right: 20,
 | 
				
			||||||
 | 
					          bottom: 20,
 | 
				
			||||||
 | 
					          containLabel: true,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        legend: {},
 | 
				
			||||||
 | 
					        series: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '当月回款金额(元)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.currentMonthCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '上月回款金额(元)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.lastMonthCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '去年同月回款金额(元)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            data: res.map((s: any) => s.lastYearCount),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '环比增长率(%)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            yAxisIndex: 1,
 | 
				
			||||||
 | 
					            data: res.map((s: any) =>
 | 
				
			||||||
 | 
					              s.lastMonthCount === 0
 | 
				
			||||||
 | 
					                ? 'NULL'
 | 
				
			||||||
 | 
					                : (
 | 
				
			||||||
 | 
					                    ((s.currentMonthCount - s.lastMonthCount) /
 | 
				
			||||||
 | 
					                      s.lastMonthCount) *
 | 
				
			||||||
 | 
					                    100
 | 
				
			||||||
 | 
					                  ).toFixed(2),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: '同比增长率(%)',
 | 
				
			||||||
 | 
					            type: 'line',
 | 
				
			||||||
 | 
					            yAxisIndex: 1,
 | 
				
			||||||
 | 
					            data: res.map((s: any) =>
 | 
				
			||||||
 | 
					              s.lastYearCount === 0
 | 
				
			||||||
 | 
					                ? 'NULL'
 | 
				
			||||||
 | 
					                : (
 | 
				
			||||||
 | 
					                    ((s.currentMonthCount - s.lastYearCount) /
 | 
				
			||||||
 | 
					                      s.lastYearCount) *
 | 
				
			||||||
 | 
					                    100
 | 
				
			||||||
 | 
					                  ).toFixed(2),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        toolbox: {
 | 
				
			||||||
 | 
					          feature: {
 | 
				
			||||||
 | 
					            dataZoom: {
 | 
				
			||||||
 | 
					              xAxisIndex: false, // 数据区域缩放:Y 轴不缩放
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            brush: {
 | 
				
			||||||
 | 
					              type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            saveAsImage: { show: true, name: '客户总量分析' }, // 保存为图片
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        tooltip: {
 | 
				
			||||||
 | 
					          trigger: 'axis',
 | 
				
			||||||
 | 
					          axisPointer: {
 | 
				
			||||||
 | 
					            type: 'shadow',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        yAxis: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'value',
 | 
				
			||||||
 | 
					            name: '金额(元)',
 | 
				
			||||||
 | 
					            axisTick: {
 | 
				
			||||||
 | 
					              show: false,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            axisLabel: {
 | 
				
			||||||
 | 
					              color: '#BDBDBD',
 | 
				
			||||||
 | 
					              formatter: '{value}',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            /** 坐标轴轴线相关设置 */
 | 
				
			||||||
 | 
					            axisLine: {
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#BDBDBD',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            splitLine: {
 | 
				
			||||||
 | 
					              show: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#e6e6e6',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            type: 'value',
 | 
				
			||||||
 | 
					            name: '',
 | 
				
			||||||
 | 
					            axisTick: {
 | 
				
			||||||
 | 
					              alignWithLabel: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                width: 0,
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            axisLabel: {
 | 
				
			||||||
 | 
					              color: '#BDBDBD',
 | 
				
			||||||
 | 
					              formatter: '{value}%',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            /** 坐标轴轴线相关设置 */
 | 
				
			||||||
 | 
					            axisLine: {
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#BDBDBD',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            splitLine: {
 | 
				
			||||||
 | 
					              show: true,
 | 
				
			||||||
 | 
					              lineStyle: {
 | 
				
			||||||
 | 
					                color: '#e6e6e6',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        xAxis: {
 | 
				
			||||||
 | 
					          type: 'category',
 | 
				
			||||||
 | 
					          name: '日期',
 | 
				
			||||||
 | 
					          data: res.map((s: any) => s.time),
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    default: {
 | 
				
			||||||
 | 
					      return {};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,74 @@
 | 
				
			||||||
 | 
					import type { VbenFormSchema } from '#/adapter/form';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useUserStore } from '@vben/stores';
 | 
				
			||||||
 | 
					import { beginOfDay, endOfDay, formatDateTime, handleTree } from '@vben/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { getSimpleDeptList } from '#/api/system/dept';
 | 
				
			||||||
 | 
					import { getSimpleUserList } from '#/api/system/user';
 | 
				
			||||||
 | 
					import { getRangePickerDefaultProps } from '#/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const userStore = useUserStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const customerSummaryTabs = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    tab: '员工合同数量统计',
 | 
				
			||||||
 | 
					    key: 'ContractCountPerformance',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    tab: '员工合同金额统计',
 | 
				
			||||||
 | 
					    key: 'ContractPricePerformance',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    tab: '员工回款金额统计',
 | 
				
			||||||
 | 
					    key: 'ReceivablePricePerformance',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 列表的搜索表单 */
 | 
				
			||||||
 | 
					export function useGridFormSchema(): VbenFormSchema[] {
 | 
				
			||||||
 | 
					  return [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'times',
 | 
				
			||||||
 | 
					      label: '时间范围',
 | 
				
			||||||
 | 
					      component: 'RangePicker',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        ...getRangePickerDefaultProps(),
 | 
				
			||||||
 | 
					        picker: 'year',
 | 
				
			||||||
 | 
					        showTime: false,
 | 
				
			||||||
 | 
					        format: 'YYYY',
 | 
				
			||||||
 | 
					        ranges: {},
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      defaultValue: [
 | 
				
			||||||
 | 
					        formatDateTime(beginOfDay(new Date(new Date().getFullYear(), 0, 1))),
 | 
				
			||||||
 | 
					        formatDateTime(endOfDay(new Date(new Date().getFullYear(), 11, 31))),
 | 
				
			||||||
 | 
					      ] as [Date, Date],
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'deptId',
 | 
				
			||||||
 | 
					      label: '归属部门',
 | 
				
			||||||
 | 
					      component: 'ApiTreeSelect',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        api: async () => {
 | 
				
			||||||
 | 
					          const data = await getSimpleDeptList();
 | 
				
			||||||
 | 
					          return handleTree(data);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        labelField: 'name',
 | 
				
			||||||
 | 
					        valueField: 'id',
 | 
				
			||||||
 | 
					        childrenField: 'children',
 | 
				
			||||||
 | 
					        treeDefaultExpandAll: true,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      defaultValue: userStore.userInfo?.deptId,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'userId',
 | 
				
			||||||
 | 
					      label: '员工',
 | 
				
			||||||
 | 
					      component: 'ApiSelect',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        api: getSimpleUserList,
 | 
				
			||||||
 | 
					        allowClear: true,
 | 
				
			||||||
 | 
					        labelField: 'nickname',
 | 
				
			||||||
 | 
					        valueField: 'id',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,28 +1,156 @@
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { Page } from '@vben/common-ui';
 | 
					import type { EchartsUIType } from '@vben/plugins/echarts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Button } from 'ant-design-vue';
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import type { CrmStatisticsCustomerApi } from '#/api/crm/statistics/customer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { onMounted, ref } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Page } from '@vben/common-ui';
 | 
				
			||||||
 | 
					import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Tabs } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  getContractCountPerformance,
 | 
				
			||||||
 | 
					  getContractPricePerformance,
 | 
				
			||||||
 | 
					  getReceivablePricePerformance,
 | 
				
			||||||
 | 
					} from '#/api/crm/statistics/performance';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { getChartOptions } from './chartOptions';
 | 
				
			||||||
 | 
					import { customerSummaryTabs, useGridFormSchema } from './data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const activeTabName = ref('ContractCountPerformance');
 | 
				
			||||||
 | 
					const chartRef = ref<EchartsUIType>();
 | 
				
			||||||
 | 
					const { renderEcharts } = useEcharts(chartRef);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Grid, gridApi] = useVbenVxeGrid({
 | 
				
			||||||
 | 
					  formOptions: {
 | 
				
			||||||
 | 
					    schema: useGridFormSchema(),
 | 
				
			||||||
 | 
					    handleSubmit: async () => {
 | 
				
			||||||
 | 
					      await handleTabChange(activeTabName.value);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  gridOptions: {
 | 
				
			||||||
 | 
					    columns: [],
 | 
				
			||||||
 | 
					    height: 'auto',
 | 
				
			||||||
 | 
					    keepSource: true,
 | 
				
			||||||
 | 
					    pagerConfig: {
 | 
				
			||||||
 | 
					      enabled: false,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    proxyConfig: {
 | 
				
			||||||
 | 
					      enabled: false,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    data: [],
 | 
				
			||||||
 | 
					    rowConfig: {
 | 
				
			||||||
 | 
					      keyField: 'id',
 | 
				
			||||||
 | 
					      isHover: true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    toolbarConfig: {
 | 
				
			||||||
 | 
					      enabled: false,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  } as VxeTableGridOptions<CrmStatisticsCustomerApi.CustomerSummaryByUser>,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function handleTabChange(key: any) {
 | 
				
			||||||
 | 
					  activeTabName.value = key;
 | 
				
			||||||
 | 
					  const params = (await gridApi.formApi.getValues()) as any;
 | 
				
			||||||
 | 
					  let data: any[] = [];
 | 
				
			||||||
 | 
					  const columnsData: any[] = [];
 | 
				
			||||||
 | 
					  let tableData: any[] = [];
 | 
				
			||||||
 | 
					  switch (key) {
 | 
				
			||||||
 | 
					    case 'ContractCountPerformance': {
 | 
				
			||||||
 | 
					      tableData = [
 | 
				
			||||||
 | 
					        { title: '当月合同数量统计(个)' },
 | 
				
			||||||
 | 
					        { title: '上月合同数量统计(个)' },
 | 
				
			||||||
 | 
					        { title: '去年当月合同数量统计(个)' },
 | 
				
			||||||
 | 
					        { title: '环比增长率(%)' },
 | 
				
			||||||
 | 
					        { title: '同比增长率(%)' },
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					      data = await getContractCountPerformance(params);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 'ContractPricePerformance': {
 | 
				
			||||||
 | 
					      tableData = [
 | 
				
			||||||
 | 
					        { title: '当月合同金额统计(元)' },
 | 
				
			||||||
 | 
					        { title: '上月合同金额统计(元)' },
 | 
				
			||||||
 | 
					        { title: '去年当月合同金额统计(元)' },
 | 
				
			||||||
 | 
					        { title: '环比增长率(%)' },
 | 
				
			||||||
 | 
					        { title: '同比增长率(%)' },
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					      data = await getContractPricePerformance(params);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 'ReceivablePricePerformance': {
 | 
				
			||||||
 | 
					      tableData = [
 | 
				
			||||||
 | 
					        { title: '当月回款金额统计(元)' },
 | 
				
			||||||
 | 
					        { title: '上月回款金额统计(元)' },
 | 
				
			||||||
 | 
					        { title: '去年当月回款金额统计(元)' },
 | 
				
			||||||
 | 
					        { title: '环比增长率(%)' },
 | 
				
			||||||
 | 
					        { title: '同比增长率(%)' },
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					      data = await getReceivablePricePerformance(params);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    default: {
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  const columnObj = {
 | 
				
			||||||
 | 
					    title: '日期',
 | 
				
			||||||
 | 
					    field: 'title',
 | 
				
			||||||
 | 
					    minWidth: 200,
 | 
				
			||||||
 | 
					    align: 'left',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  columnsData.splice(0); // 清空数组
 | 
				
			||||||
 | 
					  columnsData.push(columnObj);
 | 
				
			||||||
 | 
					  data.forEach((item: any, index: number) => {
 | 
				
			||||||
 | 
					    const columnObj = { title: item.time, field: `field${index}` };
 | 
				
			||||||
 | 
					    columnsData.push(columnObj);
 | 
				
			||||||
 | 
					    tableData[0][`field${index}`] = item.currentMonthCount;
 | 
				
			||||||
 | 
					    tableData[1][`field${index}`] = item.lastMonthCount;
 | 
				
			||||||
 | 
					    tableData[2][`field${index}`] = item.lastYearCount;
 | 
				
			||||||
 | 
					    tableData[3][`field${index}`] =
 | 
				
			||||||
 | 
					      item.lastMonthCount === 0
 | 
				
			||||||
 | 
					        ? 'NULL'
 | 
				
			||||||
 | 
					        : (
 | 
				
			||||||
 | 
					            ((item.currentMonthCount - item.lastMonthCount) /
 | 
				
			||||||
 | 
					              item.lastMonthCount) *
 | 
				
			||||||
 | 
					            100
 | 
				
			||||||
 | 
					          ).toFixed(2);
 | 
				
			||||||
 | 
					    tableData[4][`field${index}`] =
 | 
				
			||||||
 | 
					      item.lastYearCount === 0
 | 
				
			||||||
 | 
					        ? 'NULL'
 | 
				
			||||||
 | 
					        : (
 | 
				
			||||||
 | 
					            ((item.currentMonthCount - item.lastYearCount) /
 | 
				
			||||||
 | 
					              item.lastYearCount) *
 | 
				
			||||||
 | 
					            100
 | 
				
			||||||
 | 
					          ).toFixed(2);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  renderEcharts(getChartOptions(key, data), true);
 | 
				
			||||||
 | 
					  gridApi.grid.reloadColumn(columnsData);
 | 
				
			||||||
 | 
					  gridApi.grid.reloadData(tableData);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					onMounted(() => {
 | 
				
			||||||
 | 
					  handleTabChange(activeTabName.value);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Page>
 | 
					  <Page auto-content-height>
 | 
				
			||||||
    <Button
 | 
					    <Grid>
 | 
				
			||||||
      danger
 | 
					      <template #top>
 | 
				
			||||||
      type="link"
 | 
					        <Tabs v-model:active-key="activeTabName" @change="handleTabChange">
 | 
				
			||||||
      target="_blank"
 | 
					          <Tabs.TabPane
 | 
				
			||||||
      href="https://github.com/yudaocode/yudao-ui-admin-vue3"
 | 
					            v-for="item in customerSummaryTabs"
 | 
				
			||||||
    >
 | 
					            :key="item.key"
 | 
				
			||||||
      该功能支持 Vue3 + element-plus 版本!
 | 
					            :tab="item.tab"
 | 
				
			||||||
    </Button>
 | 
					            :force-render="true"
 | 
				
			||||||
    <br />
 | 
					          />
 | 
				
			||||||
    <Button
 | 
					        </Tabs>
 | 
				
			||||||
      type="link"
 | 
					        <EchartsUI class="mb-20 h-full w-full" ref="chartRef" />
 | 
				
			||||||
      target="_blank"
 | 
					      </template>
 | 
				
			||||||
      href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/crm/statistics/performance/index"
 | 
					    </Grid>
 | 
				
			||||||
    >
 | 
					 | 
				
			||||||
      可参考
 | 
					 | 
				
			||||||
      https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/crm/statistics/performance/index
 | 
					 | 
				
			||||||
      代码,pull request 贡献给我们!
 | 
					 | 
				
			||||||
    </Button>
 | 
					 | 
				
			||||||
  </Page>
 | 
					  </Page>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue