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
Commit
762b51a5
authored
Mar 04, 2024
by
dhb52
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: [CRM-客户统计]根据Code-Review 修改
parent
d0501ee0
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
316 additions
and
161 deletions
+316
-161
src/api/crm/statistics/customer.ts
+86
-23
src/views/crm/statistics/customer/components/CustomerConversionStat.vue
+46
-28
src/views/crm/statistics/customer/components/CustomerDealCycle.vue
+36
-21
src/views/crm/statistics/customer/components/CustomerFollowupSummary.vue
+33
-21
src/views/crm/statistics/customer/components/CustomerFollowupType.vue
+23
-16
src/views/crm/statistics/customer/components/CustomerSummary.vue
+60
-22
src/views/crm/statistics/customer/index.vue
+32
-30
No files found.
src/api/crm/statistics/customer.ts
View file @
762b51a5
import
request
from
'@/config/axios'
export
interface
StatisticsCustomer
RespVO
{
count
:
number
c
ycle
:
number
c
ategory
:
string
export
interface
CrmStatisticsCustomerSummaryByDate
RespVO
{
time
:
string
c
ustomerCreateCount
:
number
c
ustomerDealCount
:
number
}
// 客户总量分析 API
export
interface
CrmStatisticsCustomerSummaryByUserRespVO
{
ownerUserName
:
string
customerCreateCount
:
number
customerDealCount
:
number
contractPrice
:
number
receivablePrice
:
number
}
export
interface
CrmStatisticsFollowupSummaryByDateRespVO
{
time
:
string
followupRecordCount
:
number
followupCustomerCount
:
number
}
export
interface
CrmStatisticsFollowupSummaryByUserRespVO
{
ownerUserName
:
string
followupRecordCount
:
number
followupCustomerCount
:
number
}
export
interface
CrmStatisticsFollowupSummaryByTypeRespVO
{
followupType
:
string
followupRecordCount
:
number
}
export
interface
CrmStatisticsCustomerContractSummaryRespVO
{
customerName
:
string
contractName
:
string
totalPrice
:
number
receivablePrice
:
number
customerType
:
string
customerSource
:
string
ownerUserName
:
string
creatorUserName
:
string
createTime
:
Date
orderDate
:
Date
}
export
interface
CrmStatisticsCustomerDealCycleByDateRespVO
{
time
:
string
customerDealCycle
:
number
}
export
interface
CrmStatisticsCustomerDealCycleByUserRespVO
{
ownerUserName
:
string
customerDealCycle
:
number
customerDealCount
:
number
}
// 客户分析 API
export
const
StatisticsCustomerApi
=
{
// 客户总量(新建)
getTotalCustomerCount
:
(
params
:
any
)
=>
{
// 1.1 客户总量分析(按日期)
getCustomerSummaryByDate
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-summary-by-date'
,
params
})
},
// 1.2 客户总量分析(按用户)
getCustomerSummaryByUser
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-
total-customer-count
'
,
url
:
'/crm/statistics-customer/get-
customer-summary-by-user
'
,
params
})
},
//
客户总量(成交
)
get
DealTotalCustomerCount
:
(
params
:
any
)
=>
{
//
2.1 客户跟进次数分析(按日期
)
get
FollowupSummaryByDate
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-
deal-total-customer-count
'
,
url
:
'/crm/statistics-customer/get-
followup-summary-by-date
'
,
params
})
},
//
获取客户跟进次数
get
RecordCount
:
(
params
:
any
)
=>
{
//
2.2 客户跟进次数分析(按用户)
get
FollowupSummaryByUser
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-
record-count
'
,
url
:
'/crm/statistics-customer/get-
followup-summary-by-user
'
,
params
})
},
//
获取客户跟进次
数
get
DistinctRecordCount
:
(
params
:
any
)
=>
{
//
3.1 获取客户跟进方式统计
数
get
FollowupSummaryByType
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-
distinct-record-count
'
,
url
:
'/crm/statistics-customer/get-
followup-summary-by-type
'
,
params
})
},
//
获取客户跟进方式统计数
get
RecordTypeCount
:
(
params
:
any
)
=>
{
//
4.1 合同摘要信息(客户转化率页面)
get
ContractSummary
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-
record-type-count
'
,
url
:
'/crm/statistics-customer/get-
followup-summary-by-type
'
,
params
})
},
//
获取客户成交周期
getCustomer
Cycl
e
:
(
params
:
any
)
=>
{
//
5.1 获取客户成交周期(按日期)
getCustomer
DealCycleByDat
e
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-
cycl
e'
,
url
:
'/crm/statistics-customer/get-customer-
deal-cycle-by-dat
e'
,
params
})
},
// 5.2 获取客户成交周期(按用户)
getCustomerDealCycleByUser
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-deal-cycle-by-user'
,
params
})
}
}
src/views/crm/statistics/customer/components/C
onversionRate
.vue
→
src/views/crm/statistics/customer/components/C
ustomerConversionStat
.vue
View file @
762b51a5
...
...
@@ -11,23 +11,43 @@
<el-card
shadow=
"never"
class=
"mt-16px"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"序号"
align=
"center"
type=
"index"
width=
"80"
/>
<el-table-column
label=
"日期"
align=
"center"
prop=
"category"
min-width=
"200"
/>
<el-table-column
label=
"新增客户数"
align=
"center"
prop=
"customerCount"
min-width=
"200"
/>
<el-table-column
label=
"成交客户数"
align=
"center"
prop=
"dealCustomerCount"
min-width=
"200"
/>
<el-table-column
label=
"转化率(%)"
align=
"center"
prop=
"conversionRate"
min-width=
"200"
/>
<el-table-column
label=
"客户名称"
align=
"center"
prop=
"customerName"
min-width=
"200"
/>
<el-table-column
label=
"合同名称"
align=
"center"
prop=
"contractName"
min-width=
"200"
/>
<el-table-column
label=
"合同总金额"
align=
"center"
prop=
"totalPrice"
min-width=
"200"
/>
<el-table-column
label=
"回款金额"
align=
"center"
prop=
"receivablePrice"
min-width=
"200"
/>
<el-table-column
label=
"负责人"
align=
"center"
prop=
"ownerUserName"
min-width=
"200"
/>
<el-table-column
label=
"创建人"
align=
"center"
prop=
"creatorUserName"
min-width=
"200"
/>
<el-table-column
label=
"创建时间"
align=
"center"
prop=
"createTime"
:formatter=
"dateFormatter"
min-width=
"200"
/>
<el-table-column
label=
"下单日期"
align=
"center"
prop=
"orderDate"
:formatter=
"dateFormatter2"
min-width=
"200"
/>
</el-table>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
StatisticsCustomerApi
,
StatisticsCustomerRespVO
}
from
'@/api/crm/statistics/customer'
import
{
StatisticsCustomerApi
,
CrmStatisticsCustomerSummaryByDateRespVO
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
import
{
round
}
from
'lodash-es'
;
import
{
round
}
from
'lodash-es'
import
{
dateFormatter
,
dateFormatter2
}
from
'@/utils/formatTime'
defineOptions
({
name
:
'C
onversionRate
'
})
defineOptions
({
name
:
'C
ustomerConversionStat
'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
StatisticsCustomer
RespVO
[]
>
([])
// 列表的数据
const
list
=
ref
<
CrmStatisticsCustomerSummaryByDate
RespVO
[]
>
([])
// 列表的数据
/** 柱状图配置:纵向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
...
...
@@ -37,13 +57,13 @@ const echartsOption = reactive<EChartsOption>({
bottom
:
20
,
containLabel
:
true
},
legend
:
{
},
legend
:
{},
series
:
[
{
name
:
'客户转化率'
,
type
:
'line'
,
data
:
[]
}
,
}
],
toolbox
:
{
feature
:
{
...
...
@@ -77,30 +97,28 @@ const echartsOption = reactive<EChartsOption>({
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
customerCount
=
await
StatisticsCustomerApi
.
get
TotalCustomerCount
(
props
.
queryParams
)
const
dealCustomerCount
=
await
StatisticsCustomerApi
.
getDealTotalCustomerCount
(
props
.
queryParams
)
const
customerCount
=
await
StatisticsCustomerApi
.
get
CustomerSummaryByDate
(
props
.
queryParams
)
const
contractSummary
=
await
StatisticsCustomerApi
.
getContractSummary
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
xAxis
&&
echartsOption
.
xAxis
[
'data'
])
{
echartsOption
.
xAxis
[
'data'
]
=
customerCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
category
)
echartsOption
.
xAxis
[
'data'
]
=
customerCount
.
map
(
(
s
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
s
.
time
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
customerCount
.
map
((
item
:
StatisticsCustomerRespVO
,
index
:
number
)
=>
{
return
{
name
:
item
.
category
,
value
:
item
.
count
?
round
(
dealCustomerCount
[
index
].
count
/
item
.
count
*
100
,
2
)
:
0
,
}
})
echartsOption
.
series
[
0
][
'data'
]
=
customerCount
.
map
(
(
item
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
{
return
{
name
:
item
.
time
,
value
:
item
.
customerCreateCount
?
round
((
item
.
customerDealCount
/
item
.
customerCreateCount
)
*
100
,
2
)
:
0
}
}
)
}
// 2.2 更新列表数据
const
tableData
=
customerCount
.
map
((
item
:
StatisticsCustomerRespVO
,
index
:
number
)
=>
{
return
{
category
:
item
.
category
,
dealCustomerCount
:
dealCustomerCount
[
index
].
count
,
customerCount
:
item
.
count
,
conversionRate
:
item
.
count
?
round
(
dealCustomerCount
[
index
].
count
/
item
.
count
*
100
,
2
)
:
0
,
}
})
list
.
value
=
tableData
list
.
value
=
contractSummary
loading
.
value
=
false
}
defineExpose
({
loadData
})
...
...
src/views/crm/statistics/customer/components/CustomerCycle.vue
→
src/views/crm/statistics/customer/components/Customer
Deal
Cycle.vue
View file @
762b51a5
...
...
@@ -11,21 +11,30 @@
<el-card
shadow=
"never"
class=
"mt-16px"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"序号"
align=
"center"
type=
"index"
width=
"80"
/>
<el-table-column
label=
"日期"
align=
"center"
prop=
"category"
min-width=
"200"
/>
<el-table-column
label=
"成交周期(天)"
align=
"center"
prop=
"customerCycle"
min-width=
"200"
/>
<el-table-column
label=
"成交客户数"
align=
"center"
prop=
"dealCustomerCount"
min-width=
"200"
/>
<el-table-column
label=
"日期"
align=
"center"
prop=
"ownerUserName"
min-width=
"200"
/>
<el-table-column
label=
"成交周期(天)"
align=
"center"
prop=
"customerDealCycle"
min-width=
"200"
/>
<el-table-column
label=
"成交客户数"
align=
"center"
prop=
"customerDealCount"
min-width=
"200"
/>
</el-table>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
StatisticsCustomerApi
,
StatisticsCustomerRespVO
}
from
'@/api/crm/statistics/customer'
import
{
StatisticsCustomerApi
,
CrmStatisticsCustomerDealCycleByDateRespVO
,
CrmStatisticsCustomerSummaryByDateRespVO
,
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'
TotalCustomerCount
'
})
defineOptions
({
name
:
'
CustomerDealCycle
'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
StatisticsCustomer
RespVO
[]
>
([])
// 列表的数据
const
list
=
ref
<
CrmStatisticsCustomerDealCycleByDate
RespVO
[]
>
([])
// 列表的数据
/** 柱状图配置:纵向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
...
...
@@ -35,7 +44,7 @@ const echartsOption = reactive<EChartsOption>({
bottom
:
20
,
containLabel
:
true
},
legend
:
{
},
legend
:
{},
series
:
[
{
name
:
'成交周期(天)'
,
...
...
@@ -46,7 +55,7 @@ const echartsOption = reactive<EChartsOption>({
name
:
'成交客户数'
,
type
:
'bar'
,
data
:
[]
}
,
}
],
toolbox
:
{
feature
:
{
...
...
@@ -80,27 +89,33 @@ const echartsOption = reactive<EChartsOption>({
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
customerCycle
=
await
StatisticsCustomerApi
.
getCustomerCycle
(
props
.
queryParams
)
const
dealCustomerCount
=
await
StatisticsCustomerApi
.
getDealTotalCustomerCount
(
props
.
queryParams
)
const
customerDealCycleByDate
=
await
StatisticsCustomerApi
.
getCustomerDealCycleByDate
(
props
.
queryParams
)
const
customerSummaryByDate
=
await
StatisticsCustomerApi
.
getCustomerSummaryByDate
(
props
.
queryParams
)
const
customerDealCycleByUser
=
await
StatisticsCustomerApi
.
getCustomerDealCycleByUser
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
xAxis
&&
echartsOption
.
xAxis
[
'data'
])
{
echartsOption
.
xAxis
[
'data'
]
=
customerCycle
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
category
)
echartsOption
.
xAxis
[
'data'
]
=
customerDealCycleByDate
.
map
(
(
s
:
CrmStatisticsCustomerDealCycleByDateRespVO
)
=>
s
.
time
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
customerCycle
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
[
'cycle'
])
echartsOption
.
series
[
0
][
'data'
]
=
customerDealCycleByDate
.
map
(
(
s
:
CrmStatisticsCustomerDealCycleByDateRespVO
)
=>
s
.
customerDealCycle
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
1
]
&&
echartsOption
.
series
[
1
][
'data'
])
{
echartsOption
.
series
[
1
][
'data'
]
=
dealCustomerCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
count
)
echartsOption
.
series
[
1
][
'data'
]
=
customerSummaryByDate
.
map
(
(
s
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
s
.
customerDealCount
)
}
// 2.2 更新列表数据
const
tableData
=
customerCycle
.
map
((
item
:
StatisticsCustomerRespVO
,
index
:
number
)
=>
{
return
{
category
:
item
.
category
,
customerCycle
:
item
.
cycle
,
dealCustomerCount
:
dealCustomerCount
[
index
].
count
,
}
})
list
.
value
=
tableData
list
.
value
=
customerDealCycleByUser
loading
.
value
=
false
}
defineExpose
({
loadData
})
...
...
src/views/crm/statistics/customer/components/
FollowupCount
.vue
→
src/views/crm/statistics/customer/components/
CustomerFollowupSummary
.vue
View file @
762b51a5
...
...
@@ -11,21 +11,30 @@
<el-card
shadow=
"never"
class=
"mt-16px"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"序号"
align=
"center"
type=
"index"
width=
"80"
/>
<el-table-column
label=
"日期"
align=
"center"
prop=
"category"
min-width=
"200"
/>
<el-table-column
label=
"跟进客户数"
align=
"center"
prop=
"distinctRecordCount"
min-width=
"200"
/>
<el-table-column
label=
"跟进次数"
align=
"center"
prop=
"recordCount"
min-width=
"200"
/>
<el-table-column
label=
"员工姓名"
align=
"center"
prop=
"ownerUserName"
min-width=
"200"
/>
<el-table-column
label=
"跟进次数"
align=
"right"
prop=
"followupRecordCount"
min-width=
"200"
/>
<el-table-column
label=
"跟进客户数"
align=
"right"
prop=
"followupCustomerCount"
min-width=
"200"
/>
</el-table>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
StatisticsCustomerApi
,
StatisticsCustomerRespVO
}
from
'@/api/crm/statistics/customer'
import
{
StatisticsCustomerApi
,
CrmStatisticsFollowupSummaryByDateRespVO
,
CrmStatisticsFollowupSummaryByUserRespVO
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'
FollowupCount
'
})
defineOptions
({
name
:
'
CustomerFollowupSummary
'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
StatisticsCustom
erRespVO
[]
>
([])
// 列表的数据
const
list
=
ref
<
CrmStatisticsFollowupSummaryByUs
erRespVO
[]
>
([])
// 列表的数据
/** 柱状图配置:纵向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
...
...
@@ -35,7 +44,7 @@ const echartsOption = reactive<EChartsOption>({
bottom
:
20
,
containLabel
:
true
},
legend
:
{
},
legend
:
{},
series
:
[
{
name
:
'跟进客户数'
,
...
...
@@ -46,7 +55,7 @@ const echartsOption = reactive<EChartsOption>({
name
:
'跟进次数'
,
type
:
'bar'
,
data
:
[]
}
,
}
],
toolbox
:
{
feature
:
{
...
...
@@ -80,27 +89,30 @@ const echartsOption = reactive<EChartsOption>({
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
recordCount
=
await
StatisticsCustomerApi
.
getRecordCount
(
props
.
queryParams
)
const
distinctRecordCount
=
await
StatisticsCustomerApi
.
getDistinctRecordCount
(
props
.
queryParams
)
const
followupSummaryByDate
=
await
StatisticsCustomerApi
.
getFollowupSummaryByDate
(
props
.
queryParams
)
const
followupSummaryByUser
=
await
StatisticsCustomerApi
.
getFollowupSummaryByUser
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
xAxis
&&
echartsOption
.
xAxis
[
'data'
])
{
echartsOption
.
xAxis
[
'data'
]
=
recordCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
category
)
echartsOption
.
xAxis
[
'data'
]
=
followupSummaryByDate
.
map
(
(
s
:
CrmStatisticsFollowupSummaryByDateRespVO
)
=>
s
.
time
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
distinctRecordCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
count
)
echartsOption
.
series
[
0
][
'data'
]
=
followupSummaryByDate
.
map
(
(
s
:
CrmStatisticsFollowupSummaryByDateRespVO
)
=>
s
.
followupCustomerCount
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
1
]
&&
echartsOption
.
series
[
1
][
'data'
])
{
echartsOption
.
series
[
1
][
'data'
]
=
recordCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
count
)
echartsOption
.
series
[
1
][
'data'
]
=
followupSummaryByDate
.
map
(
(
s
:
CrmStatisticsFollowupSummaryByDateRespVO
)
=>
s
.
followupRecordCount
)
}
// 2.2 更新列表数据
const
tableData
=
recordCount
.
map
((
item
:
StatisticsCustomerRespVO
,
index
:
number
)
=>
{
return
{
category
:
item
.
category
,
recordCount
:
item
.
count
,
distinctRecordCount
:
distinctRecordCount
[
index
].
count
,
}
})
list
.
value
=
tableData
list
.
value
=
followupSummaryByUser
loading
.
value
=
false
}
defineExpose
({
loadData
})
...
...
src/views/crm/statistics/customer/components/FollowupType.vue
→
src/views/crm/statistics/customer/components/
Customer
FollowupType.vue
View file @
762b51a5
...
...
@@ -11,22 +11,25 @@
<el-card
shadow=
"never"
class=
"mt-16px"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"序号"
align=
"center"
type=
"index"
width=
"80"
/>
<el-table-column
label=
"跟进方式"
align=
"center"
prop=
"
category
"
min-width=
"200"
/>
<el-table-column
label=
"个数"
align=
"center"
prop=
"
c
ount"
min-width=
"200"
/>
<el-table-column
label=
"跟进方式"
align=
"center"
prop=
"
followupType
"
min-width=
"200"
/>
<el-table-column
label=
"个数"
align=
"center"
prop=
"
followupRecordC
ount"
min-width=
"200"
/>
<el-table-column
label=
"占比(%)"
align=
"center"
prop=
"portion"
min-width=
"200"
/>
</el-table>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
StatisticsCustomerApi
,
StatisticsCustomerRespVO
}
from
'@/api/crm/statistics/customer'
import
{
StatisticsCustomerApi
,
CrmStatisticsFollowupSummaryByTypeRespVO
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
import
{
round
,
sumBy
}
from
'lodash-es'
defineOptions
({
name
:
'FollowupType'
})
defineOptions
({
name
:
'
Customer
FollowupType'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
StatisticsCustomer
RespVO
[]
>
([])
// 列表的数据
const
list
=
ref
<
CrmStatisticsFollowupSummaryByType
RespVO
[]
>
([])
// 列表的数据
/** 饼图配置 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
...
...
@@ -68,23 +71,27 @@ const echartsOption = reactive<EChartsOption>({
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
recordTypeCount
=
await
StatisticsCustomerApi
.
getRecordTypeCount
(
props
.
queryParams
)
const
followupSummaryByType
=
await
StatisticsCustomerApi
.
getFollowupSummaryByType
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
recordTypeCount
.
map
((
r
:
StatisticsCustomerRespVO
)
=>
{
return
{
name
:
r
.
category
,
value
:
r
.
count
echartsOption
.
series
[
0
][
'data'
]
=
followupSummaryByType
.
map
(
(
r
:
CrmStatisticsFollowupSummaryByTypeRespVO
)
=>
{
return
{
name
:
r
.
followupType
,
value
:
r
.
followupRecordCount
}
}
}
)
)
}
// 2.2 更新列表数据
const
totalCount
=
sumBy
(
recordTypeCount
,
'c
ount'
)
list
.
value
=
recordTypeCount
.
map
((
r
:
StatisticsCustomer
RespVO
)
=>
{
const
totalCount
=
sumBy
(
followupSummaryByType
,
'followupRecordC
ount'
)
list
.
value
=
followupSummaryByType
.
map
((
r
:
CrmStatisticsFollowupSummaryByType
RespVO
)
=>
{
return
{
category
:
r
.
category
,
count
:
r
.
c
ount
,
portion
:
round
((
r
.
c
ount
/
totalCount
)
*
100
,
2
)
followupType
:
r
.
followupType
,
followupRecordCount
:
r
.
followupRecordC
ount
,
portion
:
round
((
r
.
followupRecordC
ount
/
totalCount
)
*
100
,
2
)
}
})
loading
.
value
=
false
...
...
src/views/crm/statistics/customer/components/
TotalCustomerCount
.vue
→
src/views/crm/statistics/customer/components/
CustomerSummary
.vue
View file @
762b51a5
<!-- 客户
总量分析
-->
<!-- 客户
统计
-->
<
template
>
<!-- Echarts图 -->
<el-card
shadow=
"never"
>
...
...
@@ -11,21 +11,56 @@
<el-card
shadow=
"never"
class=
"mt-16px"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"序号"
align=
"center"
type=
"index"
width=
"80"
/>
<el-table-column
label=
"日期"
align=
"center"
prop=
"category"
min-width=
"200"
/>
<el-table-column
label=
"新增客户数"
align=
"center"
prop=
"customerCount"
min-width=
"200"
/>
<el-table-column
label=
"成交客户数"
align=
"center"
prop=
"dealCustomerCount"
min-width=
"200"
/>
<el-table-column
label=
"员工姓名"
prop=
"ownerUserName"
min-width=
"100"
/>
<el-table-column
label=
"新增客户数"
align=
"right"
prop=
"customerCreateCount"
min-width=
"200"
/>
<el-table-column
label=
"成交客户数"
align=
"right"
prop=
"customerDealCount"
min-width=
"200"
/>
<el-table-column
label=
"客户成交率(%)"
align=
"right"
min-width=
"200"
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
customerCreateCount
!==
0
?
round
((
scope
.
row
.
customerDealCount
/
scope
.
row
.
customerCreateCount
)
*
100
,
2
)
:
0
}}
</
template
>
</el-table-column>
<el-table-column
label=
"合同总金额"
align=
"right"
prop=
"contractPrice"
min-width=
"200"
/>
<el-table-column
label=
"回款金额"
align=
"right"
prop=
"receivablePrice"
min-width=
"200"
/>
<el-table-column
label=
"未回款金额"
align=
"right"
min-width=
"200"
>
<
template
#
default=
"scope"
>
{{
round
(
scope
.
row
.
contractPrice
-
scope
.
row
.
receivablePrice
,
2
)
}}
</
template
>
</el-table-column>
<el-table-column
label=
"回款完成率(%)"
align=
"right"
min-width=
"200"
>
<
template
#
default=
"scope"
>
{{
scope
.
row
.
contractPrice
!==
0
?
round
((
scope
.
row
.
receivablePrice
/
scope
.
row
.
contractPrice
)
*
100
,
2
)
:
0
}}
</
template
>
</el-table-column>
</el-table>
</el-card>
</template>
<
script
setup
lang=
"ts"
>
import
{
StatisticsCustomerApi
,
StatisticsCustomerRespVO
}
from
'@/api/crm/statistics/customer'
import
{
StatisticsCustomerApi
,
CrmStatisticsCustomerSummaryByDateRespVO
,
CrmStatisticsCustomerSummaryByUserRespVO
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
import
{
round
}
from
'lodash-es'
defineOptions
({
name
:
'
TotalCustomerCount
'
})
defineOptions
({
name
:
'
CustomerSummary
'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
StatisticsCustom
erRespVO
[]
>
([])
// 列表的数据
const
list
=
ref
<
CrmStatisticsCustomerSummaryByUs
erRespVO
[]
>
([])
// 列表的数据
/** 柱状图配置:纵向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
...
...
@@ -35,7 +70,7 @@ const echartsOption = reactive<EChartsOption>({
bottom
:
20
,
containLabel
:
true
},
legend
:
{
},
legend
:
{},
series
:
[
{
name
:
'新增客户数'
,
...
...
@@ -46,7 +81,7 @@ const echartsOption = reactive<EChartsOption>({
name
:
'成交客户数'
,
type
:
'bar'
,
data
:
[]
}
,
}
],
toolbox
:
{
feature
:
{
...
...
@@ -80,27 +115,30 @@ const echartsOption = reactive<EChartsOption>({
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
customerCount
=
await
StatisticsCustomerApi
.
getTotalCustomerCount
(
props
.
queryParams
)
const
dealCustomerCount
=
await
StatisticsCustomerApi
.
getDealTotalCustomerCount
(
props
.
queryParams
)
const
customerSummaryByDate
=
await
StatisticsCustomerApi
.
getCustomerSummaryByDate
(
props
.
queryParams
)
const
customerSummaryByUser
=
await
StatisticsCustomerApi
.
getCustomerSummaryByUser
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
xAxis
&&
echartsOption
.
xAxis
[
'data'
])
{
echartsOption
.
xAxis
[
'data'
]
=
customerCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
category
)
echartsOption
.
xAxis
[
'data'
]
=
customerSummaryByDate
.
map
(
(
s
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
s
.
time
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
customerCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
count
)
echartsOption
.
series
[
0
][
'data'
]
=
customerSummaryByDate
.
map
(
(
s
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
s
.
customerCreateCount
)
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
1
]
&&
echartsOption
.
series
[
1
][
'data'
])
{
echartsOption
.
series
[
1
][
'data'
]
=
dealCustomerCount
.
map
((
s
:
StatisticsCustomerRespVO
)
=>
s
.
count
)
echartsOption
.
series
[
1
][
'data'
]
=
customerSummaryByDate
.
map
(
(
s
:
CrmStatisticsCustomerSummaryByDateRespVO
)
=>
s
.
customerDealCount
)
}
// 2.2 更新列表数据
const
tableData
=
customerCount
.
map
((
item
:
StatisticsCustomerRespVO
,
index
:
number
)
=>
{
return
{
category
:
item
.
category
,
customerCount
:
item
.
count
,
dealCustomerCount
:
dealCustomerCount
[
index
].
count
,
}
})
list
.
value
=
tableData
list
.
value
=
customerSummaryByUser
loading
.
value
=
false
}
defineExpose
({
loadData
})
...
...
src/views/crm/statistics/customer/index.vue
View file @
762b51a5
...
...
@@ -49,44 +49,44 @@
</el-form>
</ContentWrap>
<!--
排行数据
-->
<!--
客户统计
-->
<el-col>
<el-tabs
v-model=
"activeTab"
>
<!-- 客户总量分析 -->
<el-tab-pane
label=
"客户总量分析"
name=
"
totalCustomerCount
"
lazy
>
<
TotalCustomerCount
:query-params=
"queryParams"
ref=
"totalCustomerCount
Ref"
/>
<el-tab-pane
label=
"客户总量分析"
name=
"
customerSummary
"
lazy
>
<
CustomerSummary
:query-params=
"queryParams"
ref=
"customerSummary
Ref"
/>
</el-tab-pane>
<!-- 客户跟进次数分析 -->
<el-tab-pane
label=
"客户跟进次数分析"
name=
"followup
Count
"
lazy
>
<
FollowupCount
:query-params=
"queryParams"
ref=
"followupCount
Ref"
/>
<el-tab-pane
label=
"客户跟进次数分析"
name=
"followup
Summary
"
lazy
>
<
CustomerFollowupSummary
:query-params=
"queryParams"
ref=
"followupSummary
Ref"
/>
</el-tab-pane>
<!-- 客户跟进方式分析 -->
<el-tab-pane
label=
"客户跟进方式分析"
name=
"followupType"
lazy
>
<FollowupType
:query-params=
"queryParams"
ref=
"followupTypeRef"
/>
<
Customer
FollowupType
:query-params=
"queryParams"
ref=
"followupTypeRef"
/>
</el-tab-pane>
<!-- 客户转化率分析 -->
<el-tab-pane
label=
"客户转化率分析"
name=
"conversion
Rate
"
lazy
>
<C
onversionRate
:query-params=
"queryParams"
ref=
"conversionRate
Ref"
/>
<el-tab-pane
label=
"客户转化率分析"
name=
"conversion
Stat
"
lazy
>
<C
ustomerConversionStat
:query-params=
"queryParams"
ref=
"conversionStat
Ref"
/>
</el-tab-pane>
<!-- 成交周期分析 -->
<el-tab-pane
label=
"成交周期分析"
name=
"
customer
Cycle"
lazy
>
<Customer
Cycle
:query-params=
"queryParams"
ref=
"customer
CycleRef"
/>
<el-tab-pane
label=
"成交周期分析"
name=
"
deal
Cycle"
lazy
>
<Customer
DealCycle
:query-params=
"queryParams"
ref=
"deal
CycleRef"
/>
</el-tab-pane>
</el-tabs>
</el-col>
</
template
>
<
script
lang=
"ts"
setup
>
import
*
as
DeptApi
from
'@/api/system/dept'
import
*
as
UserApi
from
'@/api/system/user'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
beginOfDay
,
defaultShortcuts
,
endOfDay
,
formatDate
}
from
'@/utils/formatTime'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
TotalCustomerCount
from
'./components/TotalCustomerCount.vue'
import
FollowupCount
from
'./components/FollowupCount.vue'
import
FollowupType
from
'./components/FollowupType.vue'
import
ConversionRate
from
'./components/ConversionRate.vue'
import
CustomerCycle
from
'./components/CustomerCycle.vue'
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
CustomerDealCycle
from
'./components/CustomerDealCycle.vue'
defineOptions
({
name
:
'CrmStatisticsCustomer'
})
...
...
@@ -105,41 +105,43 @@ const deptList = ref<Tree[]>([]) // 部门树形结构
const
userList
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 全量用户清单
// 根据选择的部门筛选员工清单
const
userListByDeptId
=
computed
(()
=>
queryParams
.
deptId
?
userList
.
value
.
filter
((
u
:
UserApi
.
UserVO
)
=>
u
.
deptId
===
queryParams
.
deptId
)
:
[]
queryParams
.
deptId
?
userList
.
value
.
filter
((
u
:
UserApi
.
UserVO
)
=>
u
.
deptId
===
queryParams
.
deptId
)
:
[]
)
// 活跃标签
const
activeTab
=
ref
(
'
totalCustomerCount
'
)
const
activeTab
=
ref
(
'
customerSummary
'
)
// 1.客户总量分析
const
totalCustomerCount
Ref
=
ref
()
const
customerSummary
Ref
=
ref
()
// 2.客户跟进次数分析
const
followup
Count
Ref
=
ref
()
const
followup
Summary
Ref
=
ref
()
// 3.客户跟进方式分析
const
followupTypeRef
=
ref
()
// 4.客户转化率分析
const
conversion
Rate
Ref
=
ref
()
const
conversion
Stat
Ref
=
ref
()
// 5.公海客户分析
// 缺 crm_owner_record 表
// 6.成交周期分析
const
customer
CycleRef
=
ref
()
const
deal
CycleRef
=
ref
()
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
switch
(
activeTab
.
value
)
{
case
'
totalCustomerCount
'
:
totalCustomerCount
Ref
.
value
?.
loadData
?.()
case
'
customerSummary
'
:
customerSummary
Ref
.
value
?.
loadData
?.()
break
case
'followup
Count
'
:
followup
Count
Ref
.
value
?.
loadData
?.()
case
'followup
Summary
'
:
followup
Summary
Ref
.
value
?.
loadData
?.()
break
case
'followupType'
:
followupTypeRef
.
value
?.
loadData
?.()
break
case
'conversion
Rate
'
:
conversion
Rate
Ref
.
value
?.
loadData
?.()
case
'conversion
Stat
'
:
conversion
Stat
Ref
.
value
?.
loadData
?.()
break
case
'
customer
Cycle'
:
customer
CycleRef
.
value
?.
loadData
?.()
case
'
deal
Cycle'
:
deal
CycleRef
.
value
?.
loadData
?.()
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