diff --git a/apps/web-antd/src/api/crm/statistics/performance.ts b/apps/web-antd/src/api/crm/statistics/performance.ts index ab3451250..2bfcdd57a 100644 --- a/apps/web-antd/src/api/crm/statistics/performance.ts +++ b/apps/web-antd/src/api/crm/statistics/performance.ts @@ -1,5 +1,3 @@ -import type { PageParam } from '@vben/request'; - import { requestClient } from '#/api/request'; export namespace CrmStatisticsPerformanceApi { @@ -10,10 +8,17 @@ export namespace CrmStatisticsPerformanceApi { lastMonthCount: 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( '/crm/statistics-performance/get-contract-price-performance', { params }, @@ -21,7 +26,9 @@ export function getContractPricePerformance(params: PageParam) { } /** 员工获得回款统计 */ -export function getReceivablePricePerformance(params: PageParam) { +export function getReceivablePricePerformance( + params: CrmStatisticsPerformanceApi.PerformanceParams, +) { return requestClient.get( '/crm/statistics-performance/get-receivable-price-performance', { params }, @@ -29,7 +36,9 @@ export function getReceivablePricePerformance(params: PageParam) { } /** 员工获得签约合同数量统计 */ -export function getContractCountPerformance(params: PageParam) { +export function getContractCountPerformance( + params: CrmStatisticsPerformanceApi.PerformanceParams, +) { return requestClient.get( '/crm/statistics-performance/get-contract-count-performance', { params }, diff --git a/apps/web-antd/src/views/crm/statistics/performance/chartOptions.ts b/apps/web-antd/src/views/crm/statistics/performance/chartOptions.ts new file mode 100644 index 000000000..329b4d7ff --- /dev/null +++ b/apps/web-antd/src/views/crm/statistics/performance/chartOptions.ts @@ -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 {}; + } + } +} diff --git a/apps/web-antd/src/views/crm/statistics/performance/data.ts b/apps/web-antd/src/views/crm/statistics/performance/data.ts new file mode 100644 index 000000000..dd08f80cb --- /dev/null +++ b/apps/web-antd/src/views/crm/statistics/performance/data.ts @@ -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', + }, + }, + ]; +} diff --git a/apps/web-antd/src/views/crm/statistics/performance/index.vue b/apps/web-antd/src/views/crm/statistics/performance/index.vue index 54f2eb5cf..bfa56f5d4 100644 --- a/apps/web-antd/src/views/crm/statistics/performance/index.vue +++ b/apps/web-antd/src/views/crm/statistics/performance/index.vue @@ -1,28 +1,156 @@