Files
yudao-ui-admin-vben/apps/web-antd/src/views/crm/statistics/funnel/chartOptions.ts
YunaiV c96cf0ead9 feat: 迁移 CRM 数据统计与业绩目标设置
- 迁移 CRM 销售漏斗分析,补充漏斗图、阶段统计和商机转化率分析
- 迁移 CRM 员工业绩分析,补充合同汇总统计
- 迁移 CRM 产品分析,新增产品销售情况和产品分类销售分析
- 新增 CRM 业绩达成统计,支持销售目标和回款目标达成情况展示
- 新增 CRM 业绩目标设置,支持部门和员工维度的目标配置
- 补充 web-antd、web-antdv-next、web-ele 对应 API 和页面实现
- 调整统计图表配置、筛选项和表格展示,统一多端 CRM 统计交互
2026-07-06 08:50:17 +08:00

278 lines
7.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { erpCalculatePercentage, erpPriceInputFormatter } from '@vben/utils';
const getLegend = (extra: Record<string, any> = {}) => ({
top: 10,
...extra,
});
const getGrid = (extra: Record<string, any> = {}) => ({
left: 20,
right: 20,
bottom: 20,
containLabel: true,
...extra,
});
const getTooltip = (extra: Record<string, any> = {}) => ({
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
...extra,
});
export function getChartOptions(
activeTabName: any,
active: boolean,
res: any,
): any {
switch (activeTabName) {
case 'businessInversionRateSummary': {
return {
color: ['#6ca2ff', '#6ac9d7', '#ff7474'],
tooltip: getTooltip(),
legend: getLegend({
data: ['赢单转化率', '商机总数', '赢单商机数'],
bottom: '0px',
itemWidth: 14,
}),
grid: getGrid({
top: '40px',
left: '40px',
right: '40px',
bottom: '40px',
borderColor: '#fff',
}),
xAxis: [
{
type: 'category',
data: res.map((s: any) => s.time),
axisTick: {
alignWithLabel: true,
lineStyle: { width: 0 },
},
axisLabel: {
color: '#BDBDBD',
},
/** 坐标轴轴线相关设置 */
axisLine: {
lineStyle: { color: '#BDBDBD' },
},
splitLine: {
show: false,
},
},
],
yAxis: [
{
type: 'value',
name: '赢单转化率',
axisTick: {
alignWithLabel: true,
lineStyle: { width: 0 },
},
axisLabel: {
color: '#BDBDBD',
formatter: '{value}%',
},
/** 坐标轴轴线相关设置 */
axisLine: {
lineStyle: { color: '#BDBDBD' },
},
splitLine: {
show: false,
},
},
{
type: 'value',
name: '商机数',
axisTick: {
alignWithLabel: true,
lineStyle: { width: 0 },
},
axisLabel: {
color: '#BDBDBD',
formatter: '{value}个',
},
/** 坐标轴轴线相关设置 */
axisLine: {
lineStyle: { color: '#BDBDBD' },
},
splitLine: {
show: false,
},
},
],
series: [
{
name: '赢单转化率',
type: 'line',
yAxisIndex: 0,
data: res.map((s: any) =>
erpCalculatePercentage(s.businessWinCount, s.businessCount),
),
},
{
name: '商机总数',
type: 'bar',
yAxisIndex: 1,
barWidth: 15,
data: res.map((s: any) => s.businessCount),
},
{
name: '赢单商机数',
type: 'bar',
yAxisIndex: 1,
barWidth: 15,
data: res.map((s: any) => s.businessWinCount),
},
],
};
}
case 'businessSummary': {
return {
grid: getGrid({
left: 30,
right: 30, // 让 X 轴右侧显示完整
}),
legend: getLegend(),
series: [
{
name: '新增商机数量',
type: 'bar',
yAxisIndex: 0,
data: res.map((s: any) => s.businessCreateCount),
},
{
name: '新增商机金额',
type: 'bar',
yAxisIndex: 1,
data: res.map((s: any) => s.totalPrice),
},
],
toolbox: {
feature: {
dataZoom: {
xAxisIndex: false, // 数据区域缩放Y 轴不缩放
},
brush: {
type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
},
saveAsImage: { show: true, name: '新增商机分析' }, // 保存为图片
},
},
tooltip: getTooltip(),
yAxis: [
{
type: 'value',
name: '新增商机数量',
min: 0,
minInterval: 1, // 显示整数刻度
},
{
type: 'value',
name: '新增商机金额',
min: 0,
minInterval: 1, // 显示整数刻度
splitLine: {
lineStyle: {
type: 'dotted', // 右侧网格线虚化, 减少混乱
opacity: 0.7,
},
},
},
],
xAxis: {
type: 'category',
name: '日期',
data: res.map((s: any) => s.time),
},
};
}
case 'funnel': {
const list = res.map((item: any) => ({
value: active
? Number(item.businessCount || 0)
: Number(item.totalPrice || 0),
name: `${item.statusName}-${item.businessCount || 0}`,
statusName: item.statusName,
statusPercent: item.statusPercent,
businessCount: item.businessCount,
totalPrice: item.totalPrice,
}));
const maxValue = Math.max(
...list.map((item: any) => Number(item.value || 0)),
1,
);
return {
title: {
text: '销售漏斗',
},
tooltip: getTooltip({
trigger: 'item',
axisPointer: undefined,
formatter: (params: any) => {
const data = params.data || {};
return [
data.statusName || params.name,
`商机数:${data.businessCount || 0}`,
`商机金额:${erpPriceInputFormatter(data.totalPrice || 0)}`,
`赢单率:${data.statusPercent || 0}%`,
].join('<br/>');
},
}),
toolbox: {
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {},
},
},
legend: getLegend({
data: list.map((item: any) => item.name),
}),
series: [
{
name: '销售漏斗',
type: 'funnel',
left: '10%',
top: 60,
bottom: 60,
width: '80%',
min: 0,
max: maxValue,
minSize: '0%',
maxSize: '100%',
sort: 'none',
gap: 2,
label: {
show: true,
position: 'inside',
},
labelLine: {
length: 10,
lineStyle: {
width: 1,
type: 'solid',
},
},
itemStyle: {
borderColor: '#fff',
borderWidth: 1,
},
emphasis: {
label: {
fontSize: 20,
},
},
data: list,
},
],
};
}
default: {
return {};
}
}
}