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
cce1fadc
authored
Mar 24, 2024
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CRM: 新增客户行业、来源、级别统计、区域数据统计
parent
6b45ed7e
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
785 additions
and
20 deletions
+785
-20
src/api/crm/statistics/customer.ts
+58
-0
src/api/mall/statistics/member.ts
+1
-1
src/views/crm/statistics/customer/components/CustomerAddress.vue
+150
-0
src/views/crm/statistics/customer/components/CustomerIndustry.vue
+171
-0
src/views/crm/statistics/customer/components/CustomerLevel.vue
+171
-0
src/views/crm/statistics/customer/components/CustomerSource.vue
+171
-0
src/views/crm/statistics/customer/index.vue
+63
-19
No files found.
src/api/crm/statistics/customer.ts
View file @
cce1fadc
...
@@ -49,6 +49,36 @@ export interface CrmStatisticsCustomerDealCycleByDateRespVO {
...
@@ -49,6 +49,36 @@ export interface CrmStatisticsCustomerDealCycleByDateRespVO {
customerDealCycle
:
number
customerDealCycle
:
number
}
}
export
interface
CrmStatisticCustomerBaseRespVO
{
customerCount
:
number
dealCount
:
number
dealPortion
:
number
}
export
interface
CrmStatisticCustomerIndustryRespVO
extends
CrmStatisticCustomerBaseRespVO
{
industryId
:
number
industryName
:
string
industryPortion
:
number
}
export
interface
CrmStatisticCustomerSourceRespVO
extends
CrmStatisticCustomerBaseRespVO
{
source
:
number
sourceName
:
string
sourcePortion
:
number
}
export
interface
CrmStatisticCustomerLevelRespVO
extends
CrmStatisticCustomerBaseRespVO
{
level
:
number
levelName
:
string
levelPortion
:
number
}
export
interface
CrmStatisticCustomerAreaRespVO
extends
CrmStatisticCustomerBaseRespVO
{
areaId
:
number
areaName
:
string
areaPortion
:
number
}
export
interface
CrmStatisticsCustomerDealCycleByUserRespVO
{
export
interface
CrmStatisticsCustomerDealCycleByUserRespVO
{
ownerUserName
:
string
ownerUserName
:
string
customerDealCycle
:
number
customerDealCycle
:
number
...
@@ -112,5 +142,33 @@ export const StatisticsCustomerApi = {
...
@@ -112,5 +142,33 @@ export const StatisticsCustomerApi = {
url
:
'/crm/statistics-customer/get-customer-deal-cycle-by-user'
,
url
:
'/crm/statistics-customer/get-customer-deal-cycle-by-user'
,
params
params
})
})
},
// 6.1 获取客户行业统计数据
getCustomerIndustry
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-industry-summary'
,
params
})
},
// 6.1 获取客户来源统计数据
getCustomerSource
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-source-summary'
,
params
})
},
// 6.1 获取客户行业统计数据
getCustomerLevel
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-level-summary'
,
params
})
},
// 6.1 获取客户行业统计数据
getCustomerArea
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-customer-area-summary'
,
params
})
}
}
}
}
src/api/mall/statistics/member.ts
View file @
cce1fadc
...
@@ -5,7 +5,7 @@ import { formatDate } from '@/utils/formatTime'
...
@@ -5,7 +5,7 @@ import { formatDate } from '@/utils/formatTime'
/** 会员分析 Request VO */
/** 会员分析 Request VO */
export
interface
MemberAnalyseReqVO
{
export
interface
MemberAnalyseReqVO
{
times
:
[
dayjs
.
ConfigType
,
dayjs
.
ConfigType
]
times
:
dayjs
.
ConfigType
[
]
}
}
/** 会员分析 Response VO */
/** 会员分析 Response VO */
...
...
src/views/crm/statistics/customer/components/CustomerAddress.vue
0 → 100644
View file @
cce1fadc
<!-- 客户城市分布 -->
<
template
>
<!-- Echarts图 -->
<el-card
shadow=
"never"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption"
/>
</el-skeleton>
</el-col>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption2"
/>
</el-skeleton>
</el-col>
</el-row>
</el-card>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
EChartsOption
}
from
'echarts'
import
china
from
'@/assets/map/json/china.json'
import
echarts
from
'@/plugins/echarts'
import
{
CrmStatisticCustomerAreaRespVO
,
StatisticsCustomerApi
}
from
'@/api/crm/statistics/customer'
defineOptions
({
name
:
'CustomerAddress'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
// 注册地图
echarts
?.
registerMap
(
'china'
,
china
as
any
)
const
loading
=
ref
(
false
)
// 加载中
const
areaStatisticsList
=
ref
<
CrmStatisticCustomerAreaRespVO
[]
>
([])
// 列表的数据
/** 地图配置 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'全部客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
,
showDelay
:
0
,
transitionDuration
:
0.2
},
visualMap
:
{
text
:
[
'高'
,
'低'
],
realtime
:
false
,
calculable
:
true
,
top
:
'middle'
,
inRange
:
{
color
:
[
'#fff'
,
'#3b82f6'
]
}
},
series
:
[
{
name
:
'客户地域分布'
,
type
:
'map'
,
map
:
'china'
,
roam
:
false
,
selectedMode
:
false
,
data
:
[]
}
]
})
as
EChartsOption
/** 地图配置 */
const
echartsOption2
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'成交客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
,
showDelay
:
0
,
transitionDuration
:
0.2
},
visualMap
:
{
text
:
[
'高'
,
'低'
],
realtime
:
false
,
calculable
:
true
,
top
:
'middle'
,
inRange
:
{
color
:
[
'#fff'
,
'#3b82f6'
]
}
},
series
:
[
{
name
:
'客户地域分布'
,
type
:
'map'
,
map
:
'china'
,
roam
:
false
,
selectedMode
:
false
,
data
:
[]
}
]
})
as
EChartsOption
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
areaList
=
await
StatisticsCustomerApi
.
getCustomerArea
(
props
.
queryParams
)
areaStatisticsList
.
value
=
areaList
.
map
((
item
:
CrmStatisticCustomerAreaRespVO
)
=>
{
return
{
...
item
,
areaName
:
item
.
areaName
.
replace
(
'维吾尔自治区'
,
''
)
.
replace
(
'壮族自治区'
,
''
)
.
replace
(
'回族自治区'
,
''
)
.
replace
(
'自治区'
,
''
)
.
replace
(
'省'
,
''
)
}
})
builderLeftMap
()
builderRightMap
()
loading
.
value
=
false
}
defineExpose
({
loadData
})
const
builderLeftMap
=
()
=>
{
let
min
=
0
let
max
=
0
echartsOption
.
series
!
[
0
].
data
=
areaStatisticsList
.
value
.
map
((
item
)
=>
{
min
=
Math
.
min
(
min
,
item
.
customerCount
||
0
)
max
=
Math
.
max
(
max
,
item
.
customerCount
||
0
)
return
{
...
item
,
name
:
item
.
areaName
,
value
:
item
.
customerCount
||
0
}
})
echartsOption
.
visualMap
!
[
'min'
]
=
min
echartsOption
.
visualMap
!
[
'max'
]
=
max
}
const
builderRightMap
=
()
=>
{
let
min
=
0
let
max
=
0
echartsOption2
.
series
!
[
0
].
data
=
areaStatisticsList
.
value
.
map
((
item
)
=>
{
min
=
Math
.
min
(
min
,
item
.
dealCount
||
0
)
max
=
Math
.
max
(
max
,
item
.
dealCount
||
0
)
return
{
...
item
,
name
:
item
.
areaName
,
value
:
item
.
dealCount
||
0
}
})
echartsOption2
.
visualMap
!
[
'min'
]
=
min
echartsOption2
.
visualMap
!
[
'max'
]
=
max
}
/** 初始化 */
onMounted
(()
=>
{
loadData
()
})
</
script
>
src/views/crm/statistics/customer/components/CustomerIndustry.vue
0 → 100644
View file @
cce1fadc
<!-- 客户行业分析 -->
<
template
>
<!-- Echarts图 -->
<el-card
shadow=
"never"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption"
/>
</el-skeleton>
</el-col>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption2"
/>
</el-skeleton>
</el-col>
</el-row>
</el-card>
<!-- 统计列表 -->
<el-card
class=
"mt-16px"
shadow=
"never"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
align=
"center"
label=
"序号"
type=
"index"
width=
"80"
/>
<el-table-column
align=
"center"
label=
"客户行业"
min-width=
"200"
prop=
"industryName"
/>
<el-table-column
align=
"center"
label=
"客户个数"
min-width=
"200"
prop=
"customerCount"
/>
<el-table-column
align=
"center"
label=
"成交个数"
min-width=
"200"
prop=
"dealCount"
/>
<el-table-column
align=
"center"
label=
"行业占比(%)"
min-width=
"200"
prop=
"industryPortion"
/>
<el-table-column
align=
"center"
label=
"成交占比(%)"
min-width=
"200"
prop=
"dealPortion"
/>
</el-table>
</el-card>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
CrmStatisticCustomerIndustryRespVO
,
StatisticsCustomerApi
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'CustomerIndustry'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
CrmStatisticCustomerIndustryRespVO
[]
>
([])
// 列表的数据
/** 饼图配置 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'全部客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
},
toolbox
:
{
feature
:
{
saveAsImage
:
{
show
:
true
,
name
:
'全部客户'
}
// 保存为图片
}
},
series
:
[
{
name
:
'全部客户'
,
type
:
'pie'
,
radius
:
[
'40%'
,
'70%'
],
avoidLabelOverlap
:
false
,
itemStyle
:
{
borderRadius
:
10
,
borderColor
:
'#fff'
,
borderWidth
:
2
},
label
:
{
show
:
false
,
position
:
'center'
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
40
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
false
},
data
:
[]
}
]
})
as
EChartsOption
/** 饼图配置 */
const
echartsOption2
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'成交客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
},
toolbox
:
{
feature
:
{
saveAsImage
:
{
show
:
true
,
name
:
'成交客户'
}
// 保存为图片
}
},
series
:
[
{
name
:
'成交客户'
,
type
:
'pie'
,
radius
:
[
'40%'
,
'70%'
],
avoidLabelOverlap
:
false
,
itemStyle
:
{
borderRadius
:
10
,
borderColor
:
'#fff'
,
borderWidth
:
2
},
label
:
{
show
:
false
,
position
:
'center'
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
40
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
false
},
data
:
[]
}
]
})
as
EChartsOption
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
industryList
=
await
StatisticsCustomerApi
.
getCustomerIndustry
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
industryList
.
map
((
r
:
CrmStatisticCustomerIndustryRespVO
)
=>
{
return
{
name
:
r
.
industryName
,
value
:
r
.
customerCount
}
})
}
// 2.2 更新 Echarts2 数据
if
(
echartsOption2
.
series
&&
echartsOption2
.
series
[
0
]
&&
echartsOption2
.
series
[
0
][
'data'
])
{
echartsOption2
.
series
[
0
][
'data'
]
=
industryList
.
map
((
r
:
CrmStatisticCustomerIndustryRespVO
)
=>
{
return
{
name
:
r
.
industryName
,
value
:
r
.
dealCount
}
})
}
list
.
value
=
industryList
loading
.
value
=
false
}
defineExpose
({
loadData
})
/** 初始化 */
onMounted
(()
=>
{
loadData
()
})
</
script
>
src/views/crm/statistics/customer/components/CustomerLevel.vue
0 → 100644
View file @
cce1fadc
<!-- 客户来源分析 -->
<
template
>
<!-- Echarts图 -->
<el-card
shadow=
"never"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption"
/>
</el-skeleton>
</el-col>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption2"
/>
</el-skeleton>
</el-col>
</el-row>
</el-card>
<!-- 统计列表 -->
<el-card
class=
"mt-16px"
shadow=
"never"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
align=
"center"
label=
"序号"
type=
"index"
width=
"80"
/>
<el-table-column
align=
"center"
label=
"客户来源"
min-width=
"200"
prop=
"levelName"
/>
<el-table-column
align=
"center"
label=
"客户个数"
min-width=
"200"
prop=
"customerCount"
/>
<el-table-column
align=
"center"
label=
"成交个数"
min-width=
"200"
prop=
"dealCount"
/>
<el-table-column
align=
"center"
label=
"级别占比(%)"
min-width=
"200"
prop=
"levelPortion"
/>
<el-table-column
align=
"center"
label=
"成交占比(%)"
min-width=
"200"
prop=
"dealPortion"
/>
</el-table>
</el-card>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
CrmStatisticCustomerLevelRespVO
,
StatisticsCustomerApi
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'CustomerSource'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
CrmStatisticCustomerLevelRespVO
[]
>
([])
// 列表的数据
/** 饼图配置 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'全部客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
},
toolbox
:
{
feature
:
{
saveAsImage
:
{
show
:
true
,
name
:
'全部客户'
}
// 保存为图片
}
},
series
:
[
{
name
:
'全部客户'
,
type
:
'pie'
,
radius
:
[
'40%'
,
'70%'
],
avoidLabelOverlap
:
false
,
itemStyle
:
{
borderRadius
:
10
,
borderColor
:
'#fff'
,
borderWidth
:
2
},
label
:
{
show
:
false
,
position
:
'center'
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
40
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
false
},
data
:
[]
}
]
})
as
EChartsOption
/** 饼图配置 */
const
echartsOption2
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'成交客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
},
toolbox
:
{
feature
:
{
saveAsImage
:
{
show
:
true
,
name
:
'成交客户'
}
// 保存为图片
}
},
series
:
[
{
name
:
'成交客户'
,
type
:
'pie'
,
radius
:
[
'40%'
,
'70%'
],
avoidLabelOverlap
:
false
,
itemStyle
:
{
borderRadius
:
10
,
borderColor
:
'#fff'
,
borderWidth
:
2
},
label
:
{
show
:
false
,
position
:
'center'
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
40
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
false
},
data
:
[]
}
]
})
as
EChartsOption
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
levelList
=
await
StatisticsCustomerApi
.
getCustomerLevel
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
levelList
.
map
((
r
:
CrmStatisticCustomerLevelRespVO
)
=>
{
return
{
name
:
r
.
levelName
,
value
:
r
.
customerCount
}
})
}
// 2.2 更新 Echarts2 数据
if
(
echartsOption2
.
series
&&
echartsOption2
.
series
[
0
]
&&
echartsOption2
.
series
[
0
][
'data'
])
{
echartsOption2
.
series
[
0
][
'data'
]
=
levelList
.
map
((
r
:
CrmStatisticCustomerLevelRespVO
)
=>
{
return
{
name
:
r
.
levelName
,
value
:
r
.
dealCount
}
})
}
list
.
value
=
levelList
loading
.
value
=
false
}
defineExpose
({
loadData
})
/** 初始化 */
onMounted
(()
=>
{
loadData
()
})
</
script
>
src/views/crm/statistics/customer/components/CustomerSource.vue
0 → 100644
View file @
cce1fadc
<!-- 客户来源分析 -->
<
template
>
<!-- Echarts图 -->
<el-card
shadow=
"never"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption"
/>
</el-skeleton>
</el-col>
<el-col
:span=
"12"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:height=
"500"
:options=
"echartsOption2"
/>
</el-skeleton>
</el-col>
</el-row>
</el-card>
<!-- 统计列表 -->
<el-card
class=
"mt-16px"
shadow=
"never"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
align=
"center"
label=
"序号"
type=
"index"
width=
"80"
/>
<el-table-column
align=
"center"
label=
"客户来源"
min-width=
"200"
prop=
"sourceName"
/>
<el-table-column
align=
"center"
label=
"客户个数"
min-width=
"200"
prop=
"customerCount"
/>
<el-table-column
align=
"center"
label=
"成交个数"
min-width=
"200"
prop=
"dealCount"
/>
<el-table-column
align=
"center"
label=
"来源占比(%)"
min-width=
"200"
prop=
"sourcePortion"
/>
<el-table-column
align=
"center"
label=
"成交占比(%)"
min-width=
"200"
prop=
"dealPortion"
/>
</el-table>
</el-card>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
CrmStatisticCustomerSourceRespVO
,
StatisticsCustomerApi
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
defineOptions
({
name
:
'CustomerSource'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
CrmStatisticCustomerSourceRespVO
[]
>
([])
// 列表的数据
/** 饼图配置 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'全部客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
},
toolbox
:
{
feature
:
{
saveAsImage
:
{
show
:
true
,
name
:
'全部客户'
}
// 保存为图片
}
},
series
:
[
{
name
:
'全部客户'
,
type
:
'pie'
,
radius
:
[
'40%'
,
'70%'
],
avoidLabelOverlap
:
false
,
itemStyle
:
{
borderRadius
:
10
,
borderColor
:
'#fff'
,
borderWidth
:
2
},
label
:
{
show
:
false
,
position
:
'center'
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
40
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
false
},
data
:
[]
}
]
})
as
EChartsOption
/** 饼图配置 */
const
echartsOption2
=
reactive
<
EChartsOption
>
({
title
:
{
text
:
'成交客户'
,
left
:
'center'
},
tooltip
:
{
trigger
:
'item'
},
legend
:
{
orient
:
'vertical'
,
left
:
'left'
},
toolbox
:
{
feature
:
{
saveAsImage
:
{
show
:
true
,
name
:
'成交客户'
}
// 保存为图片
}
},
series
:
[
{
name
:
'成交客户'
,
type
:
'pie'
,
radius
:
[
'40%'
,
'70%'
],
avoidLabelOverlap
:
false
,
itemStyle
:
{
borderRadius
:
10
,
borderColor
:
'#fff'
,
borderWidth
:
2
},
label
:
{
show
:
false
,
position
:
'center'
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
40
,
fontWeight
:
'bold'
}
},
labelLine
:
{
show
:
false
},
data
:
[]
}
]
})
as
EChartsOption
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
sourceList
=
await
StatisticsCustomerApi
.
getCustomerSource
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
sourceList
.
map
((
r
:
CrmStatisticCustomerSourceRespVO
)
=>
{
return
{
name
:
r
.
sourceName
,
value
:
r
.
customerCount
}
})
}
// 2.2 更新 Echarts2 数据
if
(
echartsOption2
.
series
&&
echartsOption2
.
series
[
0
]
&&
echartsOption2
.
series
[
0
][
'data'
])
{
echartsOption2
.
series
[
0
][
'data'
]
=
sourceList
.
map
((
r
:
CrmStatisticCustomerSourceRespVO
)
=>
{
return
{
name
:
r
.
sourceName
,
value
:
r
.
dealCount
}
})
}
list
.
value
=
sourceList
loading
.
value
=
false
}
defineExpose
({
loadData
})
/** 初始化 */
onMounted
(()
=>
{
loadData
()
})
</
script
>
src/views/crm/statistics/customer/index.vue
View file @
cce1fadc
...
@@ -3,49 +3,55 @@
...
@@ -3,49 +3,55 @@
<ContentWrap>
<ContentWrap>
<!-- 搜索工作栏 -->
<!-- 搜索工作栏 -->
<el-form
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
ref=
"queryFormRef"
:inline=
"true"
:inline=
"true"
:model=
"queryParams"
class=
"-mb-15px"
label-width=
"68px"
label-width=
"68px"
>
>
<el-form-item
label=
"时间范围"
prop=
"orderDate"
>
<el-form-item
label=
"时间范围"
prop=
"orderDate"
>
<el-date-picker
<el-date-picker
v-model=
"queryParams.times"
v-model=
"queryParams.times"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
:shortcuts=
"defaultShortcuts"
:shortcuts=
"defaultShortcuts"
class=
"!w-240px"
class=
"!w-240px"
end-placeholder=
"结束日期"
end-placeholder=
"结束日期"
start-placeholder=
"开始日期"
start-placeholder=
"开始日期"
type=
"daterange"
type=
"daterange"
value-format=
"YYYY-MM-DD HH:mm:ss"
value-format=
"YYYY-MM-DD HH:mm:ss"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"归属部门"
prop=
"deptId"
>
<el-form-item
label=
"归属部门"
prop=
"deptId"
>
<el-tree-select
<el-tree-select
v-model=
"queryParams.deptId"
v-model=
"queryParams.deptId"
class=
"!w-240px"
:data=
"deptList"
:data=
"deptList"
:props=
"defaultProps"
:props=
"defaultProps"
check-strictly
check-strictly
class=
"!w-240px"
node-key=
"id"
node-key=
"id"
placeholder=
"请选择归属部门"
placeholder=
"请选择归属部门"
@
change=
"queryParams.userId = undefined"
@
change=
"queryParams.userId = undefined"
/>
/>
</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"
placeholder=
"员工"
clearable
>
<el-select
v-model=
"queryParams.userId"
class=
"!w-240px"
clearable
placeholder=
"员工"
>
<el-option
<el-option
v-for=
"(user, index) in userListByDeptId"
v-for=
"(user, index) in userListByDeptId"
:key=
"index"
:label=
"user.nickname"
:label=
"user.nickname"
:value=
"user.id"
:value=
"user.id"
:key=
"index"
/>
/>
</el-select>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
>
<Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"handleQuery"
>
<el-button
@
click=
"resetQuery"
>
<Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
</ContentWrap>
</ContentWrap>
...
@@ -54,24 +60,40 @@
...
@@ -54,24 +60,40 @@
<el-col>
<el-col>
<el-tabs
v-model=
"activeTab"
>
<el-tabs
v-model=
"activeTab"
>
<!-- 客户总量分析 -->
<!-- 客户总量分析 -->
<el-tab-pane
label=
"客户总量分析"
name=
"customerSummary"
lazy
>
<el-tab-pane
label=
"客户总量分析"
lazy
name=
"customerSummary"
>
<CustomerSummary
:query-params=
"queryParams"
ref=
"customerSummaryRef
"
/>
<CustomerSummary
ref=
"customerSummaryRef"
:query-params=
"queryParams
"
/>
</el-tab-pane>
</el-tab-pane>
<!-- 客户跟进次数分析 -->
<!-- 客户跟进次数分析 -->
<el-tab-pane
label=
"客户跟进次数分析"
name=
"followupSummary"
lazy
>
<el-tab-pane
label=
"客户跟进次数分析"
lazy
name=
"followupSummary"
>
<CustomerFollowupSummary
:query-params=
"queryParams"
ref=
"followupSummaryRef
"
/>
<CustomerFollowupSummary
ref=
"followupSummaryRef"
:query-params=
"queryParams
"
/>
</el-tab-pane>
</el-tab-pane>
<!-- 客户跟进方式分析 -->
<!-- 客户跟进方式分析 -->
<el-tab-pane
label=
"客户跟进方式分析"
name=
"followupType"
lazy
>
<el-tab-pane
label=
"客户跟进方式分析"
lazy
name=
"followupType"
>
<CustomerFollowupType
:query-params=
"queryParams"
ref=
"followupTypeRef
"
/>
<CustomerFollowupType
ref=
"followupTypeRef"
:query-params=
"queryParams
"
/>
</el-tab-pane>
</el-tab-pane>
<!-- 客户转化率分析 -->
<!-- 客户转化率分析 -->
<el-tab-pane
label=
"客户转化率分析"
name=
"conversionStat"
lazy
>
<el-tab-pane
label=
"客户转化率分析"
lazy
name=
"conversionStat"
>
<CustomerConversionStat
:query-params=
"queryParams"
ref=
"conversionStatRef
"
/>
<CustomerConversionStat
ref=
"conversionStatRef"
:query-params=
"queryParams
"
/>
</el-tab-pane>
</el-tab-pane>
<!-- 成交周期分析 -->
<!-- 成交周期分析 -->
<el-tab-pane
label=
"成交周期分析"
name=
"dealCycle"
lazy
>
<el-tab-pane
label=
"成交周期分析"
lazy
name=
"dealCycle"
>
<CustomerDealCycle
:query-params=
"queryParams"
ref=
"dealCycleRef"
/>
<CustomerDealCycle
ref=
"dealCycleRef"
:query-params=
"queryParams"
/>
</el-tab-pane>
<!-- 城市分布分析 -->
<el-tab-pane
label=
"城市分布分析"
lazy
name=
"addressRef"
>
<CustomerAddress
ref=
"addressRef"
:query-params=
"queryParams"
/>
</el-tab-pane>
<!-- 客户级别分析 -->
<el-tab-pane
label=
"客户级别分析"
lazy
name=
"levelRef"
>
<CustomerLevel
ref=
"levelRef"
:query-params=
"queryParams"
/>
</el-tab-pane>
<!-- 客户来源分析 -->
<el-tab-pane
label=
"客户来源分析"
lazy
name=
"sourceRef"
>
<CustomerSource
ref=
"sourceRef"
:query-params=
"queryParams"
/>
</el-tab-pane>
<!-- 客户行业分析 -->
<el-tab-pane
label=
"客户行业分析"
lazy
name=
"industryRef"
>
<CustomerIndustry
ref=
"industryRef"
:query-params=
"queryParams"
/>
</el-tab-pane>
</el-tab-pane>
</el-tabs>
</el-tabs>
</el-col>
</el-col>
...
@@ -88,6 +110,10 @@ import CustomerFollowupSummary from './components/CustomerFollowupSummary.vue'
...
@@ -88,6 +110,10 @@ import CustomerFollowupSummary from './components/CustomerFollowupSummary.vue'
import
CustomerFollowupType
from
'./components/CustomerFollowupType.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
CustomerAddress
from
'./components/CustomerAddress.vue'
import
CustomerIndustry
from
'./components/CustomerIndustry.vue'
import
CustomerSource
from
'./components/CustomerSource.vue'
import
CustomerLevel
from
'./components/CustomerLevel.vue'
defineOptions
({
name
:
'CrmStatisticsCustomer'
})
defineOptions
({
name
:
'CrmStatisticsCustomer'
})
...
@@ -125,7 +151,13 @@ const conversionStatRef = ref()
...
@@ -125,7 +151,13 @@ const conversionStatRef = ref()
// 缺 crm_owner_record 表
// 缺 crm_owner_record 表
// 6.成交周期分析
// 6.成交周期分析
const
dealCycleRef
=
ref
()
const
dealCycleRef
=
ref
()
const
addressRef
=
ref
()
// 客户级别
const
levelRef
=
ref
()
// 客户来源
const
sourceRef
=
ref
()
// 客户行业
const
industryRef
=
ref
()
/** 搜索按钮操作 */
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
const
handleQuery
=
()
=>
{
switch
(
activeTab
.
value
)
{
switch
(
activeTab
.
value
)
{
...
@@ -144,6 +176,18 @@ const handleQuery = () => {
...
@@ -144,6 +176,18 @@ const handleQuery = () => {
case
'dealCycle'
:
case
'dealCycle'
:
dealCycleRef
.
value
?.
loadData
?.()
dealCycleRef
.
value
?.
loadData
?.()
break
break
case
'addressRef'
:
addressRef
.
value
?.
loadData
?.()
break
case
'levelRef'
:
levelRef
.
value
?.
loadData
?.()
break
case
'sourceRef'
:
sourceRef
.
value
?.
loadData
?.()
break
case
'industryRef'
:
industryRef
.
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