Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
091ce903
authored
Apr 07, 2024
by
芋道源码
Committed by
Gitee
Apr 07, 2024
Browse files
Options
Browse Files
Download
Plain Diff
!417 feat: 增加[客户公海分析]tab
Merge pull request !417 from dhb52/dev
parents
8f8edc95
3c54f5f5
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
359 additions
and
55 deletions
+359
-55
src/api/crm/statistics/customer.ts
+28
-2
src/views/crm/statistics/customer/components/CustomerConversionStat.vue
+17
-8
src/views/crm/statistics/customer/components/CustomerDealCycle.vue
+39
-11
src/views/crm/statistics/customer/components/CustomerFollowUpSummary.vue
+42
-9
src/views/crm/statistics/customer/components/CustomerFollowUpType.vue
+15
-4
src/views/crm/statistics/customer/components/CustomerSummary.vue
+39
-10
src/views/crm/statistics/customer/components/PoolSummary.vue
+148
-0
src/views/crm/statistics/customer/index.vue
+31
-11
No files found.
src/api/crm/statistics/customer.ts
View file @
091ce903
...
@@ -44,6 +44,18 @@ export interface CrmStatisticsCustomerContractSummaryRespVO {
...
@@ -44,6 +44,18 @@ export interface CrmStatisticsCustomerContractSummaryRespVO {
orderDate
:
Date
orderDate
:
Date
}
}
export
interface
CrmStatisticsPoolSummaryByDateRespVO
{
time
:
string
customerPutCount
:
number
customerTakeCount
:
number
}
export
interface
CrmStatisticsPoolSummaryByUserRespVO
{
ownerUserName
:
string
customerPutCount
:
number
customerTakeCount
:
number
}
export
interface
CrmStatisticsCustomerDealCycleByDateRespVO
{
export
interface
CrmStatisticsCustomerDealCycleByDateRespVO
{
time
:
string
time
:
string
customerDealCycle
:
number
customerDealCycle
:
number
...
@@ -99,14 +111,28 @@ export const StatisticsCustomerApi = {
...
@@ -99,14 +111,28 @@ export const StatisticsCustomerApi = {
params
params
})
})
},
},
// 5.1 获取客户成交周期(按日期)
// 5.1 获取客户公海分析(按日期)
getPoolSummaryByDate
:
(
param
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-pool-summary-by-date'
,
params
:
param
})
},
// 5.2 获取客户公海分析(按用户)
getPoolSummaryByUser
:
(
param
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-pool-summary-by-user'
,
params
:
param
})
},
// 6.1 获取客户成交周期(按日期)
getCustomerDealCycleByDate
:
(
params
:
any
)
=>
{
getCustomerDealCycleByDate
:
(
params
:
any
)
=>
{
return
request
.
get
({
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-deal-cycle-by-date'
,
url
:
'/crm/statistics-customer/get-customer-deal-cycle-by-date'
,
params
params
})
})
},
},
//
5
.2 获取客户成交周期(按用户)
//
6
.2 获取客户成交周期(按用户)
getCustomerDealCycleByUser
:
(
params
:
any
)
=>
{
getCustomerDealCycleByUser
:
(
params
:
any
)
=>
{
return
request
.
get
({
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-deal-cycle-by-user'
,
url
:
'/crm/statistics-customer/get-customer-deal-cycle-by-user'
,
...
...
src/views/crm/statistics/customer/components/CustomerConversionStat.vue
View file @
091ce903
...
@@ -69,12 +69,12 @@ import {
...
@@ -69,12 +69,12 @@ import {
CrmStatisticsCustomerSummaryByDateRespVO
CrmStatisticsCustomerSummaryByDateRespVO
}
from
'@/api/crm/statistics/customer'
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
import
{
EChartsOption
}
from
'echarts'
import
{
round
}
from
'lodash-es'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
DICT_TYPE
}
from
'@/utils/dict'
defineOptions
({
name
:
'CustomerConversionStat'
})
defineOptions
({
name
:
'CustomerConversionStat'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
loading
=
ref
(
false
)
// 加载中
...
@@ -84,7 +84,7 @@ const list = ref<CrmStatisticsCustomerSummaryByDateRespVO[]>([]) // 列表的数
...
@@ -84,7 +84,7 @@ const list = ref<CrmStatisticsCustomerSummaryByDateRespVO[]>([]) // 列表的数
const
echartsOption
=
reactive
<
EChartsOption
>
({
const
echartsOption
=
reactive
<
EChartsOption
>
({
grid
:
{
grid
:
{
left
:
20
,
left
:
20
,
right
:
20
,
right
:
40
,
// 让X轴右侧显示完整
bottom
:
20
,
bottom
:
20
,
containLabel
:
true
containLabel
:
true
},
},
...
@@ -124,11 +124,9 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -124,11 +124,9 @@ const echartsOption = reactive<EChartsOption>({
}
}
})
as
EChartsOption
})
as
EChartsOption
/** 获取
统计数据
*/
/** 获取
数据并填充图表
*/
const
loadData
=
async
()
=>
{
const
fetchAndFill
=
async
()
=>
{
// 1. 加载统计数据
// 1. 加载统计数据
loading
.
value
=
true
// TODO @ddhb52:这里调用 StatisticsCustomerApi.getCustomerSummaryByDate 好像不太对???
const
customerCount
=
await
StatisticsCustomerApi
.
getCustomerSummaryByDate
(
props
.
queryParams
)
const
customerCount
=
await
StatisticsCustomerApi
.
getCustomerSummaryByDate
(
props
.
queryParams
)
const
contractSummary
=
await
StatisticsCustomerApi
.
getContractSummary
(
props
.
queryParams
)
const
contractSummary
=
await
StatisticsCustomerApi
.
getContractSummary
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
// 2.1 更新 Echarts 数据
...
@@ -143,7 +141,7 @@ const loadData = async () => {
...
@@ -143,7 +141,7 @@ const loadData = async () => {
return
{
return
{
name
:
item
.
time
,
name
:
item
.
time
,
value
:
item
.
customerCreateCount
value
:
item
.
customerCreateCount
?
round
((
item
.
customerDealCount
/
item
.
customerCreateCount
)
*
100
,
2
)
?
((
item
.
customerDealCount
/
item
.
customerCreateCount
)
*
100
).
toFixed
(
2
)
:
0
:
0
}
}
}
}
...
@@ -151,8 +149,19 @@ const loadData = async () => {
...
@@ -151,8 +149,19 @@ const loadData = async () => {
}
}
// 2.2 更新列表数据
// 2.2 更新列表数据
list
.
value
=
contractSummary
list
.
value
=
contractSummary
loading
.
value
=
false
}
}
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
loading
.
value
=
true
try
{
fetchAndFill
()
}
finally
{
loading
.
value
=
false
}
}
defineExpose
({
loadData
})
defineExpose
({
loadData
})
/** 初始化 */
/** 初始化 */
...
...
src/views/crm/statistics/customer/components/CustomerDealCycle.vue
View file @
091ce903
...
@@ -31,6 +31,7 @@ import {
...
@@ -31,6 +31,7 @@ import {
import
{
EChartsOption
}
from
'echarts'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'CustomerDealCycle'
})
defineOptions
({
name
:
'CustomerDealCycle'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
loading
=
ref
(
false
)
// 加载中
...
@@ -40,7 +41,7 @@ const list = ref<CrmStatisticsCustomerDealCycleByDateRespVO[]>([]) // 列表的
...
@@ -40,7 +41,7 @@ const list = ref<CrmStatisticsCustomerDealCycleByDateRespVO[]>([]) // 列表的
const
echartsOption
=
reactive
<
EChartsOption
>
({
const
echartsOption
=
reactive
<
EChartsOption
>
({
grid
:
{
grid
:
{
left
:
20
,
left
:
20
,
right
:
20
,
right
:
40
,
// 让X轴右侧显示完整
bottom
:
20
,
bottom
:
20
,
containLabel
:
true
containLabel
:
true
},
},
...
@@ -49,12 +50,14 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -49,12 +50,14 @@ const echartsOption = reactive<EChartsOption>({
{
{
name
:
'成交周期(天)'
,
name
:
'成交周期(天)'
,
type
:
'bar'
,
type
:
'bar'
,
data
:
[]
data
:
[],
yAxisIndex
:
0
,
},
},
{
{
name
:
'成交客户数'
,
name
:
'成交客户数'
,
type
:
'bar'
,
type
:
'bar'
,
data
:
[]
data
:
[],
yAxisIndex
:
1
,
}
}
],
],
toolbox
:
{
toolbox
:
{
...
@@ -74,10 +77,26 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -74,10 +77,26 @@ const echartsOption = reactive<EChartsOption>({
type
:
'shadow'
type
:
'shadow'
}
}
},
},
yAxis
:
{
yAxis
:
[
type
:
'value'
,
{
name
:
'数量(个)'
type
:
'value'
,
},
name
:
'成交周期(天)'
,
min
:
0
,
minInterval
:
1
,
// 显示整数刻度
},
{
type
:
'value'
,
name
:
'成交客户数'
,
min
:
0
,
minInterval
:
1
,
// 显示整数刻度
splitLine
:
{
lineStyle
:
{
type
:
'dotted'
,
// 右侧网格线虚化, 减少混乱
opacity
:
0.7
,
}
}
},
],
xAxis
:
{
xAxis
:
{
type
:
'category'
,
type
:
'category'
,
name
:
'日期'
,
name
:
'日期'
,
...
@@ -85,10 +104,9 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -85,10 +104,9 @@ const echartsOption = reactive<EChartsOption>({
}
}
})
as
EChartsOption
})
as
EChartsOption
/** 获取
统计数据
*/
/** 获取
数据并填充图表
*/
const
loadData
=
async
()
=>
{
const
fetchAndFill
=
async
()
=>
{
// 1. 加载统计数据
// 1. 加载统计数据
loading
.
value
=
true
const
customerDealCycleByDate
=
await
StatisticsCustomerApi
.
getCustomerDealCycleByDate
(
const
customerDealCycleByDate
=
await
StatisticsCustomerApi
.
getCustomerDealCycleByDate
(
props
.
queryParams
props
.
queryParams
)
)
...
@@ -116,7 +134,17 @@ const loadData = async () => {
...
@@ -116,7 +134,17 @@ const loadData = async () => {
}
}
// 2.2 更新列表数据
// 2.2 更新列表数据
list
.
value
=
customerDealCycleByUser
list
.
value
=
customerDealCycleByUser
loading
.
value
=
false
}
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
loading
.
value
=
true
try
{
fetchAndFill
()
}
finally
{
loading
.
value
=
false
}
}
}
defineExpose
({
loadData
})
defineExpose
({
loadData
})
...
...
src/views/crm/statistics/customer/components/CustomerFollowUpSummary.vue
View file @
091ce903
<!-- 客户跟进次数分析 -->
<!-- 客户跟进次数分析 -->
<
template
>
<
template
>
<!-- Echarts图 -->
<!-- Echarts图 -->
<el-card
shadow=
"never"
>
<el-card
shadow=
"never"
>
<el-skeleton
:loading=
"loading"
animated
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption"
/>
<Echart
:height=
"500"
:options=
"echartsOption"
/>
</el-skeleton>
</el-skeleton>
...
@@ -28,9 +28,11 @@ import {
...
@@ -28,9 +28,11 @@ import {
CrmStatisticsFollowUpSummaryByDateRespVO
,
CrmStatisticsFollowUpSummaryByDateRespVO
,
CrmStatisticsFollowUpSummaryByUserRespVO
CrmStatisticsFollowUpSummaryByUserRespVO
}
from
'@/api/crm/statistics/customer'
}
from
'@/api/crm/statistics/customer'
import
Echart
from
'@/components/Echart/src/Echart.vue'
;
import
{
EChartsOption
}
from
'echarts'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'CustomerFollowupSummary'
})
defineOptions
({
name
:
'CustomerFollowupSummary'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
loading
=
ref
(
false
)
// 加载中
...
@@ -40,7 +42,7 @@ const list = ref<CrmStatisticsFollowUpSummaryByUserRespVO[]>([]) // 列表的数
...
@@ -40,7 +42,7 @@ const list = ref<CrmStatisticsFollowUpSummaryByUserRespVO[]>([]) // 列表的数
const
echartsOption
=
reactive
<
EChartsOption
>
({
const
echartsOption
=
reactive
<
EChartsOption
>
({
grid
:
{
grid
:
{
left
:
20
,
left
:
20
,
right
:
20
,
right
:
30
,
// 让X轴右侧显示完整
bottom
:
20
,
bottom
:
20
,
containLabel
:
true
containLabel
:
true
},
},
...
@@ -49,11 +51,13 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -49,11 +51,13 @@ const echartsOption = reactive<EChartsOption>({
{
{
name
:
'跟进客户数'
,
name
:
'跟进客户数'
,
type
:
'bar'
,
type
:
'bar'
,
yAxisIndex
:
0
,
data
:
[]
data
:
[]
},
},
{
{
name
:
'跟进次数'
,
name
:
'跟进次数'
,
type
:
'bar'
,
type
:
'bar'
,
yAxisIndex
:
1
,
data
:
[]
data
:
[]
}
}
],
],
...
@@ -74,19 +78,38 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -74,19 +78,38 @@ const echartsOption = reactive<EChartsOption>({
type
:
'shadow'
type
:
'shadow'
}
}
},
},
yAxis
:
{
yAxis
:
[
type
:
'value'
,
{
name
:
'数量(个)'
type
:
'value'
,
},
name
:
'跟进客户数'
,
min
:
0
,
minInterval
:
1
,
// 显示整数刻度
},
{
type
:
'value'
,
name
:
'跟进次数'
,
min
:
0
,
minInterval
:
1
,
// 显示整数刻度
splitLine
:
{
lineStyle
:
{
type
:
'dotted'
,
// 右侧网格线虚化, 减少混乱
opacity
:
0.7
,
}
}
}
],
xAxis
:
{
xAxis
:
{
type
:
'category'
,
type
:
'category'
,
name
:
'日期'
,
name
:
'日期'
,
axisTick
:
{
alignWithLabel
:
true
},
data
:
[]
data
:
[]
}
}
})
as
EChartsOption
})
as
EChartsOption
/** 获取
统计数据
*/
/** 获取
数据并填充图表
*/
const
loadData
=
async
()
=>
{
const
fetchAndFill
=
async
()
=>
{
// 1. 加载统计数据
// 1. 加载统计数据
loading
.
value
=
true
loading
.
value
=
true
const
followUpSummaryByDate
=
await
StatisticsCustomerApi
.
getFollowUpSummaryByDate
(
const
followUpSummaryByDate
=
await
StatisticsCustomerApi
.
getFollowUpSummaryByDate
(
...
@@ -113,7 +136,17 @@ const loadData = async () => {
...
@@ -113,7 +136,17 @@ const loadData = async () => {
}
}
// 2.2 更新列表数据
// 2.2 更新列表数据
list
.
value
=
followUpSummaryByUser
list
.
value
=
followUpSummaryByUser
loading
.
value
=
false
}
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
loading
.
value
=
true
try
{
fetchAndFill
()
}
finally
{
loading
.
value
=
false
}
}
}
defineExpose
({
loadData
})
defineExpose
({
loadData
})
...
...
src/views/crm/statistics/customer/components/CustomerFollowUpType.vue
View file @
091ce903
...
@@ -32,6 +32,7 @@ import { DICT_TYPE, getDictLabel } from '@/utils/dict'
...
@@ -32,6 +32,7 @@ import { DICT_TYPE, getDictLabel } from '@/utils/dict'
import
{
erpCalculatePercentage
}
from
'@/utils'
import
{
erpCalculatePercentage
}
from
'@/utils'
defineOptions
({
name
:
'CustomerFollowupType'
})
defineOptions
({
name
:
'CustomerFollowupType'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
loading
=
ref
(
false
)
// 加载中
...
@@ -73,10 +74,9 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -73,10 +74,9 @@ const echartsOption = reactive<EChartsOption>({
]
]
})
as
EChartsOption
})
as
EChartsOption
/** 获取
统计数据
*/
/** 获取
数据并填充图表
*/
const
loadData
=
async
()
=>
{
const
fetchAndFill
=
async
()
=>
{
// 1. 加载统计数据
// 1. 加载统计数据
loading
.
value
=
true
const
followUpSummaryByType
=
await
StatisticsCustomerApi
.
getFollowUpSummaryByType
(
const
followUpSummaryByType
=
await
StatisticsCustomerApi
.
getFollowUpSummaryByType
(
props
.
queryParams
props
.
queryParams
)
)
...
@@ -99,8 +99,19 @@ const loadData = async () => {
...
@@ -99,8 +99,19 @@ const loadData = async () => {
portion
:
erpCalculatePercentage
(
row
.
followUpRecordCount
,
totalCount
)
portion
:
erpCalculatePercentage
(
row
.
followUpRecordCount
,
totalCount
)
}
}
})
})
loading
.
value
=
false
}
}
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
loading
.
value
=
true
try
{
fetchAndFill
()
}
finally
{
loading
.
value
=
false
}
}
defineExpose
({
loadData
})
defineExpose
({
loadData
})
/** 初始化 */
/** 初始化 */
...
...
src/views/crm/statistics/customer/components/CustomerSummary.vue
View file @
091ce903
...
@@ -61,6 +61,7 @@ import { EChartsOption } from 'echarts'
...
@@ -61,6 +61,7 @@ import { EChartsOption } from 'echarts'
import
{
erpCalculatePercentage
,
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
erpCalculatePercentage
,
erpPriceTableColumnFormatter
}
from
'@/utils'
defineOptions
({
name
:
'CustomerSummary'
})
defineOptions
({
name
:
'CustomerSummary'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
loading
=
ref
(
false
)
// 加载中
...
@@ -70,7 +71,7 @@ const list = ref<CrmStatisticsCustomerSummaryByUserRespVO[]>([]) // 列表的数
...
@@ -70,7 +71,7 @@ const list = ref<CrmStatisticsCustomerSummaryByUserRespVO[]>([]) // 列表的数
const
echartsOption
=
reactive
<
EChartsOption
>
({
const
echartsOption
=
reactive
<
EChartsOption
>
({
grid
:
{
grid
:
{
left
:
20
,
left
:
20
,
right
:
20
,
right
:
30
,
// 让X轴右侧显示完整
bottom
:
20
,
bottom
:
20
,
containLabel
:
true
containLabel
:
true
},
},
...
@@ -79,11 +80,13 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -79,11 +80,13 @@ const echartsOption = reactive<EChartsOption>({
{
{
name
:
'新增客户数'
,
name
:
'新增客户数'
,
type
:
'bar'
,
type
:
'bar'
,
yAxisIndex
:
0
,
data
:
[]
data
:
[]
},
},
{
{
name
:
'成交客户数'
,
name
:
'成交客户数'
,
type
:
'bar'
,
type
:
'bar'
,
yAxisIndex
:
1
,
data
:
[]
data
:
[]
}
}
],
],
...
@@ -104,21 +107,36 @@ const echartsOption = reactive<EChartsOption>({
...
@@ -104,21 +107,36 @@ const echartsOption = reactive<EChartsOption>({
type
:
'shadow'
type
:
'shadow'
}
}
},
},
yAxis
:
{
yAxis
:
[
type
:
'value'
,
{
name
:
'数量(个)'
type
:
'value'
,
},
name
:
'新增客户数'
,
min
:
0
,
minInterval
:
1
,
// 显示整数刻度
},
{
type
:
'value'
,
name
:
'成交客户数'
,
min
:
0
,
minInterval
:
1
,
// 显示整数刻度
splitLine
:
{
lineStyle
:
{
type
:
'dotted'
,
// 右侧网格线虚化, 减少混乱
opacity
:
0.7
,
}
}
}
],
xAxis
:
{
xAxis
:
{
type
:
'category'
,
type
:
'category'
,
name
:
'日期'
,
name
:
'日期'
,
data
:
[]
data
:
[]
,
}
}
})
as
EChartsOption
})
as
EChartsOption
/** 获取
统计数据
*/
/** 获取
数据并填充图表
*/
const
loadData
=
async
()
=>
{
const
fetchAndFill
=
async
()
=>
{
// 1. 加载统计数据
// 1. 加载统计数据
loading
.
value
=
true
const
customerSummaryByDate
=
await
StatisticsCustomerApi
.
getCustomerSummaryByDate
(
const
customerSummaryByDate
=
await
StatisticsCustomerApi
.
getCustomerSummaryByDate
(
props
.
queryParams
props
.
queryParams
)
)
...
@@ -141,10 +159,21 @@ const loadData = async () => {
...
@@ -141,10 +159,21 @@ const loadData = async () => {
(
s
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
s
.
customerDealCount
(
s
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
s
.
customerDealCount
)
)
}
}
// 2.2 更新列表数据
// 2.2 更新列表数据
list
.
value
=
customerSummaryByUser
list
.
value
=
customerSummaryByUser
loading
.
value
=
false
}
}
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
loading
.
value
=
true
try
{
fetchAndFill
()
}
finally
{
loading
.
value
=
false
}
}
defineExpose
({
loadData
})
defineExpose
({
loadData
})
/** 初始化 */
/** 初始化 */
...
...
src/views/crm/statistics/customer/components/PoolSummary.vue
0 → 100644
View file @
091ce903
<!-- 客户总量统计 -->
<
template
>
<!-- Echarts图 -->
<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"
fixed=
"left"
/>
<el-table-column
label=
"员工姓名"
prop=
"ownerUserName"
min-width=
"100"
fixed=
"left"
/>
<el-table-column
label=
"进入公海客户数"
align=
"right"
prop=
"customerPutCount"
min-width=
"200"
/>
<el-table-column
label=
"公海领取客户数"
align=
"right"
prop=
"customerTakeCount"
min-width=
"200"
/>
</el-table>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
StatisticsCustomerApi
,
CrmStatisticsPoolSummaryByDateRespVO
,
CrmStatisticsPoolSummaryByUserRespVO
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'CustomerSummary'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
CrmStatisticsPoolSummaryByUserRespVO
[]
>
([])
// 列表的数据
/** 柱状图配置:纵向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
grid
:
{
left
:
20
,
right
:
40
,
// 让X轴右侧显示完整
bottom
:
20
,
containLabel
:
true
},
legend
:
{},
series
:
[
{
name
:
'进入公海客户数'
,
type
:
'bar'
,
yAxisIndex
:
0
,
data
:
[]
},
{
name
:
'公海领取客户数'
,
type
:
'bar'
,
yAxisIndex
:
1
,
data
:
[]
}
],
toolbox
:
{
feature
:
{
dataZoom
:
{
xAxisIndex
:
false
// 数据区域缩放:Y 轴不缩放
},
brush
:
{
type
:
[
'lineX'
,
'clear'
]
// 区域缩放按钮、还原按钮
},
saveAsImage
:
{
show
:
true
,
name
:
'公海客户分析'
}
// 保存为图片
}
},
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
}
},
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
:
[],
}
})
as
EChartsOption
/** 获取数据并填充图表 */
const
fetchAndFill
=
async
()
=>
{
// 1. 加载统计数据
const
poolSummaryByDate
=
await
StatisticsCustomerApi
.
getPoolSummaryByDate
(
props
.
queryParams
)
const
poolSummaryByUser
=
await
StatisticsCustomerApi
.
getPoolSummaryByUser
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
xAxis
&&
echartsOption
.
xAxis
[
'data'
])
{
echartsOption
.
xAxis
[
'data'
]
=
poolSummaryByDate
.
map
(
(
s
:
CrmStatisticsPoolSummaryByDateRespVO
)
=>
s
.
time
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
poolSummaryByDate
.
map
(
(
s
:
CrmStatisticsPoolSummaryByDateRespVO
)
=>
s
.
customerPutCount
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
1
]
&&
echartsOption
.
series
[
1
][
'data'
])
{
echartsOption
.
series
[
1
][
'data'
]
=
poolSummaryByDate
.
map
(
(
s
:
CrmStatisticsPoolSummaryByDateRespVO
)
=>
s
.
customerTakeCount
)
}
// 2.2 更新列表数据
list
.
value
=
poolSummaryByUser
}
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
loading
.
value
=
true
try
{
fetchAndFill
()
}
finally
{
loading
.
value
=
false
}
}
defineExpose
({
loadData
})
/** 初始化 */
onMounted
(()
=>
{
loadData
()
})
</
script
>
src/views/crm/statistics/customer/index.vue
View file @
091ce903
...
@@ -19,10 +19,16 @@
...
@@ -19,10 +19,16 @@
start-placeholder=
"开始日期"
start-placeholder=
"开始日期"
type=
"daterange"
type=
"daterange"
value-format=
"YYYY-MM-DD HH:mm:ss"
value-format=
"YYYY-MM-DD HH:mm:ss"
@
change=
"handleQuery"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"时间间隔"
prop=
"interval"
>
<el-form-item
label=
"时间间隔"
prop=
"interval"
>
<el-select
v-model=
"queryParams.interval"
class=
"!w-240px"
placeholder=
"间隔类型"
>
<el-select
v-model=
"queryParams.interval"
class=
"!w-240px"
placeholder=
"间隔类型"
@
change=
"handleQuery"
>
<el-option
<el-option
v-for=
"dict in getIntDictOptions(DICT_TYPE.DATE_INTERVAL)"
v-for=
"dict in getIntDictOptions(DICT_TYPE.DATE_INTERVAL)"
:key=
"dict.value"
:key=
"dict.value"
...
@@ -40,11 +46,18 @@
...
@@ -40,11 +46,18 @@
class=
"!w-240px"
class=
"!w-240px"
node-key=
"id"
node-key=
"id"
placeholder=
"请选择归属部门"
placeholder=
"请选择归属部门"
@
change=
"queryParams.userId = undefined"
@
change=
"queryParams.userId = undefined;handleQuery()
"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"员工"
prop=
"userId"
>
<el-form-item
label=
"员工"
prop=
"userId"
>
<el-select
v-model=
"queryParams.userId"
class=
"!w-240px"
clearable
placeholder=
"员工"
>
<el-select
v-model=
"queryParams.userId"
class=
"!w-240px"
clearable
placeholder=
"员工"
@
change=
"handleQuery"
>
<el-option
<el-option
v-for=
"(user, index) in userListByDeptId"
v-for=
"(user, index) in userListByDeptId"
:key=
"index"
:key=
"index"
...
@@ -56,7 +69,7 @@
...
@@ -56,7 +69,7 @@
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
>
<el-button
@
click=
"handleQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
查询
</el-button>
</el-button>
<el-button
@
click=
"resetQuery"
>
<el-button
@
click=
"resetQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
...
@@ -85,6 +98,10 @@
...
@@ -85,6 +98,10 @@
<el-tab-pane
label=
"客户转化率分析"
lazy
name=
"conversionStat"
>
<el-tab-pane
label=
"客户转化率分析"
lazy
name=
"conversionStat"
>
<CustomerConversionStat
ref=
"conversionStatRef"
:query-params=
"queryParams"
/>
<CustomerConversionStat
ref=
"conversionStatRef"
:query-params=
"queryParams"
/>
</el-tab-pane>
</el-tab-pane>
<!-- 公海客户分析 -->
<el-tab-pane
label=
"公海客户分析"
lazy
name=
"poolSummary"
>
<PoolSummary
ref=
"poolSummaryRef"
:query-params=
"queryParams"
/>
</el-tab-pane>
<!-- 成交周期分析 -->
<!-- 成交周期分析 -->
<el-tab-pane
label=
"成交周期分析"
lazy
name=
"dealCycle"
>
<el-tab-pane
label=
"成交周期分析"
lazy
name=
"dealCycle"
>
<CustomerDealCycle
ref=
"dealCycleRef"
:query-params=
"queryParams"
/>
<CustomerDealCycle
ref=
"dealCycleRef"
:query-params=
"queryParams"
/>
...
@@ -97,19 +114,20 @@
...
@@ -97,19 +114,20 @@
import
*
as
DeptApi
from
'@/api/system/dept'
import
*
as
DeptApi
from
'@/api/system/dept'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
UserApi
from
'@/api/system/user'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
beginOfDay
,
defaultShortcuts
,
endOfDay
,
formatDate
}
from
'@/utils/formatTime'
import
{
beginOfDay
,
defaultShortcuts
,
endOfDay
,
formatDate
}
from
'@/utils/formatTime'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
CustomerSummary
from
'./components/CustomerSummary.vue'
import
CustomerFollowUpSummary
from
'./components/CustomerFollowUpSummary.vue'
import
CustomerFollowUpType
from
'./components/CustomerFollowUpType.vue'
import
CustomerConversionStat
from
'./components/CustomerConversionStat.vue'
import
CustomerConversionStat
from
'./components/CustomerConversionStat.vue'
import
CustomerDealCycle
from
'./components/CustomerDealCycle.vue'
import
CustomerDealCycle
from
'./components/CustomerDealCycle.vue'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
CustomerFollowUpSummary
from
'./components/CustomerFollowUpSummary.vue'
import
CustomerFollowUpType
from
'./components/CustomerFollowUpType.vue'
import
CustomerSummary
from
'./components/CustomerSummary.vue'
import
PoolSummary
from
'./components/PoolSummary.vue'
defineOptions
({
name
:
'CrmStatisticsCustomer'
})
defineOptions
({
name
:
'CrmStatisticsCustomer'
})
const
queryParams
=
reactive
({
const
queryParams
=
reactive
({
interval
:
1
,
interval
:
2
,
// WEEK, 周
deptId
:
useUserStore
().
getUser
.
deptId
,
deptId
:
useUserStore
().
getUser
.
deptId
,
userId
:
undefined
,
userId
:
undefined
,
times
:
[
times
:
[
...
@@ -135,8 +153,7 @@ const customerSummaryRef = ref() // 1. 客户总量分析
...
@@ -135,8 +153,7 @@ const customerSummaryRef = ref() // 1. 客户总量分析
const
followUpSummaryRef
=
ref
()
// 2. 客户跟进次数分析
const
followUpSummaryRef
=
ref
()
// 2. 客户跟进次数分析
const
followUpTypeRef
=
ref
()
// 3. 客户跟进方式分析
const
followUpTypeRef
=
ref
()
// 3. 客户跟进方式分析
const
conversionStatRef
=
ref
()
// 4. 客户转化率分析
const
conversionStatRef
=
ref
()
// 4. 客户转化率分析
// 5. TODO 公海客户分析
const
poolSummaryRef
=
ref
()
// 5. 客户公海分析
// 缺 crm_owner_record 表 TODO @dhb52:可以先做界面 + 接口,接口数据直接写死返回,相当于 mock 出来
const
dealCycleRef
=
ref
()
// 6. 成交周期分析
const
dealCycleRef
=
ref
()
// 6. 成交周期分析
/** 搜索按钮操作 */
/** 搜索按钮操作 */
...
@@ -154,6 +171,9 @@ const handleQuery = () => {
...
@@ -154,6 +171,9 @@ const handleQuery = () => {
case
'conversionStat'
:
// 客户转化率分析
case
'conversionStat'
:
// 客户转化率分析
conversionStatRef
.
value
?.
loadData
?.()
conversionStatRef
.
value
?.
loadData
?.()
break
break
case
'poolSummary'
:
// 公海客户分析
poolSummaryRef
.
value
?.
loadData
?.()
break
case
'dealCycle'
:
// 成交周期分析
case
'dealCycle'
:
// 成交周期分析
dealCycleRef
.
value
?.
loadData
?.()
dealCycleRef
.
value
?.
loadData
?.()
break
break
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment