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
441b9138
authored
Feb 27, 2024
by
dhb52
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: CRM/数据统计/客户总量分析
parent
0db264dc
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
262 additions
and
0 deletions
+262
-0
src/api/crm/statistics/customer.ts
+24
-0
src/views/crm/statistics/customer/components/TotalCustomerCount.vue
+113
-0
src/views/crm/statistics/customer/index.vue
+125
-0
No files found.
src/api/crm/statistics/customer.ts
0 → 100644
View file @
441b9138
import
request
from
'@/config/axios'
export
interface
StatisticsCustomerRespVO
{
count
:
number
category
:
string
}
// 客户总量分析 API
export
const
StatisticsCustomerApi
=
{
// 客户总量(新建)
getTotalCustomerCount
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-total-customer-count'
,
params
})
},
// 客户总量(成交)
getDealTotalCustomerCount
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/statistics-customer/get-deal-total-customer-count'
,
params
})
},
}
src/views/crm/statistics/customer/components/TotalCustomerCount.vue
0 → 100644
View file @
441b9138
<!-- 客户总量分析 -->
<
template
>
<!-- 柱状图 -->
<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"
/>
<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>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
StatisticsCustomerApi
,
StatisticsCustomerRespVO
}
from
'@/api/crm/statistics/customer'
import
{
EChartsOption
}
from
'echarts'
import
{
clone
}
from
'lodash-es'
defineOptions
({
name
:
'TotalCustomerCount'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
StatisticsCustomerRespVO
[]
>
([])
// 列表的数据
/** 柱状图配置:纵向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
grid
:
{
left
:
20
,
right
:
20
,
bottom
:
20
,
containLabel
:
true
},
legend
:
{
},
series
:
[
{
name
:
'新增客户数'
,
type
:
'bar'
,
data
:
[]
},
{
name
:
'成交客户数'
,
type
:
'bar'
,
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
:
'数量(个)'
},
xAxis
:
{
type
:
'category'
,
name
:
'日期'
,
data
:
[]
}
})
as
EChartsOption
/** 获取统计数据 */
const
loadData
=
async
()
=>
{
// 1. 加载统计数据
loading
.
value
=
true
const
customerCount
=
await
StatisticsCustomerApi
.
getTotalCustomerCount
(
props
.
queryParams
)
const
dealCustomerCount
=
await
StatisticsCustomerApi
.
getDealTotalCustomerCount
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
xAxis
&&
echartsOption
.
xAxis
[
'data'
])
{
echartsOption
.
xAxis
[
'data'
]
=
clone
(
customerCount
.
map
(
s
=>
s
[
'category'
]))
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
0
]
&&
echartsOption
.
series
[
0
][
'data'
])
{
echartsOption
.
series
[
0
][
'data'
]
=
clone
(
customerCount
.
map
(
s
=>
s
[
'count'
]))
}
if
(
echartsOption
.
series
&&
echartsOption
.
series
[
1
]
&&
echartsOption
.
series
[
1
][
'data'
])
{
echartsOption
.
series
[
1
][
'data'
]
=
clone
(
dealCustomerCount
.
map
(
s
=>
s
[
'count'
]))
}
// 2.2 更新列表数据
const
tableData
=
customerCount
.
map
((
item
,
index
)
=>
{
return
{
category
:
item
[
'category'
],
customerCount
:
item
[
'count'
],
dealCustomerCount
:
dealCustomerCount
[
index
][
'count'
],
}
})
list
.
value
=
tableData
loading
.
value
=
false
}
defineExpose
({
loadData
})
/** 初始化 */
onMounted
(()
=>
{
loadData
()
})
</
script
>
src/views/crm/statistics/customer/index.vue
0 → 100644
View file @
441b9138
<!-- 数据统计 - 员工客户分析 -->
<
template
>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"时间范围"
prop=
"orderDate"
>
<el-date-picker
v-model=
"queryParams.times"
:shortcuts=
"defaultShortcuts"
class=
"!w-240px"
end-placeholder=
"结束日期"
start-placeholder=
"开始日期"
type=
"daterange"
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
label=
"归属部门"
prop=
"deptId"
>
<el-tree-select
v-model=
"queryParams.deptId"
:data=
"deptList"
:props=
"defaultProps"
check-strictly
node-key=
"id"
placeholder=
"请选择归属部门"
@
change=
"queryParams.userId = undefined"
/>
</el-form-item>
<el-form-item
label=
"员工"
prop=
"userId"
>
<el-select
v-model=
"queryParams.userId"
class=
"!w-240px"
placeholder=
"员工"
clearable
>
<el-option
v-for=
"(user, index) in userListByDeptId"
:label=
"user.nickname"
:value=
"user.id"
:key=
"index"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
>
<Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 排行数据 -->
<el-col>
<el-tabs
v-model=
"activeTab"
>
<!-- 客户总量分析 -->
<el-tab-pane
label=
"客户总量分析"
name=
"totalCustomerCount"
lazy
>
<TotalCustomerCount
:query-params=
"queryParams"
ref=
"totalCustomerCountRef"
/>
</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'
defineOptions
({
name
:
'CrmStatisticsCustomer'
})
const
queryParams
=
reactive
({
deptId
:
useUserStore
().
getUser
.
deptId
,
userId
:
undefined
,
times
:
[
// 默认显示最近一周的数据
formatDate
(
beginOfDay
(
new
Date
(
new
Date
().
getTime
()
-
3600
*
1000
*
24
*
7
))),
formatDate
(
endOfDay
(
new
Date
(
new
Date
().
getTime
()
-
3600
*
1000
*
24
)))
]
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
deptList
=
ref
<
Tree
[]
>
([])
// 部门树形结构
const
userList
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 全量用户清单
// 根据选择的部门筛选员工清单
const
userListByDeptId
=
computed
(()
=>
queryParams
.
deptId
?
userList
.
value
.
filter
((
u
)
=>
u
.
deptId
===
queryParams
.
deptId
)
:
[]
)
// 活跃标签
const
activeTab
=
ref
(
'totalCustomerCount'
)
// 1.客户总量分析
const
totalCustomerCountRef
=
ref
()
// 2.客户跟进次数分析
// 3.客户跟进方式分析
// 4.客户转化率分析
// 5.公海客户分析
// 6.成交周期分析
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
switch
(
activeTab
.
value
)
{
case
'totalCustomerCount'
:
totalCustomerCountRef
.
value
?.
loadData
?.()
break
}
}
// 当 activeTab 改变时,刷新当前活动的 tab
watch
(
activeTab
,
()
=>
{
handleQuery
()
})
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryFormRef
.
value
.
resetFields
()
handleQuery
()
}
// 加载部门树
onMounted
(
async
()
=>
{
deptList
.
value
=
handleTree
(
await
DeptApi
.
getSimpleDeptList
())
userList
.
value
=
handleTree
(
await
UserApi
.
getSimpleUserList
())
})
</
script
>
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