Skip to content

Commit d0501ee

Browse files
committed
feat: CRM/数据统计/员工客户分析 初稿
1 parent 3ddba81 commit d0501ee

File tree

7 files changed

+510
-10
lines changed

7 files changed

+510
-10
lines changed

src/api/crm/statistics/customer.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import request from '@/config/axios'
22

33
export interface StatisticsCustomerRespVO {
44
count: number
5+
cycle: number
56
category: string
67
}
78

@@ -21,4 +22,32 @@ export const StatisticsCustomerApi = {
2122
params
2223
})
2324
},
25+
// 获取客户跟进次数
26+
getRecordCount: (params: any) => {
27+
return request.get({
28+
url: '/crm/statistics-customer/get-record-count',
29+
params
30+
})
31+
},
32+
// 获取客户跟进次数
33+
getDistinctRecordCount: (params: any) => {
34+
return request.get({
35+
url: '/crm/statistics-customer/get-distinct-record-count',
36+
params
37+
})
38+
},
39+
// 获取客户跟进方式统计数
40+
getRecordTypeCount: (params: any) => {
41+
return request.get({
42+
url: '/crm/statistics-customer/get-record-type-count',
43+
params
44+
})
45+
},
46+
// 获取客户成交周期
47+
getCustomerCycle: (params: any) => {
48+
return request.get({
49+
url: '/crm/statistics-customer/get-customer-cycle',
50+
params
51+
})
52+
},
2453
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<!-- 客户转化率分析 -->
2+
<template>
3+
<!-- Echarts图 -->
4+
<el-card shadow="never">
5+
<el-skeleton :loading="loading" animated>
6+
<Echart :height="500" :options="echartsOption" />
7+
</el-skeleton>
8+
</el-card>
9+
10+
<!-- 统计列表 -->
11+
<el-card shadow="never" class="mt-16px">
12+
<el-table v-loading="loading" :data="list">
13+
<el-table-column label="序号" align="center" type="index" width="80" />
14+
<el-table-column label="日期" align="center" prop="category" min-width="200" />
15+
<el-table-column label="新增客户数" align="center" prop="customerCount" min-width="200" />
16+
<el-table-column label="成交客户数" align="center" prop="dealCustomerCount" min-width="200" />
17+
<el-table-column label="转化率(%)" align="center" prop="conversionRate" min-width="200" />
18+
</el-table>
19+
</el-card>
20+
</template>
21+
<script setup lang="ts">
22+
import { StatisticsCustomerApi, StatisticsCustomerRespVO } from '@/api/crm/statistics/customer'
23+
import { EChartsOption } from 'echarts'
24+
import { round } from 'lodash-es';
25+
26+
defineOptions({ name: 'ConversionRate' })
27+
const props = defineProps<{ queryParams: any }>() // 搜索参数
28+
29+
const loading = ref(false) // 加载中
30+
const list = ref<StatisticsCustomerRespVO[]>([]) // 列表的数据
31+
32+
/** 柱状图配置:纵向 */
33+
const echartsOption = reactive<EChartsOption>({
34+
grid: {
35+
left: 20,
36+
right: 20,
37+
bottom: 20,
38+
containLabel: true
39+
},
40+
legend: { },
41+
series: [
42+
{
43+
name: '客户转化率',
44+
type: 'line',
45+
data: []
46+
},
47+
],
48+
toolbox: {
49+
feature: {
50+
dataZoom: {
51+
xAxisIndex: false // 数据区域缩放:Y 轴不缩放
52+
},
53+
brush: {
54+
type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮
55+
},
56+
saveAsImage: { show: true, name: '客户转化率分析' } // 保存为图片
57+
}
58+
},
59+
tooltip: {
60+
trigger: 'axis',
61+
axisPointer: {
62+
type: 'shadow'
63+
}
64+
},
65+
yAxis: {
66+
type: 'value',
67+
name: '转化率(%)'
68+
},
69+
xAxis: {
70+
type: 'category',
71+
name: '日期',
72+
data: []
73+
}
74+
}) as EChartsOption
75+
76+
/** 获取统计数据 */
77+
const loadData = async () => {
78+
// 1. 加载统计数据
79+
loading.value = true
80+
const customerCount = await StatisticsCustomerApi.getTotalCustomerCount(props.queryParams)
81+
const dealCustomerCount = await StatisticsCustomerApi.getDealTotalCustomerCount(props.queryParams)
82+
// 2.1 更新 Echarts 数据
83+
if (echartsOption.xAxis && echartsOption.xAxis['data']) {
84+
echartsOption.xAxis['data'] = customerCount.map((s: StatisticsCustomerRespVO) => s.category)
85+
}
86+
if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) {
87+
echartsOption.series[0]['data'] = customerCount.map((item: StatisticsCustomerRespVO, index: number) => {
88+
return {
89+
name: item.category,
90+
value: item.count ? round(dealCustomerCount[index].count / item.count * 100, 2) : 0,
91+
}
92+
})
93+
}
94+
// 2.2 更新列表数据
95+
const tableData = customerCount.map((item: StatisticsCustomerRespVO, index: number) => {
96+
return {
97+
category: item.category,
98+
dealCustomerCount: dealCustomerCount[index].count,
99+
customerCount: item.count,
100+
conversionRate: item.count ? round(dealCustomerCount[index].count / item.count * 100, 2) : 0,
101+
}
102+
})
103+
list.value = tableData
104+
loading.value = false
105+
}
106+
defineExpose({ loadData })
107+
108+
/** 初始化 */
109+
onMounted(() => {
110+
loadData()
111+
})
112+
</script>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<!-- 成交周期分析 -->
2+
<template>
3+
<!-- Echarts图 -->
4+
<el-card shadow="never">
5+
<el-skeleton :loading="loading" animated>
6+
<Echart :height="500" :options="echartsOption" />
7+
</el-skeleton>
8+
</el-card>
9+
10+
<!-- 统计列表 -->
11+
<el-card shadow="never" class="mt-16px">
12+
<el-table v-loading="loading" :data="list">
13+
<el-table-column label="序号" align="center" type="index" width="80" />
14+
<el-table-column label="日期" align="center" prop="category" min-width="200" />
15+
<el-table-column label="成交周期(天)" align="center" prop="customerCycle" min-width="200" />
16+
<el-table-column label="成交客户数" align="center" prop="dealCustomerCount" min-width="200" />
17+
</el-table>
18+
</el-card>
19+
</template>
20+
<script setup lang="ts">
21+
import { StatisticsCustomerApi, StatisticsCustomerRespVO } from '@/api/crm/statistics/customer'
22+
import { EChartsOption } from 'echarts'
23+
24+
defineOptions({ name: 'TotalCustomerCount' })
25+
const props = defineProps<{ queryParams: any }>() // 搜索参数
26+
27+
const loading = ref(false) // 加载中
28+
const list = ref<StatisticsCustomerRespVO[]>([]) // 列表的数据
29+
30+
/** 柱状图配置:纵向 */
31+
const echartsOption = reactive<EChartsOption>({
32+
grid: {
33+
left: 20,
34+
right: 20,
35+
bottom: 20,
36+
containLabel: true
37+
},
38+
legend: { },
39+
series: [
40+
{
41+
name: '成交周期(天)',
42+
type: 'bar',
43+
data: []
44+
},
45+
{
46+
name: '成交客户数',
47+
type: 'bar',
48+
data: []
49+
},
50+
],
51+
toolbox: {
52+
feature: {
53+
dataZoom: {
54+
xAxisIndex: false // 数据区域缩放:Y 轴不缩放
55+
},
56+
brush: {
57+
type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮
58+
},
59+
saveAsImage: { show: true, name: '成交周期分析' } // 保存为图片
60+
}
61+
},
62+
tooltip: {
63+
trigger: 'axis',
64+
axisPointer: {
65+
type: 'shadow'
66+
}
67+
},
68+
yAxis: {
69+
type: 'value',
70+
name: '数量(个)'
71+
},
72+
xAxis: {
73+
type: 'category',
74+
name: '日期',
75+
data: []
76+
}
77+
}) as EChartsOption
78+
79+
/** 获取统计数据 */
80+
const loadData = async () => {
81+
// 1. 加载统计数据
82+
loading.value = true
83+
const customerCycle = await StatisticsCustomerApi.getCustomerCycle(props.queryParams)
84+
const dealCustomerCount = await StatisticsCustomerApi.getDealTotalCustomerCount(props.queryParams)
85+
// 2.1 更新 Echarts 数据
86+
if (echartsOption.xAxis && echartsOption.xAxis['data']) {
87+
echartsOption.xAxis['data'] = customerCycle.map((s: StatisticsCustomerRespVO) => s.category)
88+
}
89+
if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) {
90+
echartsOption.series[0]['data'] = customerCycle.map((s: StatisticsCustomerRespVO) => s['cycle'])
91+
}
92+
if (echartsOption.series && echartsOption.series[1] && echartsOption.series[1]['data']) {
93+
echartsOption.series[1]['data'] = dealCustomerCount.map((s: StatisticsCustomerRespVO) => s.count)
94+
}
95+
// 2.2 更新列表数据
96+
const tableData = customerCycle.map((item: StatisticsCustomerRespVO, index: number) => {
97+
return {
98+
category: item.category,
99+
customerCycle: item.cycle,
100+
dealCustomerCount: dealCustomerCount[index].count,
101+
}
102+
})
103+
list.value = tableData
104+
loading.value = false
105+
}
106+
defineExpose({ loadData })
107+
108+
/** 初始化 */
109+
onMounted(() => {
110+
loadData()
111+
})
112+
</script>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<!-- 客户跟进次数分析 -->
2+
<template>
3+
<!-- Echarts图 -->
4+
<el-card shadow="never">
5+
<el-skeleton :loading="loading" animated>
6+
<Echart :height="500" :options="echartsOption" />
7+
</el-skeleton>
8+
</el-card>
9+
10+
<!-- 统计列表 -->
11+
<el-card shadow="never" class="mt-16px">
12+
<el-table v-loading="loading" :data="list">
13+
<el-table-column label="序号" align="center" type="index" width="80" />
14+
<el-table-column label="日期" align="center" prop="category" min-width="200" />
15+
<el-table-column label="跟进客户数" align="center" prop="distinctRecordCount" min-width="200" />
16+
<el-table-column label="跟进次数" align="center" prop="recordCount" min-width="200" />
17+
</el-table>
18+
</el-card>
19+
</template>
20+
<script setup lang="ts">
21+
import { StatisticsCustomerApi, StatisticsCustomerRespVO } from '@/api/crm/statistics/customer'
22+
import { EChartsOption } from 'echarts'
23+
24+
defineOptions({ name: 'FollowupCount' })
25+
const props = defineProps<{ queryParams: any }>() // 搜索参数
26+
27+
const loading = ref(false) // 加载中
28+
const list = ref<StatisticsCustomerRespVO[]>([]) // 列表的数据
29+
30+
/** 柱状图配置:纵向 */
31+
const echartsOption = reactive<EChartsOption>({
32+
grid: {
33+
left: 20,
34+
right: 20,
35+
bottom: 20,
36+
containLabel: true
37+
},
38+
legend: { },
39+
series: [
40+
{
41+
name: '跟进客户数',
42+
type: 'bar',
43+
data: []
44+
},
45+
{
46+
name: '跟进次数',
47+
type: 'bar',
48+
data: []
49+
},
50+
],
51+
toolbox: {
52+
feature: {
53+
dataZoom: {
54+
xAxisIndex: false // 数据区域缩放:Y 轴不缩放
55+
},
56+
brush: {
57+
type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮
58+
},
59+
saveAsImage: { show: true, name: '客户跟进次数分析' } // 保存为图片
60+
}
61+
},
62+
tooltip: {
63+
trigger: 'axis',
64+
axisPointer: {
65+
type: 'shadow'
66+
}
67+
},
68+
yAxis: {
69+
type: 'value',
70+
name: '数量(个)'
71+
},
72+
xAxis: {
73+
type: 'category',
74+
name: '日期',
75+
data: []
76+
}
77+
}) as EChartsOption
78+
79+
/** 获取统计数据 */
80+
const loadData = async () => {
81+
// 1. 加载统计数据
82+
loading.value = true
83+
const recordCount = await StatisticsCustomerApi.getRecordCount(props.queryParams)
84+
const distinctRecordCount = await StatisticsCustomerApi.getDistinctRecordCount(props.queryParams)
85+
// 2.1 更新 Echarts 数据
86+
if (echartsOption.xAxis && echartsOption.xAxis['data']) {
87+
echartsOption.xAxis['data'] = recordCount.map((s: StatisticsCustomerRespVO) => s.category)
88+
}
89+
if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) {
90+
echartsOption.series[0]['data'] = distinctRecordCount.map((s: StatisticsCustomerRespVO) => s.count)
91+
}
92+
if (echartsOption.series && echartsOption.series[1] && echartsOption.series[1]['data']) {
93+
echartsOption.series[1]['data'] = recordCount.map((s: StatisticsCustomerRespVO) => s.count)
94+
}
95+
// 2.2 更新列表数据
96+
const tableData = recordCount.map((item: StatisticsCustomerRespVO, index: number) => {
97+
return {
98+
category: item.category,
99+
recordCount: item.count,
100+
distinctRecordCount: distinctRecordCount[index].count,
101+
}
102+
})
103+
list.value = tableData
104+
loading.value = false
105+
}
106+
defineExpose({ loadData })
107+
108+
/** 初始化 */
109+
onMounted(() => {
110+
loadData()
111+
})
112+
</script>

0 commit comments

Comments
 (0)